/* The public marketing site.
 *
 * Direction: "The well-kept board" (dense-tiles), seed 1883948498, dealt by
 * the design-taste-frontend skill. Type: Switzer. Palette: bottle ink, yellow.
 *
 * Everything here is scoped under `body.site`. app.css still owns the
 * dashboard and the admin panel, which are app screens under their own rules
 * (quiet borders and repeated panels are correct there and banned here), and a
 * wholesale rewrite of app.css would have taken them with it.
 *
 * The idea: this business publishes the numbers its competitors hide -- what a
 * node really holds, what renewal really costs. So the page is a board where
 * every tile is one true thing, and the largest tile is the invoice, issued
 * twice with the same figure on both.
 *
 * House rules this file obeys, because the inspector measures them: no
 * gradients, no shadows on anything at rest, no thin rules, no outlined boxes,
 * no backdrop blur, no uppercase tracked labels, no monospace outside code, no
 * icon-topped cards. Surfaces separate by a step in tone. One radius: 0.
 */

/* --- Tokens ---------------------------------------------------------------- */

body.site {
  /* Dealt palette. Off-white ground, type in a near-black bottle green rather
     than black, and yellow as the only saturated note. */
  --bg: #f7f7f7;
  --surface: #ebebeb;
  --surface-2: #e0e0e0;
  --ink: #0d2a1c;
  --ink-soft: #1a4330;
  --muted: #3c4a43;
  --accent: #f6e016;
  --accent-ink: #0d2a1c;
  --accent-deep: #d8c300;

  /* Five steps. Nothing between them. */
  --step-small: clamp(0.8125rem, 0.79rem + 0.1vw, 0.875rem);
  --step-body: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);
  --step-lead: clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);
  --step-head: clamp(2rem, 1.3rem + 3.2vw, 4rem);
  --step-display: clamp(2.75rem, 1.2rem + 6.2vw, 7rem);

  --gap: 8px;
  --edge: 20px;
  --radius: 0;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

@media (max-width: 760px) {
  body.site { --gap: 14px; --edge: 16px; }
}

/* --- Reset and base -------------------------------------------------------- */

body.site {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: Switzer, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: var(--step-body);
  line-height: 1.5;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
}

body.site * { box-sizing: border-box; }

body.site h1, body.site h2, body.site h3 {
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 0.95;
  margin: 0;
  text-wrap: balance;
}

body.site p { margin: 0; }
body.site img, body.site svg { display: block; max-width: 100%; }

body.site a { color: inherit; text-decoration: none; }
body.site a.underline { text-decoration: underline; text-underline-offset: 3px; }

body.site :focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}
body.site .on-dark :focus-visible,
body.site .tile--ink :focus-visible { outline-color: var(--accent); }

body.site ::selection { background: var(--accent); color: var(--accent-ink); }

body.site .skip {
  position: absolute; left: -9999px;
  background: var(--ink); color: var(--bg); padding: 12px 16px; z-index: 50;
}
body.site .skip:focus { left: var(--edge); top: var(--edge); }


/* --- Resets of app.css -----------------------------------------------------
 * app.css is loaded before this file and styles the dark application shell:
 * white headings, a gradient wordmark, a blue glow on every <button>, and a
 * legacy `.hero` that centres its text and adds 96px of padding. None of that
 * belongs on the board, and all of it is scoped away from the dashboard by
 * `body.site`.
 */

body.site, body.site .wrap { text-align: left; }
body.site h1, body.site h2, body.site h3, body.site h4 {
  color: inherit;
  font-weight: 600;
  margin: 0;
}
body.site .brand-text {
  background: none;
  -webkit-text-fill-color: currentColor;
  color: inherit;
}
/* taste-skill-ignore: resets app.css's glow on bare <button>. The selector has
   to out-specify `button:not(.link):not(.tab-btn)`, which is (0,2,1) -- loading
   this file later is not enough. The six question buttons were inheriting it. */
body.site button:not(.link):not(.tab-btn),
body.site .button, body.site a.button { box-shadow: none; } /* taste-skill-ignore: a reset of app.css's glow, not a shadow of our own */
/* app.css sets white on form labels for the dark shell. */
body.site label, body.site dt, body.site dd, body.site li, body.site p { color: inherit; }
/* ...and gives list items a dark pill background, which on a light tile made
   the plan contents unreadable. Components below set their own padding. */
body.site ul, body.site ol { list-style: none; margin: 0; padding: 0; }
body.site li { background: none; border: 0; border-radius: 0; padding: 0; }
body.site button:hover, body.site .button:hover, body.site a.button:hover {
  transform: none; filter: none;
}


/* --- The board ------------------------------------------------------------- */

body.site .board {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--gap);
  padding: 0 var(--edge);
  margin: 0 0 var(--gap);
}

body.site .tile {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 24px;
  min-width: 0;
  /* Tiles are filled, never outlined and never shadowed. */
}

body.site .tile--ink { background: var(--ink); color: var(--bg); }
body.site .tile--ink .muted { color: #9fb3a8; }
body.site .tile--soft { background: var(--ink-soft); color: var(--bg); }
body.site .tile--soft .muted { color: #9fb3a8; }
body.site .tile--accent { background: var(--accent); color: var(--accent-ink); }
body.site .tile--2 { background: var(--surface-2); }
body.site .tile--paper { background: var(--bg); }
body.site .tile--flush { padding: 0; overflow: hidden; }

body.site .tile > * + * { margin-top: 12px; }

body.site .muted { color: var(--muted); }
body.site .small { font-size: var(--step-small); }
body.site .lead { font-size: var(--step-lead); line-height: 1.35; letter-spacing: -0.015em; }

/* Column spans. */
body.site .c1{grid-column:span 1}  body.site .c2{grid-column:span 2}
body.site .c3{grid-column:span 3}  body.site .c4{grid-column:span 4}
body.site .c5{grid-column:span 5}  body.site .c6{grid-column:span 6}
body.site .c7{grid-column:span 7}  body.site .c8{grid-column:span 8}
body.site .c9{grid-column:span 9}  body.site .c10{grid-column:span 10}
body.site .c12{grid-column:1 / -1}

body.site .photo { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --- Header: a plain bar, no chrome ---------------------------------------- */

body.site .site-header {
  background: var(--bg);
  border: 0;
  position: static;
  backdrop-filter: none; /* taste-skill-ignore: a reset, not a use -- app.css glasses this bar and the board wants a plain one */
  padding: 0 var(--edge);
}
body.site .site-header .wrap {
  max-width: none; margin: 0; padding: 14px 0;
  display: flex; align-items: center; gap: 24px;
}
body.site .site-header nav { margin-left: auto; display: flex; align-items: center; gap: 22px; }
body.site .site-header nav a { font-size: var(--step-small); color: var(--ink); }
body.site .site-header nav a:hover { color: var(--muted); }
body.site .brand { display: flex; align-items: center; gap: 9px; }
body.site .brand-mark { width: 26px; height: 26px; }
body.site .brand-text { font-weight: 600; font-size: 17px; letter-spacing: -0.03em; }
body.site .brand-tld { color: var(--muted); }

/* The status badge keeps its dot but loses the pill, the border and the glow. */
body.site .status-badge { display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 0; padding: 0; border-radius: 0; }
body.site .pulse-dot { width: 7px; height: 7px; border-radius: 50%; background: #1f9d55; }

body.site .site-header .button,
body.site a.button, body.site button.button {
  background: var(--accent); color: var(--accent-ink);
  border: 0; border-radius: var(--radius);
  padding: 11px 18px; font: inherit; font-size: var(--step-small); font-weight: 500;
  box-shadow: none; /* taste-skill-ignore: a reset of app.css's glow; nothing here rests on a shadow */
  cursor: pointer;
  transition: background 140ms var(--ease), transform 140ms var(--ease);
}
body.site a.button:hover, body.site button.button:hover { background: var(--accent-deep); }
body.site a.button:active, body.site button.button:active { transform: translateY(1px); }

/* Written as `body.site .button--ink`, this modifier never once applied: the
   base rule above it is `body.site a.button, body.site button.button`, which
   carries an extra element selector and therefore wins. Every "ink" button on
   the site rendered in the accent -- including the one in a tile that is
   itself accent, i.e. a yellow button on a yellow field, which is how it was
   finally noticed. Matched on the element here so it outranks the base. */
body.site a.button.button--ink,
body.site button.button.button--ink { background: var(--ink); color: var(--bg); }
body.site a.button.button--ink:hover,
body.site button.button.button--ink:hover { background: var(--ink-soft); }

/* --- Main ------------------------------------------------------------------ */

body.site main.wrap { max-width: none; margin: 0; padding: 0; }

/* --- Hero: name band and rails --------------------------------------------- */

body.site .hero-board { margin-bottom: 96px; }

body.site .namestrip {
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--radius);
  height: 170px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
body.site .namestrip h1 {
  font-size: clamp(140px, 14.4vw, 220px);
  letter-spacing: -0.045em;
  line-height: 1;
  white-space: nowrap;
  font-weight: 600;
  margin: 0;
}
body.site .namestrip .tld { color: var(--accent); }

body.site .herolinks { }
body.site .herolinks a {
  display: flex; align-items: center;
  height: 64px; padding: 0 20px;
  background: var(--surface);
  font-size: 16px;
  transition: background 140ms var(--ease);
}
body.site .herolinks a:hover { background: var(--surface-2); }

body.site .hero-board-main { align-items: stretch; }
body.site .hero-centre { position: relative; min-height: 46vh; }
body.site .hero-centre .photo { position: absolute; inset: 0; }
body.site .hero-statement {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--bg); padding: 24px;
}
body.site .hero-statement p {
  font-size: clamp(20px, 2.4vw, 32px);
  line-height: 1.2; letter-spacing: -0.03em; max-width: 36ch;
}

body.site .factlist { list-style: none; padding: 0; margin: 0; }
body.site .factlist li { font-size: 16px; padding: 7px 0; }
body.site .factlist li + li { margin: 0; }
body.site .factlist b { font-weight: 600; }

body.site .rail { display: grid; gap: var(--gap); grid-auto-rows: 1fr; }
body.site .rail .tile { display: flex; flex-direction: column; justify-content: flex-end; }
body.site .rail .tile > * + * { margin-top: 6px; }

/* --- Section headings ------------------------------------------------------ */

body.site section { margin-bottom: 120px; }
body.site .sec-head {
  padding: 0 var(--edge);
  margin-bottom: 40px;
}
body.site .sec-head h2 { font-size: var(--step-head); max-width: 18ch; }
body.site .sec-head p { margin-top: 14px; max-width: 54ch; font-size: var(--step-body); color: var(--muted); }

/* --- The invoice pair (the idea) ------------------------------------------- */

body.site .invoice {
  background: var(--bg);
  padding: 26px;
  display: flex; flex-direction: column; height: 100%;
}
body.site .invoice--ink { background: var(--ink); color: var(--bg); }
body.site .invoice h3 { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.3; }
body.site .invoice .figure {
  font-size: clamp(44px, 5vw, 76px); font-weight: 600;
  letter-spacing: -0.045em; line-height: 1; margin-top: auto; padding-top: 28px;
}
body.site .invoice dl { margin: 16px 0 0; font-size: 16px; }
body.site .invoice div { display: flex; justify-content: space-between; gap: 16px; padding: 5px 0; }
body.site .invoice dt { color: var(--muted); }
body.site .invoice--ink dt { color: #9fb3a8; }
body.site .invoice dd { margin: 0; font-variant-numeric: tabular-nums; }

/* --- The live thing: the renewal reckoner ---------------------------------- */

body.site .reckoner { display: grid; grid-template-columns: 1fr; gap: var(--gap); }
body.site .reckoner-controls { background: var(--surface); padding: 24px; }
body.site .reckoner-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; min-height: 44px;
}
body.site .reckoner-row + .reckoner-row { margin-top: 4px; }
body.site .reckoner-row label { font-size: 16px; }
body.site .reckoner-row input[type="number"] {
  width: 112px; font: inherit; font-size: 16px;
  background: var(--bg); color: var(--ink);
  border: 2px solid var(--ink); border-radius: var(--radius);
  padding: 7px 10px; text-align: right; font-variant-numeric: tabular-nums;
}
body.site .reckoner-row input[type="range"] { width: 150px; accent-color: var(--ink); }
body.site .reckoner-out { background: var(--accent); color: var(--accent-ink); padding: 28px 24px; }
body.site .reckoner-out .figure {
  font-size: clamp(40px, 4.6vw, 68px); font-weight: 600;
  letter-spacing: -0.045em; line-height: 1; font-variant-numeric: tabular-nums;
}
body.site .reckoner-verdict { font-size: var(--step-lead); line-height: 1.3; letter-spacing: -0.02em; }

/* --- Staggered fragment cells (features) ----------------------------------- */

body.site .cells { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); padding: 0 var(--edge); }
body.site .cell {
  background: var(--surface);
  min-height: 430px;
  display: flex; flex-direction: column;
  overflow: hidden;
}
body.site .cell--ink { background: var(--ink); color: var(--bg); }
body.site .cell--ink .muted { color: #9fb3a8; }
body.site .cell--flip { flex-direction: column-reverse; }
body.site .cell-text { padding: 24px; }
body.site .cell-text h3 { font-size: 17px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.25; }
body.site .cell-text p { margin-top: 10px; font-size: 16px; line-height: 1.45; color: inherit; }
body.site .cell-frag { margin-top: auto; padding: 0 0 0 24px; }
body.site .cell--flip .cell-frag { margin-top: 0; margin-bottom: auto; }

/* --- Real interface fragments (data-ui) ------------------------------------
 * These are the product's own screens, so they keep the product's borders and
 * controls: the inspector leaves anything under [data-ui] alone.
 */

body.site [data-ui] {
  background: #fff; color: var(--ink);
  font-size: 13px; line-height: 1.4;
  border: 1px solid #d5d9d7;
  width: min(340px, 100%); max-width: 100%;
}
body.site [data-ui] .ui-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-bottom: 1px solid #e3e6e5; font-weight: 500;
}
body.site [data-ui] .ui-body { padding: 10px; }
body.site [data-ui] table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
body.site [data-ui] th { text-align: left; font-weight: 500; color: #5f6b64; padding: 5px 6px; }
body.site [data-ui] td { padding: 5px 6px; border-top: 1px solid #eceeed; font-variant-numeric: tabular-nums; }
body.site [data-ui] tr[aria-selected="true"] td { background: #fdf7c9; }
body.site [data-ui] .ui-meter { height: 6px; background: #e8eceA; width: 100%; }
body.site [data-ui] .ui-meter span { display: block; height: 100%; background: var(--ink); }
body.site [data-ui] .ui-pill { background: #e7f3ec; color: #16694a; padding: 1px 7px; font-size: 11.5px; }

/* --- Showcase: live demo with controls ------------------------------------- */

body.site .demo { display: grid; grid-template-columns: 62fr 38fr; }
body.site .demo-stage { background: var(--surface); padding: 28px; display: flex; align-items: center; justify-content: center; }
body.site .demo-side { background: var(--surface-2); padding: 20px; }

/* --- Stats: photograph with figure tiles ----------------------------------- */

body.site .mosaic { display: grid; grid-template-columns: 2fr 1fr; gap: 0; }
body.site .mosaic-figures { display: grid; grid-template-rows: 1fr 1fr; gap: 0; }
body.site .mosaic-figures > div { padding: 28px; }
body.site .mosaic .figure { font-size: clamp(56px, 5.6vw, 96px); font-weight: 600; letter-spacing: -0.05em; line-height: 0.9; }
body.site .mosaic p { margin-top: 14px; font-size: 17px; line-height: 1.3; max-width: 22ch; }

/* --- Pricing: plans that step up ------------------------------------------- */

body.site .steps { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--gap); align-items: end; padding: 0 var(--edge); }
body.site .step-plan { grid-column: span 4; display: flex; flex-direction: column; padding: 0; }
body.site .step-plan .inner { padding: 28px; flex: 1; }
body.site .step-plan:nth-child(1) { min-height: 360px; background: var(--surface); }
body.site .step-plan:nth-child(2) { min-height: 480px; background: var(--ink-soft); color: var(--bg); }
body.site .step-plan:nth-child(3) { min-height: 600px; background: var(--accent); color: var(--accent-ink); }
body.site .step-plan:nth-child(2) .muted { color: #9fb3a8; }
body.site .step-plan h3 { font-size: 28px; letter-spacing: -0.03em; }
body.site .step-plan .price { font-size: 56px; font-weight: 600; letter-spacing: -0.045em; line-height: 1; margin-top: 10px; }
body.site .step-plan .price span { font-size: 17px; font-weight: 400; letter-spacing: -0.01em; }
body.site .step-plan ul { list-style: none; padding: 0; margin: 20px 0 0; }
body.site .step-plan li { font-size: 17px; padding: 6px 0; }
body.site .step-plan .strip {
  display: block; height: 64px; padding: 0 28px;
  display: flex; align-items: center;
  font-weight: 500; font-size: 17px;
  transition: filter 140ms var(--ease);
}
body.site .step-plan:nth-child(1) .strip { background: var(--surface-2); color: var(--ink); }
body.site .step-plan:nth-child(2) .strip { background: var(--ink); color: var(--bg); }
body.site .step-plan:nth-child(3) .strip { background: var(--accent-deep); color: var(--accent-ink); }
body.site .step-plan .strip:hover { filter: brightness(0.94); }

/* --- FAQ: question index, one answer --------------------------------------- */

body.site .qa { display: grid; grid-template-columns: 5fr 1fr 6fr; gap: var(--gap); padding: 0 var(--edge); }
body.site .qa-list { list-style: none; margin: 0; padding: 0; }
body.site .qa-list li + li { margin-top: 18px; }
body.site .qa-list button {
  display: flex; align-items: baseline; gap: 12px;
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; font-size: 17px; line-height: 1.35; text-align: left;
  color: var(--muted); cursor: pointer; width: 100%;
}
body.site .qa-list button::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: currentColor; flex: none; transform: translateY(-2px);
}
body.site .qa-list button[aria-selected="true"] { color: var(--ink); }
body.site .qa-list button[aria-selected="true"]::before { background: var(--accent-deep); }
body.site .qa-answer {
  grid-column: 3 / 4; position: sticky; top: 40px; align-self: start;
  font-size: clamp(20px, 2vw, 27px); line-height: 1.3; letter-spacing: -0.02em; max-width: 30ch;
  transition: opacity 150ms var(--ease);
}
body.site .qa-heading { font-size: 17px; color: var(--muted); margin-bottom: 18px; }

/* --- Marquee: the signature move ------------------------------------------- */

body.site .marquee { overflow: hidden; background: var(--ink); color: var(--bg); padding: 26px 0; margin-bottom: 120px; }
body.site .marquee-track { display: flex; gap: 48px; width: max-content; animation: site-marquee 34s linear infinite; }
body.site .marquee:hover .marquee-track { animation-play-state: paused; }
body.site .marquee span { font-size: clamp(38px, 5.2vw, 84px); font-weight: 600; letter-spacing: -0.04em; white-space: nowrap; }
body.site .marquee em { font-style: normal; color: var(--accent); }
@keyframes site-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* --- CTA: the action tile -------------------------------------------------- */

body.site .closer { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--gap); }
body.site .closer > * { min-height: 360px; }
body.site .closer-main { grid-column: 3 / 11; background: var(--accent); color: var(--accent-ink);
  display: flex; flex-direction: column; justify-content: center; padding: 40px; }
body.site .closer-main h2 { font-size: 40px; max-width: 16ch; }
body.site .closer-main p { margin-top: 16px; font-size: 17px; max-width: 46ch; }
body.site .closer-main .actions { margin-top: 28px; display: flex; gap: var(--gap); flex-wrap: wrap; }
body.site .closer-side { grid-column: span 2; background: var(--ink); overflow: hidden; }

/* --- Footer: the mark, built large ----------------------------------------- */

body.site .site-footer { background: var(--ink); color: var(--bg); border: 0; margin: 0; padding: 56px var(--edge) 32px; }
body.site .site-footer .wrap { max-width: none; margin: 0; padding: 0; }
body.site .blockmark { display: flex; align-items: flex-end; gap: 4px; height: 26svh; min-height: 150px; }
body.site .blockmark span {
  display: flex; align-items: flex-end; justify-content: center;
  background: var(--surface); color: var(--ink);
  font-size: clamp(32px, 7vw, 104px); font-weight: 600; letter-spacing: -0.05em; line-height: 0.82;
  flex: 1; padding-bottom: 6px;
}
body.site .blockmark span:nth-child(3n) { background: var(--accent); color: var(--accent-ink); }
body.site .blockmark span:nth-child(4n) { background: var(--ink-soft); color: var(--bg); }
body.site .footer-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--gap); margin-top: 56px; }
body.site .footer-links { display: flex; flex-direction: column; gap: 9px; align-items: flex-start; }
body.site .footer-links a { font-size: 16px; color: var(--bg); }
body.site .footer-links a:hover { color: var(--accent); }
body.site .footer-col h3 { font-size: 16px; font-weight: 500; margin-bottom: 12px; color: #9fb3a8; letter-spacing: -0.01em; }
body.site .footer-last { display: flex; justify-content: space-between; align-items: center; gap: 24px; margin-top: 48px; flex-wrap: wrap; }
body.site .credits { font-size: var(--step-small); color: #9fb3a8; max-width: 90ch; margin-top: 28px; }
body.site .credits a { text-decoration: underline; text-underline-offset: 2px; }
body.site .site-footer .fine { color: #9fb3a8; font-size: var(--step-small); }

/* --- Motion ---------------------------------------------------------------- */

/* Content is NEVER hidden by CSS. An element animates only once the observer
   marks it, so a page whose JavaScript fails shows everything, and there is no
   class to set before first paint -- which is what the inline script used to
   do, in breach of the strict CSP (test_no_inline_script_so_the_strict_csp_holds).
   Elements below the fold are off-screen when their animation starts, so
   beginning at opacity 0 is never seen as a flash. */
body.site [data-rise].is-in {
  animation: site-in 620ms var(--ease) both;
  animation-delay: var(--rise-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  body.site *, body.site *::before, body.site *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  body.site [data-rise] { opacity: 1; transform: none; }
  body.site .marquee-track { animation: none; }
}

/* --- Phone: its own board -------------------------------------------------- */

@media (max-width: 900px) {
  body.site .cells { grid-template-columns: 1fr; }
  body.site .demo { grid-template-columns: 1fr; }
  body.site .qa { grid-template-columns: 1fr; }
  body.site .qa-answer { position: static; grid-column: 1; max-width: none; margin-top: 20px; }
  body.site .steps { grid-template-columns: 1fr; }
  body.site .step-plan { grid-column: 1; min-height: 0 !important; }
  /* Two columns and the action tile first. Left as source order, the full
     width .closer-main split the two flanking tiles onto rows of their own,
     and each left the right half of its row empty -- which is what the
     inspector measured as a blank stretch. */
  body.site .closer { grid-template-columns: repeat(2, 1fr); }
  body.site .closer-main { order: -1; grid-column: 1 / -1; min-height: 300px; padding: 28px; }
  body.site .closer-main h2 { font-size: 28px; }
  body.site .closer-side { grid-column: span 1; min-height: 140px; }
  body.site .mosaic { grid-template-columns: 1fr; }
  body.site .mosaic-figures { grid-template-columns: 1fr 1fr; grid-template-rows: none; }
}

@media (max-width: 760px) {
  body.site .namestrip { height: 110px; }
  body.site .namestrip h1 { font-size: 26vw; }
  body.site .board { grid-template-columns: repeat(2, 1fr); }
  body.site .board > * { grid-column: span 1 !important; }
  body.site .board > .span-full { grid-column: 1 / -1 !important; }
  body.site .hero-centre { min-height: 52vw; }
  body.site .hero-statement p { font-size: 6vw; }
  body.site .site-header .wrap { gap: 12px; }
  body.site .site-header nav { gap: 14px; }
  body.site .footer-grid { grid-template-columns: repeat(2, 1fr); }
  body.site .footer-grid > * { grid-column: span 1; }
  body.site section { margin-bottom: 80px; }
  body.site .marquee { margin-bottom: 80px; }
}

/* --- Corrections from the first look round --------------------------------- */

/* The rails must fill the hero row, or the left column ends in a grey offcut. */
body.site .hero-board-main > * { min-height: 46vh; }
body.site .rail .tile--flush { padding: 0; }
body.site .rail .tile--flush .photo { height: 100%; }

/* The closing tile kept its text on the left and left 747px of accent empty.
   The heading and the action now sit on opposite sides of the same tile, so
   the width is used rather than padded. */
body.site .closer-main {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  align-items: center;
  gap: 40px;
}
body.site .closer-main h2 { max-width: 14ch; }
body.site .closer-main .closer-say { grid-column: 2; }
body.site .closer-main p { margin: 0; }
body.site .closer-main .actions { margin-top: 20px; }

@media (max-width: 900px) {
  body.site .closer-main { grid-template-columns: 1fr; gap: 20px; }
  body.site .closer-main .closer-say { grid-column: 1; }
  body.site .hero-board-main > * { min-height: 0; }
}

/* --- The hero moves on load ------------------------------------------------
 * In CSS rather than through the observer, because these elements are in view
 * at first paint: the observer adds its class in the same frame and nothing
 * transitions, so the page measured as still.
 */
@keyframes site-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: no-preference) {
  body.site .namestrip h1 { animation: site-in 760ms var(--ease) both; }
  body.site .herolinks a { animation: site-in 620ms var(--ease) both; }
  body.site .herolinks a:nth-child(1) { animation-delay: 90ms; }
  body.site .herolinks a:nth-child(2) { animation-delay: 160ms; }
  body.site .herolinks a:nth-child(3) { animation-delay: 230ms; }
  body.site .herolinks a:nth-child(4) { animation-delay: 300ms; }
  body.site .hero-board-main > * { animation: site-in 720ms var(--ease) both; }
  body.site .hero-board .board > * { animation: site-in 700ms var(--ease) both; }
  body.site .hero-board .board:nth-of-type(2) > * { animation-delay: 160ms; }
  body.site .hero-board .board:nth-of-type(3) > * { animation-delay: 240ms; }
  body.site .hero-board-main > *:nth-child(1) { animation-delay: 360ms; }
  body.site .hero-board-main > *:nth-child(2) { animation-delay: 430ms; }
  body.site .hero-board-main > *:nth-child(3) { animation-delay: 500ms; }
  body.site .hero-statement { animation: site-in 700ms var(--ease) both; animation-delay: 580ms; }
}

/* The parts of a cell arrive separately: text, then the interface fragment. */
body.site .cell.is-in .cell-text { animation: site-in 560ms var(--ease) both; }
body.site .cell.is-in .cell-frag { animation: site-in 560ms var(--ease) both; animation-delay: 110ms; }

/* Feedback on every control. */
body.site .factlist li, body.site .qa-list button { transition: color 140ms var(--ease); }
body.site .step-plan { transition: transform 180ms var(--ease); }
body.site .step-plan:hover { transform: translateY(-4px); }
body.site .herolinks a:hover { background: var(--surface-2); }

@media (max-width: 760px) {
  /* The answer leads, the dials follow. */
  body.site #reckoner .board { display: flex; flex-direction: column; }
  body.site #reckoner .rk-controls { order: 3; }
  /* The invoice pair stays a pair. */
  body.site #invoices .tile--flush { grid-column: span 1 !important; }
}

body.site .is-in .factlist li { animation: site-in 480ms var(--ease) both; }
body.site .is-in .factlist li:nth-child(2) { animation-delay: 60ms; }
body.site .is-in .factlist li:nth-child(3) { animation-delay: 120ms; }
body.site .is-in .factlist li:nth-child(4) { animation-delay: 180ms; }
body.site .is-in .factlist li:nth-child(5) { animation-delay: 240ms; }
body.site .qa.is-in .qa-list li { animation: site-in 460ms var(--ease) both; }
body.site .qa.is-in .qa-list li:nth-child(n+2) { animation-delay: 70ms; }
body.site .qa.is-in .qa-list li:nth-child(n+4) { animation-delay: 140ms; }
body.site .steps.is-in .step-plan:nth-child(2) { animation: site-in 600ms var(--ease) both; animation-delay: 90ms; }
body.site .steps.is-in .step-plan:nth-child(3) { animation: site-in 600ms var(--ease) both; animation-delay: 180ms; }

/* Rail tiles carry a figure as well as a fact, so a tall block is filled
   rather than holding one line adrift in it. */
body.site .rail-figure {
  font-size: clamp(34px, 3.4vw, 52px); font-weight: 600;
  letter-spacing: -0.05em; line-height: 0.9; margin: 0;
}
body.site .rail .tile { justify-content: flex-start; }

/* The one moving picture: the city drifts, slowly, behind the statement. */
@media (prefers-reduced-motion: no-preference) {
  body.site .drift { animation: site-drift 26s ease-in-out infinite alternate; }
}
@keyframes site-drift { from { transform: scale(1.02); } to { transform: scale(1.1) translateY(-1.5%); } }

/* One statement per rail tile, set large enough to be the tile's content
   rather than a caption adrift in it. */
body.site .rail-say { font-size: 19px; line-height: 1.25; letter-spacing: -0.015em; margin: 0; }
@media (max-width: 760px) { body.site .rail-say { font-size: 17px; } }

/* One or two plans should fill the row rather than leave most of it empty. */
body.site .steps-1 .step-plan { grid-column: span 12; min-height: 320px !important; }
body.site .steps-2 .step-plan { grid-column: span 6; }
/* Tiles on the simpler pages carry their fragment the same way the cells do. */


body.site .cells-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) { body.site .cells-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 760px) { body.site .cells-4 { grid-template-columns: 1fr; } }

/* A short page title fits the band rather than being cropped by its top and
   bottom. The cropping device belongs to the long wordmark on the home page,
   where it is the ends that are cut. */
body.site .namestrip--short h1 { font-size: clamp(64px, 9.5vw, 136px); line-height: 1.04; }
@media (max-width: 760px) { body.site .namestrip--short h1 { font-size: 16vw; } }

/* --- Hero (rebuilt) --------------------------------------------------------
   The first screen carries three claims. Everything here is flat colour and
   type: no gradient, no glow, no glass, nothing floating at rest. The future
   look is
   carried by scale, a figure that animates, and the brief that assembles
   itself, not by the usual costume.
   -------------------------------------------------------------------------- */

body.site .hero-claim {
  padding: clamp(28px, 4.5vw, 72px);
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.4vw, 36px);
}

/* The one display size on the page. Two lines at every width: each half of the
   sentence is its own span with a non-breaking space inside it, so "One price."
   can never split across lines on its own. */
body.site .hero-line {
  margin: 0;
  font-size: var(--step-display);
  line-height: 0.88;
  letter-spacing: -0.035em;
  font-weight: 600;
  max-width: 14ch;
}
body.site .hero-line span { display: inline-block; }

/* A statement, not a second headline: capped at statement size and measure so
   it cannot start reading as one. */
body.site .hero-say {
  margin: 0;
  font-size: var(--step-lead);
  line-height: 1.35;
  max-width: 46ch;
  color: var(--bg);
}

body.site .hero-actions {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 4px;
}
body.site .hero-second {
  color: var(--accent);
  font-size: var(--step-body);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* --- The term strip: the claim drawn ---------------------------------------
   36 cells, one per month of a three-year term, every one the same colour.
   A competitor's strip would change colour at month 12; that is the argument.
   It is a figure, which is why it is allowed to be the decorative-looking
   thing on the page -- it carries data, not ornament. */
body.site .termstrip { margin: 0; display: flex; flex-direction: column; gap: 12px; }
body.site .termstrip-cells {
  display: grid;
  grid-template-columns: repeat(36, 1fr);
  gap: 3px;
  max-width: 560px;
}
body.site .termstrip-cells i {
  display: block;
  height: clamp(28px, 3.4vw, 46px);
  background: var(--accent);
  /* Visible without script: the animation only replays the fill. */
  transform-origin: bottom;
}
body.site .termstrip figcaption { color: #9fb3a8; max-width: 52ch; }

/* --- The builder ----------------------------------------------------------- */
body.site .builder {
  padding: clamp(24px, 3vw, 44px);
  display: flex;
  flex-direction: column;
  gap: 18px;
  justify-content: flex-start;
}
body.site .builder-head {
  margin: 0;
  font-size: var(--step-head);
  line-height: 0.95;
  letter-spacing: -0.03em;
  max-width: 16ch;
}
body.site .builder-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; }
body.site .builder-form label { flex: 1 0 100%; }
body.site .builder-form input {
  flex: 1 0 100%;
  min-width: 0;
  font: inherit;
  font-size: var(--step-body);
  padding: 14px 16px;
  border: 2px solid var(--accent-ink);
  background: var(--bg);
  color: var(--ink);
  border-radius: 0;
}
body.site .builder-form input::placeholder { color: var(--muted); }
body.site .builder-form button { flex: 0 0 auto; }

body.site .builder-out:empty { display: none; }
body.site .builder-out {
  display: grid;
  gap: 14px;
  background: var(--accent-ink);
  color: var(--bg);
  padding: 20px;
}
body.site .builder-out h3 {
  margin: 0; font-size: var(--step-body); font-weight: 600; color: var(--accent);
}
body.site .builder-pages { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
body.site .builder-pages li {
  background: var(--accent); color: var(--accent-ink);
  padding: 6px 12px; font-size: var(--step-small); font-weight: 500;
}
body.site .builder-draft { margin: 0; font-size: var(--step-lead); line-height: 1.2; max-width: 28ch; }
body.site .builder-out .small { color: #9fb3a8; margin: 0; }

/* --- The trust rail -------------------------------------------------------- */
body.site .hero-rail { display: flex; flex-direction: column; gap: var(--gap); }
body.site .hero-rail .tile { flex: 1; justify-content: flex-start; padding: clamp(20px, 2.2vw, 32px); }
body.site .rail-head {
  margin: 0; font-size: var(--step-lead); line-height: 1.05;
  letter-spacing: -0.02em; font-weight: 600;
}
body.site .renewal-pair { display: flex; gap: 32px; flex-wrap: wrap; }
body.site .renewal-fig {
  margin: 0; font-size: clamp(32px, 4vw, 56px); line-height: 1;
  letter-spacing: -0.03em; font-weight: 600; font-variant-numeric: tabular-nums;
}

/* --- Motion ----------------------------------------------------------------
   Transform and opacity only. Nothing is hidden by CSS: every animation that
   starts at opacity 0 is added by script once the element is in view, so a
   page with no JavaScript shows all of it. */
@media (prefers-reduced-motion: no-preference) {
  /* The two halves of the headline arrive one after the other. */
  body.site .hero-claim.is-in .hero-line span {
    animation: hero-word 700ms var(--ease) both;
  }
  body.site .hero-claim.is-in .hero-line span:nth-child(2) { animation-delay: 90ms; }

  /* The term fills, left to right, one cell at a time. The whole run is about
     a second: long enough to read as deliberate, short enough that nobody
     waits for it. */
  body.site .hero-claim.is-in .termstrip-cells i {
    animation: term-fill 420ms var(--ease) both;
    animation-delay: calc(260ms + var(--cell) * 22ms);
  }

  /* The brief's parts arrive in the order someone would write them. */
  body.site .builder-out > * {
    animation: site-in 460ms var(--ease) both;
    animation-delay: calc(var(--out-i, 0) * 80ms);
  }

  body.site .builder-form input { transition: border-color 160ms var(--ease); }
  body.site .builder-form input:focus { border-color: var(--ink-soft); }
  body.site .button { transition: transform 140ms var(--ease); }
  body.site .button:active { transform: translateY(2px); }
  body.site .hero-second { transition: opacity 140ms var(--ease); }
  body.site .hero-second:hover { opacity: 0.75; }
  body.site .builder-pages li { transition: transform 140ms var(--ease); }
  body.site .builder-pages li:hover { transform: translateY(-2px); }
}

@keyframes hero-word {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}
@keyframes term-fill {
  from { opacity: 0; transform: scaleY(0.12); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  body.site .hero-line span,
  body.site .termstrip-cells i,
  body.site .builder-out > * { opacity: 1; transform: none; animation: none; }
}

/* --- Phone ----------------------------------------------------------------- */
@media (max-width: 760px) {
  body.site .hero-claim { padding: 24px 20px; gap: 18px; }
  body.site .hero-line { max-width: none; }
  /* 36 cells at phone width would be hairlines. Twelve rows of three keeps
     each cell wide enough to read as a month. */
  body.site .termstrip-cells { grid-template-columns: repeat(12, 1fr); max-width: none; }
  body.site .termstrip-cells i { height: 22px; }
  body.site .builder-form input { flex: 1 0 100%; }
  body.site .builder-form button { width: 100%; }
  body.site .renewal-pair { gap: 20px; }
}

/* --- Hero, second pass ------------------------------------------------------
   The first screen had 37% of its width as one empty block: the claim sat in
   the left half and nothing closed it on the right. The builder moved up
   beside it, which fills the void with the thing a visitor can actually do.
   -------------------------------------------------------------------------- */

body.site .hero-top,
body.site .hero-foot { align-items: stretch; }
body.site .hero-top > *,
body.site .hero-foot > * { min-height: 0; }

/* Narrower column, so the display size needs a tighter measure to stay on two
   lines. */
body.site .hero-claim .hero-line { max-width: 11ch; }
body.site .hero-claim .hero-say { max-width: 38ch; }
body.site .termstrip-cells { max-width: none; }

/* One size, reused: the renewal figures take the heading step rather than
   introducing another clamp of their own. */
/* Statement scale, not heading scale. At the heading step these read as
   headings to anything measuring the page -- and the button above them then
   reads as a kicker label, which is exactly what it looked like. They are
   data: a figure the sentence beside them refers to. */
body.site .renewal-fig { font-size: clamp(26px, 2.6vw, 34px); }

body.site .hero-support {
  display: flex; flex-direction: column; gap: 20px; justify-content: space-between;
  padding: clamp(24px, 3vw, 44px);
}
body.site .hero-support .rail-say { max-width: 44ch; }

/* The caption runs the full width at the foot of the picture, so the row is
   closed on both sides instead of leaving a void beside a text block. */
body.site .hero-centre { position: relative; min-height: 340px; }
body.site .hero-centre .hero-statement {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 20px clamp(20px, 2.4vw, 32px);
  background: var(--ink); color: var(--bg);
}
body.site .hero-centre .hero-statement p {
  margin: 0; font-size: var(--step-body); max-width: 60ch;
}

@media (max-width: 760px) {
  body.site .hero-claim .hero-line,
  body.site .hero-claim .hero-say { max-width: none; }
  body.site .hero-centre { min-height: 240px; }
}

/* The page's two outer margins must match. They did not: 20px on the left and
   38px on the right at 1440px, because the scrollbar took its width from the
   right edge alone. Reserving the gutter on both sides costs a few pixels of
   measure and makes the frame symmetrical, which is the first thing a reader
   notices when it is wrong. */
html { scrollbar-gutter: stable both-edges; }

/* The builder's heading is a title now, so it takes the heading step and keeps
   to two lines at every width. */
body.site .builder-head { max-width: 12ch; }

/* The brief is shown on arrival, for the sentence already in the field, so the
   tile is not half an empty yellow rectangle until someone types. */
body.site .builder-form button { flex: 1 0 100%; }
body.site .builder { gap: 14px; }
body.site .builder-out { padding: 18px; gap: 12px; }

/* The two ends of the term. Set at the heading step and aligned to the ends of
   the strip above them, so the eye reads first month and last month as one
   statement rather than two numbers that happen to match. */
body.site .termstrip-ends {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 24px; margin-top: 2px;
}
body.site .termstrip-ends p { margin: 0; }
body.site .termstrip-end-right { text-align: right; }
body.site .termstrip-ends .small { color: #9fb3a8; }
body.site .termstrip-cells i { height: clamp(34px, 4vw, 54px); }

/* The support tile carries only its words now, so give them room to breathe
   rather than sitting in the top corner of a tall tile. */
body.site .hero-support { justify-content: center; gap: 16px; }

/* One pair of margins for the whole page.
   The header and footer inherit app.css's centred `.wrap`, which insets them
   by whatever is left of its max-width, while every board uses --edge. At
   1440px that put the navigation on a 59px margin and the content on 35px --
   the frame a reader notices first when it is wrong, and the thing the
   inspector calls off-centre. */
body.site .site-header .wrap,
body.site .site-footer .wrap {
  max-width: none;
  padding-inline: var(--edge);
}

/* The generated page, shown in the hero.
   A sandboxed frame with no allow-scripts: this is model-written HTML and it
   only has to be looked at. Fixed aspect so the tile does not jump when it
   arrives. */
body.site .builder-frame {
  width: 100%;
  aspect-ratio: 4 / 3;
  border: 0;
  background: var(--bg);
  display: block;
}
body.site .builder-step {
  margin: 0;
  font-size: var(--step-body);
  color: var(--accent);
  font-weight: 500;
}
body.site .builder-form button[disabled] { opacity: 0.7; cursor: progress; }

@media (max-width: 760px) {
  body.site .builder-frame { aspect-ratio: 3 / 4; }
}

