/* app.css — Career Tool's stylesheet. Was 30 lines inline in base.html with hardcoded
   GitHub-palette hex and no dark mode; this replaces it with the house token system shared
   by travels/Horizon Hub/mineko-dashboard, so the career tool stops being the one app outside
   the estate's design language. Fonts self-hosted from the same OFL files travels ships
   (app/static/fonts/) — no Google Fonts, no CDN.

   THREE states, not two, exactly Horizon Hub's rule (nhc app.077e6a78.css): an explicit
   choice stamps data-theme on <html>; the default "system" setting stamps nothing, so
   prefers-color-scheme alone resolves it. Hence: bare :root is the COMPLETE light palette,
   the media query redefines ONLY tokens (guarded so an explicit light choice beats a dark
   OS), and [data-theme="dark"] repeats it so the toggle wins in the other direction too.
   Never declare a colour for the first time inside either block.

   --accent vs --accent-fill contract: --accent is INK — links, active nav, icon strokes —
   and must clear 4.5:1 on --bg/--surface. --accent-fill is a FILLED surface only, always
   paired with --on-accent, never used as a bare `color:`. */

:root {
  color-scheme: light;

  --bg:#f7f9fc; --surface:#ffffff; --surface2:#eef2f8; --hover:#e4eaf3;
  --border:#dbe3ee; --border-ctl:#a9bbd2;

  --accent:#12558f; --accent-fill:#12558f; --on-accent:#ffffff;

  --text:#0b1a30; --muted:#4b607d; --faint:#4b607d;

  /* Band + status colours. apply/ok share a hue family with --accent by design — "apply" is
     the good outcome this whole tool exists to surface. */
  --ok:#1b6b44; --warn:#855708; --neutral:#4b607d; --bad:#b3261e;

  --tint:14%;                       /* badge/pill wash mix percentage, over --surface never transparent —
                                        see feedback_color-mix-transparent-contrast-trap */
  --scrim:rgba(11,26,48,.5);
  --shadow-1:0 1px 3px rgba(11,26,48,.12);
  --shadow-2:0 4px 16px rgba(11,26,48,.16);
  --ring:0 0 0 3px color-mix(in srgb, var(--accent) 45%, transparent);

  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px;
  --fs-xs:12px; --fs-sm:14px; --fs-base:16px; --fs-md:18px; --fs-lg:22px; --fs-xl:28px;

  --r-1:6px; --r-2:10px; --r-3:16px; --r-pill:999px;

  --ff-display:'Space Grotesk',system-ui,sans-serif;
  --ff-text:'Public Sans',system-ui,sans-serif;
  --ff-mono:'JetBrains Mono',ui-monospace,monospace;

  --tap:44px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:#0d1520; --surface:#132133; --surface2:#1a2c44; --hover:#223655;
    --border:#28405f; --border-ctl:#3d5a80;

    --accent:#6ab7f5; --accent-fill:#6ab7f5; --on-accent:#08151f;

    --text:#e8edf5; --muted:#a9bdd4; --faint:#a9bdd4;

    --ok:#6fd39b; --warn:#f0b429; --neutral:#a9bdd4; --bad:#ef6b60;

    /* 12%, not 14% (light) or the 16% first tried here — axe measured .band-rejected text
       (--bad) on its own tinted pill at 4.36:1 against a 16% mix, under the 4.5:1 floor.
       12% clears it (4.63:1) and only widens the margin for ok/warn/neutral, verified
       mechanically before landing. Keep this value identical in the [data-theme="dark"]
       block below — the two dark blocks must never diverge. */
    --tint:12%;
    --scrim:rgba(4,9,18,.65);
    --shadow-1:0 2px 8px rgba(0,0,0,.35);
    --shadow-2:0 4px 20px rgba(0,0,0,.45);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg:#0d1520; --surface:#132133; --surface2:#1a2c44; --hover:#223655;
  --border:#28405f; --border-ctl:#3d5a80;

  --accent:#6ab7f5; --accent-fill:#6ab7f5; --on-accent:#08151f;

  --text:#e8edf5; --muted:#a9bdd4; --faint:#a9bdd4;

  --ok:#6fd39b; --warn:#f0b429; --neutral:#a9bdd4; --bad:#ef6b60;

  /* kept in lockstep with the @media block above — see the comment there */
  --tint:12%;
  --scrim:rgba(4,9,18,.65);
  --shadow-1:0 2px 8px rgba(0,0,0,.35);
  --shadow-2:0 4px 20px rgba(0,0,0,.45);
  color-scheme: dark;
}

@font-face {
  font-family:'Space Grotesk'; font-style:normal; font-weight:500 700; font-display:swap;
  src:url('/static/fonts/space-grotesk.woff2') format('woff2');
}
@font-face {
  font-family:'Public Sans'; font-style:normal; font-weight:400 700; font-display:swap;
  src:url('/static/fonts/public-sans.woff2') format('woff2');
}
@font-face {
  font-family:'JetBrains Mono'; font-style:normal; font-weight:400 700; font-display:swap;
  src:url('/static/fonts/jetbrains-mono-subset.woff2') format('woff2');
}

*{box-sizing:border-box}
/* Author CSS always beats the UA stylesheet at equal specificity, so a plain `[hidden]` rule
   loses to `.row-main{display:grid}` (same 0,1,0 specificity, .row-main declared later) and
   instant-search rows stay visibly rendered even with the hidden attribute set — !important
   is the only thing that reliably wins here regardless of what else targets these elements. */
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%}
body{
  background:var(--bg); color:var(--text); font-family:var(--ff-text);
  margin:0; line-height:1.5; font-size:var(--fs-base);
}
a{color:var(--accent); text-decoration:none}
a:hover{text-decoration:underline}
/* inline links sitting in a run of text need a non-color cue at rest, not just on hover
   (axe: link-in-text-block) — nav/chip/card/button links stay underline-free since they're
   already set apart by shape, position and background */
p a, .muted a, dd a, .empty-state a, .role-meta-grid a, .jd a{text-decoration:underline; text-underline-offset:2px}
h1,h2,h3{font-family:var(--ff-display); font-weight:600; line-height:1.25; margin:0 0 var(--s3)}
h1{font-size:var(--fs-xl)}
h2{font-size:var(--fs-xl)}
h3{font-size:var(--fs-lg)}
button{font-family:inherit; cursor:pointer}
input,select{font-family:inherit; font-size:var(--fs-base)}

.wrap{max-width:1200px; margin:0 auto; padding:0 var(--s4)}

/* ---------- top bar ---------- */
.topbar{
  background:var(--surface); border-bottom:1px solid var(--border);
  position:sticky; top:0; z-index:10;
}
.topbar-inner{
  max-width:1200px; margin:0 auto; padding:0 var(--s4);
  display:flex; align-items:center; gap:var(--s5); min-height:var(--tap);
  flex-wrap:wrap;
}
.brand{font-family:var(--ff-display); font-weight:700; font-size:var(--fs-md); color:var(--text); padding:var(--s3) 0}
nav.primary{display:flex; gap:var(--s2); flex-wrap:wrap; margin-right:auto}
nav.primary a{
  display:flex; align-items:center; min-height:var(--tap); padding:0 var(--s3);
  color:var(--muted); font-weight:600; font-size:var(--fs-sm); border-radius:var(--r-1);
}
nav.primary a:hover{background:var(--hover); text-decoration:none}
nav.primary a.active{color:var(--accent); background:color-mix(in srgb, var(--accent) var(--tint), var(--surface))}
.topbar-user{display:flex; align-items:center; gap:var(--s3); color:var(--muted); font-size:var(--fs-sm)}
.icon-btn{
  display:inline-flex; align-items:center; justify-content:center;
  width:var(--tap); height:var(--tap); border:1px solid var(--border-ctl); border-radius:var(--r-1);
  background:var(--surface); color:var(--text);
}
.icon-btn:hover{background:var(--hover)}

/* ---------- filters / chips ---------- */
.filters{display:flex; gap:var(--s2); flex-wrap:wrap; align-items:center; margin:var(--s4) 0}
.chip{
  display:inline-flex; align-items:center; gap:var(--s1);
  min-height:var(--tap); padding:0 var(--s3); border:1px solid var(--border-ctl);
  border-radius:var(--r-pill); font-size:var(--fs-sm); font-weight:600; color:var(--text);
  background:var(--surface);
}
.chip:hover{background:var(--hover); text-decoration:none}
.chip.active{background:color-mix(in srgb, var(--accent) var(--tint), var(--surface)); border-color:var(--accent); color:var(--accent)}
/* opacity:.75 used to fade this, and on .chip.active (accent text over a tinted-not-solid
   background) that dropped to 3.65:1 in axe — under 4.5:1, because opacity blends toward
   whatever's behind the element, not the chip's own background. Inheriting the parent's
   solid color instead keeps counts legible everywhere the chip appears (6.17:1+). */
.chip .n{font-variant-numeric:tabular-nums}
.searchbar{
  margin-left:auto; display:flex; align-items:center; gap:var(--s2);
  border:1px solid var(--border-ctl); border-radius:var(--r-2); background:var(--surface);
  padding:0 var(--s3); min-height:var(--tap); min-width:220px;
}
.searchbar input{border:none; background:transparent; color:var(--text); flex:1; outline:none; min-width:0}
.searchbar svg{flex-shrink:0; color:var(--muted)}

/* ---------- hero (This Week) ---------- */
.hero{margin:var(--s5) 0}
.hero h2{display:flex; align-items:baseline; gap:var(--s3)}
.hero h2 .sub{font-family:var(--ff-text); font-weight:400; font-size:var(--fs-sm); color:var(--muted)}
.hero-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(240px,1fr)); gap:var(--s4)}
.hero-card{
  display:block; background:var(--surface); border:1px solid var(--border); border-radius:var(--r-3);
  padding:var(--s4); box-shadow:var(--shadow-1); color:var(--text);
}
.hero-card:hover{border-color:var(--border-ctl); text-decoration:none; box-shadow:var(--shadow-2)}
.hero-card .top{display:flex; justify-content:space-between; align-items:center; margin-bottom:var(--s3)}
.hero-card .rank{font-size:var(--fs-sm); color:var(--muted); font-variant-numeric:tabular-nums}
.hero-card .title{font-family:var(--ff-display); font-weight:600; font-size:var(--fs-md); margin-bottom:var(--s1)}
.hero-card .company{color:var(--muted); font-size:var(--fs-sm); margin-bottom:var(--s3)}
.hero-card .comp{font-size:var(--fs-sm); font-variant-numeric:tabular-nums; color:var(--text)}
.hero-empty{
  background:var(--surface2); border:1px dashed var(--border-ctl); border-radius:var(--r-3);
  padding:var(--s5); color:var(--muted); text-align:center;
}

/* ---------- band + status badges: tinted washes, never solid fills, never over transparent ---------- */
.band, .app-status{
  display:inline-flex; align-items:center; padding:var(--s1) var(--s3); border-radius:var(--r-pill);
  font-size:var(--fs-xs); font-weight:700; text-transform:uppercase; letter-spacing:.02em;
  border:1px solid transparent; white-space:nowrap;
}
.band-apply, .app-status-offer{
  background:color-mix(in srgb, var(--ok) var(--tint), var(--surface));
  color:var(--ok); border-color:color-mix(in srgb, var(--ok) 35%, var(--surface));
}
.band-stretch, .app-status-interview, .app-status-screening{
  background:color-mix(in srgb, var(--warn) var(--tint), var(--surface));
  color:var(--warn); border-color:color-mix(in srgb, var(--warn) 35%, var(--surface));
}
.band-watch, .app-status-ack, .app-status-drafting, .app-status-submitted{
  background:color-mix(in srgb, var(--neutral) var(--tint), var(--surface));
  color:var(--neutral); border-color:color-mix(in srgb, var(--neutral) 35%, var(--surface));
}
.band-rejected, .app-status-rejected, .app-status-withdrawn, .app-status-ghosted{
  background:color-mix(in srgb, var(--bad) var(--tint), var(--surface));
  color:var(--bad); border-color:color-mix(in srgb, var(--bad) 35%, var(--surface));
}
.band-unassessed{
  background:transparent; color:var(--muted); border-color:var(--border-ctl);
}

/* ---------- tables (desktop >=768px) / row-main cards (mobile) ----------
   mineko-dashboard's primitive (app/static/app.css:202-238): one markup structure, stacked
   card on mobile, promoted to an aligned grid at 768px via display:contents. .row-main is a
   GRID not a flex container — every child gets min-width:0 so it can't bleed off-frame
   (feedback_row-main-grid-not-flex-container); long text gets overflow-wrap, never blanket
   nowrap, for the same reason. */
.table-wrap{border:1px solid var(--border); border-radius:var(--r-3); overflow:hidden; background:var(--surface)}
a.row-main{color:inherit}
.row-main{
  display:grid; grid-template-columns:1fr auto; gap:var(--s3); align-items:center;
  min-height:calc(var(--tap) + var(--s3)); padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--border); min-width:0;
}
.row-main:last-child{border-bottom:none}
.row-main:hover, .row-main:focus-within{background:var(--hover)}
.row-main:focus-visible{outline:2px solid var(--accent); outline-offset:-2px}
.row-body{display:flex; flex-direction:column; gap:2px; min-width:0}
.row-title{font-weight:600; overflow-wrap:break-word; min-width:0; display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap}
.row-meta{display:flex; flex-wrap:wrap; gap:var(--s2); font-size:var(--fs-sm); color:var(--muted); min-width:0}
.row-meta > *{min-width:0; overflow-wrap:break-word}
.row-meta > * + *::before{content:"·"; margin-right:var(--s2)}
.row-value{font-variant-numeric:tabular-nums; white-space:nowrap; font-size:var(--fs-lg); font-weight:600; text-align:right}

/* Desktop promotion — mineko's rule verbatim (app/static/app.css:202-238): same markup, no
   JS. Requires each row to emit exactly 3 row-meta children so they land in the 3 middle
   columns; row-title (1 child of row-body) and row-value fill the outer two. */
@media (min-width:768px){
  .row-main{grid-template-columns:1fr repeat(3, minmax(0,max-content)) auto}
  .row-body, .row-meta{display:contents}
  .row-meta > *{font-size:var(--fs-sm); text-align:right}
  .row-meta > *::before{content:none}
}

/* Sort control — a chip row, not clickable table headers: row-main has no header row on
   mobile (there are no columns to head), so sort lives here instead, consistent across
   viewports rather than appearing/disappearing at the breakpoint. */
.sortbar{display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap; font-size:var(--fs-sm); color:var(--muted); margin-bottom:var(--s3)}
.sortbar .lbl{font-weight:600}
.sortbar a{
  display:inline-flex; align-items:center; gap:2px; padding:var(--s1) var(--s2);
  border-radius:var(--r-1); color:var(--muted);
}
.sortbar a:hover{background:var(--hover); text-decoration:none; color:var(--text)}
.sortbar a.active{color:var(--accent); font-weight:600}

/* Genuinely 2-D tables (Sources, Sweep history) stay tables — sticky first column +
   horizontal scroll, never a page-level scrollbar. */
.matrix-wrap{overflow-x:auto; -webkit-overflow-scrolling:touch}
table.matrix{width:100%; border-collapse:collapse; font-size:var(--fs-sm); min-width:max-content}
table.matrix th, table.matrix td{text-align:left; padding:var(--s3) var(--s4); border-bottom:1px solid var(--border); white-space:nowrap}
table.matrix thead th{
  background:var(--surface2); font-size:var(--fs-xs); font-weight:700; text-transform:uppercase;
  letter-spacing:.02em; color:var(--muted); position:sticky; top:0;
}
table.matrix th:first-child, table.matrix td:first-child{position:sticky; left:0; background:var(--surface); z-index:1}
table.matrix thead th:first-child{background:var(--surface2); z-index:2}
table.matrix thead th a{display:inline-flex; align-items:center; gap:2px; color:var(--muted)}
table.matrix thead th a:hover{color:var(--text); text-decoration:none}
table.matrix thead th a.active{color:var(--accent)}
table.matrix tbody tr:hover{background:var(--hover)}
table.matrix tbody tr:last-child td{border-bottom:none}
table.matrix td.num{font-variant-numeric:tabular-nums; text-align:right}

/* ---------- empty states ---------- */
.empty-state{
  text-align:center; padding:var(--s7) var(--s4); color:var(--muted);
  border:1px dashed var(--border-ctl); border-radius:var(--r-3); background:var(--surface2);
}
.empty-state h2{color:var(--text); margin-bottom:var(--s2); font-size:var(--fs-lg)}
.empty-state code{display:inline-block; margin-top:var(--s3)}

/* ---------- code / copy blocks ---------- */
code, .mono{font-family:var(--ff-mono); font-size:.9em}
.code-block{
  display:flex; align-items:center; gap:var(--s3); background:var(--surface2);
  border:1px solid var(--border); border-radius:var(--r-2); padding:var(--s3) var(--s4);
  font-family:var(--ff-mono); font-size:var(--fs-sm); overflow-x:auto;
}
.code-block code{flex:1; white-space:pre; color:var(--text)}
.copy-btn{
  flex-shrink:0; display:inline-flex; align-items:center; gap:var(--s1);
  height:var(--tap); padding:0 var(--s3); border:1px solid var(--border-ctl); border-radius:var(--r-1);
  background:var(--surface); color:var(--text); font-size:var(--fs-sm);
}
.copy-btn:hover{background:var(--hover)}
.copy-btn[data-copied]::after{content:"Copied"}
.copy-btn[data-copied] .lbl{display:none}

/* ---------- role detail ---------- */
.role-header{display:flex; flex-wrap:wrap; align-items:baseline; gap:var(--s3); margin-bottom:var(--s2)}
.role-meta-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(160px,1fr)); gap:var(--s3) var(--s5);
  background:var(--surface); border:1px solid var(--border); border-radius:var(--r-3);
  padding:var(--s4); margin:var(--s4) 0;
}
.role-meta-grid dt{font-size:var(--fs-xs); text-transform:uppercase; letter-spacing:.02em; color:var(--muted); margin-bottom:2px}
.role-meta-grid dd{margin:0; font-weight:600; font-variant-numeric:tabular-nums}
.gate-panel{
  background:color-mix(in srgb, var(--bad) 8%, var(--surface)); border:1px solid color-mix(in srgb, var(--bad) 30%, var(--surface));
  border-radius:var(--r-3); padding:var(--s4); margin:var(--s4) 0;
}
.gate-panel h2{color:var(--bad); font-size:var(--fs-base); margin-bottom:var(--s2)}
.gate-panel blockquote{margin:var(--s2) 0 0; padding-left:var(--s3); border-left:3px solid color-mix(in srgb, var(--bad) 40%, var(--surface)); color:var(--muted); font-style:italic}
.score-row{
  background:var(--surface); border:1px solid var(--border); border-left:3px solid var(--accent);
  border-radius:var(--r-2); padding:var(--s3) var(--s4); margin-bottom:var(--s3);
}
.score-row .dim{font-weight:700; display:flex; align-items:center; gap:var(--s2); margin-bottom:var(--s1)}
.score-row .dim .val{font-variant-numeric:tabular-nums; color:var(--accent)}
.score-row .evidence{color:var(--muted); font-size:var(--fs-sm); margin-top:var(--s2)}
.next-action{
  background:color-mix(in srgb, var(--ok) 8%, var(--surface)); border:1px solid color-mix(in srgb, var(--ok) 30%, var(--surface));
  border-radius:var(--r-3); padding:var(--s4); margin:var(--s4) 0;
}
.next-action h2{color:var(--ok); font-size:var(--fs-base)}
.jd{
  font-size:var(--fs-sm); max-height:480px; overflow-y:auto;
  border:1px solid var(--border); background:var(--surface); padding:var(--s4); border-radius:var(--r-3);
}
/* jd_text is real HTML now (was raw-escaped text needing pre-wrap to keep its line breaks) —
   give the block elements it actually contains normal spacing instead. */
.jd p{margin:0 0 var(--s3)}
.jd p:last-child{margin-bottom:0}
.jd ul, .jd ol{margin:0 0 var(--s3); padding-left:var(--s5)}
.jd li{margin-bottom:var(--s1)}
.jd blockquote{margin:0 0 var(--s3); padding-left:var(--s3); border-left:2px solid var(--border-ctl); color:var(--muted)}
.muted{color:var(--muted); font-size:var(--fs-sm)}
.back-link{display:inline-flex; align-items:center; gap:var(--s1); margin-bottom:var(--s3); font-weight:600}

/* ---------- auth pages ---------- */
.auth-page{
  min-height:calc(100vh - 200px); display:flex; align-items:center; justify-content:center; padding:var(--s5);
}
.auth-card{
  max-width:380px; width:100%; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-3); box-shadow:var(--shadow-2); padding:var(--s6) var(--s5); text-align:center;
}
.auth-card h1{margin-bottom:var(--s2)}
.auth-card p{color:var(--muted); margin-bottom:var(--s5)}
.btn-primary, .btn-secondary{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--s2);
  min-height:var(--tap); padding:0 var(--s5); border-radius:var(--r-2); font-weight:600; font-size:var(--fs-base);
  width:100%;
}
.btn-primary{background:var(--accent-fill); color:var(--on-accent); border:1px solid transparent}
.btn-primary:hover{filter:brightness(.94); text-decoration:none}
.btn-secondary{background:var(--surface); color:var(--text); border:1px solid var(--border-ctl); margin-top:var(--s3)}
.btn-secondary:hover{background:var(--hover); text-decoration:none}

main{padding-bottom:var(--s7)}

/* ---------- market outlook (Phase 6) ---------- */
.market-section{margin:var(--s6) 0}
.market-section h1 .sub, .market-section h2 .sub{font-family:var(--ff-text); font-weight:400; font-size:var(--fs-sm); color:var(--muted)}
.chart{background:var(--surface); border:1px solid var(--border); border-radius:var(--r-3); padding:var(--s4); overflow-x:auto; margin-bottom:var(--s3)}
.chart svg{display:block; max-width:100%}
.chart-legend{display:flex; flex-wrap:wrap; gap:var(--s3); font-size:var(--fs-sm); color:var(--muted); margin-bottom:var(--s3)}
.chart-legend .swatch{display:inline-block; width:10px; height:10px; border-radius:2px; margin-right:4px; vertical-align:middle}

/* Cited/derived badges reuse the same tinted-wash contract as .band-* (never a solid fill,
   never over transparent — feedback_color-mix-transparent-contrast-trap applies here too). */
.badge-cited, .badge-derived{
  display:inline-flex; align-items:center; padding:2px var(--s2); border-radius:var(--r-pill);
  font-size:var(--fs-xs); font-weight:700; text-transform:uppercase; letter-spacing:.02em;
  border:1px solid transparent; white-space:nowrap;
}
.badge-cited{
  background:color-mix(in srgb, var(--ok) var(--tint), var(--surface));
  color:var(--ok); border-color:color-mix(in srgb, var(--ok) 35%, var(--surface));
}
.badge-derived{
  background:color-mix(in srgb, var(--neutral) var(--tint), var(--surface));
  color:var(--neutral); border-color:color-mix(in srgb, var(--neutral) 35%, var(--surface));
}
.cited-figure, .derived-figure{display:inline-flex; flex-wrap:wrap; align-items:center; gap:var(--s2); margin-bottom:var(--s1)}
.cite-org{font-size:var(--fs-sm)}
.cite-details{width:100%; font-size:var(--fs-sm); color:var(--muted)}
.cite-details summary{cursor:pointer; color:var(--accent)}
.cite-details blockquote{margin:var(--s2) 0 0; padding-left:var(--s3); border-left:2px solid var(--border-ctl); font-style:italic}

.provenance-note{
  background:var(--surface2); border:1px dashed var(--border-ctl); border-radius:var(--r-3);
  padding:var(--s4); margin:var(--s5) 0; color:var(--muted); font-size:var(--fs-sm);
}
.provenance-note strong{color:var(--text)}

.derived-block{
  background:color-mix(in srgb, var(--neutral) 8%, var(--surface));
  border:1px solid color-mix(in srgb, var(--neutral) 30%, var(--surface));
  border-radius:var(--r-3); padding:var(--s4); margin:var(--s4) 0;
}

.market-brief{background:var(--surface); border:1px solid var(--border); border-radius:var(--r-3); padding:var(--s4)}
.market-brief p{margin:0 0 var(--s3)}
.market-brief p:last-child{margin-bottom:0}
.market-brief sup a{font-weight:700}
.cite-list{padding-left:var(--s5); font-size:var(--fs-sm)}
.cite-list li{margin-bottom:var(--s2)}

.family-card-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(240px,1fr)); gap:var(--s4)}
.family-card{background:var(--surface); border:1px solid var(--border); border-radius:var(--r-3); padding:var(--s4)}
.family-card h3{margin-bottom:var(--s2); font-size:var(--fs-base)}

/* ---------- accessibility / motion ---------- */
@media (prefers-reduced-motion: reduce){
  *{animation-duration:.001ms !important; transition-duration:.001ms !important}
}

/* :focus-visible declared last so nothing after it can override the ring. */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, .chip:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px; border-radius:var(--r-1);
}
