/* ============================================================
   BEACON — shared design system
   The AI CFO for accounting & advisory firms · by Vype Consulting

   THIS STYLESHEET IS THE MARKETING SITE'S ONLY, and that separation is the point.
   The site and the app share one origin but never one document: these pages are
   static HTML served from public/beacon/, so nothing here can reach the app's
   design tokens (styles/tokens.css) and nothing there can reach these. Two visual
   identities, no cascade between them, no naming truce to negotiate.

   Served at clean URLs — /platform, /pricing, … — via next.config.ts `rewrites`;
   '/' is decided by the proxy, which serves this site to a signed-out visitor and
   routes a signed-in one into the product. Asset paths must therefore be ABSOLUTE
   (/beacon/styles.css): at /platform a relative href resolves to /styles.css and
   404s. See docs/DEPLOY.md → "The production domain".
   ============================================================ */
/* ── BEACON BRAND — v4, LAGOON GOLD ──────────────────────────────────────────
   FOURTH PALETTE, and unlike the three before it this one was not derived here:
   it arrives as a fixed set of tokens (primary, secondary, accent, muted,
   destructive, border, card, background) and the job is to honour them, not to
   re-argue them. What IS decided here is which token may carry text, because
   that is the part a palette cannot tell you and the part that breaks pages.

   The predecessor — parchment, oxblood, brass — is gone entirely. Its reasoning
   is preserved in git rather than in a comment describing colours that are no
   longer on the page.

   THE ONE RULE THIS PALETTE NEEDS. Its secondary is #ffb400, and gold is a trap:
   at 1.78:1 on the light ground it cannot be text at any size, while at 11.8:1
   on ink it is excellent as a FILL. So gold here is a fill and a mark, never a
   text colour on light — --gold-ink exists for the times prose needs to be in
   the gold family, and it is a different colour for that reason.

   Ratios computed, not eyeballed (WCAG 2.1, sRGB relative luminance):
     Ink on background ......... 15.60  ✓ AAA
     Primary on background ...... 6.18  ✓ AA    (so it works as text, not just fill)
     Background on primary ...... 6.18  ✓ AA    (the dark sections invert cleanly)
     Muted on background ........ 6.29  ✓ AA
     Gold-ink on background ..... 5.54  ✓ AA
     Accent-on-dark on primary .. 4.88  ✓ AA
     Destructive on background .. 4.63  ✓ AA
     Gold on primary ............ 3.62  — LARGE TEXT AND MARKS ONLY (AA needs 3:1)
     Accent on background ....... 3.04  — LARGE TEXT AND UI EDGES ONLY
   ------------------------------------------------------------------------- */
:root {
  /* The ground of the dark sections, and the brand colour in prose. One token
     for both because at 6.18:1 it genuinely carries text either way round. */
  --primary: #03677f;
  /* THE GROUND OF THE DARK SECTIONS, derived rather than given — the palette is a light-mode
     token set and has no concept of a dark surface, but this site has had one since v1.
     Deriving it from the primary is what keeps the two halves one object.

     It has to be THIS dark for a reason that is measurable, not stylistic. The site states its
     secondary text as white at 0.4-0.72 alpha over the ground, a tonal system the whole page
     depends on. Against the old oxblood (L .031) those cleared 4.5:1; against the primary
     (L .113) they land between 2.7 and 4.2, and every caption on every dark section fails. The
     choice was to rewrite thirty alpha values into two flat tokens and lose the hierarchy, or to
     put the ground back where the hierarchy works. At L .023 even the faintest (0.5 alpha, 12px)
     reads 4.66:1, and the gold clears 8.1:1 — so gold becomes usable as small text here too. */
  --ground: #012e39;
  /* ~8% darker — a hover is the same colour under pressure, never a new one. */
  --primary-hover: #02566a;
  /* The palette's "accent" — brighter, and NOT text-safe on the light ground.
     Rules, edges, large display type. */
  --accent: #02a2bc;
  /* What reads as the accent once the ground goes dark. */
  --accent-on-dark: #b8e8f2;
  /* The palette's "secondary". Fill and mark only — see the rule above. */
  --gold: #ffb400;
  /* Gold as TEXT on the light ground. Darkened until it passes; still gold. */
  --gold-ink: #8a6100;
  /* A figure below zero. This meaning ONLY — the palette's "destructive". */
  --negative: #d3451f;
  /* The destructive as small TEXT on its own tint. #d3451f is 4.5:1 on white but only 3.9:1 on
     the 12% wash the status badges use, and those badges are 11.5px. Same shape as --gold-ink:
     the palette colour darkened until the smallest thing it has to carry is legible. */
  --negative-ink: #b83a17;

  --ink: #10222a;
  --ink-2: #1d3640;
  --ink-3: #2b4854;
  --bg: #f5fbfb;
  --bg-2: #e4eef0;
  /* The card white the palette names — brighter than the ground, so a table
     reads as a sheet laid on the page. */
  --card: #ffffff;
  --band: #e4eef0;
  --muted: #4d6069;
  --line: #d4e1e4;
  --line-dark: rgba(245, 251, 251, 0.22);
  --shadow:
    0 1px 2px rgba(16, 34, 42, 0.07), 0 14px 34px -20px rgba(16, 34, 42, 0.4);
  --shadow-sm: 0 1px 2px rgba(16, 34, 42, 0.07);
  /* Lagoon Gold specifies 0. */
  --radius: 0px;
  --maxw: 1140px;

  /* One family, as the theme specifies. The mono stays for figures: a tabular
     face in a table is a function, not a second typeface for its own sake. */
  --font-display: 'Google Sans Flex', system-ui, -apple-system, sans-serif;
  --font-ui: 'Google Sans Flex', system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html {
  scroll-behavior: smooth;
}
body {
  font-family: var(--font-ui);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 24px;
}
h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.1;
}
a {
  color: inherit;
  text-decoration: none;
}
.eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-ink);
}

/* KEYBOARD FOCUS, stated once for the whole site. Nothing here removed the browser's default
   ring, so this is not a repair — but the default is a thin system outline that disappears
   against the dark sections, and a marketing site is where a keyboard user decides whether the
   product was built by people who thought about them. --accent is the palette's own third
   colour and the right one for this: at 3.04:1 on the light ground it is too weak for text but
   comfortably past the 3:1 a non-text indicator needs, and it is the only place on the site that
   colour is doing a job neither --primary nor --gold could do. */
a:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 0;
}
.dark a:focus-visible,
.cta a:focus-visible,
.dark button:focus-visible {
  outline-color: var(--accent-on-dark);
}
.beam-text {
  color: var(--primary);
}
.mono {
  font-family: var(--font-mono);
}

/* NAV */
header.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(251, 250, 247, 0.82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 70px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.brand .mark {
  width: 30px;
  height: 30px;
  flex: none;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 30px;
}
.nav-links a {
  font-size: 14.5px;
  color: var(--muted);
  font-weight: 500;
  transition: color 0.2s;
}
.nav-links a:hover,
.nav-links a.active {
  color: var(--ink);
}
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-weight: 600;
  font-size: 14.5px;
  padding: 11px 20px;
  border-radius: 0;
  /* A button label never wraps: at ~400px "Request access" broke to two lines
     in the header and collided with the brand. */
  white-space: nowrap;
  transition:
    transform 0.15s ease,
    box-shadow 0.2s ease,
    background 0.2s;
  cursor: pointer;
  border: none;
}
.btn-beam {
  background: var(--primary);
  color: var(--ink);
}
.btn-beam:hover {
  transform: translateY(-1px);
  box-shadow: 0 14px 30px -10px rgba(255, 180, 0, 0.7);
}
.btn-ghost {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line);
}
.btn-ghost:hover {
  background: var(--bg-2);
}
.btn-lg {
  padding: 14px 26px;
  font-size: 15.5px;
}
/* MOBILE MENU — a <details> disclosure, no script. On desktop the links lie
   flat and this stays hidden; below 820px the flat links (and the Log in ghost
   button, which moves inside) give way to it, so the section pages stay
   reachable from the header instead of only from the footer. */
.nav-menu {
  display: none;
  position: relative;
}
.nav-menu summary {
  list-style: none;
  cursor: pointer;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink);
  padding: 9px 16px;
  border: 1px solid var(--line);
}
.nav-menu summary::-webkit-details-marker {
  display: none;
}
.nav-menu[open] summary {
  background: var(--bg-2);
}
.nav-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 12px);
  min-width: 230px;
  background: var(--card);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  padding: 6px 0;
}
.nav-menu-panel a {
  padding: 11px 18px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
}
.nav-menu-panel a:hover,
.nav-menu-panel a.active {
  background: var(--bg-2);
}
@media (max-width: 820px) {
  /* Direct children only: the same links inside .nav-menu-panel must show. */
  .nav-links > a:not(.btn),
  .nav-links > a.btn-ghost {
    display: none;
  }
  .nav-menu {
    display: block;
  }
  /* Two controls and a brand on a narrow row: the desktop 30px gap is part of
     what squeezed the button into wrapping. */
  .nav-links {
    gap: 14px;
  }
}
@media (max-width: 480px) {
  /* Header controls only — page-body buttons keep their full padding. The row
     must hold brand + CTA + Menu inside 360px without the CTA wrapping. */
  .nav-links > .btn {
    padding: 9px 12px;
  }
  .nav-menu summary {
    padding: 9px 12px;
  }
  .nav-links {
    gap: 10px;
  }
}

/* HERO / SECTION SHELL */
section.block {
  padding: 100px 0;
}
section.block.tight {
  padding: 76px 0;
}
.sec-head {
  max-width: 700px;
  margin-bottom: 56px;
}
.sec-head.center {
  margin: 0 auto 56px;
  text-align: center;
}
.sec-head h2 {
  font-size: clamp(30px, 3.8vw, 44px);
  margin-top: 14px;
}
.sec-head p {
  font-size: 17.5px;
  color: var(--muted);
  margin-top: 18px;
}

.page-hero {
  background:
    radial-gradient(
      120% 90% at 80% -10%,
      rgba(255, 180, 0, 0.14),
      transparent 55%
    ),
    var(--bg);
  padding: 84px 0 60px;
  border-bottom: 1px solid var(--line);
}
.page-hero h1 {
  font-size: clamp(34px, 4.8vw, 56px);
  max-width: 800px;
}
.page-hero p {
  font-size: 19px;
  color: var(--muted);
  margin-top: 20px;
  max-width: 600px;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 15px;
  border: 1px solid var(--line);
  border-radius: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  background: #fff;
  box-shadow: var(--shadow-sm);
}
.pill .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary);
}
@media (max-width: 860px) {
}

.card {
  border: 1px solid var(--line);
  border-radius: 0;
  padding: 30px;
  background: #fff;
  transition:
    transform 0.2s ease,
    box-shadow 0.25s ease;
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
}
.card .ic {
  width: 44px;
  height: 44px;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--band);
  color: var(--ink);
  margin-bottom: 18px;
}
.card .ic svg {
  width: 23px;
  height: 23px;
}
.card h3 {
  font-size: 20px;
  margin-bottom: 10px;
}
.card p {
  font-size: 15px;
  color: var(--muted);
}

/* DARK SECTION */
.dark {
  background: var(--ink);
  color: #fff;
}
.dark .eyebrow {
  color: var(--accent-on-dark);
}
.dark .sec-head p {
  color: rgba(255, 255, 255, 0.68);
}
.dark .card {
  background: var(--ink-2);
  border-color: var(--line-dark);
}
.dark .card p {
  color: rgba(255, 255, 255, 0.66);
}
.dark .card .ic {
  background: rgba(255, 180, 0, 0.14);
  color: var(--primary);
}

/* CHECK LIST */
.checks {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.checks li {
  display: flex;
  gap: 13px;
  align-items: flex-start;
  font-size: 15.5px;
}
.checks li .tick {
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 1px;
}
.checks li .tick svg {
  width: 13px;
  height: 13px;
}
.checks li b {
  font-weight: 600;
}
.checks li span.sub {
  color: var(--muted);
}

/* CTA BAND */
.cta {
  background: var(--ink);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.cta::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    60% 100% at 50% 0%,
    rgba(255, 180, 0, 0.22),
    transparent 60%
  );
  pointer-events: none;
}
.cta-inner {
  padding: 92px 0;
  text-align: center;
  position: relative;
  z-index: 1;
}
.cta h2 {
  font-size: clamp(30px, 4.2vw, 48px);
  max-width: 720px;
  margin: 0 auto;
}
.cta p {
  font-size: 18px;
  color: rgba(255, 255, 255, 0.72);
  margin: 20px auto 0;
  max-width: 520px;
}
.cta-btns {
  display: flex;
  gap: 14px;
  justify-content: center;
  margin-top: 34px;
  flex-wrap: wrap;
}
/* A ghost button keeps --ink, which is right on the light ground and 1.13:1 on the dark one.
   .cta had its own override and .dark never did, so the secondary CTA inside any dark section
   was effectively invisible — it only showed up once the ground went deep enough to measure. */
.cta .btn-ghost,
.dark .btn-ghost {
  color: #fff;
  border-color: var(--line-dark);
}
.cta .btn-ghost:hover,
.dark .btn-ghost:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* FOOTER */
footer {
  background: var(--bg);
  border-top: 1px solid var(--line);
  padding: 56px 0 40px;
}
.foot-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 32px;
}
/* Column labels, not headings: as <h5> they jumped the document outline from
   h2/h3 straight to level five on every page. Styled text carries the same
   look without asserting structure the outline does not have. */
.foot-grid .foot-head {
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 16px;
  font-family: var(--font-ui);
  font-weight: 600;
}
.foot-grid a {
  display: block;
  font-size: 14px;
  color: var(--muted);
  margin-bottom: 11px;
  transition: color 0.2s;
}
.foot-grid a:hover {
  color: var(--ink);
}
.foot-tag {
  font-size: 13.5px;
  color: var(--muted);
  margin-top: 12px;
  max-width: 260px;
}
.foot-bottom {
  border-top: 1px solid var(--line);
  margin-top: 40px;
  padding-top: 22px;
  font-size: 13px;
  color: var(--muted);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}
@media (max-width: 820px) {
  .foot-grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* DASHBOARD MOCK (shared) */
.dash {
  background: var(--ink);
  border-radius: 0;
  padding: 22px;
  box-shadow: var(--shadow);
  color: #fff;
  position: relative;
}
.dash-top .who {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.62);
}
.dash-top .who b {
  color: #fff;
  font-weight: 600;
}
.kpi .lab {
  font-size: 11.5px;
  color: rgba(255, 255, 255, 0.55);
  letter-spacing: 0.03em;
}
.kpi .val {
  font-family: var(--font-display);
  font-size: 26px;
  margin-top: 6px;
}
.chart {
  background: var(--ink-2);
  border: 1px solid var(--line-dark);
  border-radius: 0;
  padding: 16px 16px 10px;
}
.chart .clab {
  font-size: 11.5px;
  color: rgba(255, 255, 255, 0.55);
  margin-bottom: 12px;
  display: flex;
  justify-content: space-between;
}
.alert {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  margin-top: 16px;
  background: rgba(255, 180, 0, 0.1);
  border: 1px solid rgba(255, 180, 0, 0.28);
  border-radius: 0;
  padding: 12px 14px;
}
.alert .ic {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--primary);
}
.alert p {
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.82);
  line-height: 1.4;
}
.alert b {
  color: #fff;
}

/* TRUST FLOW DIAGRAM */
.flow {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 560px;
  margin: 0 auto;
}
.flow .node {
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 0;
  padding: 16px 20px;
  display: flex;
  align-items: center;
  gap: 14px;
}
.flow .node .n-ic {
  width: 36px;
  height: 36px;
  border-radius: 0;
  background: var(--bg-2);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  color: var(--ink);
}
.flow .node b {
  font-size: 15px;
}
.flow .node span {
  font-size: 13px;
  color: var(--muted);
  display: block;
}
.flow .node.hl {
  border-color: var(--primary);
  background: rgba(255, 180, 0, 0.06);
}
.flow .arrow {
  text-align: center;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
}

/* PRICING */
.price-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  align-items: stretch;
}
.price {
  border: 1px solid var(--line);
  border-radius: 0;
  padding: 32px;
  background: #fff;
  display: flex;
  flex-direction: column;
}
.price.feat {
  border-color: var(--primary);
  box-shadow: 0 20px 50px -24px rgba(255, 180, 0, 0.5);
  position: relative;
}
.price.feat .tag {
  position: absolute;
  top: -12px;
  left: 32px;
  /* THE GOLD EARNS ITS PLACE HERE. This badge marks the recommended plan, so it is the one spot
     on the site whose whole job is to catch the eye — and ink on gold is 11.8:1, where the ink
     on primary it used to carry was 2.53:1 and unreadable. The palette's secondary doing the one
     thing a secondary is for. */
  background: var(--gold);
  color: var(--ink);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 0;
}
.price h2 {
  font-size: 22px;
  margin-bottom: 6px;
}
.price .who {
  font-size: 13.5px;
  color: var(--muted);
  margin-bottom: 20px;
  min-height: 38px;
}
.price .amt {
  font-family: var(--font-display);
  font-size: 34px;
  margin-bottom: 4px;
}
.price .amt small {
  font-size: 15px;
  color: var(--muted);
  font-family: var(--font-ui);
}
.price ul {
  list-style: none;
  margin: 22px 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}
.price ul li {
  font-size: 14px;
  display: flex;
  gap: 10px;
  align-items: flex-start;
}
.price ul li svg {
  width: 17px;
  height: 17px;
  flex: none;
  margin-top: 2px;
  color: var(--primary);
}
@media (max-width: 860px) {
  .price-grid {
    grid-template-columns: 1fr;
  }
}
.auth-card p.sub {
  color: var(--muted);
  font-size: 15px;
  margin-bottom: 30px;
}
.field {
  margin-bottom: 18px;
}
.field label {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  margin-bottom: 7px;
}
.field input {
  width: 100%;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: 0;
  font-size: 15px;
  font-family: inherit;
  background: #fff;
  transition:
    border 0.2s,
    box-shadow 0.2s;
}
.field input:focus {
  outline: none;
  border-color: var(--primary);
  /* Was rgba(255, 180, 0, .2) — amber from the v1 palette, three identities ago. */
  box-shadow: 0 0 0 3px rgba(2, 162, 188, 0.25);
}
.auth-full {
  width: 100%;
}
.auth-quote .q {
  font-family: var(--font-display);
  font-size: 24px;
  line-height: 1.35;
}
.auth-quote .by {
  margin-top: 20px;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.6);
}
@media (max-width: 860px) {
}

/* REVEAL */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.7s ease,
    transform 0.7s ease;
}
.reveal.in {
  opacity: 1;
  transform: none;
}

/* ============================================================
   EDITORIAL LAYER — added to replace the card-grid grammar.

   WHY THIS EXISTS. The first build of this site used the layout vocabulary every
   generated marketing page uses: a centred eyebrow over a centred heading over a
   row of identical rounded cards, each with a small line icon. It is not ugly. It
   is anonymous — and anonymity is a specific problem for a product whose whole
   claim is rigour, sold to accountants, who spend their working lives reading
   documents and can tell a real one from a brochure.

   So the grammar here is a DOCUMENT, not a landing page: hairline rules instead of
   card borders, left-aligned headings with the substance in a second column,
   tabular figures, and column headings set like a ledger. Nothing on this page is
   a card with an icon in it.
   ------------------------------------------------------------------------- */

/* Figures are TABULAR everywhere they appear. Proportional digits in a column of
   money is the single fastest way to look like you have never seen a ledger. */
.fig,
.led td,
.led th,
.stat-n {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ── The editorial section head: left, not centred ────────────────────────── */
.ed {
  padding: clamp(72px, 9vw, 128px) 0;
  border-top: 1px solid var(--line);
}
.ed-head {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(24px, 5vw, 72px);
  align-items: end;
}
.ed-head h2 {
  font-size: clamp(30px, 4vw, 46px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  max-width: 16ch;
}
.ed-head .ed-sub {
  color: var(--muted);
  font-size: 16.5px;
  line-height: 1.65;
}
/* The label that replaces the eyebrow. Set like a column heading in a ledger —
   it names the section rather than announcing it. */
.ed-label {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--primary);
  display: block;
  margin-bottom: 18px;
}
.dark .ed-label {
  color: var(--primary);
}
.dark .ed-head .ed-sub {
  color: rgba(255, 255, 255, 0.68);
}

/* ── Rows, not cards. Hairline-separated, label in the margin. ────────────── */
.rows {
  margin-top: clamp(36px, 5vw, 64px);
  border-top: 1px solid var(--line);
}
.dark .rows,
.dark .row {
  border-color: var(--line-dark);
}
.row {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 9fr);
  gap: clamp(16px, 4vw, 56px);
  padding: clamp(22px, 3vw, 34px) 0;
  border-bottom: 1px solid var(--line);
}
.row-k {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);
  padding-top: 4px;
}
.dark .row-k {
  color: rgba(255, 255, 255, 0.55);
}
.row h2,
.row h3 {
  font-family: var(--font-display);
  font-size: clamp(19px, 2.1vw, 23px);
  font-weight: 500;
  letter-spacing: -0.01em;
  margin-bottom: 8px;
}
.row p {
  color: var(--muted);
  font-size: 16px;
  line-height: 1.68;
  max-width: 62ch;
}
.dark .row p {
  color: rgba(255, 255, 255, 0.7);
}

/* ── THE LEDGER. The artefact the product actually produces. ───────────────
   A working trial balance excerpt, in the shape an accountant reads: code,
   account, then debit and credit columns that must be equal. It replaces the
   invented bar chart that stood here, which was decoration pretending to be
   evidence — every generated fintech page has one. */
.led-wrap {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 0;
  box-shadow: var(--shadow);
  overflow: hidden;
}
/* The table's own scroll region: on a narrow screen the ledger slides inside
   the card instead of the wrap's overflow:hidden amputating the Cr column.
   Focusable (tabindex in the markup) so a keyboard can scroll it too. */
.led-scroll {
  overflow-x: auto;
}
.led-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
}
.led-top b {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
}
.led-top span {
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.led {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}
.led th {
  text-align: right;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  padding: 10px 20px;
  border-bottom: 1px solid var(--line);
}
.led th:first-child,
.led th:nth-child(2) {
  text-align: left;
}
.led td {
  padding: 9px 20px;
  border-bottom: 1px solid rgba(11, 18, 32, 0.05);
  text-align: right;
  color: var(--ink);
}
.led td:first-child {
  text-align: left;
  color: var(--muted);
  font-size: 12.5px;
}
.led td:nth-child(2) {
  text-align: left;
}
.led tr:last-child td {
  border-bottom: none;
}
.led .tot td {
  border-top: 2px solid var(--ink);
  font-weight: 600;
  padding-top: 11px;
}
.led .adj td:nth-child(2) span {
  display: block;
  color: var(--primary);
  font-size: 11.5px;
  margin-top: 2px;
}
/* The proof. This is the line the whole product is arguing for, so it is set as a
   statement rather than a badge — a badge reads as branding, a line reads as a
   result. */
.led-proof {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  background: var(--bg-2);
  font-size: 13px;
}
.led-proof b {
  color: var(--primary);
}
.led-proof .dotk {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--primary);
  flex: none;
}

/* ── A quoted figure set as a pull-quote, for the one claim worth enlarging ── */
.pull {
  font-family: var(--font-display);
  font-size: clamp(24px, 3.4vw, 40px);
  line-height: 1.22;
  letter-spacing: -0.02em;
  max-width: 22ch;
}
.pull em {
  font-style: normal;
  color: var(--primary);
}
.dark .pull em {
  color: var(--primary);
}

/* ── Stat strip: hairline-divided, tabular, no boxes ──────────────────────── */
.stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.dark .stats,
.dark .stat {
  border-color: var(--line-dark);
}
.stat {
  padding: clamp(20px, 3vw, 30px) clamp(16px, 2.5vw, 30px);
  border-left: 1px solid var(--line);
}
.stat:first-child {
  border-left: none;
  padding-left: 0;
}
.stat-n {
  font-family: var(--font-display);
  font-size: clamp(26px, 3.2vw, 36px);
  font-weight: 600;
  letter-spacing: -0.02em;
  display: block;
}
.stat-l {
  color: var(--muted);
  font-size: 14px;
  line-height: 1.55;
  margin-top: 6px;
  display: block;
}
.dark .stat-l {
  color: rgba(255, 255, 255, 0.65);
}

/* ── Two-column editorial split ───────────────────────────────────────────── */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 6vw, 88px);
  align-items: center;
}
.split.narrow-left {
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
}

@media (max-width: 900px) {
  .ed-head,
  .row,
  .split,
  .split.narrow-left {
    grid-template-columns: 1fr;
  }
  .ed-head {
    align-items: start;
  }
  .row-k {
    padding-top: 0;
  }
  .stats {
    grid-template-columns: 1fr;
  }
  .stat {
    border-left: none;
    border-top: 1px solid var(--line);
    padding-left: 0;
  }
  .stat:first-child {
    border-top: none;
  }
}

/* Visually hidden, still read aloud. The ledger's <caption> uses this: a screen
   reader reaching a bare table of figures needs to be told what the table IS,
   and sighted readers already have the header above it. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The hero's two columns are set inline (the grid is specific to that one
   layout), so the collapse has to live here — an inline style has no media
   query. Below 900px the ledger stacks under the claim rather than being
   squeezed into a column too narrow for four money columns. */
@media (max-width: 900px) {
  #hero-grid {
    grid-template-columns: 1fr !important;
    gap: 40px !important;
    padding-bottom: 56px !important;
  }
  /* Same defect, different page: for-firms' checks-beside-the-board split had
     the identical inline grid and no collapse, so at phone widths the client
     board overflowed the viewport (found at 412px: card right edge at 471). */
  #firm-split-grid {
    grid-template-columns: 1fr !important;
    gap: 40px !important;
  }
}

/* ============================================================
   v2 CORRECTIONS — defects the screenshot review found that the
   measurements did not.
   ------------------------------------------------------------------------- */

/* 1. CONTENT MUST NOT DEPEND ON JAVASCRIPT TO BE VISIBLE.
      `.reveal` started at opacity 0 and was faded in by an IntersectionObserver.
      A screenshot of /pricing showed all three tiers as ghosts, because the
      observer had not fired yet — and if the script fails, is blocked, or the
      element never enters the viewport, the content simply never appears. That is
      not an animation bug, it is content hidden behind a script.

      So the resting state is now VISIBLE, and the animation is an enhancement
      layered on top: only elements the script has marked `data-anim` start
      hidden, and the script only marks them once it is running. No script, no
      marking, no hiding. */
.reveal {
  opacity: 1;
  transform: none;
}
[data-anim='pending'] {
  opacity: 0;
  transform: translateY(12px);
}
[data-anim='in'] {
  opacity: 1;
  transform: none;
  transition:
    opacity 260ms cubic-bezier(0, 0, 0.2, 1),
    transform 260ms cubic-bezier(0, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {
  [data-anim='pending'],
  [data-anim='in'] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* 2. THE PROOF LINE WRAPPED WRONG.
      It was a flex row of [dot][text], so when the sentence wrapped, the dot sat
      on its own beside the second line. The dot belongs to the whole statement,
      not to a line of it — align it to the first line and let the text be a
      single flowing block. */
.led-proof {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: start;
}
.led-proof .dotk {
  margin-top: 7px;
}

/* 3. THE HERO STARTED TOO LOW. Nearly a third of the first screen was empty
      before anything was said. */
.page-hero {
  background: var(--bg);
  padding: 40px 0 56px;
}

/* 4. LEFT-ALIGN THE PAGE HEROES. The section heads were fixed in the first pass
      and the page heroes were missed, so /pricing and /platform still opened with
      a centred column — the layout this redesign exists to remove. */
.page-hero h1,
.page-hero p,
.page-hero .pill {
  margin-left: 0;
  margin-right: 0;
}
.page-hero .wrap {
  text-align: left;
}

/* 5. FIGURES ARE MONO, EVERYWHERE. The ledger, the stat strip, and any inline
      amount. This is the single strongest signal that the people who made this
      have read a set of accounts. */
.led,
.stat-n,
.fig,
.row-k,
.ed-label,
.led-top span {
  font-family: var(--font-mono);
}
.stat-n {
  font-weight: 600;
  letter-spacing: -0.03em;
}
.ed-label,
.row-k {
  font-size: 11px;
  letter-spacing: 0.08em;
}

/* Greenbar banding on the ledger — the pale green stripe accounting paper carried
   for a century. Functional, not ornamental: it is what stops the eye losing its
   row halfway across a wide table of figures. */
.led tbody tr:nth-child(odd):not(.tot) {
  background: var(--band);
}
.led .tot td {
  border-top: 2px solid var(--ink);
}
.led-proof b {
  color: var(--primary);
}
.led-proof .dotk {
  background: var(--primary);
}
.led .adj td:nth-child(2) span {
  color: var(--primary);
}

/* Display type: tracking eased off. The collision that broke "firm" came from
   negative tracking on a serif with a long f arm; Plex Serif is squarer, but a
   display size still does not need letters pulled together. */
h1,
h2 {
  letter-spacing: -0.015em;
}
.beam-text {
  color: var(--primary);
}
.dark .beam-text,
.dark .pull em {
  color: var(--accent-on-dark);
}
.btn-beam {
  background: var(--primary);
  color: var(--bg);
}
.btn-beam:hover {
  /* Was #0f4e3b — a dark green left behind by the v2 ledger palette, so the primary button
     has been turning green on hover through two changes of identity since. A hover is a state
     of the SAME colour, so it is derived from the primary rather than picked. */
  background: var(--primary-hover);
  box-shadow: none;
  transform: translateY(-1px);
}
.pill .dot {
  background: var(--primary);
}
.ed-label {
  color: var(--primary);
}
.dark .ed-label {
  color: var(--accent-on-dark);
}

/* ── v3 SURFACES ──────────────────────────────────────────────────────────
   The dark sections become the SPINE. `.dark` was near-black; on this palette
   near-black beside parchment reads as a hole in the page, where burgundy reads
   as the other half of the same object. */
.dark,
.cta {
  background: var(--ground);
  color: var(--bg);
}
.dark .card,
.cta::after {
  background: transparent;
}
.btn-beam {
  background: var(--primary);
  color: var(--bg);
}
.btn-beam:hover {
  background: var(--primary-hover);
  box-shadow: none;
}
.cta .btn-beam,
.dark .btn-beam {
  background: var(--gold);
  color: var(--ink);
}

/* The ledger sits on the brighter leaf, with its header on the spine colour —
   the one place the burgundy touches the table, so the sheet reads as bound
   into the book rather than floating beside it. */
.led-wrap {
  background: var(--card);
}
.led-top {
  background: var(--ground);
  color: var(--bg);
  border-color: var(--ground);
}
.led-top span {
  color: var(--gold);
}
.led tbody tr:nth-child(odd):not(.tot) {
  background: var(--bg);
}
.led-proof {
  background: var(--bg);
}
.led-proof b,
.led-proof .dotk,
.led .adj td:nth-child(2) span,
.ed-label,
.beam-text {
  color: var(--primary);
}
.led-proof .dotk {
  background: var(--primary);
}
.dark .ed-label,
.dark .beam-text,
.dark .pull em {
  color: var(--gold);
}
.pill .dot {
  background: var(--primary);
}

/* THE ROWS' TOP MARGIN IS FOR SITTING UNDER A HEADING, not for separating them from
   a section's own padding.

   `.rows` carries margin-top so it clears an `.ed-head` above it. On the pages where the
   converted card grid IS the section's wrap — platform, trust — there is no heading, so that
   margin stacked on top of `section.block`'s 100px and produced a 165px dead band between the
   hero and the first line of content. Measured on the live /trust: hero ends at 467, first row
   starts at 632, and the first screen was a third empty before anything was said.

   Collapsed only in that exact case, so the heading-follows case is untouched. */
section.block > .wrap.rows,
section.ed > .wrap.rows {
  margin-top: 0;
}

/* ── TWO DEFECTS FOUND BY MEASURING THE LIVE PAGE ─────────────────────────────

   1. THE PRIMARY CTA FAILED CONTRAST ON EVERY PAGE — 2.14:1, measured.
      `.nav-links a { color: var(--muted) }` is a class plus an element, so it
      outranks the single class on `.btn-beam`. The nav's "Request access" button
      therefore drew MUTED BROWN text on an oxblood fill. It looked merely washed
      out, which is how it survived three palette changes and several screenshot
      passes: nothing about it reads as broken, it just quietly sat at a third of
      the required ratio. Specificity raised to match, so the button colours win
      inside the nav as they already do everywhere else.

   2. THE STICKY NAV WAS STILL THE OLD PAPER. rgba(251,250,247) is v1's near-white;
      the page is parchment (244,239,228). A translucent header in the previous
      palette's white, sitting over the current one — visible as a faint lighter
      band across the top of every page once you know to look. */
.nav-links a.btn-beam {
  color: var(--bg);
}
.nav-links a.btn-ghost {
  color: var(--ink);
}
header.nav {
  /* Matches --bg. Translucent so the page shows through as it scrolls under. */
  background: rgba(245, 251, 251, 0.85);
}

/* The tick's fill needs light text on it — it was white on a --teal that no longer existed,
   which rendered as white on parchment: 1.15:1, invisible. Stated here so the pairing travels
   with the fill rather than depending on a colour inherited from somewhere else. */
.checks li .tick {
  color: var(--bg);
}
