/* Shared design system — amit.marketing tool network
   IDENTITY B "Studio Instrument" (PORTFOLIO-MASTER-STRATEGY §3).
   Reference standard: PriceWatch. Tools are instruments, not essays:
   light ground, one saturated functional accent, semantic green/red reserved
   for RESULTS only, tabular figures on every number a user reads or copies,
   and zero decorative motion.
   Every text/background pair below was validated at >= 4.5:1 (WCAG AA). */

:root {
  --bg: #f4f6f9;
  --bg-tint: #eaeffc;
  --surface: #ffffff;
  --surface-2: #f1f4f8;
  --ink: #0a1020;          /* 18.96:1 on surface */
  --ink-2: #37425a;        /* 10.05:1 on surface */
  --muted: #5a6479;        /*  5.94:1 on surface */
  --line: #dfe4ec;
  --line-2: #c3cbd9;
  --accent: #1a46c9;       /*  7.60:1 on surface; #fff on accent = 7.60:1 */
  --accent-2: #14379e;
  --accent-3: #1a46c9;
  --accent-soft: #eaeffc;
  --accent-line: #c2d0f4;
  /* semantic — RESULTS ONLY, never chrome */
  --pos: #05704e;          /*  6.12:1 on surface */
  --neg: #b3261e;          /*  6.54:1 on surface */
  --warn: #8a4b08;         /*  6.79:1 on surface */
  --ok: #05704e;
  /* AAA+++ 2026-07-30: 14-18px pill radii plus a four-step shadow ramp was the
     single loudest "free template" tell on the tools. 8-14px with ONE lift
     shadow reads engineered. border-radius affects no layout, so CLS stays 0. */
  --radius: 10px;
  --radius-lg: 14px;
  --radius-sm: 8px;
  --shadow-xs: none;
  --shadow-sm: none;
  --shadow: 0 1px 0 rgba(10, 16, 32, .04), 0 16px 36px -24px rgba(10, 16, 32, .22);
  --shadow-lg: 0 18px 44px -22px rgba(10, 16, 32, .24);   /* popovers/menus only */
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);

  /* ---- AAA+++ additions (additive; no existing name renamed) ---- */
  --t-fast: 140ms;
  --t-med: 220ms;
  --ease-out: cubic-bezier(0.25, 1, 0.4, 1);
  --ink-num: var(--ink);        /* result numerals; lets sleep/site-local retint */
  --surface-sunken: #eef1f6;    /* input wells — replaces ad-hoc --surface-2 misuse */
  --fs-mono: .8125rem;
  --track-label: .11em;
  --max: 1320px;
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  /* IBM Plex Mono led this stack but no font file was ever fetched, so the mono
     voice silently fell through to whatever the OS picked. System-first makes
     the rendering deterministic and keeps the zero-new-requests constraint. */
  --mono: ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Code", Consolas, Menlo, monospace;
  --netbar-bg: var(--ink);
  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #070b14;
  --bg-tint: #16203a;
  --surface: #101725;
  --surface-2: #161e2e;
  --ink: #eef2f8;          /* 15.96:1 on surface */
  --ink-2: #b9c3d3;        /* 10.08:1 on surface */
  --muted: #8e9aae;        /*  6.30:1 on surface */
  --line: #232d42;
  --line-2: #33405c;
  --accent: #8faaff;       /*  7.99:1 on surface; ink on accent = 8.45:1 */
  --accent-2: #b0c3ff;
  --accent-3: #8faaff;
  --accent-soft: #16203a;
  --accent-line: #2e3d63;
  --pos: #4ade9e;
  --neg: #ff8a80;
  --warn: #fbbf60;
  --ok: #4ade9e;
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, .5), 0 6px 14px -10px rgba(0, 0, 0, .7);
  --shadow: 0 10px 24px -16px rgba(0, 0, 0, .8);
  --shadow-lg: 0 22px 56px -28px rgba(0, 0, 0, .9);
  --netbar-bg: #05070f;
  --surface-sunken: #0b111d;
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.6;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg { display: block; max-width: 100%; }
a { color: var(--accent); }
button { font: inherit; color: inherit; cursor: pointer; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }

.wrap { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 22px; }
.narrow { max-width: 780px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- network switcher (top of every site) ---------- */
.netbar {
  background: var(--ink);
  color: #fff;
  font-size: .8rem;
  position: relative;
  z-index: 60;
}
:root[data-theme="dark"] .netbar { background: #05070f; border-bottom: 1px solid var(--line); }
.netbar-in { display: flex; align-items: center; gap: 14px; height: 40px; overflow: hidden; }
.netbar-label {
  color: rgba(255,255,255,.5); font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; font-size: .64rem; white-space: nowrap; flex: none;
}
.netbar-links { display: flex; gap: 2px; min-width: 0; overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; }
.netbar-links::-webkit-scrollbar { display: none; }
.netbar-links a {
  color: rgba(255,255,255,.72); text-decoration: none; white-space: nowrap;
  padding: 5px 10px; border-radius: 7px; font-weight: 500; transition: border-color .12s;
}
.netbar-links a:hover { color: #fff; background: rgba(255,255,255,.12); }
.netbar-links a[aria-current="page"] { color: #fff; background: rgba(255,255,255,.16); font-weight: 650; }
@media (max-width: 640px) { .netbar-label { display: none; } }

/* ---------- header ---------- */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: saturate(180%) blur(16px); -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 1px solid var(--line);
}
.head-in { display: flex; align-items: center; justify-content: space-between; gap: 14px; height: 66px; }
.brand { display: flex; align-items: center; gap: 11px; text-decoration: none; color: var(--ink); font-weight: 700; letter-spacing: -.03em; font-size: 1.05rem; }
.brand svg { width: 32px; height: 32px; flex: none; }
.brand b { color: var(--accent); font-weight: 700; }
.head-right { display: flex; align-items: center; gap: 8px; }
.head-nav { display: flex; gap: 2px; }
.head-nav a { color: var(--muted); text-decoration: none; font-size: .89rem; font-weight: 550; padding: 8px 13px; border-radius: 10px; transition: border-color .12s; }
.head-nav a:hover { color: var(--ink); background: var(--surface-2); }
@media (max-width: 900px) { .head-nav { display: none; } }
.icon-btn {
  width: 40px; height: 40px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--surface); display: grid; place-items: center; color: var(--muted); transition: border-color .12s;
}
.icon-btn:hover { color: var(--ink); border-color: var(--line-2); }
.icon-btn svg { width: 17px; height: 17px; }
:root[data-theme="dark"] .i-moon { display: none; }
:root:not([data-theme="dark"]) .i-sun { display: none; }

/* Buttons: flat, high contrast, no motion. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  padding: 11px 18px; font-size: .91rem; font-weight: 650; text-decoration: none;
  letter-spacing: -.01em; transition: border-color .12s;
}
.btn svg { width: 16px; height: 16px; }
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-2); }
:root[data-theme="dark"] .btn-primary { color: #0a1020; }        /* 8.45:1 */
:root[data-theme="dark"] .btn-primary:hover { background: var(--accent-2); }
.btn-ghost { background: var(--surface); border-color: var(--line-2); color: var(--ink-2); }
.btn-ghost:hover { border-color: var(--accent); color: var(--ink); }

/* ---------- hero ---------- */
.hero { padding: 48px 0 26px; text-align: center; position: relative; }
.hero::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 1px; z-index: -1;
  background: none; pointer-events: none;
}
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px; font-size: .72rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--accent);
  background: var(--accent-soft); border: 1px solid var(--accent-line);
  padding: 5px 13px; border-radius: 6px; margin-bottom: 18px;
}
h1 {
  font-size: clamp(2.05rem, 4.8vw, 3.2rem); line-height: 1.06; letter-spacing: -.04em;
  font-weight: 800; max-width: 17ch; margin: 0 auto 14px;
}
h1 em { font-style: normal; color: var(--accent); }
.lede { color: var(--ink-2); font-size: clamp(1rem, 1.9vw, 1.12rem); max-width: 60ch; margin: 0 auto; line-height: 1.6; }
.trust { display: flex; flex-wrap: wrap; justify-content: center; gap: 9px 20px; margin-top: 20px; color: var(--muted); font-size: .85rem; }
.trust span { display: inline-flex; align-items: center; gap: 7px; }
.trust svg { width: 15px; height: 15px; color: var(--accent); }

/* ---- the fold budget (Identity B) ------------------------------------- */
/* DESIGN-MODERNISATION-2026-08 §3.1. The contract on a 375x812 phone is that
   the calculator's RESULT ROW lands at or above 780px and the compact source
   line at or above 812px. Every value below was chosen by measuring, not by
   taste: the hero's desktop breathing room is what pushed the instrument down.
   Desktop is untouched — this only fires at <=560px. */
@media (max-width: 560px) {
  .hero { padding: 26px 0 18px; }
  .eyebrow { margin-bottom: 11px; padding: 4px 10px; }
  h1 { margin-bottom: 10px; }
  .lede { font-size: .97rem; line-height: 1.5; }
  /* The trust chip row stacks to 3 lines on a phone; tightening the row gap is
     worth ~14px of fold and costs nothing legible. */
  .trust { margin-top: 13px; gap: 6px 16px; font-size: .82rem; }
  .calc-card { margin-top: 16px; }

  /* THE ORDER, not just the spacing. CoverCheck — the measured reference —
     puts its trust row BELOW its primary action (CTA @543, trust @727). On the
     tools the trust chip row sat between the lede and the calculator and cost
     74px of fold, which is the difference between the citation being seen and
     not. Reordering is done in CSS so no markup, no desktop layout and no
     source order for a screen reader outside this breakpoint changes: the
     chips still read immediately after the instrument they describe. */
  .hero > .wrap { display: flex; flex-direction: column; }
  .hero > .wrap > * { order: 6; }
  .hero > .wrap > .eyebrow { order: 1; align-self: center; }
  .hero > .wrap > h1 { order: 2; }
  .hero > .wrap > .lede { order: 3; }
  .hero > .wrap > .calc-card,
  .hero > .wrap > .sheet,
  .hero > .wrap > .app { order: 4; }
  .hero > .wrap > .trust { order: 5; }

  /* The copy-cells under the headline figure stack one per line on a phone and
     push everything after them off the screen; two up keeps the card compact
     without shrinking the numerals. */
  .calc-card .out-grid { gap: 8px; }
}

/* ---------- app / forms ---------- */
.app { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr); gap: 24px; align-items: start; margin-top: 30px; }
.app > * { min-width: 0; }
@media (max-width: 1040px) { .app { grid-template-columns: minmax(0, 1fr); } }

.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); overflow: hidden; }
.card + .card { margin-top: 16px; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 15px 20px; border-bottom: 1px solid var(--line); background: linear-gradient(180deg, var(--surface-2), transparent); }
.card-head h2 { font-size: .76rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.card-body { padding: 20px; }

.field { margin-bottom: 14px; }
.field:last-child { margin-bottom: 0; }
label, .lbl { display: block; font-size: .78rem; font-weight: 650; color: var(--muted); margin-bottom: 6px; }
input[type="text"], input[type="number"], input[type="date"], input[type="time"], input[type="email"], textarea, select {
  width: 100%; background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 12px;
  padding: 11px 13px; font: inherit; font-size: .93rem;
  transition: border-color .16s, box-shadow .16s;
}
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); background: var(--surface); box-shadow: var(--ring); }
input::placeholder, textarea::placeholder { color: var(--muted); opacity: .6; }
textarea { resize: vertical; min-height: 78px; line-height: 1.5; }
select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7590' stroke-width='2.5'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 11px center; background-size: 15px; padding-right: 36px; }
.row { display: grid; gap: 12px; }
.row-2 { grid-template-columns: 1fr 1fr; }
.row-3 { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 560px) { .row-2, .row-3 { grid-template-columns: 1fr; } }
.hint { font-size: .77rem; color: var(--muted); margin-top: 6px; }

.logo-drop { display: flex; align-items: center; gap: 13px; padding: 13px; border: 1.5px dashed var(--line-2); border-radius: 13px; background: var(--surface-2); cursor: pointer; transition: border-color .12s; }
.logo-drop:hover { border-color: var(--accent); background: var(--accent-soft); }
.logo-drop img { width: 46px; height: 46px; object-fit: contain; border-radius: 9px; background: #fff; }
.logo-drop .ph { width: 46px; height: 46px; border-radius: 10px; background: var(--surface); border: 1px solid var(--line); display: grid; place-items: center; color: var(--muted); flex: none; }
.logo-drop .ph svg { width: 20px; height: 20px; }
.logo-drop p { font-size: .87rem; font-weight: 600; }
.logo-drop small { display: block; font-size: .75rem; color: var(--muted); font-weight: 400; }
.logo-drop button { margin-left: auto; font-size: .78rem; color: var(--muted); background: none; border: 0; text-decoration: underline; }

/* items */
.items { display: flex; flex-direction: column; gap: 8px; }
.item, .item-head { display: grid; grid-template-columns: 1fr 68px 104px 96px 34px; gap: 9px; align-items: center; }
.item-head { padding: 0 0 3px; }
.item-head span { font-size: .7rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.item-head span:nth-child(2), .item-head span:nth-child(3), .item-head span:nth-child(4) { text-align: right; }
.item input { padding: 10px 11px; font-size: .89rem; }
.item input.num { text-align: right; font-variant-numeric: tabular-nums; }
.item .amt { text-align: right; font-size: .9rem; font-weight: 650; font-variant-numeric: tabular-nums; }
.item .del { width: 32px; height: 32px; border-radius: 9px; border: 1px solid transparent; background: none; color: var(--muted); display: grid; place-items: center; transition: border-color .12s; }
.item .del:hover { color: #e11d48; background: color-mix(in srgb, #e11d48 8%, transparent); border-color: color-mix(in srgb, #e11d48 24%, transparent); }
.item .del svg { width: 15px; height: 15px; }
@media (max-width: 640px) {
  .item-head { display: none; }
  .item { grid-template-columns: 1fr 1fr 34px; grid-template-areas: "d d x" "q p a"; padding: 12px; border: 1px solid var(--line); border-radius: 13px; background: var(--surface-2); }
  .item > *:nth-child(1) { grid-area: d; } .item > *:nth-child(2) { grid-area: q; }
  .item > *:nth-child(3) { grid-area: p; } .item > *:nth-child(4) { grid-area: a; }
  .item > *:nth-child(5) { grid-area: x; justify-self: end; }
}
.add-item { margin-top: 11px; width: 100%; border: 1.5px dashed var(--line-2); background: none; color: var(--accent); border-radius: 12px; padding: 11px; font-size: .88rem; font-weight: 650; transition: border-color .12s; }
.add-item:hover { background: var(--accent-soft); border-color: var(--accent); }

/* segmented */
.seg { display: inline-flex; background: var(--surface-2); border: 1px solid var(--line); border-radius: 12px; padding: 4px; gap: 3px; }
.seg button { border: 0; background: none; padding: 8px 14px; border-radius: 9px; font-size: .83rem; font-weight: 650; color: var(--muted); transition: border-color .12s; }
.seg button:hover { color: var(--ink-2); }
.seg button[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-xs); }
:root[data-theme="dark"] .seg button[aria-pressed="true"] { background: var(--line); }

.swatches { display: flex; gap: 8px; flex-wrap: wrap; }
.swatch { width: 28px; height: 28px; border-radius: 50%; border: 2px solid transparent; box-shadow: 0 0 0 1px var(--line); transition: border-color .12s; }
.swatch:hover { box-shadow: 0 0 0 2px var(--line-2); }
.swatch[aria-pressed="true"] { border-color: var(--surface); box-shadow: 0 0 0 2px var(--ink); }

/* totals */
.totals { border-top: 1px solid var(--line); margin-top: 16px; padding-top: 13px; }
.trow { display: flex; justify-content: space-between; gap: 12px; font-size: .91rem; padding: 5px 0; color: var(--ink-2); }
.trow b { font-variant-numeric: tabular-nums; }
.trow.total { border-top: 1px solid var(--line); margin-top: 9px; padding-top: 12px; font-size: 1.12rem; font-weight: 750; color: var(--ink); letter-spacing: -.02em; }

/* preview / document */
.preview-col { position: sticky; top: 84px; min-width: 0; }
@media (max-width: 1040px) { .preview-col { position: static; } }
.preview-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.preview-bar .ttl { font-size: .76rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.paper-wrap { overflow: hidden; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); background: #fff; border: 1px solid var(--line); }

.paper { width: 794px; min-height: 1123px; background: #fff; color: #1e293b; transform-origin: top left; padding: 56px 58px; font-size: 13.5px; line-height: 1.55; position: relative; }
.paper * { color: inherit; }
.doc-top { display: flex; justify-content: space-between; gap: 30px; align-items: flex-start; }
.doc-logo { max-width: 190px; max-height: 78px; object-fit: contain; }
.doc-from h3 { font-size: 17px; font-weight: 750; letter-spacing: -.02em; margin-bottom: 3px; color: #0f172a; }
.doc-from p, .doc-to p { font-size: 12.5px; color: #475569; white-space: pre-line; }
.doc-title { text-align: right; }
.doc-title .t { font-size: 31px; font-weight: 800; letter-spacing: -.035em; line-height: 1; color: var(--doc-accent, #4f46e5); }
.doc-title .sub { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: #94a3b8; margin-top: 7px; font-weight: 650; }
.doc-meta { margin-top: 13px; font-size: 12.5px; }
.doc-meta div { display: flex; justify-content: flex-end; gap: 12px; }
.doc-meta span { color: #64748b; }
.doc-meta b { color: #0f172a; font-weight: 650; min-width: 96px; text-align: right; }
.doc-parties { display: flex; gap: 40px; margin-top: 36px; }
.doc-parties > div { flex: 1; }
.doc-parties .lbl2 { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: #94a3b8; font-weight: 700; margin-bottom: 5px; }
.doc-parties h4 { font-size: 14px; font-weight: 700; color: #0f172a; margin-bottom: 2px; }
.doc-table { width: 100%; border-collapse: collapse; margin-top: 30px; font-size: 12.5px; }
.doc-table th { text-align: left; padding: 9px 8px; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: #64748b; font-weight: 700; border-bottom: 1.5px solid var(--doc-accent, #4f46e5); }
.doc-table th.r, .doc-table td.r { text-align: right; }
.doc-table td { padding: 11px 8px; border-bottom: 1px solid #eef2f7; vertical-align: top; color: #334155; }
.doc-table td.desc { color: #0f172a; font-weight: 550; white-space: pre-line; }
.doc-table td.r { font-variant-numeric: tabular-nums; }
.doc-sum { margin-top: 20px; display: flex; justify-content: flex-end; }
.doc-sum table { font-size: 13px; min-width: 268px; }
.doc-sum td { padding: 5px 0; color: #475569; }
.doc-sum td.r { text-align: right; font-variant-numeric: tabular-nums; color: #0f172a; font-weight: 600; }
.doc-sum tr.grand td { border-top: 1.5px solid #cbd5e1; padding-top: 12px; font-size: 18px; font-weight: 800; color: #0f172a; letter-spacing: -.02em; }
.doc-sum tr.grand td.r { color: var(--doc-accent, #4f46e5); }
.doc-foot { margin-top: 38px; display: flex; gap: 36px; font-size: 12px; color: #475569; }
.doc-foot > div { flex: 1; }
.doc-foot .lbl2 { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: #94a3b8; font-weight: 700; margin-bottom: 5px; }
.doc-foot p { white-space: pre-line; }
.doc-thanks { margin-top: 34px; padding-top: 16px; border-top: 1px solid #eef2f7; font-size: 11.5px; color: #94a3b8; display: flex; justify-content: space-between; gap: 16px; }

.paper[data-tpl="classic"] { font-family: Georgia, "Times New Roman", serif; }
.paper[data-tpl="classic"] .doc-title .t { font-weight: 700; letter-spacing: 0; }
.paper[data-tpl="classic"] .doc-table th { border-bottom-color: #334155; color: #334155; }
.paper[data-tpl="bold"] { padding-top: 0; }
.paper[data-tpl="bold"]::before { content: ""; display: block; height: 14px; background: var(--doc-accent, #4f46e5); margin: 0 -58px 40px; }
.paper[data-tpl="bold"] .doc-title .t { font-size: 37px; }
.paper[data-tpl="bold"] .doc-table th { background: var(--doc-accent, #4f46e5); color: #fff !important; border-bottom: 0; padding: 11px 10px; }
.paper[data-tpl="bold"] .doc-table th:first-child { border-radius: 7px 0 0 7px; }
.paper[data-tpl="bold"] .doc-table th:last-child { border-radius: 0 7px 7px 0; }

.mobile-bar { display: none; }
@media (max-width: 1040px) {
  .mobile-bar { display: flex; position: sticky; bottom: 0; z-index: 45; gap: 10px; padding: 11px 18px; background: color-mix(in srgb, var(--surface) 92%, transparent); backdrop-filter: blur(12px); border-top: 1px solid var(--line); margin: 0 -22px; }
  .mobile-bar .btn { flex: 1; }
}

/* ---------- content ---------- */
.section { padding: 58px 0; }
.section + .section { border-top: 1px solid var(--line); }
h2.sec { font-size: clamp(1.5rem, 3.3vw, 2.05rem); font-weight: 800; letter-spacing: -.04em; margin-bottom: 15px; }
/* AAA+++ 2026-07-31: the legacy 40x3 rounded rule BELOW the heading is gone.
   The mechanics layer adds a 44x2 keel ABOVE it (h2.sec::before), so every
   section head on all 12 tools was rendering two accent rules bracketing the
   text — which reads as a mistake, not a motif. The keel is the doctrine;
   this was its predecessor. */
h3.sub { font-size: 1.1rem; font-weight: 700; letter-spacing: -.025em; margin: 26px 0 9px; }
.prose p { color: var(--ink-2); margin-bottom: 14px; line-height: 1.68; }
.prose ul, .prose ol { color: var(--ink-2); padding-left: 21px; margin-bottom: 14px; }
.prose li { margin-bottom: 7px; line-height: 1.65; }
.prose strong { color: var(--ink); font-weight: 650; }
.lead-note { color: var(--muted); font-size: .95rem; }

.checklist { list-style: none; padding: 0 !important; }
.checklist li { display: flex; gap: 11px; align-items: flex-start; margin-bottom: 11px; }
.checklist svg { width: 18px; height: 18px; color: var(--ok); flex: none; margin-top: 3px; }

.callout { padding: 17px 19px; border-radius: var(--radius); background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); color: var(--ink-2); font-size: .93rem; margin: 20px 0; }
.callout b { color: var(--ink); }

.faq details { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); margin-bottom: 10px; box-shadow: var(--shadow-xs); transition: border-color .16s; }
.faq details[open] { border-color: color-mix(in srgb, var(--accent) 34%, transparent); }
.faq summary { cursor: pointer; padding: 16px 19px; font-weight: 650; font-size: .96rem; list-style: none; display: flex; justify-content: space-between; gap: 12px; border-radius: var(--radius); transition: none; }
.faq details:not([open]) summary:hover { background: var(--surface-2); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-size: 1.35rem; line-height: 1; flex: none; transition: transform .2s; }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq .ans { padding: 0 19px 17px; color: var(--ink-2); font-size: .93rem; line-height: 1.66; }

.rec-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr)); gap: 15px; margin-top: 18px; }
.rec { display: block; text-decoration: none; color: inherit; padding: 21px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-xs); transition: border-color .12s; }
.rec:hover { border-color: var(--accent); }
.rec h3 { font-size: 1.01rem; font-weight: 700; margin-bottom: 7px; letter-spacing: -.02em; }
.rec p { font-size: .88rem; color: var(--muted); line-height: 1.6; }
.rec .go { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px; color: var(--accent); font-size: .85rem; font-weight: 700; }

.linkgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(192px, 1fr)); gap: 9px; margin-top: 16px; }
.linkgrid a { text-decoration: none; color: var(--ink-2); padding: 12px 15px; border-radius: 12px; background: var(--surface); border: 1px solid var(--line); font-size: .88rem; font-weight: 550; transition: border-color .12s; }
.linkgrid a:hover { border-color: var(--accent); color: var(--ink); }

.tbl-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); margin-top: 16px; background: var(--surface); box-shadow: var(--shadow-xs); }
.tbl-wrap table { width: 100%; border-collapse: collapse; font-size: .91rem; min-width: 460px; }
.tbl-wrap th, .tbl-wrap td { padding: 13px 16px; text-align: left; border-bottom: 1px solid var(--line); }
.tbl-wrap th { background: var(--surface-2); font-size: .74rem; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.tbl-wrap tbody tr:last-child td { border-bottom: 0; }
.tbl-wrap tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--surface-2) 55%, transparent); }
.tbl-wrap tbody tr { transition: none; }
.tbl-wrap tbody tr:hover td { background: var(--accent-soft); }

/* ---------- footer ---------- */
.site-foot { border-top: 1px solid var(--line); padding: 40px 0 46px; background: var(--surface); }
.foot-in { display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: center; }
.foot-in p, .foot-links a { color: var(--muted); font-size: .85rem; }
.foot-links { display: flex; flex-wrap: wrap; gap: 8px 17px; }
.foot-links a { text-decoration: none; }
.foot-links a:hover { color: var(--accent); }

.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 20px);
  background: var(--ink); color: var(--surface); padding: 12px 20px; border-radius: 13px;
  font-size: .88rem; font-weight: 650; box-shadow: var(--shadow); opacity: 0; pointer-events: none;
  transition: border-color .12s; z-index: 95;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- print ---------- */
@media print {
  @page { size: A4; margin: 0; }
  body { background: #fff !important; }
  body > *:not(#print-root) { display: none !important; }
  #print-root { display: block !important; position: static; }
  #print-root .paper { transform: none !important; width: 210mm !important; min-height: 297mm !important; box-shadow: none !important; border: 0 !important; padding: 16mm 15mm !important; font-size: 11pt; }
  .paper[data-tpl="bold"]::before { margin: 0 -15mm 34px !important; }
}
#print-root { display: none; }

/* =========================================================================
   IDENTITY B — "Studio Instrument" layer
   Numbers are the product: every figure a user reads or copies is set in
   tabular figures so columns align and values never jiggle as they update.
   ========================================================================= */
.v, .amt, .num, .out-val, .big, .result, .stat, .eq,
.trow b, .quick-answer b, .src-fact, .amount-input, .rate-custom,
.tbl-wrap td, .tbl-wrap th, .doc-table td.r, .doc-sum td.r,
input[type="number"], input[inputmode="decimal"], input[type="time"], input[type="date"],
output, time, td.r, .money, .pct {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* Layout rhythm: input card -> giant result -> breakdown table -> sticky loop. */
.calc-card { box-shadow: var(--shadow-sm); border-radius: var(--radius-lg); }
.out-main .v, .out-val { color: var(--accent); letter-spacing: -.04em; }

/* Semantic colour is reserved for results, never for chrome. */
.is-pos, .val-pos, .delta-up { color: var(--pos); }
.is-neg, .val-neg, .delta-down { color: var(--neg); }

/* The sticky loop, as furniture. Also styled here so it survives on pages
   that do not inline NET_CSS (privacy, etc). */
.handoff {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px;
  margin-top: 20px; padding: 15px 16px;
  border: 1px solid var(--accent-line); border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); background: var(--accent-soft);
}
.handoff .btn { flex: none; }

/* Motion: zero. Only state-change feedback (toast, focus) is allowed. */
.net-card:hover, .rec:hover, .btn:hover, .icon-btn:hover,
.linkgrid a:hover, .swatch:hover, .item .del:hover { transform: none; }

/* --- Follow strip (social distribution) ------------------------------------
   Added 2026-07-29. The NZ tool network is the portfolio's strongest audience
   match for Amit's own channels — sole traders and small-business owners are
   exactly who his marketing content is for. Quiet by design: a standing credit
   line, never louder than the tool itself. */
.soc-strip{
  margin-top:1.5rem;padding-top:1.25rem;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.75rem 1.25rem;
}
.soc-lead{margin:0;font-size:.88rem;line-height:1.5;color:var(--muted);max-width:56ch}
.soc-lead strong{color:var(--ink);font-weight:600}
/* The publisher's name is the one human path from a tool back to the hub.
   Underlined rather than accent-coloured so it reads as a credit, not a CTA. */
.soc-name{color:inherit;text-decoration:underline;text-decoration-color:var(--line);text-underline-offset:3px}
.soc-name:hover,.soc-name:focus-visible{text-decoration-color:var(--accent)}
.soc-name:hover strong,.soc-name:focus-visible strong{color:var(--accent)}
.soc-links{display:flex;flex-wrap:wrap;gap:.5rem}
.soc-link{
  display:inline-block;padding:.35rem .75rem;border:1px solid var(--line);border-radius:999px;
  font-size:.82rem;line-height:1.35;color:var(--ink);text-decoration:none;background:var(--surface);
}
.soc-link:hover,.soc-link:focus-visible{border-color:var(--accent);color:var(--accent)}
@media (max-width:640px){
  .soc-strip{flex-direction:column;align-items:flex-start}
  .soc-lead{max-width:none}
}

/* ------------------------------------------------- affiliate offer block
   Rendered by _shared/offers.mjs (renderOffer). One per page, after the
   answer. Uses the existing tokens so it inherits whichever identity the
   site wears. See _plans/AFFILIATE-REVENUE-PLAN.md §5 for the placement
   rules this component exists to satisfy. */
.aff-offer{border:1px solid var(--line,#e6e1d8);border-radius:16px;padding:20px 22px;margin:32px 0;background:var(--card,#fff)}
.aff-label{font-size:11px;letter-spacing:.14em;text-transform:uppercase;font-weight:700;color:var(--muted,#6b6459);margin:0 0 6px}
.aff-title{font-size:20px;margin:0 0 6px;line-height:1.25}
.aff-context{margin:0 0 8px;font-weight:600}
.aff-blurb{margin:0 0 10px;color:var(--muted,#6b6459)}
.aff-disclosure{font-size:12.5px;line-height:1.5;color:var(--muted,#6b6459);margin:0 0 12px}
.aff-cta{display:inline-flex;align-items:center;gap:8px;padding:11px 18px;border-radius:999px;background:var(--site-accent,#4f46e5);color:#fff;font-weight:650;text-decoration:none}
.aff-cta svg{width:17px;height:17px}
.aff-cta:hover{filter:brightness(1.07)}
[data-theme="dark"] .aff-offer{background:var(--card,#171512)}

/* ============================================================================
   AAA+++ STUDIO PREMIUM — Identity B ("Studio Instrument") mechanics
   Spec: _plans/AAA-PLUS-STUDIO-PREMIUM.md §2.2, §3, §4 (calculator-card row).
   Identity B has no serif, so its premium register is weight discipline
   (400/500/650) plus the mono voice on every figure. Instruments are smooth:
   the tools deliberately do NOT get Identity A's paper grain, and that
   difference is itself a brand cue.
   ========================================================================== */

/* ---- the mono "spec" voice --------------------------------------------- */
/* Dates, IRD citations, rate vintages, SKUs, units and step numbers. Without
   this register a calculator reads as a form; with it, as an instrument. */
.spec,
.srcline,
.crumbs,
.vintage,
.freshness,
.kicker,
.eyebrow,
.cite {
  font-family: var(--mono);
  font-size: var(--fs-mono);
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums lining-nums;
}
.spec, .cite { color: var(--muted); }
.kicker, .eyebrow { text-transform: uppercase; letter-spacing: var(--track-label); color: var(--accent-2); }

/* ---- tabular numerals with intent ------------------------------------- */
/* Any number a reader compares or copies. Live calculators re-render on every
   keystroke, so proportional figures make the result column jiggle — the
   fastest way for an instrument to look unmeasured. */
.num,
td.n,
.result-v,
.res-v,
table td,
table th,
.pager,
input[type="number"] {
  font-variant-numeric: tabular-nums lining-nums;
}

/* ---- the keel (section datum line) ------------------------------------ */
h2.sec::before,
.keel::before {
  content: "";
  display: block;
  width: 44px;
  height: 2px;
  background: var(--accent);
  margin-bottom: 14px;
}

/* ---- elevation: exactly ONE floating object per page ------------------- */
/* Everything used to float a little, which is how elevation stops meaning
   anything. The calculator card is the object that asks for action; it floats.
   Nothing else does. In dark mode nothing floats at all — elevation there is a
   surface step plus a hairline. */
.card, .rec, .tbl-wrap, .faq details, .seg button[aria-pressed="true"] { box-shadow: none; }
.calc-card { box-shadow: var(--shadow); border-radius: var(--radius-lg); }
:root[data-theme="dark"] .calc-card {
  box-shadow: none;
  background: var(--surface);
  border: 1px solid var(--line-2);
}

/* ---- sticky header: solid, not blurred -------------------------------- */
/* backdrop-filter on a sticky header costs a compositor pass on every scroll
   frame on mobile, and the frosted look is the most recognisable SaaS-template
   cue in the whole system. A solid surface with one hairline is cheaper and
   reads more expensive. */
.site-head {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.site-head .brand-sub {
  display: block;
  font-family: var(--mono);
  font-size: .7rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 2px;
}

/* ---- input wells ------------------------------------------------------- */
/* Pill inputs on a floating card read as a signup form. A sunken well with an
   inset hairline reads as a field on an instrument. 48px keeps the mobile tap
   target honest. */
/* type="time" was missing, which is the PRIMARY input on the hours calculator —
   its fields were the only ones on the site not wearing the well treatment. */
.calc-card input[type="text"],
.calc-card input[type="number"],
.calc-card input[type="date"],
.calc-card input[type="time"],
.calc-card input[type="email"],
.calc-card input[type="tel"],
.calc-card input[inputmode="decimal"],
.calc-card select,
.field input,
.field select {
  min-height: 48px;
  background: var(--surface-sunken);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 rgba(10, 16, 32, .05);
  transition: border-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}
.calc-card input:focus-visible,
.calc-card select:focus-visible,
.field input:focus-visible,
.field select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-color: var(--accent);
}
:root[data-theme="dark"] .calc-card input,
:root[data-theme="dark"] .calc-card select { box-shadow: inset 0 1px 0 rgba(0, 0, 0, .4); }

/* ---- the result ------------------------------------------------------- */
.result-v, .res-v {
  font-size: clamp(2.1rem, 6vw, 2.9rem);
  font-weight: 650;
  line-height: 1.04;
  letter-spacing: -.02em;
  color: var(--ink-num);
}
.result-u, .res-u {
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---- focus & hover with intent ---------------------------------------- */
a.draw,
.rel-card .rel-t {
  text-decoration: none;
  background: linear-gradient(var(--accent), var(--accent)) 0 100% / 0 1px no-repeat;
  transition: background-size var(--t-med) var(--ease-out);
}
a.draw:hover, a.draw:focus-visible, .rel-card:hover .rel-t { background-size: 100% 1px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* ---- the sticky-loop handoff as furniture ----------------------------- */
/* hours -> invoice, quote -> invoice, gst -> invoice, markup -> quote,
   rate -> quote, mileage -> invoice. This was a text link at the bottom of the
   page; as a full button block carrying the computed state it becomes product
   UX, which is why the rulebook exempts it from the cross-site link caps. */
.handoff {
  display: block;
  margin: var(--s4, 24px) 0 0;
  padding: 16px 18px;
  border: 1px solid var(--accent-line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent-soft);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--t-fast) var(--ease-out);
}
.handoff:hover { border-color: var(--accent); }
.handoff .handoff-k { display: block; font-family: var(--mono); font-size: .7rem; letter-spacing: .12em; text-transform: uppercase; color: var(--accent-2); margin-bottom: 5px; }
.handoff .handoff-t { font-weight: 650; font-size: 1.02rem; }
.handoff .handoff-w { display: block; color: var(--ink-2); font-size: .92rem; margin-top: 4px; }
@media (max-width: 640px) { .handoff { text-align: left; } }

/* ---- the promoted source / citation line ------------------------------ */
/* On the NZ tools the source line is the whole trust argument: an IRD-cited
   GST formula is worth more than any amount of styling. No figure without a
   source line, no source line without a date. */
.srcline {
  display: block;
  border-top: 1px solid var(--line);
  padding-top: 8px;
  margin-top: 12px;
  color: var(--muted);
  text-transform: uppercase;
}
.srcline .sep { color: var(--line-2); margin: 0 .5em; }
.srcline a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--line-2); }
.srcline a:hover { color: var(--ink-2); border-bottom-color: var(--accent); }

/* ---- the COMPACT source line, inside the instrument -------------------- */
/* DESIGN-MODERNISATION-2026-08 §3.1. Measured at a real 375x812 viewport, the
   full .srcline block on the tools landed at 1544px — a whole screen below the
   fold — on the cluster whose entire pitch is "IRD-cited". The trust signal has
   to travel WITH the number it vouches for, so this is a second, compact copy
   that lives inside .calc-card directly under the result row.
   It is exempt from the one-srcline rule only because it cites the SAME source
   as the full block below; if the two ever disagree, the bug is this rule.
   No new colour is introduced (--muted on --surface, already in the palette and
   already covered by contrast-check.mjs) — deliberately, so this change cannot
   move a contrast pair. */
.srcline-min {
  display: block;
  margin: 12px 0 0;
  padding-top: 9px;
  border-top: 1px solid var(--line);
  font-family: var(--mono);
  font-size: .72rem;
  line-height: 1.45;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--muted);
  text-align: left;
}
.srcline-min .sep { color: var(--line-2); margin: 0 .45em; }
.srcline-min a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--line-2); }
.srcline-min a:hover { color: var(--ink-2); border-bottom-color: var(--accent); }
/* Inside the card it sits flush with the card's own padding box. */
.calc-card > .srcline-min { margin-top: 14px; }

/* ---- the method mini-spec --------------------------------------------- */
.method ol { list-style: none; margin: 0; padding: 0; counter-reset: mstep; }
.method li {
  counter-increment: mstep;
  border-top: 1px solid var(--line);
  padding: 14px 0 14px 44px;
  position: relative;
  color: var(--ink-2);
}
.method li:last-child { border-bottom: 1px solid var(--line); }
.method li::before {
  content: counter(mstep, decimal-leading-zero);
  position: absolute; left: 0; top: 14px;
  font-family: var(--mono); font-size: var(--fs-mono);
  letter-spacing: .06em; color: var(--accent-2);
}
.method .formula {
  font-family: var(--mono);
  font-size: .875rem;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin: 10px 0 0;
  overflow-x: auto;
  white-space: pre;
}

/* ---- related cards that earn the click -------------------------------- */
.rel-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); margin-top: 24px; }
.rel-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 18px 18px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 2px solid var(--accent);
  border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: none;
  text-decoration: none; color: inherit;
  transition: border-color var(--t-fast) var(--ease-out);
}
.rel-card:hover { border-color: var(--line-2); border-top-color: var(--accent); }
.rel-card .rel-t { font-weight: 650; color: var(--ink); font-size: 1.02rem; align-self: flex-start; }
.rel-card .rel-why { color: var(--ink-2); font-size: .92rem; line-height: 1.5; margin: 0; }
.rel-card .freshness { margin-top: auto; padding-top: 10px; color: var(--muted); align-self: flex-end; }
/* The bridge card's dashed edge shipped in Identity A but was never added
   here, so `toolRelCards` rendered its one out-of-cluster card identically to
   the siblings — losing the "different family" grammar that stops a reader
   being surprised by where it lands. */
.rel-card.bridge { border-style: dashed; border-top-style: solid; background: var(--surface-2); }

/* ---- netbar promoted -------------------------------------------------- */
/* FIX 2026-07-31: these targeted .net-label / .net-dot, but network.mjs's
   netBar() emits .netbar-label and .nb-dot — so both rules were dead CSS on
   all 12 tools. Same class of bug as the Identity A .net-dot slip. */
.netbar .netbar-label { font-family: var(--mono); font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; opacity: .72; }
.netbar .nb-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }

/* ---- entrance choreography ------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .reveal { animation: aaa-rise 420ms var(--ease-out) both; }
  .reveal-2 { animation-delay: 60ms; }
  .reveal-3 { animation-delay: 120ms; }
  @keyframes aaa-rise { from { opacity: 0; transform: translateY(12px); } }
}
/* PRINT FIX 2026-08-04 — see the matching note in datasite.css. `both` applies
   the opacity-0 `from` keyframe in print even though the animation never runs,
   so the revealed hero printed blank. Identity B matters more here than the
   ring does: people genuinely print an invoice, a quote and a receipt. */
@media print {
  .reveal, .reveal-2, .reveal-3 {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ---- confident emptiness --------------------------------------------- */
.breathe { min-height: 18vh; }
@media (max-width: 640px) { .breathe { min-height: 10vh; } }

/* ---- the AdSense slot (pre-built 2026-08-04) --------------------------
   Identity B's cut of the same component. Inert until AD_SLOTS carries a
   real slot id; written now so the first paste does not ship ~90,000
   unstyled ad blocks. Same three rules as Identity A — look foreign,
   reserve the space, stay quiet — expressed as an instrument would: a
   sunken well rather than a ruled band, because that is how this identity
   already marks "not the page's own voice". */
.ad-slot {
  display: block;
  margin: 40px auto;
  padding: 12px 14px 14px;
  background: var(--surface-sunken, var(--surface-2));
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  text-align: center;
  clear: both;
}
.ad-label {
  display: block;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 10px;
  text-align: left;
}
.ad-slot .adsbygoogle { display: block; width: 100%; }
.ad-slot--pre-footer { max-width: 1100px; margin-top: 48px; }
@media (max-width: 640px) { .ad-slot { margin: 28px auto; } }

/* ============================================================================
   datasite.css — IDENTITY A, "Editorial Data"
   Component + token layer for the 18-site data ring. Loads AFTER styles.css
   and deliberately RETOKENS it: styles.css is the shared base for the whole
   portfolio (and is owned elsewhere), so every Identity A decision is made
   here, as an override, rather than by forking the base.

   Reference standard: SuburbIQ. Warm paper, warm hairlines, serif display,
   sans figures, hairline-divided stat rows instead of boxes, tables typeset
   flush to the measure rather than inset in a widget.

   Palette validated with _shared/contrast-check.mjs — 132 text/background
   pairs, all ≥4.5:1 (≥3:1 for large display type and UI edges). Do not change
   an accent without re-running it: several of these hues (lux #7C5A22,
   fast #8A5A14, gym #7A4E1D) had to be darkened well past "looks nice" to
   clear AA on warm paper.
   ========================================================================== */

/* ============================================================ 1. the tokens */
:root {
  /* paper stack — warm off-white ground, pure-white surfaces laid on it */
  --paper: #FBF9F5;
  --paper-2: #F4F1EA;
  --bg: var(--paper);
  --bg-tint: var(--paper-2);
  --surface: #FFFFFF;
  --surface-2: var(--paper-2);

  /* ink ramp — four real steps, never opacity-faded text */
  --ink: #14181B;
  --ink-2: #454D53;
  --muted: #646C72;
  --faint: #7E868D;

  /* warm hairlines. The warmth is the single biggest contributor to the
     "printed" feel and the easiest thing to lose when porting. */
  --line: #E7E1D6;
  --line-2: #D6CEC0;
  --rule: var(--line);
  --rule-2: var(--line-2);
  --grid: var(--line);

  /* one accent hue per site, injected on <body style="--site-accent:…"> by
     shell(). Falls back to the ring's neutral slate if a site forgets. */
  --accent: var(--site-accent, #3C4A55);
  --accent-2: var(--site-accent, #3C4A55);
  --accent-3: var(--site-accent, #3C4A55);
  --accent-soft: color-mix(in srgb, var(--accent) 9%, var(--paper));

  /* 8pt spacing scale */
  --s1: 4px; --s2: 8px; --s3: 16px; --s4: 24px; --s5: 32px;
  --s6: 48px; --s7: 64px; --s8: 96px;

  /* editorial radii — near-flat. Cards are defined by hairlines, not shadows. */
  --radius: 6px;
  --radius-lg: 8px;
  --radius-sm: 4px;

  /* two shadows exist in the whole system, both functional */
  --shadow-xs: none;
  --shadow-sm: none;
  --shadow: none;
  --shadow-lg: 0 12px 34px -14px rgba(20, 24, 27, .28);

  --max: 1180px;
  --measure: 72ch;

  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --font: var(--sans);
  color-scheme: light;

  /* ---- AAA+++ STUDIO PREMIUM additions (2026-07-30) ------------------------
     Strictly ADDITIVE. Nothing above is renamed — ~90,000 built pages resolve
     against those names. See _plans/AAA-PLUS-STUDIO-PREMIUM.md §2.1.          */

  /* The third voice. Identity A was Fraunces + Inter and nothing else, so no
     figure on any page read as *measured*. This is the specification register:
     dates, units, codes, source vintages, step numbers. System stack only —
     the zero-new-requests constraint is non-negotiable, so we never load a
     mono font file. */
  --mono: ui-monospace, "SF Mono", "Cascadia Code", Consolas, Menlo, monospace;
  --fs-mono: .8125rem;

  --paper-deep: #F0EBE0;          /* band-raised sections; one step below --paper-2 */
  --accent-deep: color-mix(in srgb, var(--accent) 78%, var(--ink));
  --on-accent: #FFFFFF;
  --accent-wash: color-mix(in srgb, var(--accent) 7%, var(--paper));

  /* The ONE elevating shadow. Reserved for the single object per page that
     asks for action. Everything else is flat or a surface step. */
  --shadow-lift: 0 1px 0 rgba(20, 24, 27, .05), 0 24px 48px -32px rgba(20, 24, 27, .25);

  --t-fast: 140ms;
  --t-med: 220ms;
  --t-slow: 420ms;
  --ease-out: cubic-bezier(0.25, 1, 0.4, 1);
  --ease-inout: cubic-bezier(0.45, 0.05, 0.25, 1);

  --fs-stat: clamp(2.8rem, 8vw, 4.8rem);   /* tokenises the .answer .big magic number */
  --track-label: .11em;
  --grain-alpha: .028;
}

/* Cluster I ships English today and Hindi later. Putting Noto Sans Devanagari
   in the stack now costs nothing (it is only fetched if a Devanagari glyph is
   actually rendered) and means the day a Hindi string lands it is already
   typeset rather than falling back to a system default. */
body[data-cluster="india"] {
  --sans: "Inter", "Noto Sans Devanagari", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* Dark mode is WARM BASALT, not a grey inversion.
   Identity A's whole material argument is warm paper; flipping to cool
   charcoal #121416 meant the brand became a different brand after sunset —
   the single strongest cue (warmth) died at night. Same doctrine as the trades
   pair's #171613. Contrast verified: #EDE9DF on #161512 = 14.4:1,
   #C7C1B4 = 9.6:1, #9C968A = 5.6:1. Re-run contrast-check.mjs if touched. */
:root[data-theme="dark"] {
  --paper: #161512;
  --paper-2: #1C1B17;
  --bg: var(--paper);
  --bg-tint: var(--paper-2);
  --surface: #1E1C18;
  --surface-2: var(--paper-2);
  --ink: #EDE9DF;
  --ink-2: #C7C1B4;
  --muted: #9C968A;
  --faint: #6E6960;
  --line: #312F28;
  --line-2: #413E35;
  --paper-deep: #131210;
  --shadow-lg: 0 24px 60px -30px rgba(0, 0, 0, .72);
  /* Dark elevation is a SURFACE STEP plus a hairline, never a shadow. A cast
     shadow on a dark ground is grey mush — it reads as a rendering artifact. */
  --shadow-lift: none;
  color-scheme: dark;
}

body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--ink);
  font-size: 16.5px;
  line-height: 1.62;
  letter-spacing: -.006em;
}
@media (max-width: 640px) { body { font-size: 16px; } }

.wrap { max-width: var(--max); padding: 0 28px; }
@media (max-width: 640px) { .wrap { padding: 0 20px; } }
/* Narrow the CHILDREN, not the container, so the left gutter stays aligned
   with every full-width section above and below it. */
.narrow { max-width: none; }
.narrow > * { max-width: var(--measure); }

/* ======================================================== 2. the type pair
   Fraunces for display; Inter for UI, body and every number a reader reads,
   compares or copies. A serif numeral looks handsome and reads slower — the
   whole product is numbers, so numbers are always sans. */
h1, h2, h3, .serif {
  font-family: var(--serif);
  font-weight: 500;
  letter-spacing: -.02em;
  font-variation-settings: "SOFT" 0, "WONK" 0;
}
h1 { font-size: clamp(2.1rem, 5.4vw, 3.4rem); line-height: 1.05; letter-spacing: -.03em; }
h2 { font-size: clamp(1.45rem, 3vw, 2rem); line-height: 1.15; letter-spacing: -.024em; }
h3 { font-size: 1.12rem; line-height: 1.3; letter-spacing: -.018em; }

.eyebrow {
  display: inline-block; font-family: var(--sans); font-size: .7rem; font-weight: 600;
  letter-spacing: .15em; text-transform: uppercase; color: var(--accent); margin-bottom: var(--s2);
}
.lede, .deck {
  font-size: 1.14rem; line-height: 1.55; color: var(--ink-2);
  max-width: 60ch; margin-top: var(--s3);
}
a { color: var(--accent); text-underline-offset: 2px; }

/* ---------------------------------------------------------- breadcrumbs */
.crumbs { border-bottom: 0; background: transparent; font-size: .82rem; }
.crumbs .wrap { height: auto; padding-top: 20px; gap: 7px; }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--accent); text-decoration: underline; }
.crumbs .sep { color: var(--line-2); }
.crumbs [aria-current] { color: var(--ink-2); font-weight: 600; }

/* ===================================================== 3. answer above fold
   The shared skeleton (§3): the number is visible without scrolling, then the
   method, then the full table, then related. */
.hero { padding: var(--s6) 0 var(--s5); border-bottom: 1px solid var(--line); }
.hero h1 { max-width: 20ch; }

/* ---- 3.1 the fold budget on a phone ---------------------------------- */
/* DESIGN-MODERNISATION-2026-08 §3.2, measured at a real 375x812 viewport.
   The India ring drifted from its Cluster G siblings not in its tokens but in
   its hero ORDER: fuel puts the search at 477px and its source line at 788px,
   both above the fold, while grow/sehat/sugar interpose a YMYL band and a
   400-500px set piece first and push the search to 939-1182px — a phone reader
   reaches the action only after two swipes.

   Fixed here rather than in six templates because it is one rule and because
   reordering in CSS changes no markup, no DOM order for assistive technology
   outside this breakpoint, and nothing at all on desktop where the set piece
   legitimately leads. `:has()` degrades to today's behaviour where unsupported,
   so the worst case is the status quo.

   THE GUARD. Every rule below is scoped to `.wrap:has(...)` — a hero that
   actually contains a recognised ACTION. Without that guard the block also
   reorders heroes it cannot help, and it did: GymFinder names its search
   `.gsearch`, so the action stayed put while the source line was promoted
   ABOVE the answer it vouches for. Reordering a hero whose action you cannot
   find is strictly worse than leaving it alone, so now it leaves it alone.

   The action is matched by CONTENT (`input[type="search"]`), not by class
   name, so .search / .searchbox / .gsearch and any future wrapper all qualify
   without this sheet having to know their names. */
@media (max-width: 560px) {
  .hero { padding: var(--s5) 0 var(--s4); }

  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) {
    display: flex; flex-direction: column;
  }
  /* The five-element hero, in the order CoverCheck proved: headline, subhead,
     ACTION, visual, trust — then everything else. `.hero-cta` and `.hero-set`
     are the generic opt-in hooks for sites whose action and set piece are not
     a search box (CostCompare's pills, NameCurve's ledger curve). */
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > * { order: 7; }
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .eyebrow,
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .kicker { order: 1; }
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > h1 { order: 2; }
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .lede { order: 3; margin-bottom: 0; }
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .hero-act,
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .hero-cta,
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > input[type="search"],
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > :has(input[type="search"]) { order: 4; }
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .hero-set { order: 5; }
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .srcline,
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .srcline-min { order: 6; }
  /* the armour band is a footnote to the answer, not a gate in front of it */
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > .ymyl,
  .hero > .wrap:has(.hero-act, .hero-cta, input[type="search"]) > :has(> .ymyl) { order: 8; }
}
h1 .unit { font-family: var(--sans); font-size: .42em; font-weight: 500; color: var(--muted); letter-spacing: 0; }

/* The generated one-sentence answer. Left accent bar, no card chrome. */
.answer {
  max-width: var(--measure); margin: var(--s4) 0 0; padding: var(--s4) var(--s4) var(--s4) var(--s4);
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); box-shadow: none; text-align: left;
}
.answer p { color: var(--ink-2); font-size: 1.02rem; line-height: 1.6; }
.answer p + p { margin-top: var(--s2); }
.answer b, .answer strong { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* THE hero numeral. Sans, proportional figures, optically large. This is the
   "answer above the fold" and it is the same component on every site — only
   the accent and the unit change. */
.answer .big, .figure-hero {
  display: block; font-family: var(--sans);
  font-size: clamp(2.8rem, 8vw, 4.8rem); font-weight: 650;
  letter-spacing: -.045em; line-height: .96; color: var(--ink);
  font-variant-numeric: proportional-nums; margin-bottom: var(--s2);
}
.answer .big { color: var(--accent); }
.figure-unit { font-size: .94rem; font-weight: 500; color: var(--muted); letter-spacing: 0; margin-top: var(--s2); }

/* Hairline stat row — not boxes. gap:0 and right-hairlines, zero left padding
   so the first stat sits flush with the wrap gutter. */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 0; border-top: 1px solid var(--line); max-width: none; margin: var(--s4) 0 0;
}
.stat {
  background: none; border: 0; border-right: 1px solid var(--line); border-radius: 0;
  padding: 18px 22px 18px 0; text-align: left; box-shadow: none;
}
.stat:last-child { border-right: 0; }
@media (max-width: 720px) {
  .stat { border-right: 0; border-bottom: 1px solid var(--line); padding-right: 0; }
  .stat:last-child { border-bottom: 0; }
}
.stat .k { display: block; font-size: .71rem; font-weight: 600; letter-spacing: .11em; text-transform: uppercase; color: var(--muted); margin-bottom: 0; }
.stat .v { font-size: 1.72rem; font-weight: 620; letter-spacing: -.032em; margin-top: 7px; line-height: 1.1; font-variant-numeric: proportional-nums; }
.stat .s { display: block; font-size: .82rem; color: var(--muted); margin-top: 3px; }

/* ==================================================== 4. sections & rhythm */
.section { padding: var(--s6) 0; }
h2.sec {
  font-family: var(--serif); font-size: clamp(1.4rem, 3vw, 1.95rem); font-weight: 500;
  letter-spacing: -.024em; margin-bottom: var(--s2);
  padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
h3.sub { font-size: 1.08rem; font-weight: 500; letter-spacing: -.018em; margin: var(--s4) 0 var(--s2); }
.sec-note { color: var(--muted); font-size: .93rem; margin-bottom: var(--s4); max-width: var(--measure); }
.prose { max-width: var(--measure); }
.prose h2 { font-size: 1.45rem; font-weight: 500; letter-spacing: -.024em; margin: var(--s5) 0 var(--s2); }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: 1.08rem; font-weight: 500; margin: var(--s4) 0 var(--s2); }
.prose p, .prose li { max-width: var(--measure); }
.prose a { font-weight: 500; }
.upd { font-size: .82rem; color: var(--muted); margin-top: var(--s5); padding-top: var(--s3); border-top: 1px solid var(--line); }

/* --------------------------------------------------- the dated source line
   Doctrine #7 as a design element: every figure carries its provenance and
   its vintage, in the same place, on every page in the ring. */
.src, .srcline {
  display: block; font-size: .82rem; color: var(--muted); line-height: 1.55;
  margin-top: var(--s3); padding-top: 10px; border-top: 1px solid var(--line);
  max-width: var(--measure);
}
.src a, .srcline a { color: var(--muted); text-decoration: underline; text-decoration-color: var(--line-2); }
.src a:hover, .srcline a:hover { color: var(--accent); }
.srcline b { color: var(--ink-2); font-weight: 600; }

/* ================================================================ 5. tables
   Typeset, not boxed: no vertical rules, no zebra, no inset. Column 1 aligns
   flush with the wrap gutter; numerals align flush right and are tabular. */
.tablewrap {
  overflow-x: auto; border: 0; border-top: 1px solid var(--line-2);
  border-radius: 0; background: none; box-shadow: none; -webkit-overflow-scrolling: touch;
}
table.data { width: 100%; border-collapse: collapse; font-size: .94rem; min-width: 440px; }
table.data caption { text-align: left; padding: 0 0 12px; font-size: .82rem; color: var(--muted); caption-side: top; }
table.data th, table.data td {
  padding: 11px 16px 11px 0; text-align: right; border-bottom: 1px solid var(--line);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
table.data th:first-child, table.data td:first-child { text-align: left; font-variant-numeric: normal; white-space: normal; }
table.data th:last-child, table.data td:last-child { padding-right: 0; }
table.data thead th {
  position: sticky; top: 0; background: var(--paper);
  font-size: .7rem; font-weight: 600; letter-spacing: .11em; text-transform: uppercase;
  color: var(--muted); z-index: 1; border-bottom: 1px solid var(--line-2);
}
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: var(--paper-2); }
table.data td a { text-decoration: none; font-weight: 550; color: var(--ink); border-bottom: 1px solid var(--line-2); }
table.data td a:hover { color: var(--accent); border-color: var(--accent); }
table.data .hi { color: var(--accent); font-weight: 600; }
table.data tr.self { background: var(--accent-soft); }
table.data tr.self td { font-weight: 600; }
.tnote { font-size: .82rem; color: var(--muted); margin-top: 10px; }

/* ================================================================ 6. search */
.search { position: relative; max-width: 560px; margin: var(--s4) 0 0; }
.search input {
  width: 100%; padding: 14px 18px 14px 46px; font-size: 1rem; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--line-2); box-shadow: none;
  font-family: var(--sans); color: var(--ink);
}
.search input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.search .ico { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--muted); pointer-events: none; }

/* ---- 6.1 the hero action affordance ---------------------------------- */
/* DESIGN-MODERNISATION-2026-08 §3.2. On the ring the search box IS the primary
   action, but a bare input reads as a form field, not as an invitation — the
   static hero scorer kept marking these heroes "no CTA" and it was right about
   the affordance even when it was wrong about the element. .hero-act is the
   line that names the action and the size of the corpus behind it
   ("Search 1,799 foods ->"), plus a compact provenance chip, so the reader
   learns what the site HAS before deciding to type.
   Additive: a site opts in by passing `heroAct` to shell(). No colour is
   introduced that is not already in the palette (accent, muted, line), so this
   rule cannot move a contrast pair. */
.hero-act {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 16px;
  max-width: 560px; margin: 10px 0 0;
}
.hero-act .hero-act-go {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: .78rem; letter-spacing: .04em;
  color: var(--accent); text-decoration: none;
  border-bottom: 1px solid var(--accent-line);
  padding-bottom: 1px;
}
.hero-act .hero-act-go:hover { border-bottom-color: var(--accent); }
.hero-act .srcline-min {
  margin: 0; padding-top: 0; border-top: 0; flex: 1 1 auto; min-width: 15ch;
}
.qr {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 40;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); overflow: hidden; text-align: left; max-height: 60vh; overflow-y: auto;
}
.qr a { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 11px 16px; text-decoration: none; color: var(--ink); font-size: .92rem; font-weight: 500; border-bottom: 1px solid var(--line); }
.qr a:last-child { border-bottom: 0; }
.qr a:hover { background: var(--paper-2); color: var(--accent); }
.qr a em { font-style: normal; font-size: .78rem; color: var(--muted); flex: none; }
.qr-none { padding: 14px 16px; color: var(--muted); font-size: .88rem; }
.qr a.on { background: var(--paper-2); color: var(--accent); }
.qr-more {
  padding: 9px 16px; margin: 0; font-family: var(--mono); font-size: .72rem;
  letter-spacing: .03em; color: var(--muted); background: var(--paper-2);
  border-top: 1px solid var(--line);
}

/* ---- 6.2 the header search box --------------------------------------- */
/* SEARCH-EVERYWHERE-2026-08. Search used to exist on 21 homepages and on none
   of the ~180,000 deep pages, which is exactly backwards: organic readers land
   deep. This box ships in .head-right on every page, so it has to be quiet
   enough to sit beside the nav and reachable enough to be the way people move
   around a 37,802-page site.

   Desktop: a 210px field that widens to 300px on focus.
   <=860px:  the header wraps and the box takes its own full-width row, still
             visible. It is NOT collapsed behind a tap-to-open magnifier —
             that needs JS and hides the one control that replaces a nav a
             phone cannot show. 38px tall, so the fold cost at 375px is one
             compact row. */
.hsearch { position: relative; flex: 0 1 210px; min-width: 0; }
.hsearch input {
  width: 100%; padding: 8px 12px 8px 34px; font-size: .88rem;
  border-radius: var(--radius-sm); background: var(--paper-2);
  border: 1px solid var(--line-2); box-shadow: none;
  font-family: var(--sans); color: var(--ink);
  text-overflow: ellipsis; transition: flex-basis .16s, border-color .16s, box-shadow .16s;
}
.hsearch input::placeholder { color: var(--muted); }
.hsearch input:focus {
  outline: none; background: var(--surface);
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.hsearch:focus-within { flex-basis: 300px; }
.hsearch .ico {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--muted); pointer-events: none;
}
/* the panel is right-aligned under a header box so it cannot overflow the
   viewport on the right edge, and wide enough to read a long row */
.hsearch .qr { left: auto; right: 0; min-width: 320px; max-width: 92vw; }
.hsearch input::-webkit-search-cancel-button { cursor: pointer; }

@media (max-width: 860px) {
  /* Two different headers carry this box: the ring shell's .head-right, and
     the .masthead-in used by SchoolFinder and SuburbIQ. Both have to be
     allowed to wrap or the full-width search row cannot take its own line.

     The box is a direct child of .masthead-in, NOT of the .nav inside it —
     measured at 375px, a box inside .nav came out 231px wide and truncated its
     own placeholder, because .nav is only as wide as what the brand leaves it.
     Wrapping has to happen on the element that spans the header. */
  .head-in .head-right, .masthead-in { flex-wrap: wrap; }
  .hsearch { flex: 1 0 100%; order: 9; }
  .hsearch input { padding-top: 9px; padding-bottom: 9px; }
  .hsearch .qr { left: 0; right: 0; min-width: 0; }
}

/* ========================================================== 7. link grids */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 0; border-top: 1px solid var(--line); }
.grid a {
  display: block; padding: 13px 18px 13px 0; text-decoration: none; color: var(--ink);
  background: none; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  font-size: .93rem; font-weight: 500; transition: color .16s; box-shadow: none;
}
.grid a:hover { color: var(--accent); transform: none; border-color: var(--line-2); }
.grid a small { display: block; font-weight: 400; color: var(--muted); font-size: .8rem; margin-top: 2px; }
.grid-tight { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }

.chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 7px 14px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line-2); text-decoration: none;
  color: var(--ink-2); font-size: .85rem; font-weight: 500; transition: .16s; box-shadow: none;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip b { color: var(--muted); font-weight: 500; font-size: .78rem; }

.az { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: var(--s4); }
.az a { width: 34px; height: 34px; display: grid; place-items: center; border-radius: var(--radius-sm); border: 1px solid var(--line-2); background: var(--surface); text-decoration: none; font-size: .85rem; font-weight: 600; color: var(--ink-2); }
.az a:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

.pager { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: var(--s5); }
.pager a, .pager span { min-width: 38px; height: 38px; padding: 0 11px; display: inline-grid; place-items: center; border-radius: var(--radius-sm); border: 1px solid var(--line-2); background: var(--surface); text-decoration: none; font-size: .87rem; font-weight: 550; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.pager a:hover { border-color: var(--accent); color: var(--accent); }
.pager .on { background: var(--accent); color: #fff; border-color: var(--accent); }
.pager .gap { border: 0; background: none; color: var(--muted); }

/* ================================================================== 8. FAQ */
.faqs { max-width: var(--measure); }
.faqs details { border: 0; border-bottom: 1px solid var(--line); border-radius: 0; background: none; margin-bottom: 0; box-shadow: none; }
.faqs summary { padding: 15px 0; font-weight: 550; font-size: .97rem; cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.faqs summary::-webkit-details-marker { display: none; }
.faqs summary::after { content: "+"; color: var(--muted); font-size: 1.3rem; font-weight: 400; line-height: 1; flex: none; }
.faqs details[open] summary::after { content: "−"; }
.faqs details[open] summary { border-bottom: 0; }
.faqs .a { padding: 0 0 18px; color: var(--ink-2); font-size: .95rem; line-height: 1.65; max-width: 66ch; }
.faqs .a p + p { margin-top: 10px; }

/* ================================================ 9. header / netbar / foot */
.netbar { background: var(--ink); }
:root[data-theme="dark"] .netbar { background: #0B0D0F; border-bottom: 1px solid var(--line); }
.netbar-links a { display: inline-flex; align-items: center; gap: 6px; font-weight: 450; }
.nb-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; flex: none; }

.site-head {
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  border-bottom: 1px solid var(--line);
}
.brand { font-family: var(--serif); font-weight: 600; letter-spacing: -.02em; font-size: 1.1rem; }
.head-nav a { font-weight: 500; }
.head-nav a:hover { background: var(--paper-2); }
.icon-btn { border-radius: var(--radius-sm); border-color: var(--line-2); }
.icon-btn:hover { transform: none; }

.site-foot { padding: var(--s5) 0 var(--s6); border-top: 1px solid var(--line); background: var(--paper-2); }
.foot-in { align-items: flex-start; }
.foot-col { max-width: 46ch; }
.foot-brand { font-family: var(--serif); font-weight: 500; color: var(--ink) !important; font-size: 1.02rem !important; margin-bottom: 6px; letter-spacing: -.02em; }
.foot-note { font-size: .85rem !important; line-height: 1.55; color: var(--muted); }
.foot-disclaimer { margin-top: var(--s2); }
.foot-links a { color: var(--ink-2); font-size: .88rem; }
.foot-links a:hover { color: var(--accent); }
.foot-legal { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px solid var(--line); }
.foot-legal p { font-size: .8rem; color: var(--muted); max-width: 88ch; }

/* ===================================================== 10. the footer ring */
.ring { padding: var(--s6) 0; border-top: 1px solid var(--line); background: var(--paper); }
.ring-h { font-family: var(--sans); font-size: .7rem; font-weight: 600; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); margin-bottom: var(--s4); }
.ring-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(238px, 1fr)); gap: var(--s3); }
.ring-card {
  display: block; text-decoration: none; color: inherit; padding: 20px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: none; transition: border-color .16s;
  border-top: 2px solid var(--card-accent, var(--accent));
}
.ring-card:hover { transform: none; border-color: var(--line-2); border-top-color: var(--card-accent, var(--accent)); }
.ring-card h3 { font-family: var(--serif); font-size: 1.05rem; font-weight: 500; letter-spacing: -.02em; margin-bottom: 6px; }
.ring-card p { font-size: .87rem; color: var(--muted); line-height: 1.55; }
.ring-card .go { display: inline-block; margin-top: 11px; font-size: .8rem; font-weight: 600; color: var(--card-accent, var(--accent)); font-family: var(--sans); }
/* The single bridge card to the other cluster reads as a footnote, not a
   sibling — a dashed edge says "different family" without extra copy. */
.ring-bridge { border-style: dashed; border-top-style: solid; }
.ring-more { margin-top: var(--s4); font-size: .88rem; }
.ring-more a { color: var(--ink-2); text-decoration: underline; text-decoration-color: var(--line-2); }
.ring-more a:hover { color: var(--accent); }

/* ================================================= 11. the /network hub page */
.hub-list { border-top: 1px solid var(--line-2); max-width: 980px; }
.hub-row {
  display: grid; grid-template-columns: 10px minmax(0, 1fr) auto; gap: var(--s3);
  align-items: baseline; padding: 20px 0; border-bottom: 1px solid var(--line);
}
.hub-dot { width: 9px; height: 9px; border-radius: 50%; align-self: center; }
.hub-name { font-family: var(--serif); font-size: 1.22rem; font-weight: 500; letter-spacing: -.02em; }
.hub-name a { text-decoration: none; color: var(--ink); border-bottom: 1px solid var(--line-2); }
.hub-name a:hover { color: var(--accent); border-color: var(--accent); }
.hub-name em { font-style: normal; font-family: var(--sans); font-size: .7rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin-left: 8px; }
.hub-blurb { font-size: .95rem; color: var(--ink-2); line-height: 1.55; max-width: 66ch; margin-top: 4px; }
.hub-host { font-size: .8rem; color: var(--faint); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hub-row.is-self { background: var(--paper-2); }
@media (max-width: 640px) { .hub-row { grid-template-columns: 10px minmax(0, 1fr); } .hub-host { display: none; } }

/* =========================================== 12. the entity bridge (§2.3)
   The one sanctioned cross-cluster contextual link, set as an editorial
   pull-quote rather than a card: it is an argument ("the same food, counted
   two ways"), and it should read like one. */
.entity-bridge {
  max-width: var(--measure); margin: var(--s5) 0;
  padding: var(--s2) 0 var(--s2) var(--s4);
  border-left: 3px solid var(--accent);
}
.eb-kicker { font-family: var(--sans); font-size: .7rem; font-weight: 600; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); margin-bottom: 10px; }
.eb-body { font-family: var(--serif); font-size: 1.16rem; font-weight: 400; line-height: 1.5; letter-spacing: -.015em; color: var(--ink); }
.eb-go { margin-top: 12px; font-size: .95rem; font-weight: 550; }
.eb-go a { color: var(--accent); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); }
.eb-go a:hover { border-color: var(--accent); }
.eb-go a::after { content: " →"; }

/* --------------------------------------------------- the entity handoff (§(c)4)
   The ring generalisation of the tools cluster's sticky loop: "you have the
   answer about X — here is the next question about X, on the site that owns
   it." Deliberately QUIETER than .entity-bridge: the bridge makes an argument
   and earns a pull-quote, the handoff is furniture at the end of the road, and
   two pull-quotes on one page would compete. Renders only when the resolver
   verified a destination, so it is never a generic "see also". */
.handoff {
  max-width: var(--measure); margin: var(--s5) 0 var(--s4);
  padding-top: var(--s3); border-top: 1px solid var(--rule);
}
.ho-k { font-family: var(--sans); font-size: .7rem; font-weight: 600; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
.ho-go { font-size: 1.05rem; font-weight: 550; }
.ho-go a { color: var(--accent); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); }
.ho-go a:hover { border-color: var(--accent); }
.ho-go a::after { content: " →"; }
.ho-why { margin-top: 8px; font-size: .92rem; color: var(--muted); }

/* ============================================== 13. the house-ad slot (§2.5)
   Deliberately the ONLY dark, cinematic surface in the system. It should not
   look like editorial content, because it is not: it is labelled, nofollowed
   and UTM'd. Keeping it visually foreign is honest and also protects the
   editorial voice of everything around it. */
.pf-cinema {
  position: relative; max-width: 980px; margin: 0 auto; overflow: hidden;
  border-radius: var(--radius-lg); border: 1px solid rgba(255, 255, 255, .08);
  background: #05070f; box-shadow: var(--shadow-lg); text-align: center;
}
.pfc-scene { position: absolute; inset: 0; pointer-events: none; }
.pfc-scene::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(900px 420px at 50% 118%, #f97316 -18%, rgba(249, 115, 22, .28) 22%, transparent 60%),
    radial-gradient(600px 300px at 82% -10%, rgba(124, 140, 255, .22), transparent 65%),
    linear-gradient(180deg, #0b1224 0%, #0a0f1e 45%, #120b18 100%);
}
.pfc-stars {
  position: absolute; inset: 0 0 34% 0; opacity: .8;
  background-image:
    radial-gradient(1.2px 1.2px at 12% 28%, #fff, transparent),
    radial-gradient(1px 1px at 31% 12%, rgba(255,255,255,.8), transparent),
    radial-gradient(1.4px 1.4px at 47% 34%, rgba(255,255,255,.9), transparent),
    radial-gradient(1px 1px at 63% 18%, rgba(255,255,255,.7), transparent),
    radial-gradient(1.3px 1.3px at 78% 30%, #fff, transparent),
    radial-gradient(1px 1px at 89% 10%, rgba(255,255,255,.75), transparent),
    radial-gradient(1px 1px at 22% 48%, rgba(255,255,255,.5), transparent),
    radial-gradient(1.1px 1.1px at 55% 52%, rgba(255,255,255,.55), transparent);
  animation: pfc-twinkle 5.5s ease-in-out infinite alternate;
}
@keyframes pfc-twinkle { from { opacity: .45; } to { opacity: .95; } }
.pfc-ridge {
  position: absolute; left: -4%; right: -4%; bottom: 0; height: 34%;
  background: linear-gradient(180deg, transparent 0%, #05070f 62%);
  clip-path: polygon(0 78%, 9% 58%, 18% 70%, 29% 40%, 38% 62%, 50% 30%, 61% 58%, 71% 44%, 82% 66%, 92% 50%, 100% 72%, 100% 100%, 0 100%);
  background-color: #060910;
}
.pfc-sweep {
  position: absolute; top: -30%; bottom: -30%; width: 34%; left: -40%;
  background: linear-gradient(100deg, transparent 0%, rgba(255, 209, 102, .07) 42%, rgba(255, 255, 255, .13) 50%, rgba(255, 209, 102, .07) 58%, transparent 100%);
  transform: skewX(-14deg);
  animation: pfc-sweep 7s cubic-bezier(.4, 0, .2, 1) infinite;
}
@keyframes pfc-sweep { 0% { left: -45%; } 55% { left: 115%; } 100% { left: 115%; } }
@media (prefers-reduced-motion: reduce) { .pfc-sweep, .pfc-stars { animation: none; } }

.pfc-in { position: relative; padding: 40px 26px 34px; }
.pfc-adlabel { font-family: var(--sans); font-size: .62rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; color: rgba(255, 255, 255, .38); margin-bottom: 16px; }
.pfc-hook { font-family: var(--serif); font-size: 1rem; color: rgba(255, 255, 255, .72); font-style: italic; margin-bottom: 14px; }
.pfc-title { font-family: var(--sans); font-size: clamp(1.7rem, 5.4vw, 3rem); font-weight: 700; letter-spacing: .04em; color: #fff; line-height: 1.04; margin-bottom: 12px; }
.pfc-title span { background: linear-gradient(92deg, #ffd166, #f97316 55%, #fb7185); -webkit-background-clip: text; background-clip: text; color: transparent; }
.pfc-sub { color: rgba(255, 255, 255, .74); font-size: .97rem; max-width: 56ch; margin: 0 auto 22px; line-height: 1.6; }
.pfc-sub strong { color: #ffd166; }
.pfc-count { display: flex; justify-content: center; align-items: flex-start; gap: 8px; margin-bottom: 24px; }
.pfc-cell { min-width: 64px; padding: 10px 8px 8px; border-radius: 10px; background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .1); }
.pfc-cell b { display: block; font-size: clamp(1.4rem, 4vw, 2rem); font-weight: 650; color: #fff; font-variant-numeric: tabular-nums; line-height: 1; }
.pfc-cell i { display: block; font-style: normal; font-size: .62rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: rgba(255, 255, 255, .5); margin-top: 5px; }
.pfc-sep { color: rgba(255, 255, 255, .3); font-size: 1.5rem; font-weight: 600; line-height: 2.2; }
.pfc-btn {
  display: inline-flex; align-items: center; gap: 10px; padding: 14px 28px; border-radius: 10px;
  background: linear-gradient(93deg, #ffd166, #f97316); color: #1a0f02;
  text-decoration: none; font-weight: 700; font-size: 1rem; letter-spacing: -.01em;
  transition: transform .16s;
}
.pfc-btn svg { width: 18px; height: 18px; }
.pfc-btn:hover { transform: translateY(-1px); }
.pfc-note { margin-top: 14px; font-size: .76rem; color: rgba(255, 255, 255, .4); }
/* Phone compaction (2026-08-04).

   Measured on a real 375x812 phone viewport, this unit rendered 593px tall —
   73% of the screen — because every element kept its desktop rhythm and the CTA
   label wrapped onto a second line (an 80px button, taller than the countdown).
   A single ad that fills three-quarters of the screen reads as an interstitial,
   which is the exact thing the "one unit per page, always after real content"
   rule in §2.5 exists to prevent. Target here is ~50% of a phone viewport.

   Breakpoint is 560px, not the old 520px: the common large phones (Pro Max /
   Ultra class, 428-430px CSS px) and every phone in landscape-ish widths sat
   just inside the old query but still needed the compaction. */
@media (max-width: 560px) {
  .pfc-in { padding: 24px 15px 22px; }
  .pfc-adlabel { margin-bottom: 10px; }
  .pfc-flag { margin-bottom: .55rem; }

  /* The hook is a decorative italic teaser and the sub-headline underneath
     already states the same offer in plainer words. On a phone it is the one
     line that can go: dropping it removes ~66px of stacked text above the
     headline without losing a single fact or claim. */
  .pfc-hook { display: none; }

  .pfc-title { font-size: clamp(1.45rem, 7vw, 1.9rem); margin-bottom: 8px; }
  .pfc-sub { font-size: .89rem; line-height: 1.5; margin-bottom: 16px; }

  .pfc-count { gap: 5px; margin-bottom: 18px; }
  .pfc-cell { min-width: 50px; padding: 7px 5px 6px; }
  .pfc-cell b { font-size: 1.3rem; }
  .pfc-sep { font-size: 1.2rem; line-height: 2.1; }

  /* Full-width block button. Inline-flex + horizontal padding is what let the
     label wrap; going full width and centring keeps it on one line and gives a
     comfortably large tap target at the same time. */
  .pfc-btn { display: flex; width: 100%; justify-content: center; padding: 13px 16px; font-size: .95rem; }
  .pfc-note { margin-top: 10px; }
}

/* legacy blocks still referenced by a few builds — retokened, not removed */
.pf-card { max-width: 860px; margin: 0 auto; border-radius: var(--radius-lg); overflow: hidden; background: #0d1117; border: 1px solid rgba(255,255,255,.09); position: relative; }
.pf-in { position: relative; padding: 32px; }
.pf-eyebrow { display: inline-block; font-size: .7rem; font-weight: 600; letter-spacing: .15em; text-transform: uppercase; color: rgba(255,255,255,.6); margin-bottom: 12px; }
.pf-title { font-family: var(--serif); font-size: clamp(1.3rem, 3.4vw, 1.85rem); font-weight: 500; letter-spacing: -.024em; color: #fff; line-height: 1.15; margin-bottom: 11px; max-width: 24ch; }
.pf-body { color: rgba(255,255,255,.7); font-size: .96rem; line-height: 1.62; max-width: 60ch; margin-bottom: 20px; }
.pf-btn { display: inline-flex; align-items: center; gap: 9px; padding: 12px 22px; border-radius: var(--radius-sm); background: #fff; color: #0d1117; text-decoration: none; font-weight: 600; font-size: .94rem; }
.pf-btn svg { width: 17px; height: 17px; }
.pf-note { margin-top: 14px; font-size: .76rem; color: rgba(255,255,255,.4); }
.ik-banner { position: relative; max-width: 980px; margin: 0 auto; overflow: hidden; border-radius: var(--radius-lg); border: 1px solid rgba(255,255,255,.1); background: linear-gradient(115deg, #071426 0%, #0c2b45 46%, #b0491f 88%, #f9a03f 105%); }
.ik-in { position: relative; padding: 30px; display: flex; flex-wrap: wrap; align-items: center; gap: 18px 28px; }
.ik-copy { flex: 1 1 320px; min-width: 0; }
.ik-eyebrow { font-size: .68rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: #f9c06b; margin-bottom: 8px; }
.ik-title { font-family: var(--serif); font-size: clamp(1.25rem, 3.4vw, 1.7rem); font-weight: 500; letter-spacing: -.024em; color: #fff; line-height: 1.18; margin-bottom: 8px; }
.ik-sub { color: rgba(255,255,255,.78); font-size: .92rem; line-height: 1.55; max-width: 52ch; }
.ik-btn { flex: none; display: inline-flex; align-items: center; gap: 9px; padding: 12px 22px; border-radius: var(--radius-sm); background: #fff; color: #0c2b45; text-decoration: none; font-weight: 700; font-size: .95rem; }
.ik-btn svg { width: 16px; height: 16px; }

/* ========================================================== 14. calculators
   State-change feedback only. The result updates instantly; nothing animates
   in, nothing slides, nothing fades. */
.calc {
  max-width: 620px; margin: var(--s4) 0 0; padding: var(--s4); text-align: left;
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--radius); box-shadow: none;
}
.calc .row { grid-template-columns: 1fr 1fr; gap: var(--s3); }
@media (max-width: 520px) { .calc .row { grid-template-columns: 1fr; } }
.calc input, .calc select { font-family: var(--sans); border-radius: var(--radius-sm); border-color: var(--line-2); background: var(--surface); color: var(--ink); font-variant-numeric: tabular-nums; }
.calc input:focus, .calc select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.calc .out { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--line); text-align: left; }
.calc .out .v { font-family: var(--sans); font-size: clamp(2rem, 7vw, 3rem); font-weight: 650; letter-spacing: -.045em; color: var(--accent); line-height: 1; font-variant-numeric: proportional-nums; }
.calc .out .k { font-size: .84rem; color: var(--muted); margin-top: var(--s2); }
.unit-toggle { display: inline-flex; gap: 3px; background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 3px; }
.unit-toggle button { border: 0; background: none; padding: 5px 11px; border-radius: 3px; font-size: .78rem; font-weight: 550; color: var(--muted); }
.unit-toggle button[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: none; border: 1px solid var(--line-2); }
:root[data-theme="dark"] .unit-toggle button[aria-pressed="true"] { background: var(--surface); }
.lbl-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.lbl-row label { margin-bottom: 0; }

/* ======================================================== 15. comparisons */
.vs { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--s3); align-items: stretch; max-width: 820px; margin: var(--s4) 0 0; }
.vs-side { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; text-align: left; box-shadow: none; }
.vs-side.win { border-color: var(--accent); box-shadow: none; border-left-width: 3px; }
.vs-side h2 { font-family: var(--serif); font-size: 1.05rem; font-weight: 500; letter-spacing: -.02em; margin-bottom: 10px; }
.vs-side .v { font-family: var(--sans); font-size: clamp(1.6rem, 5vw, 2.3rem); font-weight: 650; letter-spacing: -.04em; color: var(--accent); font-variant-numeric: proportional-nums; line-height: 1.1; }
.vs-side .s { font-size: .82rem; color: var(--muted); margin-top: 4px; }
.vs-side .badge { display: inline-block; margin-top: 12px; font-size: .68rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--accent); background: var(--accent-soft); padding: 4px 10px; border-radius: 999px; }
.vs-mid { display: grid; place-items: center; font-size: .7rem; font-weight: 600; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); }
@media (max-width: 620px) { .vs { grid-template-columns: 1fr; } .vs-mid { padding: 4px 0; } }

/* ================================================== 16. the diagram moments
   §5: each page keeps one interactive set piece an AI answer cannot
   replicate. Design and AI-Overview defence are the same work, so these are
   treated as first-class components, not decoration.                        */

/* ---- shared SVG figure chrome -------------------------------------------- */
.figure, .routemap, .plan, .dial-wrap, .bandchart {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--s3); box-shadow: none; overflow: hidden;
}
.figure svg, .routemap svg, .plan svg, .dial-wrap svg, .bandchart svg { width: 100%; height: auto; }
.figure-cap { font-size: .82rem; color: var(--muted); margin-top: 10px; }
/* SVG text scales with the viewBox — on a narrow screen an 11px label renders
   at about 5px. Bump it, or the diagram is decorative rather than readable. */
@media (max-width: 760px) {
  .figure text, .routemap text, .plan text, .dial-wrap text, .bandchart text { font-size: 20px; }
  .figure .lab-lg, .dial-wrap .lab-lg, .bandchart .lab-lg { font-size: 24px; }
}

/* fly — great-circle route strip */
.routemap .land { fill: color-mix(in srgb, var(--ink) 8%, transparent); }
.routemap .grat { stroke: var(--line); stroke-width: .4; fill: none; }
.routemap .arc { stroke: var(--accent); stroke-width: 2; fill: none; stroke-linecap: round; }
.routemap .pin { fill: var(--accent); }
.routemap .plab { fill: var(--ink-2); font-size: 7px; font-weight: 600; font-family: var(--sans); }

/* lux — the ceiling plan, kept as-is structurally and simply retokened */
.plan .room { fill: color-mix(in srgb, var(--accent) 5%, transparent); stroke: var(--ink-2); stroke-width: 1.6; }
.plan .fix { fill: var(--accent); }
.plan .fixring { fill: none; stroke: var(--accent); stroke-width: 1; opacity: .35; }
.plan .dim { stroke: var(--muted); stroke-width: .7; }
.plan .dimtext { fill: var(--muted); font-size: 9px; font-weight: 500; font-family: var(--sans); }
.plan .beam { fill: color-mix(in srgb, var(--accent) 13%, transparent); }

/* read — the pages ↔ hours progress bar (also used by any "X of Y" figure) */
.progress { display: grid; gap: 12px; margin-top: var(--s3); }
.progress-row { display: grid; grid-template-columns: 118px 1fr auto; gap: 14px; align-items: center; }
.progress-track { display: block; height: 22px; position: relative; background: var(--paper-2); border: 1px solid var(--line); border-radius: 0 3px 3px 0; }
.progress-fill { display: block; height: 20px; background: var(--accent); border-radius: 0 3px 3px 0; min-width: 2px; }
.progress-row .lbl { font-size: .9rem; color: var(--ink-2); }
.progress-row .val { font-size: .94rem; font-weight: 620; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.progress-row .cnt { font-size: .78rem; color: var(--faint); font-variant-numeric: tabular-nums; }
@media (max-width: 560px) { .progress-row { grid-template-columns: 92px 1fr auto; gap: 10px; } }

/* cook — the doneness-temperature dial */
.dial-wrap { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr); gap: var(--s4); align-items: center; }
@media (max-width: 640px) { .dial-wrap { grid-template-columns: 1fr; } }
.dial .track { fill: none; stroke: var(--line); stroke-width: 14; stroke-linecap: round; }
.dial .zone-rare { stroke: #B14A1E; }
.dial .zone-med { stroke: #8A5A14; }
.dial .zone-well { stroke: #2F6B3F; }
.dial .zone { fill: none; stroke-width: 14; opacity: .32; }
.dial .needle { stroke: var(--ink); stroke-width: 3; stroke-linecap: round; transition: transform .18s ease; transform-origin: 100px 100px; }
.dial .hubdot { fill: var(--ink); }
.dial .tick { stroke: var(--line-2); stroke-width: 1.4; }
.dial .ticklab { fill: var(--muted); font-size: 9px; font-family: var(--sans); font-variant-numeric: tabular-nums; }
.dial .readout { fill: var(--ink); font-family: var(--sans); font-size: 26px; font-weight: 650; font-variant-numeric: proportional-nums; }
.dial .readsub { fill: var(--muted); font-family: var(--sans); font-size: 9px; letter-spacing: .12em; text-transform: uppercase; }
@media (prefers-reduced-motion: reduce) { .dial .needle { transition: none; } }
.dial-choices { display: flex; flex-wrap: wrap; gap: 6px; }
.dial-choices button {
  border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-2);
  padding: 8px 14px; border-radius: 999px; font-size: .85rem; font-weight: 550;
}
.dial-choices button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }

/* sehat — the Asian-Indian vs Western BMI band comparison */
.bandchart .band-w { fill: color-mix(in srgb, var(--ink) 10%, transparent); }
.bandchart .band-a { fill: color-mix(in srgb, var(--accent) 22%, transparent); }
.bandchart .band-edge { stroke: var(--line-2); stroke-width: .8; }
.bandchart .marker { stroke: var(--ink); stroke-width: 2.4; stroke-linecap: round; }
.bandchart .lab { fill: var(--muted); font-size: 10px; font-family: var(--sans); }
.bandchart .lab-lg { fill: var(--ink); font-size: 12px; font-weight: 650; font-family: var(--sans); }
.band-legend { display: flex; flex-wrap: wrap; gap: var(--s3); font-size: .84rem; color: var(--muted); margin-top: 12px; }
.band-legend span { display: inline-flex; align-items: center; gap: 7px; }
.band-legend i { width: 14px; height: 10px; border-radius: 2px; display: inline-block; }
.bandchart { color: var(--ink); position: relative; }
.bandchart svg { display: block; width: 100%; }
.bc-axis { position: relative; height: 18px; margin-top: 2px; }
.bc-axis span { position: absolute; transform: translateX(-50%); font-size: .72rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.bc-rows { display: flex; justify-content: space-between; font-size: .72rem; font-weight: 600; letter-spacing: .11em; text-transform: uppercase; color: var(--muted); margin-top: 4px; }
.bc-slide { display: flex; align-items: center; gap: 12px; margin-top: var(--s3); font-size: .85rem; color: var(--muted); }
.bc-slide input { flex: 1; min-width: 120px; accent-color: var(--accent); }
.bc-slide output { font-family: var(--sans); font-size: 1.15rem; font-weight: 650; color: var(--ink); font-variant-numeric: tabular-nums; min-width: 3.5ch; text-align: right; }

/* thali — katori / roti unit iconography beside every figure */
.unitfig { display: inline-flex; align-items: baseline; gap: 8px; }
.unitfig svg { width: 20px; height: 20px; align-self: center; color: var(--accent); flex: none; }
.unit-icon { color: var(--accent); vertical-align: -.2em; width: 18px; height: 18px; display: inline-block; flex: none; }
.unit-icon-lg { width: clamp(30px, 6vw, 46px); height: clamp(30px, 6vw, 46px); stroke-width: 1.2; }
.assume svg { color: var(--accent); }
.serving-note { font-size: .84rem; color: var(--muted); display: flex; align-items: center; gap: 8px; margin-top: 6px; }

/* gym — city page hero: count + a map-ish locality strip */
.city-hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: var(--s5); align-items: end; }
@media (max-width: 900px) { .city-hero { grid-template-columns: 1fr; gap: var(--s4); } }
.citystrip { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); padding: var(--s3); }
.citystrip svg { width: 100%; height: auto; }
.citystrip .cs-grid { stroke: var(--line); stroke-width: .6; }
.citystrip .cs-dot { fill: var(--accent); opacity: .55; }
.citystrip .cs-dot.is-big { opacity: 1; }
.citystrip .cs-lab { fill: var(--muted); font-size: 8px; font-family: var(--sans); }
.citystrip-cap { font-size: .8rem; color: var(--muted); margin-top: 10px; }

/* ============================================================== 17. callouts */
.note {
  border: 0; border-left: 3px solid var(--accent); background: none;
  border-radius: 0; padding: 2px 0 2px var(--s3); font-size: .93rem; color: var(--ink-2); line-height: 1.6;
  max-width: var(--measure);
}
.note strong { color: var(--ink); }

/* ============================================================== 18. buttons */
.btn { border-radius: var(--radius-sm); font-weight: 600; letter-spacing: -.01em; }
.btn-primary { background: var(--accent); color: #fff; box-shadow: none; }
.btn-primary:hover { transform: none; background: var(--accent); filter: brightness(.92); }
.btn-ghost { background: var(--surface); border-color: var(--line-2); color: var(--ink-2); box-shadow: none; }
.btn-ghost:hover { transform: none; border-color: var(--accent); color: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm); }

/* --- accent derivation (must live on body, not :root) ----------------------
   shell() injects the hue as <body style="--site-accent:…">. Custom properties
   inherit DOWNWARD only, so the :root derivation above can never see it and
   every site silently painted the neutral slate fallback. Re-derived here, on
   the element that actually carries the variable. Dark cuts override --accent
   directly below, because the inline --site-accent outranks any stylesheet. */
body {
  --accent: var(--site-accent, #3C4A55);
  --accent-2: var(--site-accent, #3C4A55);
  --accent-3: var(--site-accent, #3C4A55);
  --accent-soft: color-mix(in srgb, var(--accent) 9%, var(--paper));
  /* AAA+++ FIX 2026-07-31: these two shipped in :root, where --accent still
     resolves to the #3C4A55 fallback because --site-accent is written on
     <body>. Result: on EVERY Identity A site the kickers, method step numbers
     and the .formula wash painted slate next to a correctly-accented keel.
     Same reason --accent-soft is redeclared here — they must live on the
     element that actually carries the variable. */
  --accent-deep: color-mix(in srgb, var(--accent) 78%, var(--ink));
  --accent-wash: color-mix(in srgb, var(--accent) 7%, var(--paper));
}

/* ==================================================== 19. per-site accents
   ONE hue per site, set on <body> by shell(). These blocks exist so that the
   dark theme can swap in a lighter cut of the same hue — a #7C5A22 ochre that
   is correct on warm paper is unreadable on near-black.
   Cluster G: slate / ochre / moss editorial range.
   Cluster I: a warmer band — saffron, deep green, chai brown — so the India
   ring reads as the same family at a different temperature.
   Every value below is validated by _shared/contrast-check.mjs.             */
:root[data-theme="dark"] body[data-site="burn"]  { --accent: #E8875A; --accent-2: #E8875A; --accent-3: #E8875A; --accent-soft: color-mix(in srgb, #E8875A 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="fuel"]  { --accent: #6FBF86; --accent-2: #6FBF86; --accent-3: #6FBF86; --accent-soft: color-mix(in srgb, #6FBF86 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="fly"]   { --accent: #63B4D6; --accent-2: #63B4D6; --accent-3: #63B4D6; --accent-soft: color-mix(in srgb, #63B4D6 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="lux"]   { --accent: #D9A85C; --accent-2: #D9A85C; --accent-3: #D9A85C; --accent-soft: color-mix(in srgb, #D9A85C 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="watts"] { --accent: #A79BE8; --accent-2: #A79BE8; --accent-3: #A79BE8; --accent-soft: color-mix(in srgb, #A79BE8 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="read"]  { --accent: #E4849B; --accent-2: #E4849B; --accent-3: #E4849B; --accent-soft: color-mix(in srgb, #E4849B 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="mpg"]   { --accent: #5FC0AC; --accent-2: #5FC0AC; --accent-3: #5FC0AC; --accent-soft: color-mix(in srgb, #5FC0AC 14%, var(--paper)); }
/* FIX 2026-08-04: salary had NO dark cut, so PayLens rendered its light
   accent #2F5D50 straight onto basalt — 2.44:1, unreadable. It went unnoticed
   because the site was never listed in contrast-check.mjs; it is now. This is
   a lighter cut of the same hue, in the family of the mpg/grow greens. */
:root[data-theme="dark"] body[data-site="salary"] { --accent: #5FBFA6; --accent-2: #5FBFA6; --accent-3: #5FBFA6; --accent-soft: color-mix(in srgb, #5FBFA6 14%, var(--paper)); }

/* The five Sideline editions. The clubsring engine was injecting these into its
   own <head> because it may not edit this file; registering them here means the
   dark cut applies wherever a clubs page is rendered, and lets the engine drop
   that injection. Field-guide palette, authored in clubsring/countries.mjs —
   keep the two in step. All five verified by contrast-check.mjs. */
:root[data-theme="dark"] body[data-site="clubs"] { --accent: #63BE97; --accent-2: #63BE97; --accent-3: #63BE97; --accent-soft: color-mix(in srgb, #63BE97 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="au"]    { --accent: #A9C46A; --accent-2: #A9C46A; --accent-3: #A9C46A; --accent-soft: color-mix(in srgb, #A9C46A 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="ca"]    { --accent: #7FB6D9; --accent-2: #7FB6D9; --accent-3: #7FB6D9; --accent-soft: color-mix(in srgb, #7FB6D9 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="us"]    { --accent: #A79FD2; --accent-2: #A79FD2; --accent-3: #A79FD2; --accent-soft: color-mix(in srgb, #A79FD2 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="pac"]   { --accent: #68BDBF; --accent-2: #68BDBF; --accent-3: #68BDBF; --accent-soft: color-mix(in srgb, #68BDBF 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="cook"]  { --accent: #E8887E; --accent-2: #E8887E; --accent-3: #E8887E; --accent-soft: color-mix(in srgb, #E8887E 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="tire"]  { --accent: #9DB2CC; --accent-2: #9DB2CC; --accent-3: #9DB2CC; --accent-soft: color-mix(in srgb, #9DB2CC 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="thali"] { --accent: #E28A5C; --accent-2: #E28A5C; --accent-3: #E28A5C; --accent-soft: color-mix(in srgb, #E28A5C 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="sehat"] { --accent: #5CBFB2; --accent-2: #5CBFB2; --accent-3: #5CBFB2; --accent-soft: color-mix(in srgb, #5CBFB2 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="gym"]   { --accent: #D2A468; --accent-2: #D2A468; --accent-3: #D2A468; --accent-soft: color-mix(in srgb, #D2A468 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="yoga"]  { --accent: #C58FBA; --accent-2: #C58FBA; --accent-3: #C58FBA; --accent-soft: color-mix(in srgb, #C58FBA 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="move"]  { --accent: #78B0DA; --accent-2: #78B0DA; --accent-3: #78B0DA; --accent-soft: color-mix(in srgb, #78B0DA 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="diet"]  { --accent: #A2C464; --accent-2: #A2C464; --accent-3: #A2C464; --accent-soft: color-mix(in srgb, #A2C464 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="run"]   { --accent: #E08F5C; --accent-2: #E08F5C; --accent-3: #E08F5C; --accent-soft: color-mix(in srgb, #E08F5C 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="grow"]  { --accent: #5BC0AE; --accent-2: #5BC0AE; --accent-3: #5BC0AE; --accent-soft: color-mix(in srgb, #5BC0AE 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="fast"]  { --accent: #D6A94F; --accent-2: #D6A94F; --accent-3: #D6A94F; --accent-soft: color-mix(in srgb, #D6A94F 14%, var(--paper)); }
:root[data-theme="dark"] body[data-site="sugar"] { --accent: #E1857C; --accent-2: #E1857C; --accent-3: #E1857C; --accent-soft: color-mix(in srgb, #E1857C 14%, var(--paper)); }

/* ============================================================== 20. motion
   None decorative. Only state-change feedback and the interactive diagrams,
   and all of it surrenders to prefers-reduced-motion (the base reset in
   styles.css nukes durations; these rules remove transforms too).          */
@media (prefers-reduced-motion: reduce) {
  .ring-card:hover, .btn:hover, .grid a:hover, .pfc-btn:hover, .icon-btn:hover { transform: none !important; }
}

/* ====================================================== 14. the publisher row
   "Published by Amit Sharma" + follow links, above the legal footer on every
   page. Deliberately quiet: this is a masthead credit, not a call to action —
   the page has exactly one CTA and it is the house-ad slot above. Reads as
   provenance, which is the same reason the dated-source line is styled. */
.pub {
  border-top: 1px solid var(--rule);
  background: var(--paper);
}
.pub-in {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 3rem;
  align-items: flex-start;
  justify-content: space-between;
  padding: 1.75rem 0;
}
.pub-k {
  font-size: .7rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 .35rem;
}
.pub-name {
  font-family: var(--font-display, Fraunces, Georgia, serif);
  font-size: 1.35rem;
  line-height: 1.1;
  margin: 0 0 .3rem;
}
.pub-name a { color: var(--ink); text-decoration: none; }
.pub-name a:hover { text-decoration: underline; text-underline-offset: .18em; }
.pub-tag {
  margin: 0;
  font-size: .85rem;
  color: var(--ink-2, var(--muted));
  max-width: 46ch;
}
.pub-socs { display: flex; flex-wrap: wrap; gap: .5rem; }
.pub-soc {
  --pub-ico-bg: var(--paper);
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .45rem .7rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink);
  text-decoration: none;
  font-size: .8rem;
  line-height: 1;
  background: var(--paper);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.pub-soc svg { width: 16px; height: 16px; flex: none; }
.pub-soc:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.pub-soc:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
@media (max-width: 560px) {
  .pub-soc-l { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .pub-soc { padding: .55rem; }
}

/* ============================================ 15. house-ad urgency flag (§2.5)
   The two facts that make the offer worth a click — it costs nothing and it
   ends — used to sit in 12px small print under the button. They now lead. */
.pfc-flag {
  margin: 0 0 .75rem;
  display: flex;
  justify-content: center;
}
.pfc-flag span {
  display: inline-block;
  padding: .35rem .8rem;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(255,255,255,.08);
}

/* per-site sheets (thali.css, gym.css, sehat.css …) load AFTER this file and
   may override anything above for their own set piece. */

/* --- Follow strip (social distribution) ------------------------------------
   Sits at the top of the footer on tools/property/india cluster sites only —
   see SOCIAL_CLUSTERS in globalsite.mjs for why the global ring is excluded.
   Deliberately quiet: this is a standing credit line, not a house ad. It must
   never out-shout the page's own content or the one campaign banner. */
.soc-strip{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:.75rem 1.25rem;padding:1rem 0 1.15rem;border-bottom:1px solid var(--rule);
}
.soc-lead{margin:0;font-size:.9rem;color:var(--muted);max-width:46ch}
.soc-lead strong{color:var(--ink);font-weight:600}
.soc-links{display:flex;flex-wrap:wrap;gap:.5rem}
.soc-link{
  display:inline-block;padding:.35rem .7rem;border:1px solid var(--rule);
  border-radius:999px;font-size:.82rem;line-height:1.35;color:var(--ink);
  text-decoration:none;background:var(--surface);
}
.soc-link:hover,.soc-link:focus-visible{
  border-color:var(--site-accent);color:var(--site-accent);
}
@media (max-width:640px){
  .soc-strip{flex-direction:column;align-items:flex-start}
  .soc-lead{max-width:none}
}

/* ============================================================================
   20. AAA+++ STUDIO PREMIUM — the mechanics layer
   Fable's spec: _plans/AAA-PLUS-STUDIO-PREMIUM.md §3, §4, §6.1.
   Everything here is NEW selectors or additive properties on existing ones.
   No rule below removes or overrides a layout property, so CLS stays 0.00.
   ========================================================================== */

/* ---- 20.1 the mono "spec" voice ---------------------------------------- */
/* Provenance, units, codes and vintages set as specification, not prose. This
   single register is the loudest signal that someone measured something. */
.spec,
.srcline,
.crumbs,
.vintage,
.freshness,
.kicker,
.eyebrow {
  font-family: var(--mono);
  font-size: var(--fs-mono);
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums lining-nums;
}
.spec { color: var(--muted); }
/* display:block was only ever set inside .ymyl, so a kicker used as the eyebrow
   above an h1 — its whole purpose — ran inline with the heading. */
.kicker, .eyebrow { display: block; text-transform: uppercase; letter-spacing: var(--track-label); color: var(--accent-deep); }

/* ---- 20.2 optical type scale + real Fraunces tuning -------------------- */
/* Fraunces is already served as a variable font with its opsz 9-144 axis. The
   axis was never used, which is why display type read like one weight applied
   everywhere — the tell that no typographer was paid. Two extremes per page. */
h1,
.figure-hero-serif {
  font-optical-sizing: none;
  font-variation-settings: "opsz" 84, "SOFT" 0, "WONK" 0;
}
.stat-display {
  font-family: var(--serif);
  font-weight: 340;
  font-size: var(--fs-stat);
  line-height: .92;
  font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 0;
  letter-spacing: -.02em;
  font-variant-numeric: proportional-nums lining-nums;
}
.stat-display .u { font-family: var(--mono); font-size: .26em; letter-spacing: .08em; color: var(--muted); vertical-align: .5em; margin-left: .3em; }
/* FIX 2026-07-31: §3's `.answer p` (0,1,1) outranks `.stat-display` (0,1,0),
   so a hero figure marked up as a <p> inside the answer block rendered at
   BODY size on every Identity A site — the one number the page exists to show,
   silently shrunk to 16px. Matching specificity here rather than raising
   .stat-display's, so the rule stays scoped to where the collision happens. */
.answer .stat-display,
.answer p.stat-display { font-size: var(--fs-stat); line-height: .92; color: var(--ink); }

/* ---- 20.3 hairline discipline: the keel ------------------------------- */
/* Section anatomy borrowed from the trades pair. A 44x2 accent rule above the
   kicker gives every section a datum line, which is what stops a long page
   from reading as stacked boxes. */
h2.sec::before,
.keel::before {
  content: "";
  display: block;
  width: 44px;
  height: 2px;
  background: var(--accent);
  margin-bottom: 14px;
}

/* ---- 20.4 tabular numerals with intent -------------------------------- */
/* Compared or copied -> tabular (columns must not jiggle).
   Display typography -> proportional (handled in .stat-display above). */
.num,
td.n,
.result-v,
table.data td,
table.data th,
.pager {
  font-variant-numeric: tabular-nums lining-nums;
}

/* ---- 20.5 grain: paper as material ----------------------------------- */
/* Pure CSS, one fixed non-interactive layer, zero requests. The dead-flat hex
   fill was what made the ground read as a CSS variable rather than paper. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: var(--grain-alpha);
  background-image:
    repeating-linear-gradient(0deg,  rgba(20, 24, 27, .9) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(20, 24, 27, .7) 0 1px, transparent 1px 4px);
  background-size: 3px 3px, 4px 4px;
  mix-blend-mode: multiply;
}
:root[data-theme="dark"] body::before { mix-blend-mode: screen; opacity: .02; }
body > header, body > main, body > footer, .netbar, .site-head, .site-foot { position: relative; z-index: 1; }
@media print { body::before { display: none; } }

/* ---- 20.6 focus & hover with intent ---------------------------------- */
/* Hover on a text link DRAWS an underline; it does not swap a colour. Hover on
   a card darkens its hairline and never moves it (motion here would cost CLS
   and reads as a template animation). Focus is never removed. */
a.draw,
.rel-card .rel-t,
.entity-bridge a {
  text-decoration: none;
  background: linear-gradient(var(--accent), var(--accent)) 0 100% / 0 1px no-repeat;
  transition: background-size var(--t-med) var(--ease-out);
}
a.draw:hover, a.draw:focus-visible,
.rel-card:hover .rel-t,
.entity-bridge a:hover { background-size: 100% 1px; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* ---- 20.7 elevation: exactly one shadow ------------------------------ */
.card, .rel-card, .stat, .tbl-wrap, .link-grid a { box-shadow: none; }
.lift, .lead-panel { box-shadow: var(--shadow-lift); }
:root[data-theme="dark"] .lift,
:root[data-theme="dark"] .lead-panel { box-shadow: none; background: var(--surface); border-color: var(--line-2); }

/* ---- 20.8 entrance choreography -------------------------------------- */
/* Above the fold, once, on load. Gated behind no-preference so reduced-motion
   and no-JS readers get the finished page rather than content stranded at
   opacity 0 — the failure mode that reveal-on-scroll libraries ship with. */
@media (prefers-reduced-motion: no-preference) {
  .reveal { animation: aaa-rise var(--t-slow) var(--ease-out) both; }
  .reveal-2 { animation-delay: 60ms; }
  .reveal-3 { animation-delay: 120ms; }
  @keyframes aaa-rise { from { opacity: 0; transform: translateY(12px); } }
}
/* PRINT FIX 2026-08-04, found by the TireFit build. `animation-fill-mode: both`
   applies the BACKWARDS fill — the `from` keyframe — even in print, where the
   animation never runs. The from-state is opacity 0, so the reveal stack
   (kicker, h1, the answer block: the three things a printed page most needs)
   rendered BLANK on every Identity A site. Nobody would have seen it on
   screen. Neutralised explicitly rather than by dropping `both`, because the
   fill is what stops the pre-animation flash on screen. */
@media print {
  .reveal, .reveal-2, .reveal-3 {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ---- 20.9 the promoted source line (E-E-A-T as ornament) -------------- */
/* Doctrine: no figure without a source line, no source line without a date.
   Identical position under every figure, table and diagram, on every site. */
.srcline {
  display: block;
  border-top: 1px solid var(--line);
  padding-top: 8px;
  margin-top: 12px;
  color: var(--muted);
  text-transform: uppercase;
}
.srcline .sep { color: var(--faint); margin: 0 .5em; }
.srcline a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--line-2); }
.srcline a:hover { color: var(--ink-2); border-bottom-color: var(--accent); }

/* ---- 20.10 the answer block, unboxed --------------------------------- */
/* Was a bordered card with a 3px left accent — the Bootstrap-alert shape. The
   answer is the reason the page exists; it should be open typography on paper
   with one hairline under it, not a component. */
.answer.aaa {
  background: none;
  border: 0;
  padding: 0;
  border-radius: 0;
}
.answer.aaa .big { font-family: var(--serif); font-weight: 340; font-size: var(--fs-stat); line-height: .92; letter-spacing: -.02em; font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 0; }
.answer.aaa > .srcline { margin-top: 16px; }

/* ---- 20.11 the method mini-spec -------------------------------------- */
/* A prose paragraph titled "how we compute this" is skipped by every reader.
   Numbered, ruled, with the formula in the mono voice, it gets read — and it
   is the visible half of the E-E-A-T claim. */
.method { margin: var(--s5) 0; }
.method ol { list-style: none; margin: 0; padding: 0; counter-reset: mstep; }
.method li {
  counter-increment: mstep;
  border-top: 1px solid var(--line);
  padding: 14px 0 14px 44px;
  position: relative;
  color: var(--ink-2);
}
.method li:last-child { border-bottom: 1px solid var(--line); }
.method li::before {
  content: counter(mstep, decimal-leading-zero);
  position: absolute; left: 0; top: 14px;
  font-family: var(--mono); font-size: var(--fs-mono);
  letter-spacing: .06em; color: var(--accent-deep);
}
.method .formula {
  font-family: var(--mono);
  font-size: .875rem;
  background: var(--accent-wash);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin: 10px 0 0;
  overflow-x: auto;
  white-space: pre;
}

/* ---- 20.12 related cards that earn the click (spec 6.1) --------------- */
/* The old ring cards were identical rounded boxes with a generic blurb and a
   "go" arrow, i.e. the reader was given no reason to click. This is the one
   place where link design and SEO are literally the same work, so the reason
   line is mandatory and must not be transplantable to another card. */
.rel-grid { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); margin-top: var(--s4); }
.rel-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 18px 18px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 2px solid var(--accent);
  border-radius: 0 0 var(--radius) var(--radius);
  text-decoration: none; color: inherit;
  transition: border-color var(--t-fast) var(--ease-out);
}
.rel-card:hover { border-color: var(--line-2); border-top-color: var(--accent); }
.rel-card .rel-t { font-weight: 650; color: var(--ink); font-size: 1.02rem; align-self: flex-start; }
.rel-card .rel-why { color: var(--ink-2); font-size: .92rem; line-height: 1.5; margin: 0; }
/* --faint measures 3.35:1 on dark paper, under the 4.5:1 floor. The freshness
   chip is a DATED E-E-A-T signal, not decoration — if it is too pale to read
   it is doing the opposite of its job. --muted is 5.6:1. */
.rel-card .freshness { margin-top: auto; padding-top: 10px; color: var(--muted); align-self: flex-end; }
/* Exactly one bridge card per page; the dashed edge is its "different family"
   grammar, so a reader is never surprised by where it lands. */
.rel-card.bridge { border-style: dashed; border-top-style: solid; background: var(--paper-2); }

/* ---- 20.13 netbar promoted from utility strip ------------------------- */
.netbar .net-label { font-family: var(--mono); font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; opacity: .72; }
/* FIX 2026-07-31: this was written as .net-dot, but globalsite.mjs has always
   emitted .nb-dot — so the rule was dead code on all 24 ring sites. */
.netbar .nb-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.netbar a { transition: opacity var(--t-fast) var(--ease-out); }

/* ---- 20.14 table caption vintage chip -------------------------------- */
table.data caption .vintage,
.tbl-wrap .vintage {
  display: inline-block;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: 2px 7px;
  color: var(--muted);
  text-transform: uppercase;
  margin-left: 10px;
}

/* ---- 20.15 YMYL armour band (spec 6.5) ------------------------------- */
/* Calm and ruled, never a red alert box. A scary banner above a health figure
   reads as liability panic; a hairline-ruled note reads as a journal. */
.ymyl {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 14px 0;
  margin: var(--s4) 0;
  color: var(--ink-2);
  font-size: .93rem;
}
.ymyl .kicker { display: block; margin-bottom: 6px; }

/* ---- 20.16 confident emptiness --------------------------------------- */
/* At least one full-width near-white breath per page. Cheap sites fill;
   expensive sites breathe. */
.breathe { min-height: 18vh; }
@media (max-width: 640px) { .breathe { min-height: 10vh; } }

/* ---- 20.17 the AdSense slot (pre-built 2026-08-04) --------------------
   Written BEFORE the units exist, deliberately. `adUnit()` renders nothing
   while AD_SLOTS is empty, so until approval lands this whole block is inert
   — but the day a slot id is pasted in, ~90,000 pages start rendering an
   <aside class="ad-slot"> that had no rules at all, on every site at once.
   That is not a thing to discover in production.

   Three jobs, in order of importance:
   1. LOOK FOREIGN. An ad that borrows the page's own typography reads as an
      endorsement, and AdSense policy is explicit that ads must not be
      confusable with content. So: a ruled band on the paper-2 ground, the
      label in the mono spec voice, and no serif anywhere near it.
   2. RESERVE ITS SPACE. min-height is already inline on the <ins> for CLS,
      and the reservation is repeated here so the aside holds the box even
      before the iframe arrives.
   3. STAY QUIET. Hairlines, not boxes. This is the floor of the revenue
      stack, not the point of the page — see the revenue doctrine. */
.ad-slot {
  display: block;
  margin: var(--s5) auto;
  max-width: 100%;
  padding: 12px 0 14px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: transparent;
  text-align: center;
  /* An ad is never part of the reading measure — it spans the column but is
     visibly outside the argument. */
  clear: both;
}
.ad-label {
  display: block;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: var(--track-label, .11em);
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 10px;
  text-align: left;
}
.ad-slot .adsbygoogle { display: block; width: 100%; }
/* The in-content unit sits inside a .wrap already; the pre-footer one is
   emitted by shell() outside any wrapper, so it needs its own gutter. */
.ad-slot--pre-footer {
  max-width: var(--max);
  padding-left: 28px; padding-right: 28px;
  margin-top: var(--s6);
}
:root[data-theme="dark"] .ad-slot { border-color: var(--line-2); }
@media (max-width: 640px) {
  .ad-slot { margin: var(--s4) auto; }
  .ad-slot--pre-footer { padding-left: 20px; padding-right: 20px; }
}

/* ============================================================================
   tides.css — NZ Tide Times, site-local layer.

   Loads after vendor/styles.css + vendor/datasite.css (Identity A). Everything
   the ring owns — paper, ink ramp, hairlines, .stats, .srcline, .tablewrap +
   table.data, .note, .ring*, .ad-slot, h2.sec, .prose, .eyebrow, .lede — comes
   from those and is not restated. This file adds the chrome (this site is on the
   standalone pattern, so it carries its own masthead/footer) and the site's own
   drawing hand: the tide rows, the day curve, and the safety block.

   The hand: a tide is a WAVE, so this site's marks are curved where School
   Finder's are square. One accent, no red/green — an ebb is not a failure.
   ========================================================================== */

/* ------------------------------------------------------------------ chrome */
.netbar-in { display: flex; align-items: center; gap: var(--s4); height: 34px; font-size: .78rem; }
.netbar-label { color: #B9C2C9; font-weight: 550; }
.netbar-links { display: flex; gap: var(--s3); margin-left: auto; }
.netbar-links a { color: #E6EAEE; text-decoration: none; }
.netbar-links a:hover { color: #fff; text-decoration: underline; }

.masthead { border-bottom: 1px solid var(--line); background: var(--surface); position: sticky; top: 0; z-index: 40; }
.masthead-in { display: flex; align-items: center; justify-content: space-between; height: 62px; }
.brand { display: inline-flex; align-items: center; gap: 9px; font-family: var(--serif);
  font-size: 1.06rem; font-weight: 500; letter-spacing: -.02em; color: var(--ink); text-decoration: none; }
.brand svg { width: 26px; height: 26px; flex: none; }
.nav { display: flex; align-items: center; gap: var(--s4); font-size: .89rem; }
.nav a { color: var(--ink-2); text-decoration: none; }
.nav a:hover { color: var(--accent); text-decoration: underline; }
.tbtn { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: transparent; color: var(--ink-2); cursor: pointer; }
.tbtn:hover { border-color: var(--line-2); color: var(--accent); }

.foot { border-top: 1px solid var(--line); background: var(--paper-2); padding: var(--s7) 0 var(--s5); margin-top: var(--s8); }
.foot-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s5); }
.foot-grid h4 { font-family: var(--sans); font-size: .71rem; font-weight: 600; letter-spacing: .11em;
  text-transform: uppercase; color: var(--muted); margin-bottom: var(--s2); }
.foot-grid a { display: block; font-size: .88rem; color: var(--ink-2); text-decoration: none; padding: 4px 0; }
.foot-grid a:hover { color: var(--accent); text-decoration: underline; }
.foot-base { margin-top: var(--s6); padding-top: var(--s4); border-top: 1px solid var(--line); }
.foot-base p { font-size: .8rem; color: var(--muted); line-height: 1.6; margin-bottom: var(--s2); max-width: 78ch; }
.page { padding-top: var(--s5); padding-bottom: var(--s6); }

/* --------------------------------------------------------- the safety block
   The most important object on the site. Styled to be unmissable and calm at
   the same time: a solid top rule and an accent left edge, never a red alarm
   box. Red would make a routine tide table look like a warning, and a warning
   that fires on every page is a warning nobody reads. */
.safety {
  border-top: 2px solid var(--ink);
  border-left: 3px solid var(--accent);
  background: var(--surface);
  padding: var(--s3) var(--s4);
  margin: var(--s4) 0 var(--s5);
  max-width: 74ch;
}
.safety .kicker { font-family: var(--mono); font-size: .68rem; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 7px; }
.safety p:last-child { font-size: .9rem; line-height: 1.62; color: var(--ink-2); margin: 0; }
.safety strong { color: var(--ink); font-weight: 620; }
.safety a { color: var(--accent); font-weight: 550; }

/* ------------------------------------------------------------- tide rows
   The product. A person opening this site wants one number, so the time is set
   at display size and everything else defers to it. */
.day { margin: var(--s4) 0 var(--s5); }
.dayh { display: flex; align-items: baseline; gap: var(--s3); margin-bottom: var(--s2);
  padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.dayh .dow { font-family: var(--serif); font-size: 1.08rem; font-weight: 500; color: var(--ink); }
.dayh .dnum { font-family: var(--mono); font-size: .76rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); }
.tides { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 0; }
.tide { display: flex; flex-direction: column; gap: 2px; padding: var(--s3) var(--s3) var(--s3) 0;
  border-right: 1px solid var(--line); }
.tide:last-child { border-right: 0; }
.tk { font-family: var(--sans); font-size: .68rem; font-weight: 600; letter-spacing: .11em;
  text-transform: uppercase; color: var(--muted); }
.tt { font-family: var(--serif); font-size: 1.85rem; font-weight: 500; letter-spacing: -.02em;
  color: var(--ink); line-height: 1.05; font-variant-numeric: tabular-nums; }
.th { font-family: var(--mono); font-size: .85rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.th em { font-style: normal; color: var(--muted); margin-left: 1px; }
/* High and low are distinguished by WEIGHT of the rule, not by colour: a low
   tide is not a bad tide, and a red/green pair would say it was. */
.tide.hi { border-top: 2px solid var(--accent); }
.tide.lo { border-top: 2px solid var(--line-2); }

.inline-tide { display: inline-block; margin-right: var(--s3); font-variant-numeric: tabular-nums;
  font-size: .88rem; white-space: nowrap; }
.inline-tide em { font-style: normal; color: var(--muted); font-family: var(--mono); font-size: .82em; }
.inline-tide.hi { color: var(--ink); font-weight: 550; }
.inline-tide.lo { color: var(--ink-2); }

/* ------------------------------------------------------------- the curve
   Drawn as smooth cubics, because a tide is a sinusoid and a polyline between
   highs and lows would describe water that rises linearly and turns at a corner
   — a shape the sea never makes. Every plotted point is a published value; only
   the interpolation between them is drawn, and it is drawn honestly. */
.curve { margin: var(--s3) 0 var(--s4); }
.curve svg { width: 100%; height: auto; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface); }
.curve .cline { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.curve .cdot { fill: var(--accent); }
.curve .clab { font-family: var(--mono); font-size: 9.5px; fill: var(--ink-2); }
.curve .ctick { font-family: var(--mono); font-size: 9px; fill: var(--faint); }

/* ------------------------------------------------------------ port grids */
.portgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: var(--s2); margin: var(--s3) 0 var(--s5); }
.portcard { display: block; padding: 11px var(--s3); border: 1px solid var(--line);
  border-left: 2px solid var(--accent); border-radius: var(--radius-sm);
  background: var(--surface); text-decoration: none; color: var(--ink); font-size: .93rem; }
.portcard:hover { border-color: var(--line-2); border-left-color: var(--accent); color: var(--accent); }
.portcard.sec { border-left-color: var(--line-2); }

.monthgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: var(--s2); margin: var(--s3) 0 var(--s5); }
.monthcard { display: block; text-align: center; padding: 9px 6px; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface); text-decoration: none;
  color: var(--ink-2); font-family: var(--mono); font-size: .78rem; letter-spacing: .04em; }
.monthcard:hover { border-color: var(--accent); color: var(--accent); }

/* ------------------------------------------------------------- responsive
   560px is the ring's breakpoint. At phone width the tide rows go two-up rather
   than four-up: four columns of a 1.85rem numeral on a 375px screen would
   shrink the one thing the visitor came for. */
@media (max-width: 560px) {
  .masthead-in { height: 56px; }
  .hide-sm { display: none; }
  .netbar-label { display: none; }
  .netbar-links { margin-left: 0; }
  .tides { grid-template-columns: 1fr 1fr; }
  .tide { padding-right: var(--s2); }
  .tide:nth-child(2n) { border-right: 0; }
  .tt { font-size: 1.62rem; }
  .foot-grid a { padding: 7px 0; }
}

:root[data-theme="dark"] .curve svg,
:root[data-theme="dark"] .safety { background: var(--surface-2); }

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