/* "The Paper Ledger" (DESIGN.md rev 2, supersedes Direction B — "Recovery Ops"
   entirely). Light, precise, quantified: every surface reads like a beautifully set
   financial statement. Committed to a single light identity — no dark-mode toggle —
   the one place dark appears is the optional --ink "statement block" a page can use
   once for a money hero figure (see .statement-block below), not a full theme.
   Variable NAMES kept from the prior system (--paper/--card/--ink-soft/--line) so
   every existing page that already references them repaints for free; only the VALUES
   changed, plus the new tokens DESIGN.md names explicitly (--surface-sunken,
   --accent-soft, --positive, --warn). See DECISIONS.md for why names were kept. */
:root {
  --accent: #2b6cb0;       /* ledger blue — text, links, CTAs, AA on paper */
  --accent-soft: #a9c8e8;  /* chart fills / badges / backgrounds only — never text */
  /* 2026-07 accessibility pass: --positive and --warn as originally set (#2f7d4f,
     #b7791f) failed WCAG AA (4.5:1) as TEXT on their own tinted-pill backgrounds
     (.pause-pill/.scn-badge/.scn-list-pill/.scn-compare-label etc — rgba(...)/0.1-0.14
     composited over whatever sits underneath, which in .scn-compare's case is --line,
     not --card — worth calling out since that's the darker, harder-to-clear context
     that set the real floor for both colors), and --warn additionally failed even on
     plain --paper/--card. Both darkened just enough to clear 4.5:1 across every real
     pairing this codebase uses them in — measured with a small script (WCAG relative
     luminance formula, alpha-composited against each ACTUAL underlying background, not
     assumed), not eyeballed; see DECISIONS.md. The tint backgrounds themselves
     (hardcoded rgba(47,125,79,...) / rgba(183,121,31,...) in the rules below) are
     untouched, so the pill/label shapes read the same, just with more legible text. */
  --positive: #256428;     /* recovered/actuals deltas only */
  --warn: #7a4f10;         /* alerts/caps only */
  --paper: #faf9f6;        /* warm paper, not pure white */
  --card: #ffffff;         /* surface: cards/panels */
  --surface-sunken: #f2f1ec; /* input wells, table stripes */
  --ink: #1b1d21;          /* never pure black */
  /* 2026-07 accessibility pass: measured 4.48:1 on --line-soft (.phone-input-prefix's
     own background) — under the 4.5:1 floor by a hair. Nudged just enough to clear it
     there; every other pairing this token is already used in only gains margin from a
     darkening, so this one change is safe everywhere else it appears. */
  --ink-soft: #5f656e;     /* labels, methodology prose */
  --line: #e5e3dc;         /* hairline rules — 1px, never heavier */
  --line-soft: #eeece5;
  --shadow-card: 0 1px 3px rgba(27, 29, 33, 0.06); /* the one whisper level allowed */
  --radius-card: 8px;

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", "IBM Plex Mono", ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
}

/* Self-hosted, not a Google Fonts @import — the deals page (dealsPageHtml.ts) is the
   one page in this system DESIGN.md explicitly holds to a Lighthouse 95+ mobile-
   cellular bar ("speed is the design there"), and a render-blocking cross-origin
   @import was a real, measurable regression against that (see DECISIONS.md). Both are
   real variable-font files (one file each covers the full 400-700 / 400-600 weight
   range Google itself serves for these exact weight requests — confirmed by fetching
   the CSS2 endpoint directly and finding every requested static weight for a family
   pointed at the identical URL, not four separate files), fetched from
   fonts.gstatic.com and vendored into public/fonts/ once rather than fetched from
   Google on every page load. Licensed under the SIL Open Font License — both are free
   to redistribute this way.
   preload here (not load-time discovery via the stylesheet alone) so the browser
   starts fetching before it finishes parsing the rest of this file; add matching
   <link rel="preload"> tags in a page's own <head> for the fonts that page actually
   renders above the fold if this ever needs to go further. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/inter-var.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/fonts/jetbrains-mono-var.woff2") format("woff2");
}

* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
.wrap { max-width: 640px; margin: 0 auto; padding: 88px 24px 64px; }

/* Eyebrow labels — mono, uppercase, wide tracking. Used for the site kicker and any
   section label ("METHODOLOGY", "ESTIMATED"). */
.kicker {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 16px;
}
h1 {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 32px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0 0 18px;
}
h2 {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 22px;
  margin: 36px 0 10px;
}
p.lede { font-size: 16.5px; color: var(--ink-soft); line-height: 1.55; margin: 0 0 40px; }
p, li { font-size: 15px; color: var(--ink-soft); line-height: 1.6; }

/* Every number in the product runs through this — tabular mono is the brand signature,
   not a special case. */
.num, .money { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-card); box-shadow: var(--shadow-card); }

/* The optional single --ink statement block (DESIGN.md: "money hero figures may sit
   on an --ink panel for emphasis — optional, one per page maximum"). The only place
   dark appears in this system. */
.statement-block {
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--radius-card);
  padding: 28px 30px;
}
.statement-block .num, .statement-block .money { color: var(--paper); }
.statement-block .kicker, .statement-block p { color: rgba(250, 249, 246, 0.6); }

.facts {
  border-top: 1px solid var(--line);
  padding-top: 24px;
  margin-bottom: 40px;
}
.facts div { padding: 8px 0; font-size: 14.5px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.facts strong { color: var(--ink); font-weight: 600; }
footer { border-top: 1px solid var(--line); padding-top: 20px; margin-top: 40px; font-size: 13.5px; color: var(--ink-soft); }
a { color: var(--accent); }
footer a { margin-right: 16px; }
.updated { font-size: 13px; color: var(--ink-soft); margin: 0 0 40px; }

/* MethodologyNote — DESIGN.md: "accompanies EVERY computed number — non-negotiable,
   the credibility signature." One shared class so every page renders it identically. */
.methodology-note {
  font-size: 12.5px;
  color: var(--ink-soft);
  line-height: 1.6;
  border-left: 2px solid var(--line);
  padding: 2px 0 2px 12px;
  margin: 10px 0 0;
}

/* EstimateBadge — "ESTIMATED — INDUSTRY BENCHMARKS" (sunken/dim) vs
   "FROM YOUR SQUARE DATA" (accent-soft). */
.estimate-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 4px;
  vertical-align: middle;
}
.estimate-badge.benchmark { background: var(--surface-sunken); color: var(--ink-soft); }
.estimate-badge.own-data { background: var(--accent-soft); color: var(--ink); }

/* Connect-flow stepper — "3-dot stepper under the logo (Estimate -> Connect ->
   Your report)." Square's OAuth page is a real same-tab redirect (never a popup, so
   never mounted while that page is showing) — .done/.active/.upcoming are set from the
   server side, per page, not animated between steps client-side. */
.stepper { display: flex; align-items: center; gap: 8px; margin: 0 0 28px; }
.stepper-step { display: flex; align-items: center; gap: 8px; }
.stepper-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--line); flex-shrink: 0;
}
.stepper-step.done .stepper-dot { background: var(--positive); }
.stepper-step.active .stepper-dot { background: var(--accent); }
.stepper-label { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-soft); }
.stepper-step.active .stepper-label { color: var(--ink); font-weight: 600; }
.stepper-rule { width: 20px; height: 1px; background: var(--line); }

/* CTA — accent fill, white mono-uppercase label; secondary = 1px accent outline. Only
   one primary per viewport (DESIGN.md). */
.btn {
  display: inline-block;
  background: var(--accent);
  color: #ffffff;
  border: none;
  padding: 13px 26px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  border-radius: 6px;
  cursor: pointer;
  text-decoration: none;
}
.btn:focus-visible, a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.btn-secondary {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent);
}

@media (prefers-reduced-motion: no-preference) {
  .num[data-count-up] { transition: opacity 150ms ease-out; }
}

/* App shell — DESIGN.md's dashboard IA: five destinations (Today/Open slots/
   Activity/Reports/Settings), a desktop left rail, a mobile bottom tab bar (never a
   hamburger), and a persistently-visible pause-status pill in the top bar of every
   app page. */
.app-topbar {
  height: 56px; display: flex; align-items: center; gap: 16px;
  padding: 0 20px; border-bottom: 1px solid var(--line); background: var(--paper);
  position: sticky; top: 0; z-index: 30;
}
.app-topbar-logo { font-family: var(--font-mono); font-weight: 600; font-size: 13px; color: var(--ink); text-decoration: none; }
.app-topbar-business { font-size: 13px; color: var(--ink-soft); margin-left: -4px; }
.pause-pill {
  margin-left: auto; display: flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 999px; border: none; cursor: pointer;
  background: var(--surface-sunken); color: var(--ink-soft); text-decoration: none;
}
.pause-pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-soft); }
.pause-pill.active { background: rgba(47, 125, 79, 0.1); color: var(--positive); }
.pause-pill.active .dot { background: var(--positive); }
.pause-pill.paused { background: rgba(183, 121, 31, 0.12); color: var(--warn); }
.pause-pill.paused .dot { background: var(--warn); }
.app-topbar-links { display: flex; align-items: center; gap: 14px; margin-left: 14px; font-size: 12.5px; }
.app-topbar-links a { color: var(--ink-soft); text-decoration: none; }
.app-topbar-links a:hover { color: var(--ink); text-decoration: underline; }

.app-body { display: flex; min-height: calc(100vh - 56px); }
.app-rail {
  width: 220px; flex-shrink: 0; border-right: 1px solid var(--line);
  padding: 20px 12px; display: flex; flex-direction: column; gap: 2px;
}
.app-rail-link {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 6px;
  color: var(--ink-soft); text-decoration: none; font-size: 14px;
}
.app-rail-link svg { width: 18px; height: 18px; flex-shrink: 0; }
.app-rail-link.active { background: var(--accent-soft); color: var(--ink); font-weight: 500; }
.app-main { flex: 1; min-width: 0; padding: 32px 36px 80px; }

.app-tabbar {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  background: var(--paper); border-top: 1px solid var(--line);
  padding: 4px 4px calc(4px + env(safe-area-inset-bottom));
}
.app-tabbar-inner { display: flex; }
.app-tabbar-link {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 8px 4px; min-height: 44px; color: var(--ink-soft); text-decoration: none; font-size: 10.5px;
}
.app-tabbar-link svg { width: 20px; height: 20px; }
.app-tabbar-link.active { color: var(--accent); }

@media (max-width: 900px) {
  .app-rail { display: none; }
  .app-tabbar { display: block; }
  .app-main { padding: 24px 20px 88px; }
  .app-topbar-business { display: none; }
}

/* Sub-tabs — a lightweight in-page switch between two related views on the SAME
   destination (e.g. Open Slots' Live/Blocked split, 2026-07-20 founder ask: "blocked
   cancellations" used to be its own page reachable only via a plain text link, with
   no way back into the five-destination nav other than the shell's own rail/tabbar —
   easy to miss, and it read as leaving the app rather than switching a view within it).
   Distinct from .app-tabbar (the fixed bottom nav bar across the five real
   destinations) and .admin-nav (the ops-tool top nav) — this is scoped to whatever
   page renders it, plain underline style, no icons. */
.sub-tabs { display: flex; gap: 4px; margin: 0 0 20px; border-bottom: 1px solid var(--line); }
.sub-tab {
  padding: 9px 4px; margin-right: 20px; margin-bottom: -1px;
  font-size: 13.5px; color: var(--ink-soft); text-decoration: none;
  border-bottom: 2px solid transparent;
}
.sub-tab:hover { color: var(--ink); }
.sub-tab.active { color: var(--ink); font-weight: 600; border-bottom-color: var(--accent); }

/* Shared StatBlock/LedgerTable-adjacent grid — the "cell of mono numbers" pattern
   repeated (previously duplicated per-file) across the calculator, the report, and
   every dashboard destination. */
.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius-card); overflow: hidden; margin-bottom: 32px; }
.stat-cell { background: var(--card); padding: 20px 22px; }
.stat-cell-label { font-size: 11.5px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--ink-soft); margin: 0 0 10px; }
.stat-cell-value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 28px; font-weight: 500; letter-spacing: -0.02em; margin: 0; color: var(--ink); }

.dash-section { margin-top: 40px; }
.dash-section:first-child { margin-top: 0; }
.dash-section h2 { font-size: 16px; font-weight: 600; margin: 0 0 16px; }
.dash-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: 18px 22px; }
.dash-empty { font-size: 13.5px; color: var(--ink-soft); padding: 16px 0; }

table.dash-table { width: 100%; border-collapse: collapse; }
table.dash-table th { text-align: left; font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-soft); padding: 8px 10px; border-bottom: 1px solid var(--line); }
table.dash-table td { padding: 10px; border-bottom: 1px solid var(--line-soft); font-size: 13.5px; }
table.dash-table form { margin: 0; }
/* Phone-width safety net (2026-07 mobile sweep): a multi-column dash-table (blocked
   cancellations' 5 columns especially) can exceed a ~390px viewport and drag the whole
   page into horizontal scroll, cutting off its rightmost action button. display:block
   lets the TABLE scroll inside itself instead — the page never scrolls sideways. */
@media (max-width: 767px) {
  table.dash-table { display: block; overflow-x: auto; }
}

.btn-quiet { background: transparent; color: var(--ink); border: 1px solid var(--line); text-transform: none; letter-spacing: normal; font-family: var(--font-sans); font-weight: 500; padding: 8px 14px; }
.btn-danger { background: transparent; color: #b3412c; border: 1px solid #b3412c; text-transform: none; letter-spacing: normal; font-family: var(--font-sans); font-weight: 500; }

/* Dashboard form controls — <select> had no styling at all before (2026-07 founder
   feedback: "doesn't fit the theme"), falling back to the raw browser default
   (system font, square corners, no border-radius) next to every other control here
   that's deliberately themed. Matches .dash-card's border/radius language and the
   body's own font stack, same as every other input in this system.
   2026-07 follow-up founder feedback: even with the above, the arrow itself was still
   the bare OS-native glyph — every other icon-shaped thing in this system (checkbox
   check, stepper dots) is hand-drawn to match, so the native arrow read as an
   unfinished corner next to it. appearance:none removes it in favor of a matching
   inline SVG chevron (stroke color is --ink-soft's hex directly, not var(--ink-soft) —
   custom properties don't resolve inside a data-URI string). */
select {
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--font-sans);
  font-size: 16px; /* 16px minimum — selects trigger the same iOS focus-zoom as text inputs below 16px */
  color: var(--ink);
  background: var(--card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%23666c75' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 12px center;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 9px 30px 9px 10px;
  cursor: pointer;
}
select:disabled { opacity: 0.6; cursor: not-allowed; }
/* :focus-visible for select is already covered by the shared .btn/a/button/input/
   select rule above — no separate rule needed here. */

/* Checkboxes — the eligible-services list (settingsHtml.ts) had none at all (2026-07
   founder feedback: "isn't consistent with the rest of the theming"), same gap
   <select> just got fixed for. .checkbox-row gives each label the same hover/padding
   language as .app-rail-link instead of raw inline flex/gap styling.
   2026-07 follow-up founder feedback: accent-color alone only re-tints the browser's
   own checkbox shape (square corners, no border, differs by OS/browser) — every other
   control on the page (select, .btn, .card) is a fully hand-drawn shape with a --line
   border and a matched radius, so a native widget next to them read as lower-quality
   even re-tinted. appearance:none + a custom border/radius/checked-state SVG check
   (again a literal hex, not var(), for the data-URI reason above) makes the box itself
   match the same visual language as everything around it, not just its fill color. */
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--card);
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 120ms ease-out, border-color 120ms ease-out;
}
input[type="checkbox"]:checked {
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='8' viewBox='0 0 10 8' fill='none'%3E%3Cpath d='M1 4L3.7 6.7L9 1' stroke='white' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
  border-color: var(--accent);
}
input[type="checkbox"]:disabled { opacity: 0.5; cursor: not-allowed; }
.checkbox-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  padding: 8px 10px;
  margin: 0 -10px;
  border-radius: 6px;
  cursor: pointer;
}
.checkbox-row:hover {
  background: var(--surface-sunken);
}

/* Toast — a transient success confirmation (2026-07 founder feedback: "there should
   be a toast confirmation of success" on settings save). Reuses the same
   dot+--positive language .pause-pill.active already established on this exact page
   for "things are working," rather than inventing a new success color, and stays a
   light card (not the --ink statement-block treatment reserved for money hero
   figures — DESIGN.md: "one per page maximum," and a toast isn't that). */
.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--card);
  color: var(--positive);
  border: 1px solid rgba(47, 125, 79, 0.3);
  font-size: 14px;
  font-weight: 500;
  padding: 12px 18px;
  border-radius: 8px;
  box-shadow: var(--shadow-card);
  z-index: 50;
  opacity: 1;
  transition: opacity 250ms ease-out, transform 250ms ease-out;
}
.toast::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--positive); flex-shrink: 0; }
.toast.toast-hidden { opacity: 0; transform: translateX(-50%) translateY(6px); pointer-events: none; }

/* Confirm modal — replaces the browser's own native confirm() for actions that warrant
   a pause (2026-07-20 founder feedback: "the alert dialogue doesn't follow the app
   styling pattern"). Reuses the same card/line/shadow tokens every other surface in
   this design system already does, rather than the OS's own dialog chrome. Plain
   overlay + card, no animation, no focus-trap library — [hidden] toggled by a few
   lines of inline JS at each call site (this codebase's no-bundler convention). */
.confirm-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 20, 20, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}
.confirm-overlay[hidden] { display: none; }
.confirm-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 24px;
  max-width: 420px;
  width: 100%;
}
.confirm-card h3 { margin: 0 0 10px; font-size: 17px; font-weight: 600; color: var(--ink); }
.confirm-card p { margin: 0; font-size: 14px; color: var(--ink-soft); line-height: 1.55; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }

/* Scenario Replay — client-facing "here's what actually happens" walkthroughs
   (src/demo/scenarioReplayHtml.ts). Sales-forward treatment by design (2026-07-16
   founder feedback: the quieter first draft read as less compelling than a punchier,
   more visual one) — reuses --statement-block for the big number rather than
   duplicating it, adds compare/beats/sms-bubble/pill/cta-block as new shared pieces. */
.scn-pill {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 12px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  /* 2026-07 accessibility pass: #1c5a9e on --accent-soft measured 4.03:1, under the
     4.5:1 AA floor — darkened to clear it (also applied to .scn-btn-primary below,
     which reuses this exact blue, for one consistent hue rather than two blues on the
     same page). */
  color: #164a83; background: var(--accent-soft); padding: 7px 14px; border-radius: 999px; margin: 0 0 22px;
}
.scn-pill::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: #164a83; }
.scn-list-pill {
  display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase; padding: 4px 10px; border-radius: 999px;
}
.scn-list-pill.happy { color: var(--positive); background: rgba(47, 125, 79, 0.12); }
.scn-list-pill.edge { color: var(--warn); background: rgba(183, 121, 31, 0.14); }

.scn-hero h1 { font-weight: 700; font-size: 38px; line-height: 1.1; letter-spacing: -0.02em; text-wrap: balance; margin: 0 0 14px; }
.scn-hero .hero-sub { font-size: 17px; color: var(--ink-soft); font-weight: 500; margin: 0 0 6px; max-width: 46ch; }
.scn-context { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink-soft); margin: 0 0 32px; }

/* Extends .statement-block for a big count-up headline number + a mini stat list
   beside it, instead of the single quiet money figure that class was built for. */
.statement-block.scn-statement { display: flex; align-items: flex-end; gap: 40px; flex-wrap: wrap; }
.scn-statement-label { font-family: var(--font-mono); font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(250,249,246,0.55); margin: 0 0 6px; }
.scn-statement-value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 72px; font-weight: 700; line-height: 1; letter-spacing: -0.03em; color: var(--paper); margin: 0; }
.scn-statement-value .unit { font-size: 26px; margin-left: 6px; }
.scn-mini-list { display: flex; flex-direction: column; gap: 12px; padding-bottom: 6px; }
.scn-mini { display: flex; align-items: baseline; gap: 10px; }
.scn-mini-value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 20px; font-weight: 700; color: var(--paper); }
.scn-mini-label { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: rgba(250,249,246,0.55); }

.scn-compare { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; background: var(--line); border-radius: 12px; overflow: hidden; margin: 20px 0 44px; }
.scn-compare-col { padding: 20px 22px; }
.scn-compare-col.without { background: rgba(183, 121, 31, 0.1); }
.scn-compare-col.with { background: rgba(47, 125, 79, 0.1); }
.scn-compare-label { font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; margin: 0 0 10px; }
.scn-compare-col.without .scn-compare-label { color: var(--warn); }
.scn-compare-col.with .scn-compare-label { color: var(--positive); }
.scn-compare-text { font-size: 15px; font-weight: 500; color: var(--ink); margin: 0; line-height: 1.5; }

.scn-beats { margin-bottom: 44px; }
.scn-beat { display: flex; gap: 18px; align-items: flex-start; padding: 16px 0; border-bottom: 1px solid var(--line); }
.scn-beat:last-child { border-bottom: none; }
.scn-beat-time { font-family: var(--font-mono); font-size: 12px; color: var(--ink-soft); font-variant-numeric: tabular-nums; width: 90px; flex-shrink: 0; padding-top: 3px; }
.scn-beat-body { flex: 1; }
.scn-beat-title { font-size: 16.5px; font-weight: 600; margin: 0; line-height: 1.4; }
.scn-badge { display: inline-block; font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; padding: 3px 9px; border-radius: 999px; margin-left: 8px; vertical-align: middle; position: relative; top: -1px; }
.scn-badge.win { background: rgba(47, 125, 79, 0.12); color: var(--positive); }
.scn-badge.blocked { background: rgba(183, 121, 31, 0.14); color: var(--warn); }

.scn-sms-row { margin: 10px 0 2px; }
.scn-sms-bubble { display: inline-block; max-width: 380px; padding: 11px 16px; border-radius: 16px; font-size: 14.5px; line-height: 1.4; }
.scn-sms-row.received .scn-sms-bubble { background: var(--surface-sunken); color: var(--ink); border-bottom-left-radius: 4px; }
.scn-sms-row.sent { text-align: right; }
.scn-sms-row.sent .scn-sms-bubble { background: var(--accent); color: #fff; border-bottom-right-radius: 4px; }
.scn-sms-from { font-family: var(--font-mono); font-size: 10.5px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 4px; }
.scn-sms-row.sent .scn-sms-from { text-align: right; }

.scn-cta { background: var(--accent); border-radius: 14px; padding: 32px 30px; margin-top: 8px; }
.scn-cta h3 { color: #fff; font-size: 22px; font-weight: 700; margin: 0 0 8px; letter-spacing: -0.01em; }
/* 2026-07 accessibility pass: white@0.85 on --accent measured 4.41:1, just under the
   4.5:1 AA floor — raised to 0.92 to clear it. */
.scn-cta p { color: rgba(255,255,255,0.92); font-size: 14.5px; margin: 0 0 20px; max-width: 44ch; }
.scn-cta-buttons { display: flex; gap: 12px; flex-wrap: wrap; }
.scn-btn-primary { display: inline-block; background: #fff; color: #164a83; border: none; padding: 13px 24px; font-family: var(--font-mono); font-size: 12.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; border-radius: 8px; cursor: pointer; text-decoration: none; }
.scn-btn-ghost { display: inline-block; background: transparent; color: #fff; border: 1.5px solid rgba(255,255,255,0.5); padding: 12px 22px; font-family: var(--font-mono); font-size: 12.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; border-radius: 8px; cursor: pointer; text-decoration: none; }

.scn-index-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 40px; }
.scn-index-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-card); box-shadow: var(--shadow-card);
  padding: 22px 24px; text-decoration: none; color: inherit; display: block;
}
.scn-index-card:hover { border-color: var(--accent-soft); }
.scn-index-card h3 { font-size: 17px; font-weight: 600; margin: 10px 0 8px; color: var(--ink); }
.scn-index-card p { font-size: 13.5px; color: var(--ink-soft); margin: 0; }

@media (max-width: 700px) {
  .scn-hero h1 { font-size: 28px; }
  .scn-statement-value { font-size: 48px; }
  .statement-block.scn-statement { flex-direction: column; align-items: flex-start; gap: 20px; }
  .scn-compare { grid-template-columns: 1fr; }
  .scn-beat { flex-direction: column; gap: 6px; }
  .scn-beat-time { width: auto; }
  .scn-index-grid { grid-template-columns: 1fr; }
}

/* Public listing card + priority-list signup form — the public deals page's own
   components (src/publicDeals/dealsPageHtml.ts), moved here from that page's local
   <style> block so src/publicDeals/webClaimPageHtml.ts can reuse them too (2026-07-16:
   an already-claimed link now offers whatever else is live right now, or this
   signup form as a fallback, instead of a dead end). */
.listing {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 18px 20px;
  margin-bottom: 12px;
}
.listing-when {
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 4px;
}
.listing-service {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 19px;
  margin: 0 0 4px;
}
.listing-scarcity {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--accent-soft);
  border-radius: 4px;
  padding: 3px 8px;
  margin: 0;
}
.listing-price { text-align: right; white-space: nowrap; }
.listing-percent-off {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.listing-dollar { font-family: var(--font-mono); font-size: 15px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.listing-dollar-was { text-decoration: line-through; margin-right: 4px; }

.empty-state {
  border: 1px dashed var(--line);
  border-radius: 10px;
  padding: 32px 24px;
  text-align: center;
}
.empty-state p.lede { margin-bottom: 24px; }
.priority-form { display: flex; flex-direction: column; gap: 10px; max-width: 340px; margin: 0 auto; }
/* 16px minimum on every customer-facing text input — iOS Safari auto-zooms the whole
   page when focusing an input below 16px, and these forms are exactly what a customer
   reaches from an SMS link on their phone. */
.priority-form input {
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 16px;
  background: var(--surface-sunken);
  color: var(--ink);
}

/* Shared NANP phone input (src/reports/phoneInputHtml.ts) — a fixed "+1" chip plus a
   live-formatted national-number field, used on every phone-collecting form (priority
   list, web claim, admin simulate). Higher specificity than .priority-form input /
   .claim-form input on purpose, so the input inside this group renders borderless —
   the wrapper itself carries the single visible border/background instead. */
.phone-input-group {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-sunken);
  overflow: hidden;
}
.phone-input-prefix {
  display: flex;
  align-items: center;
  padding: 0 10px;
  font-size: 15px;
  color: var(--ink-soft);
  background: var(--line-soft);
  border-right: 1px solid var(--line);
}
.phone-input-group input.phone-input {
  border: none;
  border-radius: 0;
  background: transparent;
  flex: 1;
  min-width: 0;
  padding: 11px 14px;
  font-size: 16px; /* 16px minimum — see .priority-form input's comment (iOS focus zoom) */
  color: var(--ink);
}
.phone-input-group input.phone-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Global page-navigation progress bar — 2026-07 founder feedback: "no loading
   indication when something is happening on the site... for things like auth or
   global events." The existing "Working…" button-disable pattern (adminShell.ts,
   dashboard/shell.ts, landingPageHtml.ts's NAV_SCRIPT — each has its own inline copy,
   no bundler to share one module across them) only ever covered form submits; a plain
   <a href> navigation — the OAuth connect flow chief among them — gave zero feedback
   while the browser was busy. Deliberately a thin top bar, not a full-page spinner or
   overlay: the browser is about to navigate away regardless, so this only needs to
   bridge the visual gap until the next page paints, never block interaction with the
   current one. Each JS copy pushes .active then lets the browser's own navigation
   interrupt the transition mid-flight — there is no explicit "done" call by design. */
#nav-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 0%;
  background: var(--accent); z-index: 9999; opacity: 0;
  transition: opacity 200ms ease-out 200ms;
  pointer-events: none;
}
#nav-progress.active { opacity: 1; width: 70%; transition: width 8s cubic-bezier(0.1, 0.6, 0.2, 1); }
