/* 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. */
@media (max-width: 560px) {
  .hero { padding: var(--s5) 0 var(--s4); }
  .hero > .wrap { display: flex; flex-direction: column; }
  .hero > .wrap > * { order: 6; }
  .hero > .wrap > .eyebrow,
  .hero > .wrap > .kicker { order: 1; }
  .hero > .wrap > h1 { order: 2; }
  .hero > .wrap > .lede { order: 3; }
  /* the action, then what vouches for it */
  .hero > .wrap > .search,
  .hero > .wrap > .searchbox,
  .hero > .wrap > .hero-act,
  .hero > .wrap > :has(> .search),
  .hero > .wrap > :has(> .searchbox) { order: 4; }
  .hero > .wrap > .srcline,
  .hero > .wrap > .srcline-min { order: 5; }
  /* the armour band is a footnote to the answer, not a gate in front of it */
  .hero > .wrap > .ymyl,
  .hero > .wrap > :has(> .ymyl) { order: 8; }
  .hero > .wrap > .lede { margin-bottom: 0; }
}
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; }

/* ========================================================== 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; }
}

/* ============================================================================
   schools.css — NZ School Finder, site-local layer.

   Loads LAST, after _shared/styles.css and _shared/datasite.css. Everything the
   ring already owns (paper, ink ramp, hairlines, .stats/.stat, .srcline,
   .tablewrap + table.data, .note, .ring*, .ad-slot, h2.sec, .stat-display,
   .prose, .faq, .eyebrow, .lede) comes from those two files unchanged and is
   NOT restated here. This file adds only what is specific to this site:

     1. the chrome the data ring's engine would otherwise supply (masthead,
        nav, footer grid) — this site is built on the SuburbIQ standalone
        pattern, so it carries its own, exactly as SuburbIQ does;
     2. the site's drawing hand — the year-level strip, the EQI position band,
        the roll-composition rows, the coordinate dot plot;
     3. the two ethics components, .eqi-note and .zone-note, which are the most
        important objects on the site and are styled to be unmissable without
        being alarming.

   Accent is injected as --site-accent on <body> (light) and overridden for
   dark in the page head. Nothing here hardcodes the navy.
   ========================================================================== */

/* ------------------------------------------------------------------ chrome */
.netbar-in { display: flex; align-items: center; gap: var(--s4); height: 34px; font-size: .78rem; }
.netbar-label { color: #B9C2C9; font-weight: 550; letter-spacing: .01em; }
.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); }
.muted { color: var(--muted); }
.linklist { list-style: none; padding: 0; }
.linklist li { border-bottom: 1px solid var(--line); }
.linklist a { display: block; padding: 11px 0; color: var(--ink); text-decoration: none; font-weight: 500; }
.linklist a:hover { color: var(--accent); }

/* --------------------------------------------------------- the year strip
   The site's set piece: 13 square tokens, the school's span filled. A drawn
   fact rather than a chart — there is nothing to compare, only a range to
   state, and a range reads faster as a shape than as "Years 1–8" alone. */
.yearstrip { display: flex; align-items: center; gap: var(--s3); margin: var(--s4) 0 var(--s3); flex-wrap: wrap; }
.yearstrip svg { width: min(280px, 100%); height: auto; overflow: visible; }
.yearstrip .yr { fill: none; stroke: var(--line-2); stroke-width: 1.1; }
.yearstrip .yr.on { fill: var(--accent); stroke: var(--accent); }
.yearstrip .yrlab { font-family: var(--mono); font-size: 8.5px; fill: var(--muted); letter-spacing: .06em; }
.yearlabel { font-family: var(--mono); font-size: .76rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-2); }

/* ------------------------------------------------------------ the EQI band
   Deliberately colourless. A red-to-green scale here would convert a
   description of a community into a verdict on a school, which is the single
   reading this site is built to prevent. Position on an axis is the honest
   encoding: it shows where a number sits in a distribution and implies nothing
   about direction being good or bad. */
.eqi-figure { display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; margin-bottom: var(--s2); }
.eqi-band { font-family: var(--mono); font-size: .8rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-2); }
.eqi-axis { width: 100%; max-width: 620px; height: auto; margin: var(--s3) 0 2px; overflow: visible; }
.eqi-axis .eqi-rule { stroke: var(--line-2); stroke-width: 1.1; }
.eqi-axis .eqi-tick { stroke: var(--line-2); stroke-width: 1.1; }
.eqi-axis .eqi-token { fill: var(--accent); }
.eqi-axis .eqi-val { font-family: var(--mono); font-size: 11px; fill: var(--ink); font-weight: 600; }
.eqi-axis .eqi-tok-label { font-family: var(--mono); font-size: 9px; fill: var(--muted); }
.eqi-axis .eqi-scale { font-family: var(--mono); font-size: 9.5px; fill: var(--muted); letter-spacing: .04em; }
.eqi-legend { display: flex; justify-content: space-between; max-width: 620px;
  font-family: var(--mono); font-size: .68rem; letter-spacing: .06em; color: var(--faint); margin-bottom: var(--s4); }

/* -------------------------------------------------- the two ethics blocks
   Same anatomy, deliberately: a reader learns the shape once and then knows
   that a block like this is the site telling them what a number cannot say.
   Left rule in the accent, not a coloured box — an alert box would read as a
   warning about the school rather than about the statistic. */
.eqi-note, .zone-note {
  border-top: 1px solid var(--ink);
  border-left: 3px solid var(--accent);
  background: var(--surface);
  padding: var(--s3) var(--s4);
  margin: var(--s4) 0;
  max-width: 74ch;
}
.eqi-note .kicker, .zone-note .kicker {
  font-family: var(--mono); font-size: .68rem; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 7px;
}
.eqi-note p:last-child, .zone-note p:last-child { font-size: .92rem; line-height: 1.62; color: var(--ink-2); margin: 0; }
.eqi-note strong, .zone-note strong { color: var(--ink); font-weight: 620; }
.eqi-note a, .zone-note a { color: var(--accent); font-weight: 550; }

/* ------------------------------------------------- roll composition rows
   NOT a stacked bar. MoE ethnicity is total response — the groups sum to more
   than the roll — so each group gets its own baseline and its own share of the
   roll. Stacking these to 100% would invent a whole that does not exist. */
.eth { margin: var(--s4) 0 var(--s3); max-width: 560px; }
.ethrow { display: grid; grid-template-columns: 11ch 1fr 8ch; align-items: center;
  gap: var(--s3); padding: 7px 0; border-bottom: 1px solid var(--line); }
.ethrow:last-child { border-bottom: 0; }
.ethlabel { font-size: .84rem; color: var(--ink-2); }
.ethbar { display: block; height: 9px; background: var(--paper-2); border-radius: 2px; overflow: hidden; }
.ethbar i { display: block; height: 100%; background: var(--accent); border-radius: 2px; }
.ethval { font-family: var(--mono); font-size: .82rem; text-align: right; font-variant-numeric: tabular-nums; color: var(--ink); }
.ethval em { display: block; font-style: normal; font-size: .72rem; color: var(--muted); }

/* --------------------------------------------------------------- ledger
   The Wikipedia-infobox shape, typeset in Identity A: hairline label/value
   rows, mono values, no box chrome. Readers already trust this shape for
   institutional facts, which is the whole reason to borrow it. */
.ledger { border-top: 1px solid var(--ink); margin: var(--s4) 0; max-width: 68ch; }
.lrow { display: grid; grid-template-columns: 15rem 1fr; gap: var(--s3);
  padding: 10px 0; border-bottom: 1px solid var(--line); }
.lk { font-size: .8rem; font-weight: 600; letter-spacing: .04em; color: var(--muted); }
.lv { font-family: var(--mono); font-size: .86rem; color: var(--ink); overflow-wrap: anywhere; }
.lv a { color: var(--accent); }

/* ------------------------------------------------------------- dot plot
   Plot the coordinates; draw no map. The Ministry's zone polygons are
   documented as low-resolution, so any drawn boundary would be a confident
   lie — but the points themselves are real, and their pattern is the honest
   thing a reader wants from a "where are these schools" question. */
.dotplot { margin: var(--s4) 0; }
.dotplot svg { width: 100%; height: auto; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface); }
.dotplot circle { fill: var(--accent); fill-opacity: .62; }

/* -------------------------------------------------------------- compare */
.vs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); margin: var(--s5) 0; }
.vs-side { border-top: 1px solid var(--ink); padding-top: var(--s3); }
.vs-side h2 { font-family: var(--serif); font-size: 1.2rem; font-weight: 500; letter-spacing: -.02em; margin-bottom: 4px; }
.vs-side h2 a { color: var(--ink); text-decoration: none; }
.vs-side h2 a:hover { color: var(--accent); }
/* There is deliberately no .win / .winner state anywhere in this file. */

/* ---------------------------------------------------------- region grid */
.regiongrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(184px, 1fr));
  gap: var(--s2); margin: var(--s4) 0 var(--s5); }
.regioncard { display: flex; flex-direction: column; gap: 3px; padding: var(--s3);
  border: 1px solid var(--line); border-top: 2px solid var(--accent);
  border-radius: var(--radius-sm); background: var(--surface); text-decoration: none; }
.regioncard:hover { border-color: var(--line-2); border-top-color: var(--accent); }
.regioncard .rn { font-family: var(--serif); font-size: 1rem; color: var(--ink); }
.regioncard .rc { font-family: var(--mono); font-size: .74rem; letter-spacing: .05em; color: var(--muted); }

.ring-context { border-left: 3px solid var(--accent); padding: 2px 0 2px var(--s3); margin-bottom: var(--s4); }
.ring-context p { font-size: .88rem; color: var(--muted); margin-bottom: 5px; }
.ring-context a { display: block; font-size: .92rem; font-weight: 550; color: var(--ink); padding: 3px 0; }
.ring-context a:hover { color: var(--accent); }

/* ------------------------------------------------------------- responsive
   The ring's breakpoint is 560px, not 520 — matching it here keeps the whole
   portfolio compacting at the same width on the same devices. */
@media (max-width: 560px) {
  .masthead-in { height: 56px; }
  .hide-sm { display: none; }
  .netbar-label { display: none; }
  .netbar-links { margin-left: 0; }
  .vs { grid-template-columns: 1fr; gap: var(--s4); }
  .lrow { grid-template-columns: 1fr; gap: 2px; padding: 9px 0; }
  .ethrow { grid-template-columns: 9ch 1fr 7ch; gap: var(--s2); }
  .eqi-figure { gap: var(--s3); }
  /* Tap targets stay ≥40px on the two lists a phone user actually uses. */
  .linklist a { padding: 13px 0; }
  .foot-grid a { padding: 7px 0; }
}

/* Dark mode: the set piece's outline strokes must retint to the ink ramp
   rather than to white, or the year strip glows brighter than the school's
   name — the "drawn element shouts in dark mode" failure from the AAA pass. */
:root[data-theme="dark"] .yearstrip .yr { stroke: var(--ink-2); }
:root[data-theme="dark"] .ethbar { background: var(--surface-2); }
:root[data-theme="dark"] .eqi-note, :root[data-theme="dark"] .zone-note { background: var(--surface-2); }

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