/* =============================================================================
   DealCrawler — dist.css  (single production stylesheet)
   -----------------------------------------------------------------------------
   Assembled from the approved MVP design mockups in
   execution_plan/design/mvp_ui/ : _shell.html (the spine) + _design_system.md
   (the token/component contract) + the 8 page mockups (login, deals-list,
   deal-detail, settings, account, status, exports, legal).

   - Token blocks lifted VERBATIM from _shell.html / _design_system.md (the
     canonical AA fixes: --btn-primary-bg, .foot-disc/.rail-foot/.brand small →
     --text-secondary, .btn.primary / pressed-chip → --btn-primary-bg).
   - Every shared shell/component rule is included ONCE (deduped).
   - Page-specific rules kept once each.
   - Demo-only scaffolding (state switchers, mockup dividers, "this is a
     prototype" chrome) is DROPPED — Jinja templates render ONE state.
   - No @font-face here: the two self-hosted fonts live in /static/fonts.css
     (linked by base.html). No Google Fonts @import / CDN (privacy, §10.5).

   Real selector conflicts resolved (see inline "CONFLICT" comments):
     .hint  · .state-card  · .skel-bar  · .nav button .tag
   ============================================================================= */


/* ============================ 10.1 / 10.5 TOKENS ============================ */
/* :root = LIGHT base set (the default). Verbatim from _shell.html, plus the
   canonical --btn-primary-bg and the optional --card-shadow used by login. */
:root{
  --bg-base:#FAFBFC; --bg-surface:#FFFFFF; --bg-surface-2:#F2F4F7;
  --border-subtle:#E4E8EE; --border-strong:#C2CAD4;
  --text-primary:#10161E; --text-secondary:#5A6675; --text-tertiary:#8A95A3;
  /* margin tiers — green = margin only */
  --margin-strong:#1A7F37; --margin-good:#2C7A45; --margin-neg:#6E7781;
  /* risk concern — red = risk-high only; NO GREEN ever */
  --risk-high:#CF222E; --risk-med:#9A6700; --risk-low:#5A6675; --risk-neutral:#5A6675;
  /* status freshness — neutral ramp, NOT a traffic light (D14) */
  --status-fresh:#5A6675; --status-lag:#8A95A3; --status-stale:#10161E;
  --accent:#0969DA;
  --btn-primary-bg:#0969DA; /* primary-button bg; white text 5.21:1 ✓ (links/focus keep --accent) */
  --radius-sm:6px; --radius-md:10px;
  --row-h:44px;
  --font-ui:"Inter",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --card-shadow:0 1px 2px rgba(16,22,30,.04), 0 8px 24px rgba(16,22,30,.06);
}
/* Dark set: OS prefers dark AND user hasn't forced light. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg-base:#0E1116; --bg-surface:#161B22; --bg-surface-2:#1C232D;
    --border-subtle:#2A323D; --border-strong:#3D4856;
    --text-primary:#E8EDF3; --text-secondary:#9BA7B5; --text-tertiary:#67727F;
    --margin-strong:#3FB950; --margin-good:#56A463; --margin-neg:#8B949E;
    --risk-high:#F85149; --risk-med:#D29922; --risk-low:#9BA7B5; --risk-neutral:#9BA7B5;
    --status-fresh:#9BA7B5; --status-lag:#67727F; --status-stale:#E8EDF3;
    --accent:#388BFD;
    --btn-primary-bg:#1F6FEB; /* darkened so white text = 4.63:1 ✓ (dark --accent #388BFD = 3.34:1 FAIL) */
    --card-shadow:0 8px 24px rgba(0,0,0,.32);
  }
}
/* Explicit persisted override. */
[data-theme="dark"]{
  --bg-base:#0E1116; --bg-surface:#161B22; --bg-surface-2:#1C232D;
  --border-subtle:#2A323D; --border-strong:#3D4856;
  --text-primary:#E8EDF3; --text-secondary:#9BA7B5; --text-tertiary:#67727F;
  --margin-strong:#3FB950; --margin-good:#56A463; --margin-neg:#8B949E;
  --risk-high:#F85149; --risk-med:#D29922; --risk-low:#9BA7B5; --risk-neutral:#9BA7B5;
  --status-fresh:#9BA7B5; --status-lag:#67727F; --status-stale:#E8EDF3;
  --accent:#388BFD;
  --btn-primary-bg:#1F6FEB; /* darkened so white text = 4.63:1 ✓ (dark --accent #388BFD = 3.34:1 FAIL) */
  --card-shadow:0 8px 24px rgba(0,0,0,.32);
}
[data-theme="light"]{ --card-shadow:0 1px 2px rgba(16,22,30,.04), 0 8px 24px rgba(16,22,30,.06); } /* uses :root base */
/* #3 — the [data-density="compact"]{--row-h} override was unused (no density toggle ships in
   this build); --row-h stays at its :root default (44px). */


/* ============================ base ============================ */
*{box-sizing:border-box;}
html,body{margin:0;height:100%;}
body{
  background:var(--bg-base); color:var(--text-primary);
  font-family:var(--font-ui); font-size:14px; line-height:20px;
  -webkit-font-smoothing:antialiased;
}
.mono{font-family:var(--font-mono); font-variant-numeric:tabular-nums;}
button{font-family:inherit;}
a{color:var(--accent); text-decoration:none;}
a:hover{text-decoration:underline;}
:focus-visible{outline:2px solid var(--border-strong); outline-offset:1px; border-radius:4px;}

/* screen-reader-only / visually-hidden utilities (deals-list .sr-only, exports
   .sr-only, status .vh) — merged into one rule. */
.sr-only,.vh{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;}


/* ============================ app shell ============================ */
.app{display:grid; grid-template-columns:240px 1fr; min-height:100vh;}

.rail{
  background:var(--bg-surface); border-right:1px solid var(--border-subtle);
  display:flex; flex-direction:column; position:sticky; top:0; height:100vh;
}
.brand{display:flex; align-items:center; gap:9px; padding:16px; font-weight:700; font-size:15px; letter-spacing:-.2px;}
.brand .logo{width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,var(--accent),#7C5CFF);display:grid;place-items:center;color:#fff;font-size:13px;font-weight:800;}
.brand small{display:block;font-weight:500;font-size:11px;color:var(--text-secondary);letter-spacing:0;} /* conveyed "solo seat · beta" → secondary; AA ✓ */

.nav{display:flex; flex-direction:column; gap:2px; padding:8px;}
.nav button, .nav .navbtn{
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  background:transparent; border:0; color:var(--text-secondary);
  padding:9px 10px; border-radius:var(--radius-sm); font-size:14px; cursor:pointer;
  text-decoration:none;
}
/* nav anchors are real links — override the global a{} accent + a:hover underline */
.nav .navbtn:hover{text-decoration:none;}
.nav button .ico, .nav .navbtn .ico{width:18px;text-align:center;opacity:.9; font-family:var(--font-mono);}
/* CONFLICT (.nav button .tag color): shell/deals/account/status/legal use
   --risk-med (amber "not linked" attention); settings used --text-secondary.
   Resolved to the shell/design-system canonical --risk-med. */
.nav button .tag, .nav .navbtn .tag{margin-left:auto; font-size:10px; font-weight:600; color:var(--risk-med);}
.nav button:hover, .nav .navbtn:hover{background:var(--bg-surface-2); color:var(--text-primary);}
.nav button[aria-current="page"], .nav .navbtn[aria-current="page"]{background:var(--bg-surface-2); color:var(--text-primary); font-weight:600; box-shadow:inset 2px 0 0 var(--accent);}
.nav .sep{height:1px; background:var(--border-subtle); margin:6px 8px;}

.rail-foot{margin-top:auto; padding:12px; border-top:1px solid var(--border-subtle); font-size:11px; color:var(--text-secondary); line-height:16px;} /* counsel disclaimer is conveyed honesty copy → secondary (was tertiary 3.04:1); AA ✓ */
.rail-foot .controls{display:flex; gap:6px; margin-bottom:10px;}
.rail-foot .controls button{
  flex:1; border:1px solid var(--border-subtle); background:var(--bg-base);
  color:var(--text-secondary); border-radius:var(--radius-sm); padding:6px 4px; cursor:pointer; font-size:11px;
}
.rail-foot .controls button:hover{border-color:var(--border-strong); color:var(--text-primary);}
.rail-foot .controls button[aria-pressed="true"]{border-color:var(--accent); color:var(--text-primary);}

.main{display:flex; flex-direction:column; min-width:0;}

/* Flow E: Telegram-not-connected amber banner — persistent until bound.
   The ONE sanctioned non-semantic use of amber: an attention banner, not a risk verdict. */
.banner{
  display:flex; align-items:center; gap:10px; padding:9px 20px; font-size:13px;
  background:color-mix(in srgb, var(--risk-med) 16%, var(--bg-surface));
  border-bottom:1px solid color-mix(in srgb, var(--risk-med) 40%, var(--border-subtle));
  color:var(--text-primary);
}
.banner .dot{color:var(--risk-med);}
.banner .bdot{color:var(--risk-med);}        /* status.html banner uses .bdot */
.banner a{margin-left:auto; font-weight:600;}
.banner .dismiss{display:none;} /* persistent — no dismiss in MVP until bound */
/* deals-list S5 neutral degraded banner — NEVER amber/red (D14); weight/shape carries severity. */
.banner.neutral{background:var(--bg-surface-2); border-bottom:1px solid var(--border-strong); color:var(--text-primary);}
.banner.neutral .dot{display:inline-block; width:11px; height:11px; border-radius:50%; border:2px solid var(--status-stale); background:transparent; color:transparent;}

.page{padding:20px 24px 64px; max-width:1280px; width:100%;}
.page-head{display:flex; align-items:flex-end; justify-content:space-between; gap:16px; margin-bottom:6px;}
.page-head h1{font-size:25px; line-height:32px; margin:0; letter-spacing:-.4px;}
h1{font-size:25px; line-height:32px; margin:0; letter-spacing:-.4px;}
.sub{color:var(--text-secondary); font-size:13px; margin:2px 0 16px;}
.sub b{color:var(--text-primary);}
/* CONFLICT (.hint color): shell/deals/exports use --text-tertiary (decorative,
   per design-system §5.1); deal-detail/settings/account/status overrode to
   --text-secondary where .hint carries conveyed prose. Resolved to the
   design-system canonical --text-tertiary — templates that need AA-conveyed
   helper text use a .help/.note class (defined below) instead. */
.hint{color:var(--text-tertiary); font-size:12px;}

/* counsel disclaimer footer — every page (§13).
   Load-bearing honesty copy → --text-secondary (light 5.3:1 / dark 7.7:1 ✓),
   never --text-tertiary (2.93:1 light / 3.86:1 dark = FAIL). */
.foot-disc{
  margin-top:26px; padding-top:14px; border-top:1px solid var(--border-subtle);
  font-size:11.5px; color:var(--text-secondary); line-height:17px;
}
.foot-disc a{color:var(--text-secondary); text-decoration:underline;}


/* ============================ buttons — .btn (§5.2) ============================ */
.btn{border:1px solid var(--border-subtle); background:var(--bg-surface-2); color:var(--text-primary); border-radius:var(--radius-sm); padding:7px 12px; font-size:13px; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; gap:7px; text-decoration:none;}
.btn:hover{border-color:var(--border-strong); text-decoration:none;}
.btn.primary{background:var(--btn-primary-bg); border-color:var(--btn-primary-bg); color:#fff;} /* white-on-accent needs ≥4.5:1; dark --accent fails 3.34:1 → --btn-primary-bg (§1.5 CANON) */
.btn.primary:hover{filter:brightness(1.06);}
.btn.ghost{background:transparent;}
.btn.sm{padding:4px 9px; font-size:12px;}
.btn.block{ width:100%; padding:10px 12px; font-size:14px; font-weight:600; margin-top:18px; } /* login full-width submit */
.btn[disabled],.btn[aria-disabled="true"],.btn[aria-busy="true"]{opacity:.7; cursor:default; pointer-events:none; filter:none;}
/* exports: disabled PRIMARY drops the accent fill so it never reads as an active primary */
.btn.primary[disabled]{background:var(--bg-surface-2); border-color:var(--border-subtle); color:var(--text-tertiary); opacity:1; filter:none;}


/* ============================ chips — .chip / .chips (§5.3) ============================ */
.chips{display:flex; flex-wrap:wrap; gap:6px;}
.chip{border:1px solid var(--border-subtle); background:var(--bg-surface); color:var(--text-secondary); border-radius:999px; padding:4px 10px; font-size:12px; cursor:pointer;}
.chip[aria-pressed="true"]{background:var(--btn-primary-bg); border-color:var(--btn-primary-bg); color:#fff;} /* white-on-accent pressed chip → --btn-primary-bg for AA (dark #388BFD=3.34:1 FAIL → #1F6FEB=4.63:1) (§1.5 CANON) */


/* ============================ glyph color classes (§4 / §5.4) ============================ */
.g-high{color:var(--risk-high);} .g-med{color:var(--risk-med);}
.g-low{color:var(--risk-low);} .g-neu{color:var(--risk-neutral);}


/* ============================ data table — table / .table-wrap (§5.4) ============================ */
.table-wrap{border:1px solid var(--border-subtle); border-radius:var(--radius-md); overflow:hidden; background:var(--bg-surface);}
.table-toolbar{display:flex; align-items:center; gap:12px; padding:10px 12px; border-bottom:1px solid var(--border-subtle); flex-wrap:wrap;}
.table-toolbar .count{font-size:13px; color:var(--text-secondary);}
.table-toolbar .count b{color:var(--text-primary);}
/* #3 Run-scan panel — a bounded card above every deals state (populated/empty/quiet), visually distinct
   from the left view-filters so the scope dropdowns aren't mistaken for filters. Neutral status copy
   (Invariant 4: a failed run is not alarmed in red). */
.scan-panel{border:1px solid var(--border-subtle); border-left:3px solid var(--accent);
  border-radius:var(--radius-md); background:var(--bg-surface); padding:12px 14px; margin-bottom:16px;}
.scan-panel-row{display:flex; align-items:flex-start; justify-content:space-between; gap:14px; flex-wrap:wrap;}
.scan-panel-intro h3{margin:0; font-size:14px; font-weight:600; color:var(--text-primary); display:flex; align-items:center; gap:6px;}
.scan-panel-intro p{margin:2px 0 0; font-size:12px; color:var(--text-secondary); max-width:52ch;}
.scan-panel-row form{margin:0;}
.scan-panel-actions{display:flex; align-items:center; gap:8px; flex:0 0 auto;}
.scan-panel-scope{display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin-top:12px; padding-top:12px; border-top:1px solid var(--border-subtle);}
.scan-panel-scope .scope-label{font-size:12px; color:var(--text-tertiary); text-transform:uppercase; letter-spacing:.4px;}
/* #3b scope multi-selects: a button toggles a checkbox popover anchored under it. Neutral surface,
   matches the filter chips' weight. */
.ms{position:relative;}
.ms-toggle{white-space:nowrap;}
.ms-panel{position:absolute; z-index:20; top:calc(100% + 4px); left:0; min-width:180px; max-height:280px;
  overflow:auto; display:flex; flex-direction:column; gap:2px; padding:8px; border:1px solid var(--border-strong);
  border-radius:var(--radius-sm); background:var(--bg-surface); box-shadow:0 8px 24px rgba(0,0,0,.28);}
/* the class's display:flex outweighs the bare [hidden] UA default (display:none) by specificity, so the
   panel would never hide — re-assert hidden with a class+attribute selector that wins. */
.ms-panel[hidden]{display:none;}
.ms-opt{display:flex; align-items:center; gap:8px; font-size:13px; color:var(--text-primary);
  padding:4px 6px; border-radius:var(--radius-sm); cursor:pointer; white-space:nowrap;}
.ms-opt:hover{background:var(--bg-surface-2);}
.ms-opt input{margin:0;}
.scan-status{font-size:13px; color:var(--text-secondary);}
.scan-status.running{color:var(--text-secondary);}
.scan-status.done{color:var(--text-primary);}
.scan-status.failed{color:var(--text-secondary);}
.spacer{flex:1;}

table{width:100%; border-collapse:collapse; font-size:14px;}
thead th{position:sticky; top:0; z-index:1; background:var(--bg-surface); text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.5px; color:var(--text-tertiary); font-weight:600; padding:9px 12px; border-bottom:1px solid var(--border-subtle); white-space:nowrap;}
thead th.num, td.num{text-align:right;}
thead th button{background:transparent; border:0; color:inherit; font:inherit; text-transform:inherit; letter-spacing:inherit; cursor:pointer; padding:0; display:inline-flex; gap:4px; align-items:center;}
/* #2 sortable headers: whole label is the click target; the ↕/▲/▼ indicator de-emphasizes when idle,
   the active column's button + indicator lift to the secondary text color. num columns right-align. */
thead th.num button{justify-content:flex-end;}
thead th button.th-sort:hover{color:var(--text-secondary);}
thead th button .sort-ind{font-size:9px; opacity:.45; transition:opacity .15s;}
thead th[aria-sort] button.th-sort{color:var(--text-secondary);}
thead th[aria-sort] button.th-sort .sort-ind{opacity:1;}
tbody tr{border-bottom:1px solid var(--border-subtle); cursor:pointer;}
tbody tr:last-child{border-bottom:0;}
tbody tr:hover{background:var(--bg-surface-2);}
td{padding:0 12px; height:var(--row-h); vertical-align:middle; white-space:nowrap;}
.thumb{width:28px;height:28px;border-radius:5px;border:1px solid var(--border-subtle);background:var(--bg-surface-2);display:grid;place-items:center;font-size:11px;color:var(--text-tertiary);font-weight:700;}
.model{display:flex; align-items:center; gap:10px;}
.model .meta{display:flex; flex-direction:column; line-height:16px;}
.model .meta b{font-weight:600; font-size:13px;}
.model .meta span{font-size:11px; color:var(--text-secondary);} /* brand·condition is conveyed identity data → secondary (AA) */
.fmv{font-size:13px;}
.fmv .conf{display:block; font-size:12px; color:var(--text-secondary);} /* D13: secondary, never bare */
.usd-approx{display:block; font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:12px; color:var(--text-secondary);} /* conveyed cross-border price → secondary; de-emphasis carried by the ≈ glyph + "USD" parenthetical, not a sub-AA hue */

/* margin cell — tier-colored money + 3px tier bar */
.margin-cell{position:relative; padding-left:14px !important;}
.margin-cell::before{content:""; position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:2px; background:var(--bar);}
.margin-cell .pct{font-weight:700; color:var(--tier);}
.tier-strong{--tier:var(--margin-strong); --bar:var(--margin-strong);}
.tier-good{--tier:var(--margin-good); --bar:var(--margin-good);}
.tier-neg{--tier:var(--margin-neg); --bar:var(--margin-neg);}

/* risk glyph cluster (preview, never a verdict). Wraps to a 2nd line within the cell so the full
   D-37 signal set shows without truncating to "+N"; max-width keeps it from widening the column. */
.glyphs{display:inline-flex; flex-wrap:wrap; gap:5px 6px; align-items:center; max-width:84px; line-height:1.15; font-family:var(--font-mono); font-size:13px;}
.glyphs .more{color:var(--text-tertiary); font-family:var(--font-ui); font-size:11px;}

/* expired rows — AA-valid muted token + non-opacity cue (italic tag), NEVER opacity. */
tr.expired td{color:var(--text-secondary);}
tr.expired .model .meta b{color:var(--text-secondary); font-weight:500;}
tr.expired .expired-tag{font-size:11px; color:var(--text-secondary); font-style:italic;}
.muted{color:var(--text-secondary);} /* Age + "unavailable"/"margin can't be computed"/"—" are conveyed data → secondary (AA) */
.rowact{color:var(--text-tertiary); font-size:16px;}

.legend{display:flex; flex-wrap:wrap; gap:16px; margin-top:18px; padding:12px 14px; border:1px solid var(--border-subtle); border-radius:var(--radius-md); background:var(--bg-surface); font-size:12px; color:var(--text-secondary);}
.legend .g{display:inline-flex; gap:6px; align-items:center;}
.legend .mono{font-size:13px;}


/* ============================ deals list — filters / .deals-grid ============================ */
/* (#3) Named areas so the scan-panel and filter rail can reorder by breakpoint without moving in the DOM:
   desktop = filters spanning the left column, scan-panel + table stacked on the right; mobile = scan
   first, then the (collapsible) filters, then the table. */
.deals-grid{display:grid; grid-template-columns:212px 1fr; gap:20px; align-items:start;
  grid-template-areas:"filters scan" "filters table";}
.deals-grid > .filters{grid-area:filters;}
.deals-grid > .scan-panel{grid-area:scan;}
.deals-grid > #tableCol{grid-area:table; min-width:0;}
.filters{font-size:13px;}
/* (#3) Mobile-only collapse affordance — hidden on desktop (rail is always shown in the left column). */
.filters-toggle{display:none;}
.filters-body{display:block;}
.filters h3{font-size:11px; text-transform:uppercase; letter-spacing:.6px; color:var(--text-tertiary); margin:20px 0 8px;}
/* Only the first facet's heading hugs the top; the rest (Source, Net margin, Condition, Qualified after)
   keep their top margin so the groups read as separated. Each h3 is the first child of its OWN <form>, so
   a :first-child rule would zero them all — scope the reset to the first form instead. */
.filters form:first-of-type h3{margin-top:0;}
.filters h3 label{color:inherit; cursor:pointer;}
.filters input[type=range]{width:100%;}
/* Hide-actioned facet — stacked checkboxes (Bought / Passed / False alarm). */
.hide-opts{display:flex; flex-direction:column; gap:6px;}
.hide-opt{display:flex; align-items:center; gap:7px; font-size:13px; color:var(--text-secondary); cursor:pointer;}
.hide-opt input{margin:0;}
.filters .note{font-size:11px; color:var(--text-secondary); margin-top:6px; line-height:15px;} /* threshold-vs-filter explanation is conveyed copy → secondary (AA) */
.filters .note b{color:var(--text-primary);}
.filter-select{width:100%; font-family:inherit; font-size:13px; color:var(--text-primary); background:var(--bg-surface); border:1px solid var(--border-subtle); border-radius:var(--radius-sm); padding:6px 8px; cursor:pointer;}
.filter-select:hover{border-color:var(--border-strong);}

/* #1 PAGER — server-side pagination control under the table. The page links are .btn.sm
   anchors (preserving all filter params); .pager is the row, .pagination the link group.
   Current page reads as a pressed .btn (accent fill); prev/next disabled at the ends. */
.pager{display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-top:16px;}
.pager .range{font-size:12px; color:var(--text-secondary);}
.pager .range b{color:var(--text-primary);}
.pagination{display:inline-flex; align-items:center; gap:6px; flex-wrap:wrap; margin-left:auto;}
.pagination .btn.sm{min-width:32px;}
.pagination .btn.sm[aria-current="page"]{background:var(--btn-primary-bg); border-color:var(--btn-primary-bg); color:#fff;}
.pagination .gap{padding:0 2px; color:var(--text-tertiary); font-size:12px;}


/* ============================ state card / checklist (§5.10) ============================
   CONFLICT (.state-card border): deals-list & exports use a DASHED empty-state
   frame; deal-detail/settings/account/status/legal use a SOLID --border-strong
   frame. Resolved by making the SOLID variant the base (the more common form),
   and reusing deals-list's `.state-card.solid` lever inverted via `.state-card.dashed`
   for the empty-state pages. Default = solid; add `.dashed` for empty/first-run. */
.state-card{border:1px solid var(--border-strong); border-radius:var(--radius-md); padding:28px; text-align:center; color:var(--text-secondary); background:var(--bg-surface);}
.state-card.dashed{border-style:dashed;}
.state-card.solid{border-style:solid;}
.state-card.error{border-style:solid;}
.state-card h3{color:var(--text-primary); margin:0 0 6px; font-size:16px;}
.state-card p{margin:0 0 16px; color:var(--text-secondary); font-size:13px; line-height:21px;}
.state-card b{color:var(--text-primary);}
.state-card .muted{color:var(--text-secondary);}
.state-card .msg{font-size:16px; color:var(--text-primary); line-height:24px;}
.state-card .ref{display:block; margin-top:12px; font-family:var(--font-mono); font-size:11px; color:var(--text-secondary);} /* conveyed support/Sentry id → secondary (AA) */
.state-card .cta,.state-card .acts,.state-card .actions,.state-card .row{margin-top:14px; display:inline-flex; gap:10px; align-items:center; justify-content:center; flex-wrap:wrap;}

.checklist{max-width:460px; margin:18px auto 0; text-align:left; display:flex; flex-direction:column; gap:10px;}
.check-item{display:flex; gap:12px; align-items:center; border:1px solid var(--border-subtle); background:var(--bg-base); border-radius:var(--radius-md); padding:12px 14px;}
.check-item .num{width:24px;height:24px;border-radius:50%;border:1.5px solid var(--border-strong); display:grid;place-items:center; font-size:12px; font-weight:700; color:var(--text-secondary); flex:none;}
.check-item .grow{flex:1;}
.check-item b{font-size:14px; color:var(--text-primary);}
.check-item small{display:block; color:var(--text-secondary); font-size:12px;} /* first-run step explanation → secondary; AA */


/* ============================ drawer — .drawer / .scrim (§5.5) ============================ */
.scrim{position:fixed; inset:0; background:rgba(0,0,0,.42); opacity:0; pointer-events:none; transition:opacity .18s; z-index:45;}
.scrim.open{opacity:1; pointer-events:auto;}
.drawer{position:fixed; top:0; right:0; height:100vh; width:420px; max-width:92vw; background:var(--bg-surface); border-left:1px solid var(--border-subtle); transform:translateX(100%); transition:transform .2s ease; z-index:50; display:flex; flex-direction:column; box-shadow:-12px 0 32px rgba(0,0,0,.22);}
.drawer.open{transform:translateX(0);}
@media (prefers-reduced-motion: reduce){ .drawer,.scrim{transition:none;} }
.drawer-head{display:flex; align-items:center; gap:10px; padding:12px 16px; border-bottom:1px solid var(--border-subtle);}
.drawer-head strong{font-size:13px;}
.drawer-head .promote{font-size:12px; margin-left:6px;}
.drawer-head .x{margin-left:auto; background:transparent; border:0; color:var(--text-secondary); font-size:20px; cursor:pointer; line-height:1; padding:4px 8px;}
.drawer-body{flex:1 1 auto; min-height:0; overflow-y:auto; padding:16px 16px 48px; display:flex; flex-direction:column; gap:18px;}
/* #6/#7 — the flex column's children default to flex-shrink:1, so .comp blocks
   (overflow:hidden) COMPRESS/clip (outcome buttons cut off, trace truncated) and the
   body never scrolls. Pin every direct child to its natural height so content overflows
   → the body scrolls; the 48px bottom padding lets the last .outcome button clear the edge. */
.drawer-body > *{flex:0 0 auto;}
.drawer-body .stub{border:1px dashed var(--border-strong); border-radius:var(--radius-md); padding:16px; font-size:13px; color:var(--text-secondary); line-height:19px;}


/* ============================ deal detail — full page + .dealhead ============================ */
.detail-page{max-width:720px;}
.detail-page .crumb{font-size:13px; margin:0 0 4px;}
.detail-page .stack{display:flex; flex-direction:column; gap:24px; margin-top:14px;}
.surface-tabs{display:flex; gap:8px; margin:0 0 14px;}

.dealhead .photo{height:150px; border-radius:var(--radius-md); border:1px solid var(--border-subtle); background:var(--bg-surface-2); display:grid; place-items:center; color:var(--text-tertiary); font-size:13px; position:relative; overflow:hidden;}
.detail-page .dealhead .photo{height:220px;}
/* #1 GALLERY — horizontal swipeable strip of ALL photo_urls (not just [0]); scroll-snap
   so each image lands centered. Matches the .dealhead .photo height (150px / 220px on the
   full page). The .carousel-dots styling below is kept as the position indicator. */
.dealhead .photo-strip{display:flex; gap:8px; overflow-x:auto; scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch; border-radius:var(--radius-md);}
.dealhead .photo-strip img{flex:0 0 100%; scroll-snap-align:center; height:150px; width:100%; object-fit:cover; border:1px solid var(--border-subtle); border-radius:var(--radius-md);}
.detail-page .dealhead .photo-strip img{height:220px;}
/* #4 GALLERY — the .carousel-dots are clickable position indicators (dot-click JS lives in the
   detail template; it moves .active across the <i> dots). Each dot is its own tap target:
   the active dot is a filled --accent pip; inactive dots are faint. Centered over the strip. */
.dealhead .carousel-dots{position:absolute; bottom:8px; left:50%; transform:translateX(-50%); display:flex; gap:6px; padding:4px 7px; border-radius:999px; background:color-mix(in srgb, var(--bg-base) 55%, transparent);}
.dealhead .carousel-dots i{width:7px; height:7px; border-radius:50%; background:var(--text-tertiary); opacity:.5; cursor:pointer; transition:opacity .15s, background .15s; box-sizing:content-box;}
.dealhead .carousel-dots i:hover{opacity:.8;}
.dealhead .carousel-dots i.active{background:var(--accent); opacity:1;}
/* fallback while the active class hasn't been applied yet (first dot reads as current) */
.dealhead .carousel-dots:not(:has(i.active)) i:first-child{background:var(--accent); opacity:1;}
/* subtle prev/next affordances — quiet circular glyph buttons over the strip edges */
.dealhead .photo .nav-prev, .dealhead .photo .nav-next{position:absolute; top:50%; transform:translateY(-50%); width:28px; height:28px; display:grid; place-items:center; border:0; border-radius:50%; background:color-mix(in srgb, var(--bg-base) 62%, transparent); color:var(--text-primary); font-size:14px; line-height:1; cursor:pointer; opacity:.7; transition:opacity .15s;}
.dealhead .photo .nav-prev:hover, .dealhead .photo .nav-next:hover{opacity:1;}
.dealhead .photo .nav-prev{left:8px;}
.dealhead .photo .nav-next{right:8px;}
.dealhead .title{margin:12px 0 2px; font-size:16px; font-weight:600;}
.detail-page .dealhead .title{font-size:25px; line-height:32px; letter-spacing:-.4px;}
.dealhead .row{display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; color:var(--text-secondary); font-size:13px;}
.dealhead .price{font-size:18px; font-weight:700; color:var(--text-primary);}
.dealhead .usd{color:var(--text-secondary); font-size:12px;} /* ≈USD/expired = conveyed content; de-emphasis via ≈ glyph + parenthetical, not sub-AA hue */
.headline-margin{margin-top:10px; display:flex; align-items:center; gap:8px; font-size:13px; color:var(--text-secondary);}
.headline-margin .big{font-family:var(--font-mono); font-size:22px; font-weight:700; color:var(--tier);}


/* ============================ component frame — .comp (§5.6) ============================ */
.comp{border:1px solid var(--border-subtle); border-radius:var(--radius-md); overflow:hidden; background:var(--bg-surface);}
.comp > h4{margin:0; padding:10px 14px; font-size:12px; text-transform:uppercase; letter-spacing:.5px; color:var(--text-secondary); border-bottom:1px solid var(--border-subtle); background:var(--bg-surface-2); display:flex; align-items:center; gap:8px;}


/* ============================ margin trace — .trace (§5.7 / §7) ============================ */
.trace{padding:8px 14px 14px;}
.trace .ln{display:grid; grid-template-columns:1fr auto; gap:12px; align-items:baseline; padding:5px 0; font-size:13px;}
.trace .ln .lbl{color:var(--text-secondary);}
.trace .ln .lbl .prov{display:block; font-size:11px; color:var(--text-secondary);} /* provenance always-visible/dispute-relevant (§7) — secondary */
.trace .ln .val{font-family:var(--font-mono); font-variant-numeric:tabular-nums; text-align:right; color:var(--text-primary);}
.trace .ln.fmv .lbl{color:var(--text-primary); font-weight:500;}
.trace .ln.fmv .conf{display:block; font-size:12px; color:var(--text-secondary); font-family:var(--font-ui);} /* D13: secondary */
.trace .ln.sub .val{color:var(--text-secondary);}
.trace .rule{border-top:1px solid var(--border-subtle); margin:7px 0;}
.trace .ln.result .lbl{color:var(--text-primary); font-weight:600;}
.trace .ln.result .val{color:var(--text-primary); font-weight:700;}
.trace .ln.result.margin .val{color:var(--tier);}
.trace .formula{font-size:11px; color:var(--text-secondary); text-align:right; margin-top:2px;} /* formula_version is auditable content (§7) — secondary */
.trace .override{margin-top:10px;}
.trace .override a{font-size:12px;}
/* #5 — .override-toggle was a boxy button; restyle it to read as a quiet inline accent
   text-link (matching the .trace inline links), not a square button. No heavy border/fill. */
.override-toggle{
  display:inline; background:transparent; border:0; padding:0; margin:0;
  font:inherit; font-size:12px; color:var(--accent); cursor:pointer; text-align:left;
}
.override-toggle:hover{text-decoration:underline;}
.override-toggle:focus-visible{outline:2px solid var(--border-strong); outline-offset:2px; border-radius:3px;}

/* #2 OVERRIDE FORM — inline "Set your own FMV" form (.fmv-override #override), rendered
   inside .trace/.comp in BOTH the full page and the drawer. Tidy inline row: label on its
   own line, then [currency prefix · number field · currency suffix · Save] on one row that
   wraps on narrow widths; .override-msg + .gap-note stacked below. Stays within the component
   (no overflow past .comp's overflow:hidden). Inputs match .num-input/.rule-row form-control. */
.fmv-override{display:flex; flex-direction:column; gap:8px; margin-top:10px; padding-top:10px; border-top:1px solid var(--border-subtle);}
.fmv-override[hidden]{display:none;}
.fmv-override > label{font-size:12px; color:var(--text-secondary);}
.fmv-override .field{display:flex; align-items:center; gap:6px; flex-wrap:wrap; min-width:0;}
.fmv-override .field .k,.fmv-override .field .cur{font-family:var(--font-mono); font-size:13px; color:var(--text-secondary); flex:0 0 auto;}
.fmv-override .field input[type=number]{flex:1 1 120px; min-width:0; max-width:100%; box-sizing:border-box; background:var(--bg-base); border:1px solid var(--border-subtle); border-radius:6px; padding:7px 10px; color:var(--text-primary); font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:14px;}
.fmv-override .field input[type=number]:hover{border-color:var(--border-strong);}
.fmv-override .field input[type=number]:disabled{color:var(--text-secondary); background:var(--bg-surface-2);}
.fmv-override .override-save{flex:0 0 auto;}
.fmv-override .override-msg{font-size:12px; color:var(--text-secondary); line-height:17px;}
.fmv-override .override-msg[hidden]{display:none;}
.fmv-override .gap-note{font-size:11.5px; color:var(--text-secondary); line-height:16px;} /* "applies to future scans" — conveyed copy, secondary (AA) */


/* ============================ risk report — .risk (§5.8 / §8) ============================ */
.risk .disc{padding:10px 14px; font-size:12px; line-height:17px; color:var(--text-secondary); background:var(--bg-surface-2); border-bottom:1px solid var(--border-subtle);}
.risk dl{margin:0; padding:4px 14px 6px;}
.risk .sig{display:grid; grid-template-columns:18px 1fr auto; gap:10px; align-items:baseline; padding:7px 0; border-bottom:1px solid var(--border-subtle);}
.risk .sig:last-child{border-bottom:0;}
.risk .sig .glyph{font-family:var(--font-mono); text-align:center;}
.risk .sig dt{font-weight:500;}
.risk .sig dt .concern{display:block; font-size:12px; color:var(--text-secondary); font-weight:400;}
.risk .sig dd{margin:0; font-family:var(--font-mono); font-variant-numeric:tabular-nums; text-align:right; font-size:13px;}
.risk .why{padding:8px 14px 12px; font-size:12px;}


/* ============================ timestamps (Invariant 7) ============================ */
.stamps{font-size:12px; color:var(--text-secondary); line-height:18px; padding:2px;}
.stamps .approx{color:var(--text-secondary);} /* listed timestamp is conveyed; approx de-emphasis via leading ≈ + "(approx)", not sub-AA hue */


/* ============================ outcome + backfill (deal detail) ============================ */
.outcome{display:flex; flex-direction:column; gap:10px; padding:14px;}
.outcome .btns{display:flex; gap:8px; flex-wrap:wrap;}
.outcome .btns .btn{flex:1; justify-content:center; min-width:96px;}
.outcome .gap-note{font-size:11.5px; color:var(--text-secondary); line-height:16px;} /* Passed-vs-False-alarm copy is conveyed — secondary */
.outcome .backfill{border:1px solid var(--border-subtle); border-radius:var(--radius-md); padding:12px; display:flex; flex-direction:column; gap:8px;}
.outcome .backfill > label{font-size:12px; color:var(--text-secondary);}
.outcome .field{display:flex; align-items:center; gap:8px;}
.outcome .field .k{width:100px; color:var(--text-secondary); font-size:12px;} /* field labels are conveyed — secondary */
.outcome input[type=text]{flex:1; background:var(--bg-base); border:1px solid var(--border-subtle); border-radius:var(--radius-sm); padding:7px 10px; color:var(--text-primary); font-family:var(--font-mono);}
.reason-chips{display:flex; flex-wrap:wrap; gap:6px; padding-top:2px;}
.status-line{font-size:12px; color:var(--text-secondary);}
.status-line b{color:var(--text-primary); font-family:var(--font-mono);}

/* (#2) Delete product — a low-emphasis destructive action at the foot of the detail pane. The button is
   neutral until hover/focus (a confirm() gates the actual delete), so it never competes with the primary
   outcome CTAs above it. NO red as alarm — red here marks the destructive control on intent only. */
.danger-zone{padding:14px; display:flex; flex-direction:column; gap:8px;}
.danger-zone .delete-deal{align-self:flex-start; color:var(--margin-neg); border-color:var(--border-subtle); background:var(--bg-surface);}
.danger-zone .delete-deal:hover,.danger-zone .delete-deal:focus-visible{color:#B42318; border-color:#B42318;}
.danger-zone .delete-deal[disabled]{opacity:.6; cursor:default;}
.danger-zone .delete-msg{font-size:12px; color:var(--text-secondary);}
.danger-zone .gap-note{font-size:11.5px; color:var(--text-secondary); line-height:16px;}


/* ============================ error / 404 (deal detail) ============================ */
.errbox{border:1px solid var(--border-subtle); border-radius:var(--radius-md); background:var(--bg-surface); padding:22px; max-width:520px;}
.errbox h3{margin:0 0 6px; font-size:16px;}
.errbox .ref{font-family:var(--font-mono); font-size:11px; color:var(--text-secondary); margin-top:10px;} /* support ref id is auditable/conveyed — secondary */


/* ============================ settings (§ /settings/filters) ============================ */
.settings{max-width:720px; display:flex; flex-direction:column; gap:18px;}
.sect{border:1px solid var(--border-subtle); border-radius:var(--radius-md); background:var(--bg-surface); padding:18px;}
.sect h2{margin:0 0 4px; font-size:16px;}
.sect .desc{color:var(--text-secondary); font-size:13px; margin:0 0 14px; line-height:19px;}
.threshold-row{display:flex; align-items:center; gap:14px; flex-wrap:wrap;}
/* Brands roster editor — removable chips + an add row. Chips read as tokens, not buttons. */
.brand-chips{list-style:none; margin:0 0 12px; padding:0; display:flex; flex-wrap:wrap; gap:8px;}
.brand-chip{display:inline-flex; align-items:center; gap:6px; padding:5px 6px 5px 11px; font-size:13px;
  border:1px solid var(--border-strong); border-radius:999px; background:var(--bg-base); color:var(--text-primary);}
.brand-chip .x{border:0; background:transparent; color:var(--text-tertiary); cursor:pointer; font-size:13px;
  line-height:1; padding:2px 4px; border-radius:50%;}
.brand-chip .x:hover{color:var(--text-primary); background:var(--bg-surface-2);}
.brand-add{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
.brand-add input{border:1px solid var(--border-strong); border-radius:var(--radius-sm); background:var(--bg-base);
  color:var(--text-primary); font-size:13px; padding:7px 10px; min-width:180px;}
.brands-editor .rules-help{margin-top:10px;}
/* Scheduled-scan repeating interval row. */
.interval-row{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.interval-row .interval-every{font-size:14px; color:var(--text-secondary);}
.interval-off{display:inline-flex; align-items:center; gap:6px; font-size:14px; cursor:pointer;}
.interval-off input{margin:0;}
.interval-row input[type=number]{width:64px; border:1px solid var(--border-strong); border-radius:var(--radius-sm); background:var(--bg-base); color:var(--text-primary); font-size:14px; padding:7px 10px; text-align:right;}
.interval-row select{border:1px solid var(--border-strong); border-radius:var(--radius-sm); background:var(--bg-base); color:var(--text-primary); font-size:14px; padding:7px 10px;}
.interval-row input[disabled], .interval-row select[disabled]{opacity:.5; cursor:default;}
/* Settings small buttons (+ Add rule / + Add / + Add time / Retry) sit taller for a comfortable hit area. */
.settings .btn.sm{padding-top:9px; padding-bottom:9px;}
/* #5 per-brand category scan rules — a head row (brand + mode + remove) over wrapping category checkboxes. */
.cat-rules{display:flex; flex-direction:column; gap:12px;}
.cat-rule{border:1px solid var(--border-subtle); border-radius:var(--radius-sm); padding:10px 12px; background:var(--bg-base);}
.cat-rule-head{display:flex; align-items:center; gap:8px;}
.cat-rule-head select{border:1px solid var(--border-strong); border-radius:var(--radius-sm); background:var(--bg-surface); color:var(--text-primary); font-size:13px; padding:6px 8px;}
.cat-rule-head .x{margin-left:auto; border:0; background:transparent; color:var(--text-tertiary); cursor:pointer; font-size:14px; padding:4px 6px; border-radius:50%;}
.cat-rule-head .x:hover{color:var(--text-primary); background:var(--bg-surface-2);}
.cat-cats{display:flex; flex-wrap:wrap; gap:6px 14px; margin-top:10px;}
.cat-chk{display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--text-secondary); cursor:pointer;}
.cat-chk input{margin:0;}
/* #4 — the Save affordance sat as a small .btn.sm next to the big .num-input box and read
   as bolted-on. Pin #thresholdSave to the num-input's height and give #thresholdStatus
   ("Saved ✓") a clean inline seat (drop its stacked margin in this row); the helper text
   breaks to its own full-width line under the controls. */
.threshold-row #thresholdSave{align-self:stretch; padding:7px 16px; font-size:14px;}
.threshold-row #thresholdStatus{margin-top:0; align-self:center;}
.threshold-row .help{flex:1 1 100%; max-width:340px; margin-top:2px;}
.num-input{display:flex; align-items:baseline; gap:4px; border:1px solid var(--border-strong); border-radius:var(--radius-md); padding:6px 14px; background:var(--bg-base);}
.num-input input{width:62px; border:0; background:transparent; color:var(--text-primary); font-family:var(--font-mono); font-size:30px; font-weight:700; text-align:right;}
.num-input .pc{font-size:20px; color:var(--text-secondary); font-family:var(--font-mono);}
/* (#5 either/or) a disabled cap field reads as inert — dimmed wrapper + not-allowed cursor — so it's
   visually obvious only the selected mode's number is in play. */
.num-input input:disabled{color:var(--text-tertiary); cursor:not-allowed;}
.num-input:has(input:disabled){opacity:.5; border-color:var(--border-subtle); background:var(--bg-surface);}
/* (#5 either/or) per-scan limit: one radio row per mode; selecting one enables only its number field. */
.limit-modes{display:flex; flex-direction:column; gap:12px; margin:6px 0 10px;}
.limit-mode{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.limit-mode > input[type=radio]{margin:0; flex:0 0 auto; cursor:pointer;}
.limit-mode > label{font-size:14px; color:var(--text-primary); cursor:pointer;}
.limit-mode .num-input{padding:4px 10px;}
.limit-mode .num-input input{font-size:20px; width:56px;}
.limit-mode .limit-unit{font-size:13px; color:var(--text-secondary);}
.threshold-row .help{font-size:13px; color:var(--text-secondary); max-width:340px;}
.help{ font-size:12px; line-height:18px; color:var(--text-secondary); } /* conveyed helper text → secondary (AA); login + settings */
.callout{display:flex; gap:10px; padding:10px 12px; border-radius:var(--radius-sm); background:var(--bg-surface-2); border:1px solid var(--border-subtle); font-size:12.5px; color:var(--text-secondary); margin-top:14px; line-height:18px;}
.callout b{color:var(--text-primary);}
.preview{margin-top:10px; font-size:12px; color:var(--text-secondary); line-height:17px;}
.rules{display:flex; flex-direction:column; gap:8px; margin-top:6px;}
.rule-row{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,auto) auto; gap:10px; align-items:center; padding:8px 10px; border:1px solid var(--border-subtle); border-radius:var(--radius-sm); font-size:13px;}
.rule-row select, .rule-row input{min-width:0; max-width:100%; box-sizing:border-box; background:var(--bg-base); border:1px solid var(--border-subtle); border-radius:6px; padding:6px 8px; color:var(--text-primary); font-family:inherit;}
.rule-row .x{background:transparent;border:0;color:var(--text-tertiary);cursor:pointer;font-size:16px; min-width:24px; min-height:24px;}
.rule-row .x:hover{color:var(--text-primary);}
.rules-help{font-size:12px; color:var(--text-secondary); margin-top:8px; line-height:17px;}
.subhead{font-size:13px; margin:18px 0 4px; color:var(--text-secondary);}

/* Telegram link (settings) */
.tg-link{display:flex; align-items:center; gap:14px; flex-wrap:wrap;}
.tg-link .code{font-family:var(--font-mono); font-size:20px; letter-spacing:3px; background:var(--bg-base); border:1px dashed var(--border-strong); border-radius:var(--radius-sm); padding:8px 16px; color:var(--text-primary);}
.tg-state{display:inline-flex;align-items:center;gap:7px;font-size:13px;color:var(--text-secondary);}
.tg-state .dot{color:var(--risk-neutral);} /* INVARIANT 4: neutral gray ● (corrects prototype amber) */
/* #5 — operator-requested GREEN connected dot. SCOPE: a binary TELEGRAM-CONNECTION
   system-status indicator on Settings, far from any deal/risk/margin surface. Dedicated
   success-green hue used for THIS dot ONLY (light #1A7F37; brighter #3FB950 in the dark
   blocks). Does NOT touch risk/margin/status-ramp tokens (§10.1 green-rationing intact). */
.tg-state .dot.ok{color:#1A7F37;}
@media (prefers-color-scheme: dark){ :root:not([data-theme="light"]) .tg-state .dot.ok{color:#3FB950;} }
[data-theme="dark"] .tg-state .dot.ok{color:#3FB950;}
.tg-after{font-size:12px; color:var(--text-secondary); margin-top:10px;}
.tg-note{font-size:13px; color:var(--text-secondary); margin-top:10px; line-height:18px;}

/* FMV overrides (settings) */
.ovr-list{display:flex; flex-direction:column; gap:8px; margin-bottom:12px;}
.ovr-row{display:grid; grid-template-columns:1fr auto auto auto; gap:10px; align-items:center; padding:8px 10px; border:1px solid var(--border-subtle); border-radius:var(--radius-sm); font-size:13px;}
.ovr-row .name{color:var(--text-primary);}
.ovr-row .fmv{text-align:right;}
.ovr-row .fmv .amt{font-family:var(--font-mono); font-variant-numeric:tabular-nums; color:var(--text-primary); font-weight:600;}
.ovr-row .fmv .prov{display:block; font-size:12px; color:var(--text-secondary);} /* INVARIANT 3: never bare */
.ovr-row .x{background:transparent;border:0;color:var(--text-tertiary);cursor:pointer;font-size:16px; min-width:24px; min-height:24px;}
.ovr-row .x:hover{color:var(--text-primary);}
.ovr-form{border:1px solid var(--border-subtle); border-radius:var(--radius-sm); background:var(--bg-surface-2); padding:12px; display:flex; flex-direction:column; gap:10px; margin-bottom:12px;}
.ovr-form label{font-size:12px; color:var(--text-secondary);}
.ovr-form .fields{display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px;}
.ovr-form select, .ovr-form input{background:var(--bg-base); border:1px solid var(--border-subtle); border-radius:6px; padding:7px 8px; color:var(--text-primary); font-family:inherit; font-size:13px;}
.ovr-form input.amt{font-family:var(--font-mono);}
.ovr-form .form-help{font-size:12px; color:var(--text-secondary); line-height:17px;}
.ovr-form .actions{display:flex; gap:8px;}

/* per-control save/error feedback (Invariant 4: failed-save is neutral, not red) */
.save-tick{font-size:12px; color:var(--text-secondary);}             /* "Saved ✓" gray, not green */
.saving{font-size:12px; color:var(--text-secondary);}
.save-err{display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:8px; padding:8px 10px; border-radius:var(--radius-sm); background:var(--bg-surface-2); border:1px solid var(--border-subtle); font-size:12.5px; color:var(--text-primary);}
.inline-status{font-size:12px; color:var(--text-secondary); margin-top:8px;}


/* ============================ account page ============================ */
.kv{display:flex; gap:8px; align-items:baseline; padding:5px 0;}
.kv .label{color:var(--text-secondary); font-size:14px;}
.kv .val{color:var(--text-primary); font-size:14px;}      /* status value = plain neutral text, NO badge/glyph (inv 2,4) */
.kv-help{color:var(--text-secondary); font-size:12px; line-height:17px; margin:2px 0 0;}
.kv-help.aside{color:var(--text-secondary);}              /* erasure retention aside — conveyed text, AA */
.kv-group{border-top:1px solid var(--border-subtle); margin-top:12px; padding-top:12px;}
.sect-actions{display:flex; gap:10px; flex-wrap:wrap; align-items:center; margin-top:14px;}
.link-back{color:var(--accent); font-size:13px;}
.inline-err{margin-top:10px; padding:8px 12px; font-size:12px; color:var(--text-primary); background:var(--bg-surface-2); border-left:3px solid var(--border-strong); border-radius:var(--radius-sm);}
/* spinner (account export-busy) */
.spin{width:14px;height:14px;border-radius:50%; border:2px solid color-mix(in srgb,#fff 45%, transparent); border-top-color:#fff; animation:spin .7s linear infinite; display:inline-block;}
@keyframes spin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion: reduce){ .spin{display:none;} }   /* label-only */


/* ============================ status page (§5.11) ============================ */
.status-grid{display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:18px;}
.stat{border:1px solid var(--border-subtle); border-radius:var(--radius-md); background:var(--bg-surface); padding:16px;}
.stat .k{font-size:12px; color:var(--text-secondary); text-transform:uppercase; letter-spacing:.5px;} /* conveyed tile label → secondary (AA) */
.stat .v{font-size:24px; font-weight:700; margin-top:6px; font-family:var(--font-mono); font-variant-numeric:tabular-nums;}
.stat .v.ok{font-size:18px; font-family:var(--font-ui);}      /* Tile 2: state, not a number */
.stat .v .unit{font-size:14px; color:var(--text-secondary); font-family:var(--font-ui); font-weight:400;}
.stat .v.muted{color:var(--text-tertiary);}                   /* the honest "—" (decorative placeholder) */
.stat .cap{font-size:12px; color:var(--text-secondary); margin-top:6px; line-height:17px;}
.stat .cta{display:inline-block; margin-top:8px; font-size:13px; font-weight:600;}
.dot-glyph{font-family:var(--font-mono); color:var(--text-secondary);} /* NEUTRAL status glyph (NOT amber — D14) */
/* #7 — the ONE sanctioned green-status dot: the binary TELEGRAM-CONNECTION indicator on the
   Status tile (mirrors Settings' .tg-state .dot.ok). Dedicated success-green for THIS dot only
   (light #1A7F37 / brighter #3FB950 in the dark blocks). Does NOT touch the neutral
   source-freshness ramp (--status-* / .dot.fresh/.lag) or any risk/margin token. */
.stat .dot-glyph.ok, .dot-glyph.connected{color:#1A7F37;}
@media (prefers-color-scheme: dark){ :root:not([data-theme="light"]) .stat .dot-glyph.ok, :root:not([data-theme="light"]) .dot-glyph.connected{color:#3FB950;} }
[data-theme="dark"] .stat .dot-glyph.ok, [data-theme="dark"] .dot-glyph.connected{color:#3FB950;}
/* ScrapFly infra-health BAD dot — the sanctioned red on this page (D-37 carve-out, mirrors the
   sanctioned green dot above). Infra up/down only; never a deal/risk/freshness verdict. */
.stat .v .health-bad{font-family:var(--font-mono); color:var(--risk-high); margin-right:2px;}

.sources{border:1px solid var(--border-subtle); border-radius:var(--radius-md); background:var(--bg-surface); overflow:hidden;}
.sources h3{margin:0; padding:12px 16px; font-size:13px; border-bottom:1px solid var(--border-subtle); background:var(--bg-surface-2); display:flex; gap:8px; align-items:baseline;}
.sources h3 .hint{font-weight:400;}
.src-row{display:grid; grid-template-columns:20px 1fr auto; gap:12px; align-items:center; padding:12px 16px; border-bottom:1px solid var(--border-subtle); font-size:14px;}
.src-row:last-child{border-bottom:0;}
.src-row .nm{color:var(--text-primary);}
.src-row .fr{font-size:13px; color:var(--text-secondary); justify-self:end; text-align:right;}
[data-density="compact"] .src-row{padding:8px 16px;}
/* freshness encoding: weight/shape, NEVER hue */
.dot{width:11px;height:11px;border-radius:50%; justify-self:center;}
.dot.fresh{background:var(--status-fresh);}                                   /* solid (legacy) */
.dot.lag{background:transparent; border:2px solid var(--status-lag);}         /* hollow ring (legacy) */
/* Source health dots — infra up/down (green/red carve-out, same tokens as the ScrapFly badge + the
   Telegram-connected dot). ok=green solid, down=red solid, muted=neutral hollow ring (paused / no data). */
.dot.ok{background:#1A7F37;}
.dot.down{background:var(--risk-high);}
.dot.muted{background:transparent; border:2px solid var(--status-lag);}
@media (prefers-color-scheme: dark){ :root:not([data-theme="light"]) .dot.ok{background:#3FB950;} }
[data-theme="dark"] .dot.ok{background:#3FB950;}
.stale-chip,.paused-chip{display:inline-flex; align-items:center; gap:6px; border:1.5px solid var(--status-stale); color:var(--status-stale); border-radius:999px; padding:2px 10px; font-size:12px; font-weight:600; background:var(--bg-surface-2); justify-self:end;}
/* down-chip — the red caption beside a missed-scan source (infra-health carve-out). */
.down-chip{display:inline-flex; align-items:center; gap:6px; border:1.5px solid var(--risk-high); color:var(--risk-high); border-radius:999px; padding:2px 10px; font-size:12px; font-weight:600; background:var(--bg-surface-2); justify-self:end;}
.src-row .we{color:var(--text-secondary); font-weight:400; font-size:13px; justify-self:end; margin-left:8px;}
/* #10 SOURCE TOGGLE — track+knob switch for enabling an available source (POSTs paused_at).
   The checkbox itself is the control (label .switch wraps it for a larger hit target); the
   accent track means enabled. Counsel-gated (not-available) sources render the LOCKED state:
   dimmed + not-allowed, never togglable. This is a system-control accent, not a margin/risk hue. */
.switch{display:inline-flex; align-items:center; cursor:pointer;}
input[type=checkbox].source-switch{
  appearance:none; -webkit-appearance:none; margin:0; flex:0 0 auto;
  width:34px; height:20px; border-radius:999px; position:relative; cursor:pointer;
  background:var(--bg-surface-2); border:1px solid var(--border-strong);
  transition:background .15s, border-color .15s;
}
input[type=checkbox].source-switch::after{
  content:""; position:absolute; top:50%; left:2px; transform:translateY(-50%);
  width:14px; height:14px; border-radius:50%; background:var(--bg-surface);
  box-shadow:0 1px 2px rgba(16,22,30,.28); transition:left .15s;
}
input[type=checkbox].source-switch:checked{background:var(--accent); border-color:var(--accent);}
input[type=checkbox].source-switch:checked::after{left:16px; background:#fff;}
input[type=checkbox].source-switch:focus-visible{outline:2px solid var(--border-strong); outline-offset:2px;}
/* locked = counsel-gated (not available): dimmed, not-allowed, no interaction */
input[type=checkbox].source-switch:disabled,
input[type=checkbox].source-switch.locked,
.switch.locked input[type=checkbox].source-switch{opacity:.45; cursor:not-allowed; pointer-events:none;}
.switch.locked{cursor:not-allowed;}
.src-empty{padding:16px; font-size:14px; color:var(--text-secondary); line-height:21px;}
.src-empty b{color:var(--text-primary); font-weight:600;}
/* encoding-explanation caption (NOT the counsel risk disclaimer) */
.status-disc{margin-top:14px; padding-top:12px; border-top:1px solid var(--border-subtle); font-size:11.5px; color:var(--text-secondary); line-height:17px;} /* D14 encoding caption → secondary (AA) */
/* status loading skeleton bars */
.stat.skel .kbar{height:11px; width:60%;}
.stat.skel .vbar{height:24px; width:45%; margin-top:10px;}
.src-row.skel .dotbar{width:11px;height:11px;border-radius:50%;background:var(--bg-surface-2); animation:skel-pulse 1.4s ease-in-out infinite;}
.src-row.skel .nmbar{height:13px; width:42%;}
.src-row.skel .frbar{height:13px; width:120px; justify-self:end;}


/* ============================ exports page ============================ */
.export-spin{display:inline-block;}
@media (prefers-reduced-motion: no-preference){ .export-spin{animation:export-rot 1.1s linear infinite;} }
@keyframes export-rot{ to{ transform:rotate(360deg);} }
.export-helper{margin-top:8px; font-size:12px; line-height:18px; color:var(--text-secondary);}
/* trust line near the affordance — keeps the file from being handed off as a clearance (Inv 6). */
.export-disc{margin-top:14px; padding:9px 12px; border-radius:var(--radius-sm); border-left:3px solid var(--border-strong); background:var(--bg-surface-2); color:var(--text-secondary); font-size:12px; line-height:18px;}
/* error block — role=alert; sanctioned amber ATTENTION recipe (banner), NOT a risk verdict */
.export-err{margin-top:10px; padding:10px 12px; border-radius:var(--radius-sm); display:flex; align-items:flex-start; gap:10px; flex-wrap:wrap;
  background:color-mix(in srgb, var(--risk-med) 14%, var(--bg-surface)); border:1px solid color-mix(in srgb, var(--risk-med) 40%, var(--border-subtle)); color:var(--text-primary); font-size:13px; line-height:19px;}
.export-err .ico{color:var(--risk-med); font-weight:700;}
.export-err .msg{flex:1; min-width:200px;}
.export-err .ref{font-size:11px; color:var(--text-tertiary); margin-left:auto;}
/* chrome skeleton (X6) — structural, near-instant, no copy */
.export-skel .sk{background:var(--bg-surface-2); border-radius:var(--radius-sm);}
.export-skel .sk-h1{height:30px; width:280px; margin-bottom:10px;}
.export-skel .sk-line{height:13px; width:520px; max-width:90%; margin-bottom:7px;}
.export-skel .sk-line.short{width:340px;}
.export-skel .sk-btn{height:34px; width:190px; margin-top:16px;}
@media (prefers-reduced-motion: no-preference){
  .export-skel .sk{background:linear-gradient(90deg,var(--bg-surface-2) 25%,var(--border-subtle) 50%,var(--bg-surface-2) 75%); background-size:200% 100%; animation:sk-shimmer 1.3s linear infinite;}
}
@keyframes sk-shimmer{ to{ background-position:-200% 0;} }


/* ============================ legal page (≤720 reading column) ============================ */
.legal-body{max-width:720px;}
.legal-prov{font-size:12px; line-height:18px; color:var(--text-secondary); margin:4px 0 0;}
.legal-prov .mono{color:inherit;}
/* sub-tab strip — quiet segmented links; active edge uses --accent (interaction only) */
.subtabs{display:flex; gap:2px; border-bottom:1px solid var(--border-subtle); margin:10px 0 20px;}
.subtabs a{font-size:14px; color:var(--text-secondary); padding:7px 12px; border-radius:var(--radius-sm) var(--radius-sm) 0 0; background:transparent; line-height:20px;}
.subtabs a:hover{background:var(--bg-surface-2); color:var(--text-primary); text-decoration:none;}
.subtabs a[aria-current="page"]{color:var(--text-primary); font-weight:600; box-shadow:inset 0 -2px 0 var(--accent);}
/* L1 placeholder note — NEUTRAL role=note. NOT amber, NOT red, NOT the chrome banner. */
.legal-note{display:flex; gap:10px; background:var(--bg-surface-2); border:1px solid var(--border-subtle); border-left:3px solid var(--border-strong); border-radius:var(--radius-md); padding:12px 14px; margin:0 0 20px; font-size:14px; line-height:21px;}
.legal-note .ico{color:var(--text-secondary); font-family:var(--font-mono); flex:0 0 auto;}
.legal-note .body{color:var(--text-primary);}
.legal-note .body .tail{color:var(--text-secondary);}
/* prose — the one place workbench density relaxes (read, not scanned) */
.prose h2{font-size:16px; line-height:24px; font-weight:600; color:var(--text-primary); margin:24px 0 6px;}
.prose h3{font-size:14px; line-height:20px; font-weight:600; color:var(--text-secondary); margin:16px 0 4px;}
.prose p{font-size:14px; line-height:22px; color:var(--text-primary); margin:0 0 12px; max-width:720px;}
.prose ul{font-size:14px; line-height:22px; color:var(--text-primary); padding-left:20px; margin:0 0 12px;}
.prose ul li{margin-bottom:4px;}
.prose code{font-family:var(--font-mono); font-size:12px; background:var(--bg-surface-2); padding:1px 6px; border-radius:var(--radius-sm); color:var(--text-primary);}
.prose strong{font-weight:600;}
/* Privacy data-rights / erasure block (reuses .comp anatomy) */
.data-rights{border:1px solid var(--border-subtle); border-radius:var(--radius-md); background:var(--bg-surface); padding:16px; margin:20px 0;}
.data-rights h3{margin-top:0;}


/* ============================ login / auth (centered, shell sits behind this) ============================ */
.auth-stage{ display:grid; place-items:center; padding:48px 16px; min-height:100vh; }
.auth-wrap{ width:100%; max-width:400px; }
.auth-brand{ display:flex; align-items:center; justify-content:center; gap:9px; margin-bottom:20px; }
.auth-brand .logo{ width:24px; height:24px; border-radius:6px; background:linear-gradient(135deg,var(--accent),#7C5CFF); display:grid; place-items:center; color:#fff; font-size:13px; font-weight:800; }
.auth-brand .name{ font-weight:700; font-size:15px; letter-spacing:-.2px; color:var(--text-primary); line-height:1.1; }
.auth-brand .name small{ display:block; font-weight:500; font-size:11px; color:var(--text-tertiary); letter-spacing:0; font-family:var(--font-mono); }
/* the card — the one tidy 'luxury chrome' dose: restrained shadow, no gloss */
.auth-card{ background:var(--bg-surface); border:1px solid var(--border-subtle); border-radius:var(--radius-md); box-shadow:var(--card-shadow); padding:28px 28px 24px; }
.auth-card h1{ font-size:25px; line-height:32px; margin:0 0 16px; letter-spacing:-.4px; color:var(--text-primary); }
/* error alert — role=alert. red ONLY here, means "submit failed", NO ▲ glyph (not a risk verdict) */
.auth-alert{ margin:0 0 16px; padding:8px 11px; border-radius:var(--radius-sm); font-size:13px; color:var(--text-primary); background:color-mix(in srgb, var(--risk-high) 8%, var(--bg-surface)); border:1px solid color-mix(in srgb, var(--risk-high) 36%, var(--border-subtle)); }
/* fields */
.field + .field{ margin-top:14px; }
.field > label{ display:block; font-size:13px; font-weight:500; color:var(--text-secondary); margin-bottom:6px; }
.field .opt{ color:var(--text-tertiary); font-weight:400; font-size:12px; margin-left:4px; }
.field input{ width:100%; background:var(--bg-base); border:1px solid var(--border-subtle); border-radius:var(--radius-sm); padding:9px 11px; font-size:14px; color:var(--text-primary); font-family:var(--font-ui); }
.field input::placeholder{ color:var(--text-tertiary); }
.field input:hover{ border-color:var(--border-strong); }
.field input:focus-visible{ outline:2px solid var(--border-strong); outline-offset:1px; border-color:var(--accent); }
.field.code input{ font-family:var(--font-mono); font-variant-numeric:tabular-nums; letter-spacing:2px; }
.field input[aria-invalid="true"]{ border-color:var(--risk-high); } /* field-level invalid mark — empty inputs only, never names which credential */
/* posture line — plain mechanism, text-xs/secondary; describes plumbing not safety */
.auth-posture{ font-size:12px; line-height:18px; color:var(--text-secondary); margin:18px 0 0; padding-top:16px; border-top:1px solid var(--border-subtle); }
/* footer — site-wide counsel disclaimer + legal links */
.auth-foot{ margin-top:20px; font-size:11.5px; line-height:17px; color:var(--text-secondary); text-align:center; }
.auth-foot a{ color:var(--text-secondary); text-decoration:underline; }
.auth-foot .links{ margin-top:6px; }
/* generic server-fault panel — no red, no stack trace */
.fault-card{ background:var(--bg-surface); border:1px dashed var(--border-strong); border-radius:var(--radius-md); padding:28px; text-align:center; color:var(--text-secondary); box-shadow:var(--card-shadow); }
.fault-card h2{ color:var(--text-primary); margin:0 0 6px; font-size:16px; }
.fault-card p{ margin:0 0 16px; }
.fault-card .ref{ display:block; margin-top:14px; font-size:11px; color:var(--text-secondary); }
.fault-card .ref .mono{ color:var(--text-secondary); }


/* ============================ skeletons (loading states) ============================
   CONFLICT (.skel / .skel-bar): the mockups define skeleton primitives with
   different geometry per page (deals-list .skel-bar is an 11px shimmer bar;
   deal-detail .skel-bar is a 12px gradient bar w/ width modifiers + .skel-card;
   settings/account .skel is a pulsing block; status .skel-bar is a 12px pulse).
   These are genuinely page-scoped skeleton shapes, so each is kept, scoped to
   avoid clobbering: deal-detail/status skeletons are namespaced under .skel
   (their container) where they collide, and the generic deals-list .skel-bar
   keeps the bare selector. */

/* deals-list shimmer bar (+ thumb modifier) */
.skel-bar{display:inline-block; height:11px; border-radius:4px; background:var(--bg-surface-2);
  background-image:linear-gradient(90deg,var(--bg-surface-2) 0%,var(--border-subtle) 50%,var(--bg-surface-2) 100%);
  background-size:200% 100%; animation:skel 1.2s ease-in-out infinite;}
.skel-bar.thumb{width:28px;height:28px;border-radius:5px;}
@keyframes skel{0%{background-position:200% 0;}100%{background-position:-200% 0;}}

/* settings/account pulsing skeleton block (.skel) — distinct from .skel-bar */
.skel{background:var(--bg-surface-2); border-radius:6px; display:block; animation:skel-pulse 1.4s ease-in-out infinite;}
.skel.num{height:48px; width:150px; border-radius:var(--radius-md);}
.skel.line{height:14px;}
.skel.row{height:38px; border-radius:var(--radius-sm);}
.skel.code{height:38px; width:200px;}
.skel.short{width:160px;}
@keyframes skel-pulse{0%,100%{opacity:1;}50%{opacity:.55;}}

/* deal-detail skeleton card + width-modified gradient bars (namespaced under .skel container) */
.skel-card{border:1px solid var(--border-subtle); border-radius:var(--radius-md); overflow:hidden; background:var(--bg-surface);}
.skel-card .hd{height:36px; background:var(--bg-surface-2); border-bottom:1px solid var(--border-subtle);}
.skel-card .bd{padding:14px; display:flex; flex-direction:column; gap:10px;}
.skel .skel-bar{height:12px; border-radius:5px; background:linear-gradient(90deg,var(--bg-surface-2) 0%,var(--border-subtle) 50%,var(--bg-surface-2) 100%); background-size:200% 100%; animation:shimmer 1.3s linear infinite;}
.skel .skel-bar.photo{height:150px;}
.skel .skel-bar.w70{width:70%;} .skel .skel-bar.w45{width:45%;} .skel .skel-bar.w90{width:90%;} .skel .skel-bar.w30{width:30%;}
@keyframes shimmer{0%{background-position:200% 0;}100%{background-position:-200% 0;}}

@media (prefers-reduced-motion: reduce){
  .skel-bar,.skel,.src-row.skel .dotbar{animation:none; background-image:none;}
}


/* ============================ responsive (<880px) ============================
   Rail collapses to a bottom tab bar; banner + footer stay full-width. */
@media (max-width:880px){
  .app{grid-template-columns:1fr; padding-bottom:56px;}
  .rail{
    position:fixed; bottom:0; left:0; right:0; top:auto; height:auto;
    flex-direction:row; align-items:stretch; z-index:40;
    border-right:0; border-top:1px solid var(--border-subtle);
  }
  .brand, .rail-foot .legal{display:none;}       /* brand + prose move off the tab bar */
  .nav{flex:1; flex-direction:row; padding:4px; gap:0;}
  .nav .sep{display:none;}
  .nav button, .nav .navbtn{flex-direction:column; gap:3px; font-size:10px; padding:6px 2px; text-align:center; justify-content:center;}
  .nav button .ico, .nav .navbtn .ico{font-size:16px;}
  .nav button .label, .nav .navbtn .label{font-size:10px;}
  .nav button .tag, .nav .navbtn .tag{display:none;}
  .nav button[aria-current="page"], .nav .navbtn[aria-current="page"]{box-shadow:inset 0 2px 0 var(--accent);} /* edge moves to top */
  .rail-foot{margin-top:0; padding:6px; border-top:0; border-left:1px solid var(--border-subtle); display:flex; align-items:center;}
  .rail-foot .controls{margin:0; flex-direction:column; gap:4px;}
  .rail-foot .controls button{padding:4px 6px;}
  /* (#3) single column: Run-a-scan first, then the (collapsible) filter rail, then the table */
  .deals-grid{grid-template-columns:1fr; grid-template-areas:"scan" "filters" "table";}
  .status-grid{grid-template-columns:1fr;}
  .subtabs{flex-wrap:wrap;}
}
@media (max-width:768px){
  /* deals page: scan card on top, filters collapsed beneath it, table full-width below; the table
     scrolls horizontally instead of overflowing the viewport */
  .deals-grid{grid-template-columns:1fr; gap:14px; grid-template-areas:"scan" "filters" "table";}
  .filters{width:100%; border:1px solid var(--border-subtle); border-radius:var(--radius-md); overflow:hidden;}
  #tableCol{min-width:0;}
  .table-wrap{overflow-x:auto; -webkit-overflow-scrolling:touch;}
  .table-wrap > table{min-width:640px;}

  /* (#3) collapsed-by-default filter rail with a tap-to-expand header */
  .filters-toggle{display:flex; align-items:center; gap:8px; width:100%; padding:11px 14px;
    background:var(--bg-surface); border:0; color:var(--text-primary); font:inherit; font-size:14px;
    font-weight:600; cursor:pointer; text-align:left;}
  .filters-toggle .chev{margin-left:auto; transition:transform .15s; color:var(--text-tertiary);}
  .filters.open .filters-toggle .chev{transform:rotate(180deg);}
  .filters-body{display:none; padding:0 14px 12px;}
  .filters.open .filters-body{display:block;}
  /* the first facet heading regains its top margin once it sits under the toggle (not flush to a card top) */
  .filters .filters-body form:first-of-type h3{margin-top:14px;}

  /* (#6) scope dropdowns stack to full width so Brands / Sources / Categories read cleanly and their
     popovers never overflow the viewport */
  .scan-panel-scope{gap:8px;}
  .scan-panel-scope .scope-label{flex:1 0 100%;}
  .scan-panel-scope .ms{flex:1 1 140px;}
  .scan-panel-scope .ms-toggle{width:100%;}
  .scan-panel-scope .ms-panel{left:0; right:0; min-width:0; max-width:calc(100vw - 36px);}
}
@media (max-width:520px){
  .ovr-form .fields{grid-template-columns:1fr;}
}
@media (max-width:480px){
  .auth-stage{ padding:28px 0; }
  .auth-wrap{ padding:0 16px; }
}
