/* ============================================================
   PESU Placements — design tokens
   ============================================================ */
/* Light theme: paper, not a lightbox.

   This was #ffffff surfaces on a #fcfcfb page — a wall of white behind a
   table of small numbers that people read for a long time. Warming the whole
   ramp drops the page's luminance without losing the sense of a light theme.

   Every pair below was measured rather than eyeballed, because beige is the
   easy way to fail: raising the background luminance quietly breaks greys
   that passed on white. Two had to move. --ink-3 went from #83817a to
   #6b634e, since the old value landed at 3.8:1 on an input background, and
   the amber chart series went from #eda100 to #a87400, which was 2.8:1
   against the card and is a bar you are supposed to be able to see. Body
   text sits at 16:1, every piece of secondary text clears 4.5:1, and the
   chart series all clear 3:1 as graphical objects.
   Re-run scripts/contrast.py before touching any of these. */
:root {
  color-scheme: light;
  --bg:            #eee5d3;
  --surface:       #f8f4e9;
  --surface-2:     #eae2cd;
  --surface-3:     #ded4ba;
  --line:          #d6cbb0;
  --line-strong:   #bdb092;
  --ink:           #201c12;
  --ink-2:         #56503f;
  --ink-3:         #6b634e;
  --accent:        #2a6fd0;
  --accent-soft:   #e2ebfa;
  --accent-ink:    #1a539e;

  --s1: #2a6fd0; --s2: #d4562a; --s3: #12946a; --s4: #a87400;
  --good: #16653f; --warn: #8f4e00; --bad: #a8332f;
  --good-bg: #e2f0e4; --warn-bg: #f7ead3; --bad-bg: #f8e6e2;

  --row-h: 46px;
  --radius: 9px;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif;
  --shadow: 0 1px 2px rgba(56,44,22,.06), 0 8px 24px rgba(56,44,22,.08);
  --shadow-lg: 0 2px 4px rgba(56,44,22,.07), 0 24px 60px rgba(56,44,22,.17);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:          #141413;
    --surface:     #1a1a19;
    --surface-2:   #222220;
    --surface-3:   #2c2c29;
    --line:        #302f2c;
    --line-strong: #45443f;
    --ink:         #f5f4ef;
    --ink-2:       #b5b3a9;
    --ink-3:       #86847c;
    --accent:      #5c9ce8;
    --accent-soft: #17283d;
    --accent-ink:  #8fbcf0;
    --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500;
    --good: #35b37e; --warn: #d99a2b; --bad: #e66767;
    --good-bg: #14291f; --warn-bg: #2c2413; --bad-bg: #2e1a19;
    --shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.35);
    --shadow-lg: 0 2px 4px rgba(0,0,0,.5), 0 24px 60px rgba(0,0,0,.6);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:          #141413;
  --surface:     #1a1a19;
  --surface-2:   #222220;
  --surface-3:   #2c2c29;
  --line:        #302f2c;
  --line-strong: #45443f;
  --ink:         #f5f4ef;
  --ink-2:       #b5b3a9;
  --ink-3:       #86847c;
  --accent:      #5c9ce8;
  --accent-soft: #17283d;
  --accent-ink:  #8fbcf0;
  --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500;
  --good: #35b37e; --warn: #d99a2b; --bad: #e66767;
  --good-bg: #14291f; --warn-bg: #2c2413; --bad-bg: #2e1a19;
  --shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.35);
  --shadow-lg: 0 2px 4px rgba(0,0,0,.5), 0 24px 60px rgba(0,0,0,.6);
}

* { box-sizing: border-box; }
/* class-based display rules outrank the UA's [hidden]; make hidden win */
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  /* app shell: the page itself never scrolls, the panes do */
  height: 100vh; height: 100dvh;
  display: flex; flex-direction: column; overflow: hidden;
}
button, input { font: inherit; color: inherit; }
svg { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.skip {
  position: absolute; left: -999px; top: 0; z-index: 100;
  background: var(--accent); color: #fff; padding: 10px 16px; border-radius: 0 0 8px 0;
}
.skip:focus { left: 0; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 5px; }

/* ============================================================ TOP BAR */
.topbar {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 14px;
  height: 64px; padding: 0 18px; flex-shrink: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: relative; z-index: 30;
}
/* Centred means centred: a flex row would park the nav wherever the brand
   happened to end, and it would shift the moment the review-queue link
   appeared for one person and not another. */
.views { justify-self: center; }
.top-actions { justify-self: end; }
.brand {
  display: flex; align-items: center; gap: 9px; flex-shrink: 0;
  color: inherit; text-decoration: none; border-radius: 9px;
  padding: 4px 6px; margin-left: -6px;
}
.brand:hover { background: var(--surface-2); }
.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The mark is drawn, not typeset. It used to be the letters PP in whatever
   sans the machine happened to have, at 12px — so it looked different on a
   Mac, a Windows box and an Android phone, and none of them looked like the
   app icon sitting next to it on a home screen. This is the icon's geometry:
   measured off icon-192.png, whose glyphs are 109x99 in a 192 tile, and
   reproduced here to 109x100. textLength with spacingAndGlyphs is what
   condenses the letters to that 2:1 proportion regardless of which font
   actually resolves. */
.mark { width: 28px; height: 28px; display: block; flex-shrink: 0; }
/* The global icon rule strokes every svg child with currentColor, which drew
   a dark outline round the tile and round both letters — the charts opt out
   the same way a few hundred lines down. */
.mark rect, .mark text { stroke: none; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-text strong { font-size: 13.5px; letter-spacing: -.01em; }
.brand-sub { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* The review queue has nothing to put on the right but the account controls,
   so a three-track grid puts the queue tabs in the true centre of the bar
   rather than wherever the brand happens to end. */
.topbar-admin {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 14px;
}
.topbar-admin .views { justify-self: center; }
.top-actions { display: flex; align-items: center; gap: 10px; justify-self: end; }

.views { display: flex; gap: 2px; background: var(--surface-2); padding: 4px; border-radius: 9px; }
.view-btn {
  border: 0; background: none; padding: 7px 15px; border-radius: 6px;
  color: var(--ink-2); cursor: pointer; font-size: 13px; font-weight: 500;
  white-space: nowrap;
}
.view-btn:hover { color: var(--ink); }
.view-btn.is-active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }

.search-wrap { position: relative; width: 420px; max-width: 100%; }
.search-ico {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--ink-3); pointer-events: none;
}
#q {
  width: 100%; height: 38px; padding: 0 34px 0 31px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 8px; font-size: 13px;
}
#q::placeholder { color: var(--ink-3); }
#q:focus { background: var(--surface); border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
#q::-webkit-search-cancel-button { -webkit-appearance: none; }
.slash {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  font: 500 11px/1 var(--mono); color: var(--ink-3);
  border: 1px solid var(--line-strong); border-radius: 4px; padding: 3px 5px;
  pointer-events: none;
}
#q:focus ~ .slash { opacity: 0; }

.icon-btn {
  width: 32px; height: 32px; display: grid; place-items: center; flex-shrink: 0;
  background: none; border: 1px solid transparent; border-radius: 7px;
  color: var(--ink-2); cursor: pointer;
}
.icon-btn:hover { background: var(--surface-2); color: var(--ink); }
.icon-btn svg { width: 17px; height: 17px; }
#panel-star[aria-pressed="true"] svg { fill: var(--s4); stroke: var(--s4); }

/* ============================================================ VIEWS */
.view { display: none; flex: 1; min-height: 0; }
.view.is-active { display: flex; flex-direction: column; }

/* ============================================================ TOOLBAR
   One row, directly above the table. The old layout put 41 filter chips and
   two sliders between the header and the first result — more than half the
   viewport, and a single visible row. The guidance is 3-8 chips inline and
   5-7 facet groups; this was five groups and forty-one chips, so the whole
   set moves behind a button and only what you actually applied stays on
   screen. */
.toolbar {
  display: flex; flex-direction: column; gap: 10px;
  padding: 14px 18px; flex-shrink: 0;
  background: var(--surface); border-bottom: 1px solid var(--line);
}
/* Three tracks, so the search box sits in the true centre of the bar and stays
   there whether or not a result count or a star count is next to it. */
.tb-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center; gap: 12px;
}
.tb-left  { display: flex; align-items: center; gap: 10px; justify-self: start; min-width: 0; }
/* Search and the filter button travel together in the centre track, so the
   button is always the next thing to the right of the box rather than parked
   at the far edge of the bar. */
.tb-mid   { display: flex; align-items: center; gap: 8px; justify-self: center; min-width: 0; }
.tb-right { display: flex; align-items: center; gap: 8px; justify-self: end; }
.tb-gap { flex: 1; min-width: 0; }
.tb-btn {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  height: 38px; padding: 0 13px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-2); color: var(--ink-2);
  font: 500 12.5px/1 var(--sans); cursor: pointer; white-space: nowrap;
}
.tb-btn:hover { border-color: var(--line-strong); color: var(--ink); }
.tb-btn svg {
  width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round;
}
.tb-btn[aria-expanded="true"] {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink);
}
/* Icon only. The word "Filters" next to a funnel is the funnel said twice,
   and the hover copy explains it for anyone the icon does not. */
.tb-icon { padding: 0; width: 38px; justify-content: center; }
.tb-icon.has-n { width: auto; padding: 0 10px 0 9px; }
.tb-n {
  min-width: 17px; height: 17px; padding: 0 5px; border-radius: 9px;
  background: var(--accent); color: #fff;
  font: 600 10.5px/17px var(--sans); text-align: center;
}
.tb-count {
  font-size: 12.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.tb-count[hidden] { display: none; }
.tb-count b { color: var(--ink); font-weight: 600; }

/* The clear button. type=search draws one of these natively in WebKit and
   nowhere else, so the native one is suppressed above and this replaces it
   everywhere — otherwise half the audience gets no way to empty the box but
   select-all and delete. */
.q-clear {
  position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
  width: 22px; height: 22px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: none; color: var(--ink-3);
  cursor: pointer; padding: 0;
}
.q-clear[hidden] { display: none; }

/* Safari zooms the whole page when you focus an input whose text is under
   16px, and then leaves you zoomed in. Keyed on the pointer rather than the
   width, because a tablet is well over the phone breakpoint and does exactly
   the same thing. The alternative — maximum-scale=1 on the viewport — stops
   the zoom by stopping everyone from zooming at all, including people who
   need to, so it is not an alternative. */
@media (pointer: coarse) {
  #q { font-size: 16px; }
}
.q-clear:hover { background: var(--surface-3); color: var(--ink); }
.q-clear svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }

/* Applied filters. With the panel shut these are the only thing that explains
   why the list is short, so they are never decoration — an invisible filter is
   the single worst failure this pattern has. */
.tb-applied { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ap {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--accent); background: var(--accent-soft);
  color: var(--accent-ink); border-radius: 999px;
  padding: 2px 3px 2px 9px; font-size: 12px; white-space: nowrap;
}
.ap-k { opacity: .65; }
.ap-x {
  width: 17px; height: 17px; display: grid; place-items: center; flex-shrink: 0;
  border: 0; border-radius: 50%; background: none; color: inherit;
  cursor: pointer; font: 400 13px/1 var(--sans);
}
.ap-x:hover { background: var(--accent); color: #fff; }

/* ============================================================ FILTERS
   An anchored popover on a laptop, a bottom sheet on a phone, one element and
   one code path. The previous build had a desktop wall and a separate mobile
   sheet that happened to reuse the markup; two behaviours meant two sets of
   bugs. */
.filters {
  position: fixed; z-index: 41;
  width: min(580px, calc(100vw - 32px));
  max-height: min(72vh, 620px);
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.filters[hidden] { display: none; }
.pop-scrim { position: fixed; inset: 0; z-index: 40; background: transparent; }
.pop-scrim[hidden] { display: none; }

.filters-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px 10px; border-bottom: 1px solid var(--line); flex-shrink: 0;
}
.filters-head strong { font-size: 14px; letter-spacing: -.01em; }
.filters-body {
  padding: 13px 14px; display: flex; flex-direction: column; gap: 14px;
  overflow-y: auto; overscroll-behavior: contain;
}
.filters-foot {
  display: flex; align-items: center; gap: 10px; flex-shrink: 0;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line); background: var(--surface);
}
.fgroup { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-width: 0; }
/* Tags subdivide: ten of them in one undifferentiated run reads as noise,
   and the three questions people actually bring are what it pays, how hard
   it is to get in, and what happened. */
.tagsub { display: flex; flex-direction: column; gap: 5px; }
.tagsub + .tagsub { margin-top: 9px; }
.tsub {
  font-size: 10px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3);
}
.flabel {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); font-weight: 600; white-space: nowrap; flex-shrink: 0;
}
.flabel b { color: var(--ink); font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0; }
.chips { display: flex; gap: 4px; flex-wrap: wrap; min-width: 0; }
.chip {
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--ink-2); border-radius: 999px; padding: 3px 10px;
  font-size: 12px; cursor: pointer; white-space: nowrap;
  transition: background .1s, color .1s, border-color .1s;
}
.chip:hover { border-color: var(--line-strong); color: var(--ink); }
.chip[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 500;
}
.chip .cnt { opacity: .55; font-variant-numeric: tabular-nums; margin-left: 3px; font-size: 11px; }

.ranges { display: flex; gap: 22px; flex-wrap: wrap; }
.range { display: flex; flex-direction: column; gap: 4px; }
.range input { width: 150px; accent-color: var(--accent); cursor: pointer; }

#count { font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
#count b { color: var(--ink); font-weight: 600; }
.link-btn {
  background: none; border: 0; color: var(--accent); cursor: pointer;
  font-size: 12.5px; padding: 2px 4px; border-radius: 5px;
}
.link-btn:hover { text-decoration: underline; }
.toggle-btn {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2);
  border-radius: 7px; padding: 4px 10px; font-size: 12.5px; cursor: pointer;
  white-space: nowrap;
}
.toggle-btn:hover { border-color: var(--line-strong); color: var(--ink); }
.toolbar .toggle-btn { height: 38px; padding: 0 12px; }
.toggle-btn svg { width: 13px; height: 13px; }
.toggle-btn[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink); }
.toggle-btn[aria-pressed="true"] svg { fill: currentColor; }

/* ============================================================ TABLE */
.table-wrap { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.thead, .row {
  display: grid;
  grid-template-columns: 34px minmax(190px, 2.1fr) 116px 92px 78px 82px 192px 108px minmax(150px, 1.5fr);
  align-items: center;
}
.thead {
  height: 34px; padding: 0 16px;
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
  position: sticky; top: 0; z-index: 5; flex-shrink: 0;
}
.th {
  background: none; border: 0; padding: 0 8px; text-align: left;
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); font-weight: 600; cursor: pointer;
  display: flex; align-items: center; gap: 4px; height: 100%;
}
.th small { font-size: 9px; opacity: .7; text-transform: none; letter-spacing: 0; }
.th[data-sort]:hover { color: var(--ink); }
.th.th-num { justify-content: flex-end; text-align: right; }
.th.th-tags, .th.th-star { cursor: default; }
/* Base and CTC share a column but sort independently, so each half is its
   own button and carries its own arrow. */
.th-pay { cursor: default; gap: 0; }
.th-sub {
  background: none; border: 0; padding: 0; font: inherit; color: inherit;
  cursor: pointer; display: inline-flex; align-items: center; gap: 3px;
}
.th-sub:hover { color: var(--ink); }
.th-sl { color: var(--line-strong); margin: 0 3px; }
.th-pay small { margin-left: 4px; }

[data-dir]::after {
  content: ''; width: 0; height: 0; border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent; flex-shrink: 0;
}
[data-dir="asc"]::after  { border-bottom: 4.5px solid var(--accent); }
[data-dir="desc"]::after { border-top: 4.5px solid var(--accent); }
[data-dir] { color: var(--ink); }

.scroller { flex: 1; overflow-y: auto; overflow-x: hidden; position: relative; }
.sizer { position: relative; width: 100%; }
.rows { position: absolute; top: 0; left: 0; right: 0; height: 100%; }

.row {
  position: absolute; left: 0; right: 0;
  height: var(--row-h); padding: 0 16px;
  border-bottom: 1px solid var(--line);
  cursor: pointer; contain: layout style paint;
}
.row:hover { background: var(--surface-2); }
.row.is-cursor { background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--accent); }
.cell { padding: 0 8px; min-width: 0; }
.cell.num {
  text-align: right; font-family: var(--mono); font-size: 12.5px;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.cell.num .dim { color: var(--ink-3); }
.c-name { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.c-name .nm {
  font-weight: 550; font-size: 13.5px; letter-spacing: -.005em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.c-name .rl {
  font-size: 11px; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.star-cell { display: grid; place-items: center; }
.star-btn {
  width: 22px; height: 22px; display: grid; place-items: center; padding: 0;
  background: none; border: 0; cursor: pointer; color: var(--line-strong); border-radius: 5px;
}
.star-btn svg { width: 13px; height: 13px; }
.star-btn:hover { color: var(--s4); background: var(--surface-3); }
.star-btn[aria-pressed="true"] { color: var(--s4); }
.star-btn[aria-pressed="true"] svg { fill: var(--s4); }

/* Six pips at 24px with 3px between them is 159px, and the column is 192px
   with 14px of padding a side — 164px of room, five to spare.

   It used to be a 132px column, which after 8px padding left 116px for 160px
   of content. Flex did what flex does and shrank every pip to about 17px, so
   the year labels were crushed together AND crushed against the columns on
   either side. flex-shrink: 0 means that can never happen silently again: if
   a seventh batch is added, the row overflows visibly and someone widens the
   column, rather than the whole strip quietly getting thinner. */
.yrs { display: flex; gap: 3px; }
.yr {
  width: 24px; height: 17px; flex-shrink: 0;
  border-radius: 4px; display: grid; place-items: center;
  font: 500 9.5px/1 var(--mono); background: var(--surface-3); color: var(--ink-3);
}
/* wider gutters than the other cells, so the strip reads as its own thing
   rather than running into the cutoff figure on one side and the tier pill
   on the other */
.c-years, .th-years { padding-left: 14px; padding-right: 14px; }
.yr.on { background: var(--accent); color: #fff; }

.tierpill {
  display: inline-block; padding: 2px 7px; border-radius: 5px;
  font-size: 11px; font-weight: 550; white-space: nowrap;
  background: var(--surface-3); color: var(--ink-2);
}
.tierpill.t-dream { background: #efe7fb; color: #5b32ab; }
.tierpill.t-1 { background: var(--good-bg); color: var(--good); }
.tierpill.t-2 { background: var(--warn-bg); color: var(--warn); }
.tierpill.t-3 { background: var(--surface-3); color: var(--ink-2); }
.tierpill.t-int { background: var(--accent-soft); color: var(--accent-ink); }
:root[data-theme="dark"] .tierpill.t-dream,
:root:not([data-theme="light"]) .tierpill.t-dream { background: #2a2140; color: #b79df0; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .tierpill.t-dream { background: #2a2140; color: #b79df0; }
}

.tagrow { display: flex; gap: 3px; overflow: hidden; }
.tag {
  font-size: 10.5px; padding: 2px 6px; border-radius: 4px; white-space: nowrap;
  background: var(--surface-3); color: var(--ink-2); flex-shrink: 0;
}
.tag.hot   { background: var(--bad-bg);  color: var(--bad); }
.tag.mass  { background: var(--warn-bg); color: var(--warn); }
.tag.rep   { background: var(--accent-soft); color: var(--accent-ink); }
.tag.easy  { background: var(--good-bg); color: var(--good); }
/* "Result pending" is the absence of a number, not a verdict — outlined rather
   than filled, so it reads as provisional next to the solid badges. */
.tag.pend {
  background: none; color: var(--ink-3);
  box-shadow: inset 0 0 0 1px var(--line);
}
.tag.more { background: none; color: var(--ink-3); padding-left: 2px; }

.empty { padding: 64px 24px; text-align: center; }
.empty-title { font-size: 15px; font-weight: 600; margin: 0 0 4px; }
.empty-sub { color: var(--ink-3); margin: 0 0 12px; font-size: 13px; }

/* ============================================================ PANEL */
.scrim {
  position: fixed; inset: 0; background: rgba(20,20,19,.32);
  z-index: 40; animation: fade .16s ease;
  -webkit-backdrop-filter: blur(1.5px); backdrop-filter: blur(1.5px);
}
@keyframes fade { from { opacity: 0; } }
.panel {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(620px, 100vw);
  background: var(--surface); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg); z-index: 41;
  display: flex; flex-direction: column;
  animation: slide .2s cubic-bezier(.22,.61,.36,1);
}
@keyframes slide { from { transform: translateX(24px); opacity: 0; } }
.panel-head {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 16px 16px 12px; border-bottom: 1px solid var(--line);
}
.panel-title-wrap { flex: 1; min-width: 0; }
#panel-title { margin: 0 0 4px; font-size: 19px; letter-spacing: -.02em; line-height: 1.2; }
.panel-sub { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; font-size: 12px; color: var(--ink-3); }
.panel-actions { display: flex; gap: 2px; flex-shrink: 0; }
.panel-tabs { display: flex; gap: 2px; padding: 8px 16px 0; border-bottom: 1px solid var(--line); }
.ptab {
  background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 6px 10px 9px; color: var(--ink-3); cursor: pointer; font-size: 13px; font-weight: 500;
}
.ptab:hover { color: var(--ink); }
.ptab.is-active { color: var(--accent); border-bottom-color: var(--accent); }
.panel-body { flex: 1; overflow-y: auto; padding: 16px; overscroll-behavior: contain; }

.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; margin-bottom: 18px; }
.kpi { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 9px 11px; }
.kpi-k { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); font-weight: 600; }
.kpi-v { font: 600 19px/1.25 var(--mono); letter-spacing: -.03em; margin-top: 3px; font-variant-numeric: tabular-nums; }
.kpi-v small { font-size: 11px; color: var(--ink-3); font-weight: 500; }

.sec { margin-bottom: 22px; }
.sec-h {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-3); font-weight: 600; margin: 0 0 9px;
  display: flex; align-items: center; gap: 8px;
}
.sec-h::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.drive {
  border: 1px solid var(--line); border-radius: var(--radius);
  margin-bottom: 9px; overflow: hidden; background: var(--surface);
}
.drive-h {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 12px; background: var(--surface-2); border-bottom: 1px solid var(--line);
}
.drive-yr { font: 600 13px var(--mono); letter-spacing: -.02em; }
.drive-meta { margin-left: auto; display: flex; gap: 10px; font-size: 11.5px; color: var(--ink-3); }
.drive-meta b { color: var(--ink-2); font-weight: 550; font-family: var(--mono); }

.rtable { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.rtable th {
  text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-3); font-weight: 600; padding: 7px 12px 5px; border-bottom: 1px solid var(--line);
}
.rtable td { padding: 7px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
.rtable tr:last-child td { border-bottom: 0; }
.rtable .n { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rtable .muted { color: var(--ink-3); }

.timeline { display: flex; flex-direction: column; gap: 0; padding: 4px 12px 10px; }
.tl-item { display: flex; gap: 10px; align-items: baseline; font-size: 12.5px; padding: 3px 0; }
.tl-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--line-strong); flex-shrink: 0; }
.tl-dot.online { background: var(--s3); }
.tl-dot.onsite { background: var(--s2); }
.tl-k { color: var(--ink-2); min-width: 86px; }
.tl-v { font-family: var(--mono); font-size: 12px; }
.tl-mode { font-size: 10.5px; padding: 1px 5px; border-radius: 3px; background: var(--surface-3); color: var(--ink-3); }
.tl-mode.online { background: var(--good-bg); color: var(--good); }
.tl-mode.onsite { background: var(--warn-bg); color: var(--warn); }

.note { font-size: 12.5px; color: var(--ink-2); line-height: 1.6; padding: 9px 12px; background: var(--surface-2); border-top: 1px solid var(--line); white-space: pre-wrap; }

.blank {
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  padding: 22px 18px; text-align: center; color: var(--ink-3);
}
.blank h4 { margin: 0 0 5px; color: var(--ink-2); font-size: 13.5px; }
.blank p { margin: 0 0 10px; font-size: 12.5px; line-height: 1.6; }
.blank code {
  font: 11.5px var(--mono); background: var(--surface-3); padding: 2px 5px;
  border-radius: 4px; color: var(--ink-2);
}
details.howto { margin-top: 10px; text-align: left; }
details.howto summary { cursor: pointer; font-size: 12px; color: var(--accent); }
details.howto pre {
  margin: 8px 0 0; padding: 10px; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 7px; overflow-x: auto; font: 11px/1.6 var(--mono); color: var(--ink-2);
}

/* ---- elsewhere: links out ---- */
.els { display: flex; flex-direction: column; gap: 9px; }
.els-lede { margin: 0 0 3px; font-size: 12.5px; line-height: 1.65; color: var(--ink-2); }
.els-card {
  display: flex; flex-direction: column; gap: 3px;
  padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); text-decoration: none; color: inherit;
  transition: border-color .12s, background .12s;
}
.els-card:hover { border-color: var(--accent); background: var(--accent-soft); }
.els-h {
  display: flex; align-items: center; gap: 6px;
  font-size: 13.5px; font-weight: 600; color: var(--accent-ink);
}
.els-h svg { width: 12px; height: 12px; flex-shrink: 0; }
.els-w { font-size: 12.5px; line-height: 1.55; color: var(--ink-3); }
.els-foot {
  margin: 4px 0 0; font-size: 11.5px; line-height: 1.55; color: var(--ink-3);
  padding-top: 10px; border-top: 1px solid var(--line);
}

/* ---- the gist, above the stack ---- */
.sum {
  border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent-soft); padding: 12px 14px; margin-bottom: 14px;
}
.sum-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 7px; flex-wrap: wrap; }
.sum-b { font-size: 12px; font-weight: 600; color: var(--accent-ink); letter-spacing: .01em; }
.sum-n { font-size: 11.5px; color: var(--ink-3); }
.sum-p { margin: 0; font-size: 13px; line-height: 1.7; color: var(--ink); }
.sum-t { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-top: 9px; }
.sum-tl { font-size: 11.5px; color: var(--ink-3); margin-right: 2px; }
.sum-t .pill { background: var(--surface); color: var(--accent-ink); }
.sum-f { margin: 9px 0 0; font-size: 11px; line-height: 1.5; color: var(--ink-3); }

.xp { border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 10px; overflow: hidden; }
.xp-h { display: flex; align-items: center; gap: 8px; padding: 9px 12px; background: var(--surface-2); border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.xp-h .yr-b { font: 600 12px var(--mono); }
.xp-h .when-b { font-size: 11.5px; color: var(--ink-3); }
.xp-h .by { margin-left: auto; font-size: 11.5px; color: var(--ink-3); }
.xp-body { padding: 11px 12px; font-size: 13px; line-height: 1.65; }
.xp-body p { margin: 0 0 9px; }
.xp-body p:last-child { margin-bottom: 0; }
.xp-round { margin-bottom: 12px; }
.xp-round:last-child { margin-bottom: 0; }
.xp-round h5 {
  margin: 0 0 4px; font-size: 12px; color: var(--accent-ink); font-weight: 600;
  display: flex; align-items: center; gap: 6px;
}
.xp-round ul { margin: 5px 0 0; padding-left: 18px; }
.xp-round li { margin-bottom: 3px; }
.pills { display: flex; gap: 4px; flex-wrap: wrap; }
.pill {
  font-size: 11px; padding: 2px 7px; border-radius: 999px;
  background: var(--surface-3); color: var(--ink-2);
}
/* Five steps, green through amber to red. The two in-between rungs are mixed
   from the neighbours so the ramp still holds if the palette is retuned. */
.pill.d-easy { background: var(--good-bg); color: var(--good); }
.pill.d-below-average {
  background: color-mix(in oklab, var(--good-bg) 55%, var(--warn-bg));
  color: color-mix(in oklab, var(--good) 50%, var(--warn));
}
.pill.d-average,
.pill.d-medium { background: var(--warn-bg); color: var(--warn); }
.pill.d-above-average {
  background: color-mix(in oklab, var(--warn-bg) 45%, var(--bad-bg));
  color: color-mix(in oklab, var(--warn) 45%, var(--bad));
}
.pill.d-hard { background: var(--bad-bg); color: var(--bad); }

/* ---- vetted stack: tick, votes ---- */
.tick-b {
  width: 17px; height: 17px; border-radius: 50%; flex-shrink: 0;
  background: var(--good); color: #fff;
  display: grid; place-items: center; font-size: 10px; font-weight: 700;
}
.xp-f {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 12px; border-top: 1px solid var(--line); background: var(--surface-2);
}
.vote {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-2); border-radius: 999px; padding: 3px 10px 3px 8px;
  font-size: 12px; cursor: pointer; font-variant-numeric: tabular-nums;
}
.vote svg { width: 13px; height: 13px; }
.vote:hover { border-color: var(--accent); color: var(--accent-ink); }
.vote.on {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink);
  font-weight: 550;
}
.vote:disabled { opacity: .6; cursor: default; }
.xp-hint { font-size: 11.5px; color: var(--ink-3); }

#to-admin { text-decoration: none; }

/* ============================================================ SUBMIT FORM */
.share {
  border: 1px solid var(--line); border-radius: var(--radius);
  margin-top: 14px; background: var(--surface-2); overflow: hidden;
}
.share > summary {
  cursor: pointer; padding: 11px 13px; display: flex; align-items: baseline;
  gap: 9px; flex-wrap: wrap; list-style: none;
}
.share > summary::-webkit-details-marker { display: none; }
.share > summary::before {
  content: '+'; font: 600 14px/1 var(--mono); color: var(--accent);
  width: 13px; flex-shrink: 0;
}
.share[open] > summary::before { content: '–'; }
.share[open] > summary { border-bottom: 1px solid var(--line); }
.share-t { font-size: 13px; font-weight: 550; color: var(--accent-ink); }
.share-s { font-size: 11.5px; color: var(--ink-3); margin-left: auto; }

.sform { padding: 13px; display: flex; flex-direction: column; gap: 11px; background: var(--surface); }
.f2 { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }
.f2-one { grid-template-columns: 1fr; }
.f3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 11px; }

/* ---- email verification gate ---- */
.verify { padding: 13px; background: var(--surface); display: flex; flex-direction: column; gap: 11px; }
.verify-lede { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--ink-2); }
.verify-warn {
  margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--ink-2);
  background: var(--warn-bg); border-radius: 8px; padding: 9px 11px;
}
.verify-warn strong { color: var(--warn); }
.verify-step { display: flex; flex-direction: column; gap: 9px; }
.verify-step .fld input { font-size: 14px; }
.verify-step [name="v_code"] {
  font-family: var(--mono); font-size: 19px; letter-spacing: .28em;
  text-align: center; padding: 9px;
}
.verify-actions { display: flex; gap: 8px; align-items: center; }
.verify-msg { min-height: 17px; }
.verified-as {
  margin: 0; font-size: 12.5px; color: var(--ink-2);
  background: var(--good-bg); border-radius: 7px; padding: 8px 11px;
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.verified-as .tick { color: var(--good); font-weight: 700; }
.verified-as strong { font-family: var(--mono); font-size: 12px; font-weight: 550; }
.verified-as .until { color: var(--ink-3); }
.fld { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.fld > span {
  font-size: 11px; font-weight: 600; color: var(--ink-2);
  display: flex; gap: 5px; align-items: baseline;
}
.fld > span i { font-style: normal; font-weight: 400; color: var(--ink-3); font-size: 10.5px; }
.fld input, .fld select, .fld textarea {
  width: 100%; background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 7px;
  padding: 7px 9px; font-size: 13px; font-family: inherit; resize: vertical;
}
.fld textarea { line-height: 1.55; }
.fld input:focus, .fld select:focus, .fld textarea:focus {
  outline: none; border-color: var(--accent); background: var(--surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.fld input::placeholder, .fld textarea::placeholder { color: var(--ink-3); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

.rounds { display: flex; flex-direction: column; gap: 11px; }
.round-row {
  border: 1px solid var(--line); border-left: 2px solid var(--accent);
  border-radius: 7px; padding: 10px 11px; display: flex; flex-direction: column; gap: 9px;
  background: var(--surface-2);
}
.round-head { display: flex; align-items: center; justify-content: space-between; }
.round-head strong { font-size: 12px; color: var(--ink-2); }
.x-btn {
  border: 0; background: none; color: var(--ink-3); cursor: pointer;
  font-size: 17px; line-height: 1; padding: 0 4px; border-radius: 4px;
}
.x-btn:hover { color: var(--bad); background: var(--surface-3); }

.ghost-btn {
  align-self: flex-start; border: 1px dashed var(--line-strong); background: none;
  color: var(--ink-2); border-radius: 7px; padding: 6px 12px; font-size: 12.5px; cursor: pointer;
}
.ghost-btn:hover { border-color: var(--accent); color: var(--accent-ink); }
.primary-btn {
  border: 0; background: var(--accent); color: #fff; font-weight: 550;
  border-radius: 7px; padding: 8px 15px; font-size: 13px; cursor: pointer;
}
.primary-btn:hover { filter: brightness(1.07); }
.primary-btn:disabled { opacity: .55; cursor: default; }
.sform-foot { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.sform-msg { font-size: 12.5px; color: var(--ink-2); }
.sform-msg.bad { color: var(--bad); }
.sform-note { margin: 0; font-size: 11.5px; color: var(--ink-3); line-height: 1.55; }
.sent { padding: 16px 4px; }
.sent strong { font-size: 13.5px; }
.sent p { margin: 5px 0 0; font-size: 12.5px; color: var(--ink-2); }
.xp-h .by::before { content: ''; }

/* ============================================================ STATS */
.stats-inner { flex: 1; overflow-y: auto; padding: 20px 16px 60px; }
.stats-grid { max-width: 1080px; margin: 0 auto; display: flex; flex-direction: column; gap: 26px; }
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: 16px 18px 18px;
}
.card-h { margin: 0 0 3px; font-size: 14.5px; letter-spacing: -.01em; }
.card-sub { margin: 0 0 16px; font-size: 12.5px; color: var(--ink-3); line-height: 1.5; }
.yearcards { display: grid; grid-template-columns: repeat(auto-fit, minmax(184px, 1fr)); gap: 12px; }
.ycard { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; }
.ycard-y { font: 600 12px var(--mono); color: var(--accent); letter-spacing: .02em; }
.ycard-n { font: 600 30px/1.1 var(--mono); letter-spacing: -.035em; margin: 5px 0 1px; font-variant-numeric: tabular-nums; }
.ycard-l { font-size: 11.5px; color: var(--ink-3); }
.ycard-rows { margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 4px; }
.ycard-row { display: flex; justify-content: space-between; font-size: 12px; }
.ycard-row span { color: var(--ink-3); }
.ycard-row b { font-family: var(--mono); font-weight: 550; font-variant-numeric: tabular-nums; }

.legend { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.lg { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--ink-2); }
.lg i { width: 9px; height: 9px; border-radius: 2.5px; display: block; }

.chart { width: 100%; }
/* the global icon rule strokes every svg child — charts opt out */
.chart rect, .chart text, .chart path { stroke: none; }
.chart text { font-family: var(--sans); fill: var(--ink-2); }
.chart .ax { font-size: 10.5px; fill: var(--ink-3); }
.chart .vlabel { font-size: 10.5px; fill: var(--ink-2); font-family: var(--mono); font-weight: 600; }
.chart .grid { stroke: var(--line); stroke-width: 1; fill: none; }
.chart .bar { transition: opacity .12s; }
.chart g:hover .bar { opacity: .82; }

/* Base sits beside CTC in one column. The CTC is what people compare on, so
   the base stays recessive rather than competing with it. */
.c-ctc .b4 { color: var(--ink-3); }
.c-ctc .sl { color: var(--line-strong); margin: 0 1px; }

.hbars { display: flex; flex-direction: column; gap: 7px; }
.hbar { display: grid; grid-template-columns: minmax(120px, 165px) 1fr 54px; gap: 10px; align-items: center; font-size: 12.5px; }
.hbar-l { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ink-2); }
.hbar-t { display: block; height: 17px; background: var(--surface-3); border-radius: 4px; overflow: hidden; }
.hbar-f { display: block; height: 100%; min-width: 3px; border-radius: 4px; background: var(--s1); }
.hbar-n { text-align: right; font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.hbar:hover .hbar-l { color: var(--ink); }

.tbl-mini { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tbl-mini th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); font-weight: 600; padding: 6px 10px 6px 0; border-bottom: 1px solid var(--line); }
.tbl-mini th.n, .tbl-mini td.n { text-align: right; padding-right: 0; }
.tbl-mini td { padding: 7px 10px 7px 0; border-bottom: 1px solid var(--line); }
.tbl-mini td.n { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.tbl-mini tr:last-child td { border-bottom: 0; }
.tbl-mini tbody tr { cursor: pointer; }
.tbl-mini tbody tr:hover td { background: var(--surface-2); }

/* ============================================================ GUIDE */
.guide-inner { flex: 1; overflow-y: auto; padding: 26px 16px 70px; }
.guide-body { max-width: 720px; margin: 0 auto; }
.guide-body h1 { font-size: 24px; letter-spacing: -.025em; margin: 0 0 6px; }
.guide-body .lede { color: var(--ink-2); font-size: 14.5px; line-height: 1.65; margin: 0 0 26px; }
.guide-body h2 { font-size: 15px; letter-spacing: -.01em; margin: 28px 0 10px; }
.guide-body p, .guide-body li { font-size: 13.5px; line-height: 1.7; color: var(--ink-2); }
.guide-body ul { padding-left: 20px; margin: 0 0 12px; }
.guide-body li { margin-bottom: 5px; }
.tierdef { display: grid; grid-template-columns: 96px 1fr; gap: 4px 14px; margin: 0 0 14px; align-items: baseline; }
.tierdef dt { font-weight: 600; font-size: 13px; }
.tierdef dd { margin: 0; font-size: 13.5px; color: var(--ink-2); }
.kbds { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 7px; }
.kbdrow { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--ink-2); }
kbd {
  font: 500 11px/1 var(--mono); border: 1px solid var(--line-strong);
  border-bottom-width: 2px; border-radius: 5px; padding: 4px 6px;
  background: var(--surface-2); color: var(--ink); min-width: 22px; text-align: center;
}
.callout {
  border-left: 3px solid var(--accent); background: var(--accent-soft);
  padding: 11px 14px; border-radius: 0 8px 8px 0; margin: 0 0 16px;
}
.callout p { margin: 0; color: var(--ink-2); font-size: 13px; }

/* ============================================================ ADMIN */
.admin-wrap { flex: 1; min-height: 0; overflow-y: auto; }
.who { font-size: 12.5px; color: var(--ink-3); font-family: var(--mono); }

.gate { display: grid; place-items: center; padding: 8vh 16px; }
.gate-card {
  width: 100%; max-width: 420px; background: var(--surface);
  border: 1px solid var(--line); border-radius: 12px; padding: 24px;
  box-shadow: var(--shadow);
}
.gate-card h1 { margin: 0 0 8px; font-size: 19px; letter-spacing: -.02em; }
.gate-card > p { margin: 0 0 18px; font-size: 13.5px; line-height: 1.65; color: var(--ink-2); }
.gate-card form { display: flex; flex-direction: column; gap: 12px; }

.queue { max-width: 760px; margin: 0 auto; padding: 20px 16px 70px; }
.q-count {
  margin: 0 0 14px; font-size: 11px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); font-weight: 600;
}
.q-empty { padding: 60px 16px; text-align: center; color: var(--ink-3); font-size: 14px; }

.sub { margin-bottom: 16px; padding: 0; overflow: hidden; transition: opacity .18s, transform .18s; }
.sub.gone { opacity: 0; transform: translateY(-6px); }
.sub-h { padding: 14px 16px 12px; border-bottom: 1px solid var(--line); background: var(--surface-2); }
.sub-h h2 {
  margin: 0 0 5px; font-size: 15.5px; letter-spacing: -.01em;
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.sub-meta { margin: 0; font-size: 12px; color: var(--ink-3); }
.sub-meta strong { color: var(--ink-2); font-weight: 550; }
.sub-meta .mono { font-family: var(--mono); font-size: 11.5px; }
.sub-meta b { color: var(--ink-2); font-family: var(--mono); }
.rev {
  display: inline-block; margin-top: 4px; font-size: 11.5px; color: var(--ink-3);
  background: var(--surface-3); padding: 2px 7px; border-radius: 5px;
}
.vtag {
  font-size: 10.5px; padding: 1px 6px; border-radius: 4px; margin-left: 5px;
  background: var(--surface-3); color: var(--ink-3);
}
.vtag.ok { background: var(--good-bg); color: var(--good); }
.sub-body { padding: 14px 16px; display: flex; flex-direction: column; gap: 12px; }
.sub-note {
  margin: 0; font-size: 12.5px; color: var(--ink-2);
  background: var(--warn-bg); padding: 8px 10px; border-radius: 7px;
}
.sub-f {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  padding: 12px 16px; border-top: 1px solid var(--line); background: var(--surface-2);
}
.danger-btn {
  border: 1px solid var(--line); background: var(--surface); color: var(--bad);
  border-radius: 7px; padding: 7px 13px; font-size: 13px; cursor: pointer; font-weight: 500;
}
.danger-btn:hover { background: var(--bad-bg); border-color: var(--bad); }
.sub-f button:disabled { opacity: .5; cursor: default; }

/* ---- overview ---- */
/* wider than the review column — a queue card is one write-up, this is a page
   of charts that would otherwise wrap into orphans */
.ov { display: block; max-width: 1120px; }
.ov-body { display: flex; flex-direction: column; gap: 14px; transition: opacity .15s; }
/* one filter row, above everything it scopes */
.ov-range { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.ov-note { font-size: 11.5px; line-height: 1.5; color: var(--ink-3); flex: 1; min-width: 240px; }
/* a hero figure reads better with proportional digits than aligned ones */
.ov-tiles .ycard-n { font-variant-numeric: normal; }
.ov-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 14px; align-items: start;          /* cards size to their content */
}
.ov-tiles { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.ov-rows { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 3px 26px; }
.ov-rows .ycard-row { padding: 5px 0; border-bottom: 1px solid var(--line); }
.card-h.mt { margin-top: 20px; }

.card-warn { border-color: var(--warn); }
.card-warn .card-sub strong { color: var(--warn); }
.ov .card-sub code {
  font: 11.5px var(--mono); background: var(--surface-3);
  padding: 1px 5px; border-radius: 4px; color: var(--ink-2);
}
.mail-err {
  margin: 12px 0 0; padding: 9px 11px; border-radius: 7px;
  background: var(--bad-bg); color: var(--ink-2);
  font: 11.5px/1.55 var(--mono); overflow-wrap: anywhere;
}
.mail-err span {
  display: block; font-family: var(--sans); font-size: 10px; font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase; color: var(--bad); margin-bottom: 4px;
}

.ov .hbar-n i {
  display: block; font-style: normal; font-size: 10.5px;
  color: var(--ink-3); white-space: nowrap;
}
.ov .hbar { grid-template-columns: minmax(96px, 150px) 1fr 76px; }
.q-empty.sm { padding: 14px 0; text-align: left; font-size: 12.5px; }

/* the whole band is the hover target, so nobody has to hit a 20px column */
.chart.traffic .hit { fill: transparent; }
.chart.traffic .tband:hover .hit { fill: var(--surface-2); }
.chart.traffic .tband:hover .bar { opacity: 1; }

.ov-table { margin-top: 12px; }
.ov-table > summary {
  cursor: pointer; font-size: 12px; color: var(--accent-ink); list-style: none; padding: 4px 0;
}
.ov-table > summary::-webkit-details-marker { display: none; }
.ov-table > summary::before { content: '▸ '; }
.ov-table[open] > summary::before { content: '▾ '; }
.ov-table .tbl-mini { margin-top: 6px; }
.ov-table .r { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* two segments, separated by surface rather than by a stroke */
.split {
  display: flex; gap: 2px; height: 18px; border-radius: 4px; overflow: hidden;
  background: var(--surface-3); margin-bottom: 9px;
}
.split-f { display: block; height: 100%; }
.split-k { display: flex; gap: 16px; flex-wrap: wrap; }
.split-k b { font-family: var(--mono); font-weight: 550; margin-left: 3px; }

/* ---- original vs tidied, side by side ---- */
.vpick { display: flex; flex-direction: column; gap: 7px; }
/* Equal height, so the two headers line up and the eye can run across. */
.vpair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: stretch; }
.vcol {
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
  background: var(--surface-2);
}
/* The live one is the whole point of the comparison, so it is the one that
   reads as chosen rather than merely present. */
.vcol.is-on { border-color: var(--accent); background: var(--accent-soft); }
.vcol-h {
  display: flex; align-items: center; gap: 8px; height: 36px; box-sizing: border-box;
  padding: 0 10px; border-bottom: 1px solid var(--line);
}
.vcol.is-on .vcol-h { border-bottom-color: color-mix(in oklab, var(--accent) 30%, transparent); }
.vcol-t { font-size: 12px; font-weight: 600; color: var(--ink-2); }
.vcol.is-on .vcol-t { color: var(--accent-ink); }
.vcol-live {
  margin-left: auto; font-size: 10.5px; font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase; color: var(--accent-ink);
}
.vuse {
  margin-left: auto; font-family: inherit; font-size: 12px; font-weight: 500;
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-2);
  border-radius: 6px; padding: 4px 10px; cursor: pointer;
}
.vuse:hover { border-color: var(--accent); color: var(--accent-ink); }
.vuse:disabled { opacity: .4; cursor: default; border-color: var(--line); }
.vcol-none { margin: 0; padding: 11px 12px; font-size: 12.5px; color: var(--ink-3); }
.ver-body { padding: 10px 12px; font-size: 12.5px; color: var(--ink-2); line-height: 1.6; }
.ver-body p { margin: 0 0 7px; }
.ver-body p:last-child { margin-bottom: 0; }
.ver-r { margin-bottom: 9px; }
.ver-r:last-child { margin-bottom: 0; }
.ver-r ul { margin: 4px 0 0; padding-left: 17px; }
.ver-t { display: flex; gap: 4px; flex-wrap: wrap; }
.vpick-s { margin: 0; font-size: 11.5px; line-height: 1.5; color: var(--ink-3); }

@media (max-width: 720px) {
  .queue { padding: 14px 12px 60px; }
  .sub-body .f2, .sub-body .f3 { grid-template-columns: 1fr; }
  .vpair { grid-template-columns: 1fr; }
  .topbar-admin { grid-template-columns: 1fr; height: auto; padding: 10px 12px; gap: 10px; }
  .topbar-admin .views, .top-actions { justify-self: stretch; }
  /* the public bar orders brand / theme / tabs; the admin bar has no search
     box and an account block instead, so it sets its own order */
  .topbar-admin .brand { order: 1; }
  .topbar-admin .views { order: 2; }
  .top-actions { order: 3; flex-wrap: wrap; }
}

/* ============================================================ INTRO */
.intro-scrim {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(20,20,19,.42);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  display: grid; place-items: center; padding: 20px;
  animation: fade .18s ease;
  overflow-y: auto;
}
.intro {
  position: relative; width: 100%; max-width: 520px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 14px; padding: 26px 26px 22px;
  box-shadow: var(--shadow-lg);
  animation: rise .22s cubic-bezier(.22,.61,.36,1);
}
@keyframes rise { from { transform: translateY(8px); opacity: 0; } }
.intro-x { position: absolute; top: 12px; right: 12px; }
.intro h2 {
  margin: 0 0 8px; font-size: 20px; line-height: 1.25;
  letter-spacing: -.025em; padding-right: 34px;
}
.intro-lede { margin: 0 0 20px; font-size: 13.5px; line-height: 1.6; color: var(--ink-2); }
.intro-lede b { color: var(--ink); font-family: var(--mono); font-size: 13px; }

.intro-list { list-style: none; margin: 0 0 20px; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.intro-list li { display: flex; gap: 12px; align-items: flex-start; }
.intro-list .ic {
  width: 26px; height: 26px; flex-shrink: 0; border-radius: 7px;
  background: var(--accent-soft); color: var(--accent-ink);
  display: grid; place-items: center; font-size: 13px; line-height: 1;
}
.intro-list div { min-width: 0; }
.intro-list b { display: block; font-size: 13.5px; margin-bottom: 2px; }
.intro-list span { display: block; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); }

.intro-foot {
  margin: 0 0 16px; padding-top: 14px; border-top: 1px solid var(--line);
  font-size: 12px; line-height: 1.6; color: var(--ink-3);
}
.intro-foot kbd { padding: 2px 5px; font-size: 10.5px; }
.intro .primary-btn { width: 100%; padding: 10px; font-size: 13.5px; }
.intro-btns { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.intro-btns .link-btn { font-size: 12.5px; }

@media (max-width: 520px) {
  .intro { padding: 22px 18px 18px; border-radius: 12px; }
  .intro h2 { font-size: 18px; }
}

/* ---- anonymity note on the submission form ---- */
.anon-note {
  margin: 0; padding: 10px 12px; border-radius: 8px;
  background: var(--good-bg); color: var(--ink-2);
  font-size: 12.5px; line-height: 1.6;
}
.anon-note strong { color: var(--good); }

/* ============================================================ TOAST */
.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translate(-50%, 14px);
  background: var(--ink); color: var(--bg); padding: 9px 16px; border-radius: 8px;
  font-size: 13px; z-index: 60; opacity: 0; pointer-events: none;
  transition: opacity .18s, transform .18s; box-shadow: var(--shadow-lg);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ============================================================ RESPONSIVE */
/* Trim the least load-bearing columns as width goes; the row stays a grid so
   the virtual list always knows its row height. */
@media (max-width: 1180px) {
  .thead, .row { grid-template-columns: 32px minmax(170px, 2fr) 112px 84px 72px 78px 192px 100px; }
  .th-tags, .cell.c-tags { display: none; }
}
@media (max-width: 940px) {
  .thead, .row { grid-template-columns: 32px minmax(150px, 2fr) 108px 74px 76px 100px; }
  .th-num:nth-of-type(2), .cell.c-stip { display: none; }
  .th-years, .cell.c-years { display: none; }
}

/* Phones: one card per row, but still a fixed height so virtualization holds. */
@media (max-width: 720px) {
  /* The virtual list needs a fixed height, so this is measured rather than
     left to the content: it was 112px when the card carried a tag row and a
     tier pill on lines of their own. With those gone the card is the name, the
     roles under it and one line of figures, and t_mobile.mjs fails if the
     content ever grows past what is set here. */
  :root { --row-h: 82px; }
  /* Two rows: brand and actions, then the view tabs full width. The nav keeps
     its centred track on a laptop and gives it up here, where centring three
     equal tabs across the full width amounts to the same thing. */
  .topbar {
    display: grid; grid-template-columns: 1fr auto; height: auto;
    padding: 9px 12px 10px; gap: 9px 10px;
  }
  /* Rows have to be stated. Auto-placement reads the DOM order — brand, tabs,
     actions — and puts the actions on a third row of their own below the
     full-width tabs, which is 40px of nothing. */
  .brand { grid-column: 1; grid-row: 1; }
  .top-actions { grid-column: 2; grid-row: 1; justify-self: end; }
  /* Only the review queue still puts a tab strip on a second row down here;
     the public bar hides its tabs and uses the switcher. Scoped to the admin
     bar, because `flex: 1` sets flex-basis to 0, and the switcher's menu is a
     COLUMN of .view-btn — an unscoped rule collapsed every item in it from
     40px to the height of its own text. */
  .topbar-admin .views { grid-column: 1 / -1; grid-row: 2; width: 100%; }
  .topbar-admin .view-btn { flex: 1; }
  .thead { display: none; }

  /* The card was four uppercase labels — BASE / CTC, STIPEND, HIRED, CUTOFF —
     competing for 390px, so every row wrapped mid-figure and read as noise.
     The labels shrink to lowercase units that sit against their number, and
     the row becomes one line that scrolls rather than four that wrap. */
  .row {
    display: flex; flex-wrap: wrap; align-items: center; align-content: center;
    gap: 3px 10px; padding: 9px 26px 9px 12px;   /* right gutter clears the chevron */
  }
  .cell { padding: 0; }
  .star-cell { position: absolute; right: 30px; top: 9px; }
  .c-name {
    flex: 1 1 100%; padding-right: 58px;
    display: flex; flex-direction: column; gap: 1px; min-width: 0;
  }
  .c-name .nm {
    font-size: 14.5px; display: flex; align-items: center; gap: 6px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .c-name .rl {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font-size: 11.5px; max-width: 100%;
  }
  /* the chevron says "this opens" — on a phone nothing else does */
  .row-go {
    display: block; position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    font-size: 19px; line-height: 1; color: var(--ink-3); pointer-events: none;
  }

  .cell.num, .c-tier { display: inline-flex; }
  .cell.num {
    flex: 0 0 auto; text-align: left; align-items: baseline; gap: 3px;
    font-size: 13px; white-space: nowrap;
  }
  /* unit after the number reads faster than a label before it */
  .cell.num::before { content: none; }
  .cell.num::after {
    font-family: var(--sans); font-size: 9.5px; letter-spacing: .02em;
    color: var(--ink-3); font-weight: 600; text-transform: none;
  }
  .c-ctc::after  { content: 'LPA'; }
  .c-stip::after { content: '/mo'; }
  .c-hire::after { content: 'hired'; }
  .c-cut::after  { content: 'cutoff'; }
  .c-years { display: none; }          /* the pips need more room than they earn here */
  .c-tier { flex: 0 0 auto; }
  .cell.c-tags { display: flex; flex: 1 1 100%; min-width: 0; }
  .c-tags .tagrow { flex-wrap: nowrap; overflow: hidden; }

  .panel { width: 100vw; border-left: 0; }
  .hbar { grid-template-columns: minmax(88px, 118px) 1fr 42px; }
  .stats-inner, .guide-inner { padding-left: 12px; padding-right: 12px; }
  .card { padding: 14px 13px 16px; }
  .kpis { grid-template-columns: repeat(2, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ============================================================ MOBILE FILTERS
   On a phone the filter block was 282px of an 844px screen — half the viewport
   before a single result. It folds behind a bar and opens as a bottom sheet.
   None of this exists above 720px; the desktop layout is untouched. */
/* On a phone the same element docks to the bottom as a sheet. Nothing about
   its contents or its wiring changes — only where it sits and how far it
   opens. 44px minimum touch targets throughout, which the chips did not meet
   before. */
@media (max-width: 720px) {
  /* The centring grid gives way to a stack: at 366px there is no middle to be
     in, and the search wants the whole width. */
  .toolbar { padding: 10px 12px; gap: 8px; position: sticky; top: 0; z-index: 12; background: var(--bg); }
  .tb-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
  .search-wrap { order: -1; width: 100%; max-width: none; }
  #q { height: 42px; }
  .q-clear { width: 26px; height: 26px; right: 8px; }
  .tb-left { flex: 1 1 auto; }
  .tb-right { margin-left: auto; gap: 6px; }
  .tb-btn { height: 40px; padding: 0 13px; font-size: 13px; }
  .tb-count { font-size: 12px; min-width: 0; }
  /* 366px will not hold both figures next to the filter button and the three
     action buttons. The company count is the one that answers "what am I
     looking at"; the offers total is the one that can wait for Analytics. */
  .tb-offers { display: none; }
  /* The word next to a star is redundant beside a star, and 366px will not
     hold it as well as everything else on the row. */
  .tb-saved-label { display: none; }
  .tb-gap { display: none; }
  .toolbar .toggle-btn { height: 40px; padding: 0 11px; }
  #starred-only { padding: 0 10px; }

  .filters {
    left: 0; right: 0; bottom: 0; top: auto; width: auto;
    max-height: 84vh;
    border-radius: 16px 16px 0 0;
    border-left: 0; border-right: 0; border-bottom: 0;
  }
  .filters-head { padding: 14px 14px 11px; }
  .filters-head strong { font-size: 15px; }
  .filters-body { padding: 14px; gap: 17px; }
  .filters .chip { padding: 8px 13px; font-size: 13px; min-height: 36px; display: inline-flex; align-items: center; }
  .filters .range input { width: 100%; height: 26px; }
  .filters .ranges { flex-direction: column; gap: 14px; width: 100%; }
  .filters .range { width: 100%; }
  #filters-done { flex: 1; padding: 12px; font-size: 14px; }
  .pop-scrim { background: rgba(32,28,19,.4); animation: fade .18s ease; }
  body.filters-open { overflow: hidden; }
}

/* ============================================================ TOOLTIPS
   One mechanism for both input types: hover opens it with a pointer, tap
   toggles it on touch. Touch has no hover, so a title attribute is invisible
   to half the audience — these replace them on anything worth explaining. */
.tip-host { position: relative; }
/* This was background: var(--ink) with color: var(--bg), which is a dark
   tooltip in light mode and a BRIGHT WHITE SLAB in dark mode, because --ink
   flips to #f5f4ef there. A fixed translucent dark panel instead: it reads the
   same way in both themes, and the blur keeps it legible over a dense table
   without having to go fully opaque. */
.tipbox {
  position: fixed; z-index: 70; max-width: min(280px, calc(100vw - 24px));
  padding: 9px 11px; border-radius: 9px;
  background: rgba(32, 28, 19, .9); color: #f7f4ec;
  border: 1px solid rgba(255, 255, 255, .1);
  -webkit-backdrop-filter: blur(10px) saturate(1.4);
  backdrop-filter: blur(10px) saturate(1.4);
  font: 400 12.5px/1.5 var(--sans); letter-spacing: -.005em;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .3); pointer-events: none;
  opacity: 0; transform: translateY(3px); transition: opacity .13s, transform .13s;
}
.tipbox.show { opacity: 1; transform: none; }
.tipbox::after {
  content: ''; position: absolute; width: 8px; height: 8px;
  /* the same colour stated flat: `inherit` would stack a second layer of
     alpha over the box and leave a darker notch where the two overlap */
  background: rgba(32, 28, 19, .9); transform: rotate(45deg);
}
.tipbox[data-side="top"]::after    { bottom: -4px; left: var(--ax, 50%); margin-left: -4px; }
.tipbox[data-side="bottom"]::after { top: -4px;    left: var(--ax, 50%); margin-left: -4px; }
[data-tip] { cursor: help; }
button[data-tip], a[data-tip] { cursor: pointer; }

/* ============================================================ WALKTHROUGH */
.tour-scrim {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(20,20,19,.55); animation: fade .2s ease;
}
.tour-hole {
  position: fixed; z-index: 81; border-radius: 10px;
  box-shadow: 0 0 0 9999px rgba(32,28,19,.58), 0 0 0 2px var(--accent);
  transition: all .26s cubic-bezier(.22,.61,.36,1); pointer-events: none;
}
/* No transition on top/left. The card used to slide between steps, and
   because its height is measured after the new text goes in, it first
   re-rendered at the OLD coordinates with the NEW content and then travelled —
   two separate movements per step, which reads as the thing wandering around
   looking for somewhere to sit. It now fades out, is placed while invisible,
   and fades in. The ring keeps its slide: that one is doing a job, leading
   your eye from the last element to the next. */
.tour-card {
  position: fixed; z-index: 82; width: min(330px, calc(100vw - 28px));
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 13px; padding: 16px 16px 13px; box-shadow: var(--shadow-lg);
  transition: opacity .16s ease;
}
.tour-card h3 { margin: 0 0 6px; font-size: 15px; letter-spacing: -.015em; }
.tour-card p { margin: 0 0 14px; font-size: 13px; line-height: 1.6; color: var(--ink-2); }
.tour-foot { display: flex; align-items: center; gap: 8px; }
.tour-dots { display: flex; gap: 5px; flex: 1; }
.tour-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--line); }
.tour-dot.on { background: var(--accent); }
.tour-card .link-btn { font-size: 12.5px; }
.tour-next {
  padding: 8px 15px; min-height: 38px; border: 0; border-radius: 8px;
  background: var(--accent); color: #fff; font: 600 13px/1 var(--sans); cursor: pointer;
}
@media (max-width: 720px) {
  .tour-card { left: 14px !important; right: 14px; width: auto; }
}

/* ============================================================ INSTALL PROMPT */
.install-bar {
  position: fixed; left: 12px; right: 12px; z-index: 55;
  bottom: calc(12px + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border-radius: 13px;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  animation: rise .24s cubic-bezier(.22,.61,.36,1);
}
@media (min-width: 721px) { .install-bar { left: auto; width: 360px; right: 18px; } }
.install-ico {
  /* same condensed letterforms as the mark and the app icon */
  font-stretch: condensed; letter-spacing: -.04em;
  width: 38px; height: 38px; flex-shrink: 0; border-radius: 9px;
  background: var(--accent); color: #fff; display: grid; place-items: center;
  font: 700 15px/1 var(--sans);
}
.install-txt { flex: 1; min-width: 0; }
.install-txt b { display: block; font-size: 13.5px; margin-bottom: 1px; }
.install-txt span { display: block; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.install-bar .tour-next { flex-shrink: 0; }
.ios-steps { margin: 10px 0 0; padding-left: 18px; font-size: 12.5px; line-height: 1.7; color: var(--ink-2); }
.ios-steps b { color: var(--ink); }

/* The "verify at the end" note sits above the anonymity note and should read
   as information, not as a warning — it is telling you the good news. */
.verify-first { background: var(--accent-soft); color: var(--ink-2); }
.verify-first strong { color: var(--accent-ink); }
.sform-msg.good { color: var(--good); }

/* ---- write-up count on a row ----------------------------------------------
   This was a 9.5px chip reading "XP", which told a student nothing. The row is
   the only route to the OA and interview write-ups, so the row has to say they
   exist and that it opens. */
.xp-badge {
  flex-shrink: 0; padding: 1px 6px; border-radius: 4px;
  background: var(--accent-soft); color: var(--accent-ink);
  font: 600 10px/1.6 var(--sans); white-space: nowrap;
}
@media (min-width: 721px) { .row-go { display: none; } }

/* The review notice reuses the install bar's shape — same corner, same size,
   so two different pieces of news do not each invent their own furniture. */
.review-note .install-ico { background: var(--good); }
.sform-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.sform-foot .link-btn { margin-right: auto; }
.sent { padding: 2px 0; }
.sent strong { display: block; margin-bottom: 5px; font-size: 14px; }
.sent p { margin: 0 0 9px; font-size: 12.5px; line-height: 1.6; color: var(--ink-2); }

/* ============================================================ SHORTCUTS SHEET
   The shortcuts existed from the start and were listed nowhere, so nobody had
   them. ? opens this; on a phone it never does, there being no keyboard. */
.keys-scrim {
  position: fixed; inset: 0; z-index: 75;
  background: rgba(20,20,19,.45);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  display: grid; place-items: center; padding: 20px; overflow-y: auto;
  animation: fade .16s ease;
}
.keys {
  width: 100%; max-width: 460px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 14px; padding: 20px 22px 22px;
  box-shadow: var(--shadow-lg); animation: rise .2s cubic-bezier(.22,.61,.36,1);
}
.keys-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 14px;
}
.keys-head strong { font-size: 16px; letter-spacing: -.02em; }
.keys h4 {
  margin: 16px 0 7px; font-size: 10.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3);
}
.keys h4:first-of-type { margin-top: 0; }
.keys-list {
  margin: 0; display: grid; grid-template-columns: auto 1fr;
  gap: 7px 14px; align-items: baseline;
}
.keys-list dt { display: flex; gap: 4px; flex-wrap: wrap; justify-self: start; }
.keys-list dd { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.keys kbd {
  padding: 2px 6px; border-radius: 5px; border: 1px solid var(--line);
  background: var(--surface-2, var(--surface-3)); color: var(--ink);
  font: 500 11px/1.5 var(--mono); white-space: nowrap;
}
.keys-term { font-size: 12px; font-weight: 600; color: var(--ink); white-space: nowrap; }

/* ============================================================ TOUR CONTROLS
   Pinned, and pinned is the whole point: the card moves to whatever it is
   pointing at, so if the buttons travelled with it you would chase them across
   the screen seven times. These stay exactly where your cursor left them. */
.tour-nav {
  position: fixed; z-index: 83; left: 50%; transform: translateX(-50%);
  bottom: calc(20px + env(safe-area-inset-bottom));
  width: min(420px, calc(100vw - 24px));
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 14px; padding: 11px 14px 10px;
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; gap: 9px;
  animation: rise .2s cubic-bezier(.22,.61,.36,1);
}
/* where each press goes, so it is never a guess */
.tnav-ctx {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px;
  align-items: baseline; font-size: 11px; line-height: 1.3;
}
.tnav-side {
  color: var(--ink-3); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.tnav-r { text-align: right; }
.tnav-step {
  font: 600 10.5px/1.3 var(--mono); color: var(--ink-3);
  letter-spacing: .02em; white-space: nowrap;
}
.tnav-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tnav-b {
  min-height: 42px; padding: 10px 14px; border-radius: 9px;
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--ink); font: 600 13.5px/1 var(--sans); cursor: pointer;
  transition: background .12s, border-color .12s;
}
.tnav-b:hover:not(:disabled) { background: var(--surface-3); }
.tnav-b:disabled { opacity: .38; cursor: default; }
.tnav-b.is-next { background: var(--accent); border-color: var(--accent); color: #fff; }
.tnav-b.is-next:hover { filter: brightness(1.06); background: var(--accent); }
.tnav-skip {
  align-self: center; font-size: 11.5px; padding: 2px 6px; color: var(--ink-3);
}
@media (max-width: 720px) {
  .tour-nav { bottom: calc(12px + env(safe-area-inset-bottom)); }
}
/* the card keeps its foot only for the single-step "Got it" case */
.tour-card .tour-foot:empty { display: none; }

/* A search hit whose cause is nowhere on the row reads as a bug. This says so
   and carries the snippet, rather than leaving someone to guess. */
.why {
  margin-left: 7px; padding: 0 5px; border-radius: 4px;
  border: 1px dashed var(--line); background: none;
  font-size: 10px; color: var(--ink-3); white-space: nowrap; cursor: help;
}

/* ============================================================ MY WRITE-UPS
   What a non-admin gets where the review queue link would be: the same
   question answered for the only submissions they are entitled to ask about. */
#notifs { position: relative; }
.notif-dot {
  position: absolute; top: 5px; right: 5px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 2px var(--bg);
}
.mine { max-width: 560px; }
.mine h2 { margin-bottom: 6px; }
.mine-list { list-style: none; margin: 4px 0 0; padding: 0; }
.mine-row {
  display: grid; grid-template-columns: 1fr auto auto; gap: 8px 12px;
  align-items: center; padding: 11px 2px;
  border-top: 1px solid var(--line); cursor: pointer;
}
.mine-row:hover { background: var(--surface-2); }
.mine-main { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.mine-main strong { font-size: 13.5px; }
.mine-kind { font-size: 11.5px; color: var(--ink-3); }
.mine-when { font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }
.mine-st {
  padding: 2px 8px; border-radius: 5px; font: 600 11px/1.7 var(--sans); white-space: nowrap;
}
.st-approved { background: var(--good-bg); color: var(--good); }
.st-rejected { background: var(--surface-3); color: var(--ink-3); }
.st-pending  { background: var(--accent-soft); color: var(--accent-ink); }
.mine-empty { margin: 8px 0 0; font-size: 13px; line-height: 1.65; color: var(--ink-2); }
@media (max-width: 520px) {
  .mine-row { grid-template-columns: 1fr auto; }
  .mine-when { grid-column: 1; order: 3; }
}

/* ============================================================ QUEUE AS LIST
   Every submission used to render its whole edit form inline, so finding out
   what was in the queue meant scrolling past a page of fields per item. Each
   is now one line that opens to the same form, untouched. */
.q-bar { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
details.sub { padding: 0; overflow: hidden; }
details.sub > .sub-body { padding: 0 16px 16px; border-top: 1px solid var(--line); }
.qsum {
  display: grid; gap: 3px; padding: 12px 16px; cursor: pointer;
  list-style: none; user-select: none;
}
.qsum::-webkit-details-marker { display: none; }
.qsum:hover { background: var(--surface-2); }
details.sub[open] > .qsum { background: var(--surface-2); }
.qsum-top { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.qsum-co { font-size: 14.5px; letter-spacing: -.01em; }
.qsum-co::before {
  content: '▸'; display: inline-block; margin-right: 7px;
  color: var(--ink-3); font-size: 11px; transition: transform .15s;
}
details.sub[open] .qsum-co::before { transform: rotate(90deg); }
.qsum-when { margin-left: auto; font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }
.qsum-v { font-size: 11.5px; color: var(--ink-3); }
.qsum-gist {
  font-size: 12.5px; line-height: 1.5; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding-left: 18px;
}
.qsum-who { font-size: 11.5px; color: var(--ink-3); padding-left: 18px; }
.qsum-who strong { color: var(--ink-2); }
@media (max-width: 720px) {
  .qsum { padding: 11px 12px; }
  .qsum-when { margin-left: 0; width: 100%; }
  details.sub > .sub-body { padding: 0 12px 14px; }
}

/* ─────────────────── Overview: what gets used, what doesn't ───────────────────
   Three tables and a set of grouped bars. The dead list is the point of the
   section, so it is first and it is a table, not bars: a bar of length zero
   next to forty other bars of length zero says nothing. */
.ov-h4 {
  display: flex; align-items: center; gap: 8px;
  margin: 26px 0 6px; font-size: 13px; font-weight: 650; color: var(--ink);
}
.ov-h4:first-of-type { margin-top: 18px; }
.ov-h4 .pill {
  background: var(--surface-2); color: var(--ink-2);
  font-family: var(--mono); font-size: 11px; padding: 1px 7px; border-radius: 20px;
}
.tbl-dead { margin-top: 8px; }
.tbl-dead tbody tr { cursor: default; }
.tbl-dead tbody tr:hover td { background: transparent; }
.tbl-dead .r {
  text-align: right; font-variant-numeric: tabular-nums;
  color: var(--ink-2); white-space: nowrap;
}
.tbl-dead .r i { display: block; font-style: normal; font-size: 10.5px; color: var(--ink-3); }
.tbl-dead kbd { font-family: var(--mono); }
.tbl-dead tr.is-dead td { color: var(--ink-3); }
/* The id, not the label, is what the stored rows are keyed on, so it has to be
   visible — it is the thing I grep for when a name in this table means nothing. */
.cid {
  display: block; font-family: var(--mono); font-size: 10.5px;
  color: var(--ink-3); margin-top: 1px;
}
.ov-sub { margin-top: 14px; }
.ov-sub h5 {
  margin: 0 0 5px; font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3);
}
/* Not a warning in the error sense — a finding. Amber, not red. */
.ov-flag {
  margin: 14px 0 4px; padding: 12px 14px; border-radius: 10px;
  background: var(--warn-bg); border: 1px solid color-mix(in srgb, var(--warn) 28%, transparent);
}
.ov-flag strong { display: block; font-size: 12.5px; color: var(--warn); }
.ov-flag span { display: block; margin-top: 3px; font-size: 12px; color: var(--ink-2); }
.ov-flag ul { margin: 8px 0 0; padding-left: 18px; font-size: 12.5px; }
.ov-flag li { margin: 2px 0; }
.ov-flag b { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* These bars carry three numbers under the label instead of one, so the
   right-hand column needs more than the 76px the rest of the page gives it —
   at 76px "96/55" wrapped off the edge. */
.ov-sub .hbar { grid-template-columns: minmax(96px, 150px) 1fr 104px; }

/* Which screens a control exists on has a column of its own on a laptop; on a
   phone that column is gone and this line carries it instead. */
.conly { display: none; }

@media (max-width: 720px) {
  /* Four columns do not fit, and two of them are repeatable elsewhere: the
     group is in the grouped bars below, and "exists for" moves into the first
     cell. What is left is the control and the finding, which is the point. */
  .tbl-dead th:nth-child(2), .tbl-dead td:nth-child(2),
  .tbl-dead th:nth-child(3), .tbl-dead td:nth-child(3) { display: none; }
  .tbl-dead { font-size: 12px; }
  .tbl-dead .r { white-space: normal; }
  .conly {
    display: inline-block; margin-top: 3px; padding: 0 5px; border-radius: 4px;
    background: var(--surface-2); color: var(--ink-3); font-size: 10px;
  }
  .ov-sub .hbar { grid-template-columns: minmax(80px, 110px) 1fr 84px; }
}

/* ─────────────────────────── The weekly read ─────────────────────────── */
.wk-when {
  margin-left: 8px; font-weight: 500; font-size: 11.5px; color: var(--ink-3);
}
.wk-line {
  margin: 12px 0 0; font-size: 14.5px; line-height: 1.45; color: var(--ink);
  font-weight: 550;
}
.wk-quiet { margin: 12px 0 0; font-size: 13px; color: var(--ink-2); }
.wk-sugg { margin: 12px 0 0; padding-left: 20px; display: grid; gap: 11px; }
.wk-sugg li { font-size: 13px; line-height: 1.5; }
.wk-sugg b { display: block; color: var(--ink); }
.wk-sugg span { display: block; color: var(--ink-2); margin-top: 1px; }
/* The numbers the model was handed, kept next to what it wrote — the only way
   to catch it embroidering. */
.wk-f, .wk-old { margin-top: 14px; }
.wk-flist { margin: 8px 0 0; padding-left: 18px; display: grid; gap: 7px; }
.wk-flist li { font-size: 12.5px; line-height: 1.45; color: var(--ink-2); }
.wk-flist code {
  font-family: var(--mono); font-size: 10.5px; padding: 1px 5px; border-radius: 4px;
  background: var(--surface-2); color: var(--ink-3);
}
.wk-ev { margin: 5px 0 0; padding-left: 16px; display: grid; gap: 2px; }
.wk-ev li { font-size: 12px; color: var(--ink-3); }
.wk-ev b { font-family: var(--mono); color: var(--ink-2); }
.wk-ev i { font-style: normal; font-size: 10.5px; }
.wk-past { padding: 12px 0; border-top: 1px solid var(--line); }
.wk-past h5 {
  margin: 0; font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3);
}
/* Which finding a suggestion rests on. Small, but it is the difference
   between advice and a claim you can check. */
.wk-from {
  display: inline-block; margin-top: 4px; padding: 1px 6px; border-radius: 4px;
  background: var(--surface-2); color: var(--ink-3);
  font: 500 10px/1.7 var(--mono); font-style: normal;
}
#run-weekly { margin-top: 16px; }

/* The dataset's own size, stated once where someone is already looking at
   figures, instead of on every view of the main table. */
.stats-lede {
  margin: 0 0 16px; font-size: 14px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.stats-lede b { color: var(--ink); font-weight: 650; }

/* Who sent a submission. This used to be 11.5px in the faintest grey the
   palette has, under the gist, which is where you put something you do not
   expect anyone to read — and it is the one thing a reviewer has to weigh
   before publishing a stranger's account of a company. */
.qsum-who {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12px; color: var(--ink-3); padding-left: 18px;
}
.who-n { font-weight: 600; color: var(--ink-2); }
.who-anon { font-weight: 500; font-style: italic; color: var(--ink-3); }
.who-mail {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--mono); font-size: 11px;
  padding: 2px 7px; border-radius: 5px;
}
.who-mail.ok   { background: var(--good-bg); color: var(--good); }
.who-mail.ok b { font-size: 11px; }
/* Amber, not red: an unconfirmed address is not an error, it is just not
   evidence, and it has to read differently from one that is. */
.who-mail.warn { background: var(--warn-bg); color: var(--warn); }
.who-mail.none { background: var(--surface-2); color: var(--ink-3); font-style: italic; }

/* ─────────────────── Phone: the floating close, and the swipe ───────────────
   The panel is full screen on a phone, so its header X lands in the top-right
   corner — the furthest point from a thumb on a 6-inch screen held in one
   hand. This is the same action within reach. Desktop keeps the header one
   and never draws this. */
.panel-fab { display: none; }

@media (max-width: 720px) {
  .panel-fab {
    display: grid; place-items: center;
    position: fixed; right: 16px; z-index: 46;
    bottom: calc(16px + env(safe-area-inset-bottom));
    width: 52px; height: 52px; border-radius: 50%;
    border: 1px solid var(--line);
    background: var(--ink); color: var(--bg);
    box-shadow: var(--shadow-lg); cursor: pointer;
  }
  .panel-fab svg {
    width: 20px; height: 20px; fill: none; stroke: currentColor;
    stroke-width: 1.9; stroke-linecap: round;
  }
  .panel-fab:active { transform: scale(.94); }
  /* so the last line of a write-up is not sitting under the button */
  .panel-body { padding-bottom: 84px; }
  /* Claim horizontal drags for the swipe while leaving vertical scrolling to
     the browser, which is what keeps the list feeling native. */
  #rows .row, .panel { touch-action: pan-y; }
}

/* The tour's gesture ghost: a puck with a trail, drawn over everything so it
   reads against both the dimmed backdrop and the page. */
.swipe-ghost {
  position: fixed; z-index: 82; width: 44px; height: 44px;
  margin: -22px 0 0 -22px; border-radius: 50%;
  background: rgba(255, 255, 255, .97);
  /* The ring is not decoration. The tour punches a hole in its own backdrop
     so the highlighted row shows at full brightness, and a white puck on a
     white row in light mode is nothing at all — which is how the first take
     of this looked. The dark edge makes it read on either theme. */
  border: 2px solid rgba(28, 28, 28, .62);
  box-shadow: 0 0 0 10px rgba(130, 130, 130, .26), 0 6px 20px rgba(0, 0, 0, .45);
  opacity: 0; pointer-events: none;
  transition: transform 1s cubic-bezier(.32, .72, .3, 1), opacity .26s ease;
}
/* The trail streams out behind the puck, and the puck now travels right to
   left, so the trail hangs off its right-hand side. */
.swipe-ghost i {
  position: absolute; left: 24px; top: 50%; height: 6px; width: 0;
  transform: translateY(-50%); border-radius: 3px;
  background: linear-gradient(to right, rgba(255,255,255,.95), rgba(255,255,255,0));
  box-shadow: 0 0 0 1px rgba(28, 28, 28, .28);
  transition: width 1s cubic-bezier(.32, .72, .3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .swipe-ghost, .swipe-ghost i { transition: opacity .2s ease; }
}

/* ═══════════════════════════════ THE VIEW SWITCHER ═══════════════════════════
   Companies / Analytics / Guide was a segmented strip in the middle of the
   header — a permanent slot in a 64px bar on a laptop and a whole second row
   on a phone, spent on two destinations you visit and leave. It is a floating
   control now, in the bottom-right corner the company panel's close button
   already established as where this site puts one.

   The button states where you are and the menu opens upward out of it, so the
   button itself never moves and the thing you just pressed is still under your
   finger when the menu appears. */
.vnav { position: fixed; right: 20px; bottom: 20px; z-index: 44; }

.vnav-btn {
  display: flex; align-items: center; gap: 8px;
  height: 44px; padding: 0 15px 0 13px; border-radius: 22px;
  border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink);
  font: 600 13px/1 var(--sans); letter-spacing: -.01em;
  box-shadow: var(--shadow-lg); cursor: pointer;
  transition: transform .14s, background .14s;
}
.vnav-btn:hover { background: var(--surface-2); }
.vnav-btn:active { transform: scale(.97); }
.vnav-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vnav-ico { display: grid; place-items: center; color: var(--accent); }
.vnav-ico svg {
  display: block; width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.vnav-now { white-space: nowrap; }
.vnav-chev {
  width: 13px; height: 13px; color: var(--ink-3);
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .16s;
}
.vnav-btn[aria-expanded="true"] .vnav-chev { transform: rotate(180deg); }

.vmenu {
  position: absolute; right: 0; bottom: calc(100% + 9px);
  min-width: 194px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: 13px; box-shadow: var(--shadow-lg);
  animation: rise .16s cubic-bezier(.22,.61,.36,1);
}
.vmenu-list { display: flex; flex-direction: column; gap: 2px; }
/* These carry .view-btn so that switchView, the 1/2/3 keys and the analytics
   control list keep finding them by the selectors they used in the header.
   Everything the strip's styling did has to be undone here. */
.vitem {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 0 11px; height: 40px;
  border-radius: 9px; text-align: left; font-size: 13.5px;
}
.vitem svg {
  width: 17px; height: 17px; flex-shrink: 0;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--ink-3);
}
.vitem:hover { background: var(--surface-2); }
.vitem.is-active {
  background: var(--accent-soft); color: var(--accent-ink);
  box-shadow: none; font-weight: 600;
}
.vitem.is-active svg { color: var(--accent); }
/* Below the three views, the things that were each costing a phone a slot in
   a bar. Separated by a rule because they are actions, not destinations —
   picking one does something and closes the menu rather than taking you
   somewhere. */
.vmenu-actions:not(:empty) {
  margin-top: 6px; padding-top: 6px;
  border-top: 1px solid var(--line);
}
/* Descendant, not child: #tb-share travels as one node and is display:contents,
   so the buttons render as rows of this menu while the DOM still has the
   wrapper in between. */
#vmenu .vmenu-actions button {
  display: flex; align-items: center; gap: 10px;
  width: 100%; height: 40px; padding: 0 11px;
  border: 0; border-radius: 9px; background: none;
  color: var(--ink); font: 500 13.5px/1 var(--sans);
  text-align: left; cursor: pointer;
}
#vmenu .vmenu-actions button:hover,
#vmenu .vmenu-actions button:active { background: var(--surface-2); }
#vmenu .vmenu-actions svg {
  width: 17px; height: 17px; flex-shrink: 0;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--ink-3);
}
#vmenu .vmenu-actions .lbl-long { flex: 1; }
/* A floating control has no business hovering over a full-screen company or
   over the filter sheet — in both cases it would be the only thing on screen
   that does not belong to what you just opened. */
body.panel-open .vnav, body.filters-any .vnav { display: none; }

/* ═══════════════════════════════ THE PHONE'S BOTTOM BAR ═════════════════════
   Search is the one thing everyone does here, and on a phone the top of the
   screen is the one place a thumb cannot reach. The box and the filter button
   move to the bottom edge; the filter still opens the same bottom sheet.
   Nothing below 721px-wide screens applies to the desktop layout. */
.botbar { display: none; }
.tb-share { display: contents; }

/* Two labels per button, one rendered. A button standing in the toolbar has
   room for "Link"; the same button in the switcher's menu has a whole row and
   says "Share link". No JavaScript rewrites any text. */
.lbl-long, .lbl-ico { display: none; }
#vmenu .lbl-long { display: inline; }
#vmenu .lbl-short { display: none; }
#vmenu .lbl-ico { display: block; }

/* A laptop keeps its tabs and never draws the floating switcher. */
@media (min-width: 721px) {
  .vnav, #vnav-scrim { display: none !important; }
}

@media (max-width: 720px) {
  /* One number the rest of the bottom furniture is measured against, so the
     bar, the switcher, the toast and the install prompt cannot drift apart. */
  :root { --bot-h: 58px; }

  .botbar {
    display: flex; align-items: center; gap: 8px;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 39;
    padding: 8px 12px calc(8px + env(safe-area-inset-bottom));
    background: var(--surface);
    border-top: 1px solid var(--line);
    box-shadow: 0 -4px 18px rgba(0, 0, 0, .07);
  }
  .botbar[hidden] { display: none; }
  .botbar .tb-mid { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
  .botbar .search-wrap { flex: 1; width: auto; max-width: none; order: 0; }
  .botbar #filters-btn { flex-shrink: 0; height: 42px; width: 46px; }
  /* There is no keyboard to press / on, and it was eating the width the
     placeholder needed. */
  .botbar .slash { display: none; }
  .botbar #q { padding-right: 34px; }

  /* The last row has to be able to clear the bar, and clientHeight counting
     the padding only makes the virtual window render a row or two spare. */
  .scroller { padding-bottom: calc(var(--bot-h) + env(safe-area-inset-bottom)); }

  /* Just the mark. "PESU Placements / 2022 – 2027" is 120px of a 366px bar
     restating the tab you are already in, and it was pushing the buttons that
     do something off the row. */
  .brand-text { display: none; }
  .brand { margin-left: 0; padding: 4px; }

  /* The tabs are the switcher's job down here. Scoped to the public bar: the
     review queue's own tabs use the same class and still need to be visible. */
  #view-tabs { display: none; }

  /* The toolbar row is empty on a phone — the count is gone, Saved has moved
     up to the logo row, Link and CSV into the switcher, search and filters to
     the bottom bar. What is left is 56px of nothing between the header and
     the first company, so it is not drawn at all.

     The applied-filter chips are NOT part of that row, and they stay: with
     every panel shut they are the only thing saying why the list is short. */
  .tb-row { display: none; }
  .toolbar { padding: 0; gap: 0; }
  #applied:not([hidden]) { padding: 9px 12px; }

  /* Saved, lifted up beside the mark. */
  .top-actions #starred-only { height: 34px; padding: 0 10px; font-size: 12.5px; }

  /* The switcher sits above the bar rather than on it: three destinations do
     not earn a permanent third of the bar that search and filters share. */
  .vnav { right: 14px; bottom: calc(var(--bot-h) + 14px + env(safe-area-inset-bottom)); }
  .vnav-btn { height: 42px; padding: 0 13px 0 12px; gap: 7px; }
  .vnav-now { display: none; }              /* the icon and the menu say it */
  .vnav-chev { width: 12px; height: 12px; }
  .vmenu { min-width: 188px; }
  .vmenu-foot { display: none; }            /* no keyboard to press 1, 2 or 3 with */

  /* Everything else that docks to the bottom edge clears the bar. */
  .toast { bottom: calc(var(--bot-h) + 16px + env(safe-area-inset-bottom)); }
  .install-bar { bottom: calc(var(--bot-h) + 12px + env(safe-area-inset-bottom)); }

  /* The card is the company, two or three numbers, and a way in. Tier repeats
     what the CTC already says and the tags were a second line of colour for
     things nobody filtered by — both gone, and the row is shorter for it. */
  .cell.c-tier, .cell.c-tags, .cell.c-hire { display: none; }
}

/* ═════════════════════════ DRAGGING THE COMPANY PANEL ═══════════════════════
   The panel used to appear and disappear on a 200ms animation whichever way it
   was asked. A swipe that opens something the instant your finger passes a
   threshold tells you nothing while you are making it — you cannot see how far
   you have to go, and you cannot change your mind. So the panel is attached to
   the finger: it comes in from the right edge as you pull left, follows you
   back out if you push right, and only animates for the last stretch after you
   let go. */
.panel.is-dragging, .scrim.is-dragging {
  animation: none; transition: none;
}
.panel.is-dragging { will-change: transform; }
.panel.is-settling {
  animation: none;
  transition: transform .22s cubic-bezier(.22, .61, .36, 1);
}
.scrim.is-settling { animation: none; transition: opacity .22s ease; }
@media (prefers-reduced-motion: reduce) {
  .panel.is-settling, .scrim.is-settling { transition-duration: .01ms; }
}
