/* ListView — the shared record-list toolbar and table affordances.
   Everything structural (.tbl, .tbl-wrap, .cardable, .toolrow, .t-main,
   .t-sub, .num) already exists in styles.css; this adds only what a
   searchable, sortable, exportable list needs on top. */

.lv-bar { gap: 8px; }

.lv-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 240px;
  max-width: 340px;
  min-width: 0;
}
.lv-search svg {
  position: absolute;
  left: 11px;
  width: 15px; height: 15px;
  color: var(--ink-faint);
  pointer-events: none;
}
.lv-search input {
  width: 100%;
  min-width: 0;
  padding: 8px 12px 8px 33px;
  border: 1px solid var(--stroke);
  border-radius: 99px;
  background: var(--paper);
  font: inherit;
  font-size: 13px;
  color: var(--ink);
}
.lv-search input:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(169, 130, 76, .13);
}
/* Safari draws its own clear button; it collides with the pill radius. */
.lv-search input::-webkit-search-decoration,
.lv-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.lv-filter {
  border: 1px solid var(--stroke);
  border-radius: 99px;
  background: var(--paper);
  color: var(--ink-soft);
  padding: 7px 11px;
  font: inherit;
  font-size: 12.5px;
  max-width: 190px;
  cursor: pointer;
}
.lv-filter:hover { border-color: var(--gold); }
.lv-filter:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
/* An applied filter has to be visible at a glance — otherwise a list that is
   hiding records looks like a list that has none. */
.lv-filter.on {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
  font-weight: 600;
}

.lv-clear { flex: 0 0 auto; }

/* Count, columns, view toggle, export and the primary action travel together.
   With a bare flex spacer they were eight independent items, so the toolbar
   broke wherever it ran out of room — which put "+ New employer" alone on a
   second line, reading as a stray button rather than this list's main action.
   As one group it wraps as a block and stays right-aligned. */
.lv-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-left: auto;
}

.lv-count {
  font-size: 12px;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---- sortable headers ---- */
.lv-tbl th.lv-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.lv-tbl th.lv-sortable:hover { color: var(--ink); }
.lv-tbl th.lv-sortable:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}
.lv-tbl th.lv-sorted { color: var(--ink); }
.lv-arrow {
  display: inline-block;
  width: 10px;
  margin-left: 4px;
  font-size: 8px;
  vertical-align: middle;
  color: var(--gold-deep);
}

.lv-empty { padding: 26px 16px; }
.lv-empty .e-s { margin: 4px 0 12px; }
.lv-grid-empty {
  background: rgba(255, 255, 255, .55);
  border: 1px solid var(--stroke-soft);
  border-radius: var(--r-lg);
}

/* ---- view toggle ---- */
.lv-view {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  background: var(--bone);
  border-radius: 9px;
  flex: 0 0 auto;
}
.lv-view button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 26px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.lv-view button svg { width: 15px; height: 15px; }
.lv-view button:hover { color: var(--ink); }
.lv-view button.on {
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 1px 3px rgba(26, 27, 24, .10);
}
.lv-view button:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }

/* ---- column picker ---- */
.lv-cols { position: relative; flex: 0 0 auto; }
.lv-cols > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.lv-cols > summary::-webkit-details-marker { display: none; }
.lv-cols-n { font-variant-numeric: tabular-nums; color: var(--ink-faint); font-size: 11.5px; }
.lv-cols-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  min-width: 210px;
  max-height: 320px;
  overflow-y: auto;
  padding: 8px;
  background: var(--paper);
  border: 1px solid var(--stroke);
  border-radius: 12px;
  box-shadow: 0 12px 30px rgba(26, 27, 24, .14);
}
.lv-cols-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 8px;
  border-radius: 8px;
  font-size: 13px;
  cursor: pointer;
}
.lv-cols-item:hover { background: var(--bone); }
.lv-cols-item input { accent-color: var(--gold-deep); cursor: pointer; }
/* The last remaining column is disabled rather than hidden: a table with no
   columns is a bug the user would have to guess their way out of. */
.lv-cols-item input:disabled { cursor: not-allowed; }
.lv-cols-item input:disabled + span { opacity: .5; }
.lv-cols-reset { width: 100%; margin-top: 6px; }

.lv-dir { flex: 0 0 auto; min-width: 34px; font-size: 10px; }

/* ------------------------------------------------------------------
   CARD GRID
   ------------------------------------------------------------------ */

/* auto-fill, not auto-fit: with two records left after a filter, auto-fit
   stretches them across the full width into two enormous cards. auto-fill
   keeps the column width honest and leaves the empty tracks empty. */
.lv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
  /* stretch, not start: every card in a row takes the height of the tallest,
     so the grid reads as a grid rather than as a ragged wall. The cards are
     built to expect it — .lv-c-stats carries margin-top:auto, so the counts
     sit on one baseline across the row instead of floating wherever the text
     above them happened to end. */
  align-items: stretch;
}

/* The firm preferred the card this app shipped before the list view existed,
   so .lv-card is now only the hit area and the focus ring — the LOOK comes
   from employer.css's .emp-card rules, which never went away. Everything here
   is what a clickable region needs and nothing that decides appearance;
   duplicating the gradient, radius and lift would be the same rule written
   twice, and the two would drift the first time one was tuned. */
.lv-card {
  display: flex;
  flex-direction: column;
  gap: 0;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  background: linear-gradient(160deg, rgba(255, 255, 255, .82), rgba(244, 240, 233, .55));
  border: 1px solid var(--stroke-soft);
  border-radius: var(--r-lg, 16px);
  padding: 18px;
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.lv-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow);
  border-color: rgba(169, 130, 76, .35);
}
.lv-card:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* --- the shell the pages compose their cards from --- */

/* Identity line: avatar, then the name and the one line under it that says
   which record this is. */
.lv-c-head { display: flex; align-items: flex-start; gap: 11px; min-width: 0; }
.lv-c-ava {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bone);
  color: var(--gold-deep);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .02em;
}
/* A photograph fills the same 36px square the initials occupy, so a list of
   workers with photos and without stays on one grid. object-fit:cover crops a
   portrait to the square instead of squashing the face. */
img.lv-c-ava {
  object-fit: cover;
  object-position: center 25%;   /* faces sit above centre in a portrait */
  background: var(--bone);
}

/* The dossier's 84px avatar, when it is a real person rather than initials.
   .dh-ava carries `animation: idleFloat` and a gold gradient — decoration
   that reads fine behind two letters and badly behind a client's face, which
   should sit still and not be tinted. */
img.dh-ava {
  object-fit: cover;
  object-position: center 25%;
  animation: none;
  background: var(--bone);
}

.lv-c-id { min-width: 0; flex: 1 1 auto; }
.lv-c-name {
  font-family: 'Bricolage Grotesque', Georgia, serif;
  font-size: 15px;
  line-height: 1.25;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.lv-c-sub {
  font-size: 12px;
  color: var(--ink-soft);
  line-height: 1.4;
  margin-top: 2px;
  overflow-wrap: anywhere;
}
/* Top-right of the card: the one thing that would make you open it now. */
.lv-c-alert { flex: 0 0 auto; }

/* A row of small facts — chips, pills, whatever the page already uses. */
.lv-c-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

/* The counted facts, on their own baseline at the foot of the card so every
   card in a row lines up regardless of how long the name above it ran. */
.lv-c-stats {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--stroke-soft);
}
.lv-c-stat { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lv-c-stat b {
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.lv-c-stat span {
  font-size: 10px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}
/* A zero is not news. Dimming it lets the counts that matter carry the row. */
.lv-c-stat.zero b { color: var(--ink-faint); font-weight: 600; }

/* A labelled line for facts that are text rather than counts. */
.lv-c-line { display: flex; gap: 8px; font-size: 12.5px; line-height: 1.45; min-width: 0; }
.lv-c-line dt {
  flex: 0 0 84px;
  color: var(--ink-faint);
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding-top: 1px;
}
.lv-c-line dd { margin: 0; min-width: 0; color: var(--ink); overflow-wrap: anywhere; }

/* An inline target inside a row or card: the employer on a worker's card, a
   count that opens the thing it counts. Underlined on hover rather than
   always, because a card with six permanently-underlined values reads as a
   pile of links instead of a record with a few ways out of it. */
.lv-link,
[data-lv-row] a[href] {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .12s ease, border-color .12s ease;
}
.lv-link:hover,
[data-lv-row] a[href]:hover {
  color: var(--gold-deep);
  border-bottom-color: var(--gold);
}
.lv-link:focus-visible,
[data-lv-row] a[href]:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 3px;
}
/* A clickable stat keeps its number's weight; only the hover tells you it
   leads somewhere. */
.lv-c-stat .lv-link { display: flex; flex-direction: column; gap: 1px; }

/* A link wrapping the alert chip. flex, because an inline-block wrapper's line
   box adds descender space beneath the chip and drops it off the head row's
   centre line. Owned here rather than as an inline style on the chip: this
   file loads last, so it is the file that has to concede the point. */
.lv-c-alert.lv-link { display: flex; align-items: center; }

/* ---- phone ---- */
@media (max-width: 640px) {
  /* The toolbar is the first thing on the screen; it must not need a
     horizontal scroll to reach the export button. Search takes its own line,
     the filters wrap beneath it. */
  .lv-bar { gap: 7px; }
  .lv-search { flex: 1 1 100%; max-width: none; }
  .lv-filter { flex: 1 1 auto; max-width: none; font-size: 12px; }
  .lv-count { order: 99; }

  /* One card per row: two 290px columns cannot fit 390px, and the point of
     the card view on a phone is that each record gets the width to be read. */
  .lv-grid { grid-template-columns: 1fr; gap: 10px; }

  /* Anchored to the right edge of the screen rather than of the button, which
     on a phone can sit far enough right to push the menu off-screen. */
  .lv-cols { position: static; }
  .lv-cols-menu { right: 12px; left: 12px; min-width: 0; }

  /* .tbl.cardable turns each row into a card and prints the column label from
     data-l, so the sort headers are gone here by design — sorting stays
     available from the filters and from a wider screen. */
}

/* ---- progressive drawing (listview.js, "progressive drawing") ----
   A long list is drawn with its first rows showing; the row marked .lv-cut
   and everything after it are in the page but not drawn yet, and the cut
   moves down in idle-time chunks until it is gone. Screen only: a printout
   always carries every row, whatever the screen had got to. !important
   because .tbl.cardable sets display on rows at phone width, and this has to
   win over any page's own display rule for its rows and cards. */
@media screen {
  .lv-tbl > tbody > tr.lv-cut,
  .lv-tbl > tbody > tr.lv-cut ~ tr,
  .lv-grid > .lv-cut,
  .lv-grid > .lv-cut ~ * { display: none !important; }
  /* Columns frozen while the rows arrive — see freeze() in listview.js.
     overflow-wrap so a later row's long address or email breaks inside
     its column instead of spilling over the next one. */
  .lv-tbl.lv-fixed { table-layout: fixed; width: var(--lv-tw, 100%); }
  .lv-tbl.lv-fixed > thead > tr:first-child > th { width: var(--lv-w, auto); }
  .lv-tbl.lv-fixed > tbody > tr > td { overflow-wrap: anywhere; }
}
