/* ==========================================================================
   NOVARUS V5  ·  monochrome, liquid, and a real product UI
   2026-07-26. Loads last and overrides v4.

   Three moves:
   1. Colour comes out. The corpus offers two winning poles and says never land
      between them: scream ONE saturated colour, or remove colour and out-craft.
      This is the second pole. The only colour left is the delta on the
      dashboard, which is the one place 1,434 measured product screens allow it.
   2. The background is liquid glass: soft masses merged with a gooey filter,
      drifting behind a frosted pane. Transform only, so it stays composited.
   3. The hero visual is an actual product dashboard, built to the measured
      conventions in 06-product-ui-and-dashboards.md rather than invented.
   ========================================================================== */

:root{
  --paper:#FBFBFA;
  --paper-2:#F4F4F3;
  --canvas:#FBFBFA;
  --surface:#FFFFFF;

  --void:#0B0B0C;
  --void-2:#141416;
  --void-3:#1D1D20;

  --ink:#111112;
  --ink-2:#42424A;
  --muted:#6B6B73;
  --faint:#97979E;

  --line:rgba(17,17,18,.09);
  --line-2:rgba(17,17,18,.16);

  /* the accent is now ink. every gold token resolves to a neutral so nothing
     downstream has to be hunted down and rewritten. */
  --gold:#111112;
  --gold-lift:#2A2A2E;
  --gold-deep:#111112;
  --gold-wash:rgba(17,17,18,.05);

  /* the single exception, per 6.3: the delta on a KPI tile is the only place
     colour is allowed, and only as small text. */
  --up:#1B7F4B;
  --down:#B4382C;
}

body{ background:var(--paper); color:var(--ink); }

/* gold survived in a few v3/v4 rules as literal hex, so neutralise those */
.em-word{ color:var(--ink); }
.band--dark .em-word{ color:#FFFFFF; }
.band--dark{ --gold:#FFFFFF; --gold-deep:#FFFFFF; --gold-wash:rgba(255,255,255,.08); }
.docnum b{ color:var(--ink); }
.band--dark .docnum b{ color:#FFFFFF; }
.plain__no{ color:var(--muted); }
.band--dark .plain__no{ color:rgba(255,255,255,.55); }
.jarvis__cap i{ background:var(--ink); }
.band--dark .jarvis__cap i{ background:#FFFFFF; }
.eyebrow-pill i{ background:var(--ink); }
.btn--gold{ background:var(--ink); color:#FBFBFA; }
.btn--gold:hover{ opacity:.86; filter:none; }
.ledger__mark{ border-color:var(--line-2); color:var(--ink); }
.versus__col + .versus__col{ background:rgba(17,17,18,.028); }
.versus__col + .versus__col li::before{ color:var(--ink); }
.calc__opt[aria-pressed="true"]{ border-color:var(--ink); background:rgba(17,17,18,.04); }
.calc__opt[aria-pressed="true"] .calc__box{ background:var(--ink); border-color:var(--ink); }
.calc__box svg{ color:#FFFFFF; }
.idx__item[aria-current="true"] span{ color:var(--ink); }
.plan__list li::before{ color:var(--ink); }
.pick[aria-pressed="true"]{ background:rgba(17,17,18,.06); border-color:var(--line-2); color:var(--ink); }

/* ====================================================== LIQUID GLASS BG ====
   Four soft masses drift on long, offset loops inside a container that is
   blurred hard and then contrast-boosted. The blur plus contrast is what
   welds them into one liquid body instead of four circles, and the frosted
   pane over the top is what makes it read as glass rather than as a gradient.
   ========================================================================== */
.liquid{
  position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden;
  background:var(--paper);
}
.goo-def{ position:absolute; width:0; height:0; }
.liquid__goo{
  position:absolute; inset:-18%;
  filter:url(#goo);
  opacity:.85;
}
.liquid__blob{
  position:absolute; border-radius:50%;
  background:radial-gradient(circle at 50% 50%, #D6D6DD 0%, #D6D6DD 52%, rgba(214,214,221,0) 72%);
  will-change:transform;
}
.liquid__blob:nth-child(1){ width:46vw; height:46vw; left:-6vw;  top:2vh;
  animation:drift1 34s ease-in-out infinite; }
.liquid__blob:nth-child(2){ width:38vw; height:38vw; right:-4vw; top:22vh;
  animation:drift2 41s ease-in-out infinite; }
.liquid__blob:nth-child(3){ width:32vw; height:32vw; left:26vw;  bottom:-8vh;
  animation:drift3 29s ease-in-out infinite; }
.liquid__blob:nth-child(4){ width:27vw; height:27vw; right:20vw; top:-6vh;
  animation:drift4 47s ease-in-out infinite; }

@keyframes drift1{
  0%,100%{ transform:translate3d(0,0,0) scale(1); }
  33%{ transform:translate3d(16vw,10vh,0) scale(1.18); }
  66%{ transform:translate3d(6vw,26vh,0) scale(.9); }
}
@keyframes drift2{
  0%,100%{ transform:translate3d(0,0,0) scale(1.05); }
  40%{ transform:translate3d(-20vw,14vh,0) scale(.86); }
  70%{ transform:translate3d(-8vw,-8vh,0) scale(1.2); }
}
@keyframes drift3{
  0%,100%{ transform:translate3d(0,0,0) scale(.95); }
  50%{ transform:translate3d(-14vw,-20vh,0) scale(1.25); }
}
@keyframes drift4{
  0%,100%{ transform:translate3d(0,0,0) scale(1); }
  45%{ transform:translate3d(-10vw,22vh,0) scale(1.16); }
  80%{ transform:translate3d(8vw,6vh,0) scale(.88); }
}

/* the pane. this is the "glass" half: it sits over the liquid and frosts it,
   which is what stops the movement reading as a cheap animated gradient. */
.liquid__pane{
  position:absolute; inset:0;
  backdrop-filter:blur(34px) saturate(0%);
  -webkit-backdrop-filter:blur(34px) saturate(0%);
  background:linear-gradient(180deg, rgba(251,251,250,.30), rgba(251,251,250,.58));
}

/* the old particle field is retired by this build */
.ambient,.ambient--page{ display:none !important; }

@media (prefers-reduced-motion:reduce){
  /* match the specificity of the per-blob rules above, otherwise nth-child
     wins and the animation keeps running */
  .liquid__blob:nth-child(1),.liquid__blob:nth-child(2),
  .liquid__blob:nth-child(3),.liquid__blob:nth-child(4){ animation:none; }
  .liquid__goo{ opacity:.55; }
}
/* the gooey filter is expensive on low-power phones, so drop to a plain wash */
@media (max-width:700px){
  .liquid__goo{ filter:blur(38px); opacity:.55; }
  .liquid__pane{ backdrop-filter:blur(24px); -webkit-backdrop-filter:blur(24px); }
}

/* ============================================================== PRODUCT UI ==
   A real dashboard, built to the measured conventions: light canvas, grouped
   sidebar with tiny all-caps section labels, breadcrumb, a date-range control
   row, 4 KPI tiles, one big chart panel plus a side panel, then a table.
   Product-UI density, which is materially tighter than marketing density:
   body 13-14px, labels 10-12px, radius 4-8px, hairlines instead of shadows.
   ========================================================================== */
.ui{
  position:relative; z-index:1;
  border-radius:14px; overflow:hidden;
  background:#FFFFFF; border:1px solid rgba(17,17,18,.11);
  box-shadow:0 1px 2px rgba(17,17,18,.04), 0 30px 70px -40px rgba(17,17,18,.3);
  display:grid; grid-template-columns:212px minmax(0,1fr);
  font-size:13px; color:var(--ink);
}
.ui *{ letter-spacing:0; }

/* ---- window chrome, so it reads as software rather than as a web section -- */
.ui__top{
  grid-column:1 / -1; display:flex; align-items:center; gap:8px;
  padding:9px 13px; border-bottom:1px solid rgba(17,17,18,.09); background:#FAFAFA;
}
.ui__dots{ display:flex; gap:5px; }
.ui__dots i{ width:9px; height:9px; border-radius:50%; background:#DCDCDE; }
.ui__url{
  margin:0 auto; padding:3px 12px; border-radius:5px; background:#F1F1F2;
  font-family:var(--f-mono); font-size:10.5px; color:#7B7B82;
}

/* ---- sidebar --------------------------------------------------------- */
.ui__side{
  border-right:1px solid rgba(17,17,18,.09); background:#FCFCFC;
  padding:13px 9px; display:flex; flex-direction:column; gap:3px; min-width:0;
}
.ui__brand{
  display:flex; align-items:center; gap:7px; padding:2px 7px 11px;
  font-size:13px; font-weight:600;
}
.ui__brand svg{ width:16px; height:16px; }
.ui__seclbl{
  padding:11px 7px 4px; font-family:var(--f-mono); font-size:9px;
  letter-spacing:.13em; text-transform:uppercase; color:#A0A0A7;
}
.ui__nav{
  display:flex; align-items:center; gap:8px; padding:6px 7px; border-radius:5px;
  font-size:12.5px; color:#5A5A62; white-space:nowrap; overflow:hidden;
}
.ui__nav svg{ width:14px; height:14px; opacity:.7; flex:none; }
.ui__nav[data-on="true"]{ background:#EFEFF0; color:var(--ink); font-weight:550; }
.ui__nav b{ margin-left:auto; font-family:var(--f-mono); font-size:9.5px; font-weight:400; color:#A0A0A7; }
.ui__plan{
  margin-top:auto; padding:9px 8px; border-radius:6px; background:#F5F5F6;
  font-size:11px; color:#6B6B73; line-height:1.45;
}
.ui__meter{ display:block; height:3px; border-radius:2px; background:#E2E2E4; margin-top:6px; overflow:hidden; }
.ui__meter i{ display:block; height:100%; width:68%; background:var(--ink); border-radius:2px; }

/* ---- main ------------------------------------------------------------- */
.ui__main{ min-width:0; display:flex; flex-direction:column; }
.ui__head{ padding:15px 17px 0; }
.ui__crumb{ font-size:11px; color:#A0A0A7; }
.ui__crumb b{ color:#5A5A62; font-weight:400; }
.ui__h1{ font-size:20px; font-weight:600; letter-spacing:-.02em; margin-top:3px; }

.ui__controls{
  display:flex; align-items:center; gap:7px; flex-wrap:wrap;
  padding:12px 17px 14px;
}
.ui__ctl{
  display:inline-flex; align-items:center; gap:6px;
  padding:5px 10px; border-radius:5px; border:1px solid rgba(17,17,18,.14);
  background:#FFFFFF; font-size:11.5px; color:#42424A; white-space:nowrap;
}
.ui__ctl svg{ width:11px; height:11px; opacity:.55; }
.ui__ctl[data-on="true"]{ background:var(--ink); border-color:var(--ink); color:#FFFFFF; }
.ui__ctl--ghost{ border-style:dashed; color:#7B7B82; }
.ui__spacer{ margin-left:auto; }

/* ---- KPI tiles: label, big number, delta, sparkline -------------------- */
.ui__kpis{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  border-top:1px solid rgba(17,17,18,.09);
}
.ui__kpi{
  padding:13px 15px 11px; border-right:1px solid rgba(17,17,18,.09); min-width:0;
}
.ui__kpi:last-child{ border-right:0; }
.ui__klbl{ font-size:11px; color:#7B7B82; white-space:nowrap; }
.ui__krow{ display:flex; align-items:baseline; gap:7px; margin-top:4px; }
.ui__kval{
  font-size:23px; font-weight:600; letter-spacing:-.028em;
  font-variant-numeric:tabular-nums;
}
.ui__kdelta{ font-size:10.5px; font-variant-numeric:tabular-nums; white-space:nowrap; }
.ui__kdelta[data-dir="up"]{ color:var(--up); }
.ui__kdelta[data-dir="down"]{ color:var(--down); }
.ui__kdelta[data-dir="flat"]{ color:#A0A0A7; }
.ui__spark{ margin-top:9px; height:26px; }
.ui__spark svg{ display:block; width:100%; height:26px; overflow:visible; }

/* ---- panels ----------------------------------------------------------- */
.ui__panels{
  display:grid; grid-template-columns:1.55fr 1fr;
  border-top:1px solid rgba(17,17,18,.09);
}
.ui__panel{ padding:14px 17px 16px; border-right:1px solid rgba(17,17,18,.09); min-width:0; }
.ui__panel:last-child{ border-right:0; }
.ui__ptitle{ display:flex; align-items:baseline; gap:8px; margin-bottom:12px; }
.ui__ptitle h4{ font-size:12.5px; font-weight:600; letter-spacing:-.01em; }
.ui__ptitle span{ font-size:10.5px; color:#A0A0A7; margin-left:auto; font-variant-numeric:tabular-nums; }
.ui__chart svg{ display:block; width:100%; height:118px; overflow:visible; }
.ui__chart .g{ stroke:#EFEFF0; stroke-width:1; }
.ui__chart .ln{ fill:none; stroke:var(--ink); stroke-width:1.7; stroke-linejoin:round; stroke-linecap:round; }
.ui__chart .ar{ fill:url(#uiFill); }
.ui__chart .ax{ font-family:var(--f-mono); font-size:8.5px; fill:#A0A0A7; }

/* the source breakdown: a bar list, not a pie */
.ui__bars{ display:grid; gap:9px; }
.ui__bar{ display:grid; grid-template-columns:64px 1fr 32px; align-items:center; gap:9px; font-size:11.5px; }
.ui__bar span:first-child{ color:#5A5A62; }
.ui__bar i{ display:block; height:5px; border-radius:3px; background:#EDEDEE; overflow:hidden; }
.ui__bar i b{ display:block; height:100%; background:var(--ink); border-radius:3px; }
.ui__bar span:last-child{
  text-align:right; font-family:var(--f-mono); font-size:10.5px; color:#7B7B82;
  font-variant-numeric:tabular-nums;
}

/* ---- table ------------------------------------------------------------ */
.ui__tablewrap{ border-top:1px solid rgba(17,17,18,.09); }
.ui__tbar{
  display:flex; align-items:center; gap:7px; padding:10px 17px;
  border-bottom:1px solid rgba(17,17,18,.09);
}
.ui__tbar h4{ font-size:12.5px; font-weight:600; }
.ui table{ width:100%; border-collapse:collapse; }
.ui thead th{
  padding:7px 17px; text-align:left; font-family:var(--f-mono);
  font-size:9px; letter-spacing:.11em; text-transform:uppercase; color:#A0A0A7;
  font-weight:400; background:#FCFCFC; border-bottom:1px solid rgba(17,17,18,.09);
  white-space:nowrap;
}
.ui thead th.r{ text-align:right; }
.ui tbody td{
  padding:9px 17px; border-bottom:1px solid rgba(17,17,18,.06);
  font-size:12.5px; color:#42424A; white-space:nowrap;
}
.ui tbody td.r{ text-align:right; font-variant-numeric:tabular-nums; font-family:var(--f-mono); font-size:11.5px; }
.ui tbody tr:last-child td{ border-bottom:0; }
.ui tbody td b{ color:var(--ink); font-weight:550; }
/* a new row slides in every few seconds: the only motion inside the product */
.ui tbody tr[data-new]{ animation:rowIn .55s cubic-bezier(.165,.84,.44,1) both; }
@keyframes rowIn{ from{ opacity:0; transform:translateY(-6px); } to{ opacity:1; transform:none; } }

/* status is a tinted pill, never coloured text */
.ui__pill{
  display:inline-flex; align-items:center; gap:5px;
  padding:2px 8px; border-radius:4px; font-size:10.5px;
  background:#F1F1F2; color:#5A5A62;
}
.ui__pill i{ width:4px; height:4px; border-radius:50%; background:currentColor; }
.ui__pill[data-s="booked"]{ background:rgba(27,127,75,.1); color:var(--up); }
.ui__pill[data-s="quoted"]{ background:#EDEDEE; color:#42424A; }
.ui__pill[data-s="answered"]{ background:#F1F1F2; color:#6B6B73; }

.ui__live{
  display:inline-flex; align-items:center; gap:5px; margin-left:auto;
  font-family:var(--f-mono); font-size:9px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--up);
}
.ui__live i{
  width:5px; height:5px; border-radius:50%; background:var(--up);
  animation:uiPulse 2.4s ease-out infinite;
}
@keyframes uiPulse{
  0%,100%{ box-shadow:0 0 0 0 rgba(27,127,75,.5); }
  60%{ box-shadow:0 0 0 6px rgba(27,127,75,0); }
}

/* ---- responsive ------------------------------------------------------- */
@media (max-width:1000px){
  .ui{ grid-template-columns:1fr; font-size:12.5px; }
  .ui__side{ display:none; }
  .ui__panels{ grid-template-columns:1fr; }
  .ui__panel{ border-right:0; border-bottom:1px solid rgba(17,17,18,.09); }
  .ui__kpis{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .ui__kpi:nth-child(2){ border-right:0; }
  .ui__kpi:nth-child(1),.ui__kpi:nth-child(2){ border-bottom:1px solid rgba(17,17,18,.09); }
}
@media (max-width:620px){
  .ui__kpis{ grid-template-columns:1fr; }
  .ui__kpi{ border-right:0; border-bottom:1px solid rgba(17,17,18,.09); }
  .ui__tablewrap{ overflow-x:auto; }
  .ui table{ min-width:520px; }
  .ui__url{ display:none; }
}

/* ------------------------------------------------------------ HERO WASH ----
   v3 painted a warm radial behind the hero. With the palette monochrome that
   read as a stain in the corners, so the hero is now clean and the only thing
   moving behind it is the liquid layer. */
.hero::before,.hero::after{ display:none !important; }
.close::before,.close::after{ display:none !important; }

/* ------------------------------------------------------------ AMB RETIRED --
   novarus.js injects a .amb layer of coloured blobs into every band (v3). Its
   gold and blue gradients are set inline in the stylesheet, which is why the
   palette audit on backgroundColor missed them and a warm cast survived on the
   right of the hero. The liquid layer replaces it entirely. */
.amb{ display:none !important; }

/* -------------------------------------------------- LET THE LIQUID THROUGH --
   The liquid is a fixed layer at z-index 0, but the page sections were painting
   opaque white on top of it at z-index 1, so none of it was visible. Only the
   full-width section backgrounds go transparent: cards, panels and the dark
   bands stay opaque, because those are surfaces rather than page background. */
body{ background:transparent; }
main,
.hero,
.band--light,
.phero,
section.close:not(.band--dark){ background:transparent !important; }

/* the dark bands stay opaque on purpose, and carry their own drift */
.band--dark{ background:#0B0B0C !important; }

/* -------------------------------------------------------- DARK BAND INK ----
   v3 set a warm off-white for text on dark. Neutral now, to match the rest. */
.band--dark{ --ink:#F2F2F3; --ink-2:#C4C4C7; --muted:#9B9B9F; --faint:#7C7C80; }

/* ------------------------------------------------------- INVISIBLE BUTTONS --
   Two separate collapses, one symptom. The mobile call button took
   background:var(--gold) with color:var(--ink) and v5 maps both to #111112, so
   it rendered as a blank black pill with the icon gone too (it inherits
   currentColor). The dark-band CTA took background:var(--ink), and .band--dark
   re-points --ink to near-white, so it was white on white at 1.08:1.
   Fixed separately on purpose: sharing a variable is what caused this. */
.callbar__btn--call{
  background:var(--ink); color:#FBFBFA; border:1px solid var(--ink);
}
.callbar__btn--call svg{ color:#FBFBFA; }
.band--dark .btn--gold{ background:#FBFBFA; color:#0B0B0C; }
.band--dark .btn--gold svg{ color:#0B0B0C; }

/* -------------------------------------------------------------- SELECTION --
   ::selection was gold on ink, both now #111112, so dragging over text turned
   it into a black redaction bar. */
::selection{ background:#111112; color:#FBFBFA; }
::-moz-selection{ background:#111112; color:#FBFBFA; }

/* -------------------------------------------------------- TOUCH TABLET NAV --
   The dock was gated behind (hover:hover), and the burger only existed below
   761px. Every iPad reports hover:hover false and is wider than 760, so dock,
   burger and call bar all computed display:none and the tablet had no way to
   reach another page except the footer. Navigation must never depend on a
   hover capability. */
@media (min-width:761px){
  .dock{
    position:fixed; left:50%; bottom:24px; z-index:var(--z-dock);
    display:flex; align-items:center; gap:6px; padding:9px;
    border-radius:var(--r-pill);
    background:rgba(251,251,250,.92); border:1px solid var(--line-2);
    backdrop-filter:saturate(180%) blur(18px);
    -webkit-backdrop-filter:saturate(180%) blur(18px);
    transform:translateX(-50%);
  }
}
/* keep the burger available on touch tablets as a second route */
@media (max-width:1000px) and (pointer:coarse){
  .burger{ display:flex !important; }
}

/* ==========================================================================
   AUDIT PASS 2
   ========================================================================== */

/* S11 .h2 was used on five section heads and defined nowhere, so it fell to the
   UA default 1.5em and measured the same 25.5px at 390 and at 1920. */
.h2{
  font-size:clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem);
  font-weight:510; font-variation-settings:"wght" 510;
  letter-spacing:-.024em; line-height:1.1;
}

/* S12 section headlines sat flush on the paragraph under them, so the lede's
   first line jammed into a 74px headline's descenders. */
.stmt, .h2{ margin-bottom:var(--s5); }
.stmt + .lede, .h2 + .lede{ margin-top:0; }

/* S13 .versus h3 span also matched the nested product token, so the right
   eyebrow stacked to three lines and the two columns went a row out of step. */
.versus h3 > span{ display:block; }
.versus h3 [data-product]{ display:inline; }

/* S18 --faint was #97979E: 2.90:1 on white and 2.66:1 on the footer, failing AA
   in 29 places at under 24px. Verified against the footer, not white. */
:root{ --faint:#6E6E76; }

/* S14 the dock sat in the middle of the reading column and half-erased body
   copy through its blur. Hide-on-scroll is NOT coming back (Journey asked for
   it to stay up), so instead it moves off the reading column, becomes properly
   opaque so anything behind it is cleanly occluded rather than smeared, and
   gets out of the way on short viewports. */
@media (min-width:761px){
  .dock{
    left:auto; right:24px; transform:none;
    background:rgba(251,251,250,.97);
    box-shadow:0 2px 8px rgba(17,17,18,.06), 0 18px 40px -24px rgba(17,17,18,.28);
  }
  .dock[data-hide="true"],.dock[data-hide]{ transform:none !important; }
}
@media (max-height:700px){ .dock{ display:none; } }
.hero{ padding-bottom:clamp(72px,10vh,120px); }

/* S15 the hero H1 is the LCP element and was being faded in over 700ms with a
   per-step delay, measuring 1652-1896ms desktop against 676ms without. Reveals
   stay everywhere below the fold. */
.hero h1[data-rv],
.hero .lede[data-rv],
.hero .hero__cta[data-rv],
.hero .hero__micro[data-rv],
.hero .eyebrow-pill[data-rv]{
  opacity:1 !important; transform:none !important; transition:none !important;
}

/* S28 the sticky nav transitioned padding, forcing about 90 layout passes per
   threshold crossing. Same visual result from a transform. */
.nav__island{ transition:transform 200ms var(--ease-ui), background 200ms var(--ease-ui); }
.nav.is-stuck .nav__island{ transform:translateY(-3px); }

/* S29 the aurora moved 7/255 at most across a 26 second leg: a permanent
   compositor layer for motion nobody can perceive. */
.band--dark::before{ animation:none; will-change:auto; }

/* S25 the reduced-motion reset squashed duration but left iteration count, so
   three infinite animations kept running: about 270 style recalcs a second on
   the page a vestibular-sensitive user is most likely to be on. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation:none !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
}

/* ------------------------------------------------------------ CONTACT FORM --
   S8: there was no form anywhere on the site. Labels above the field, never a
   placeholder standing in for one, and 16px inputs so iOS does not zoom the
   page on focus. */
.cform{ display:grid; gap:var(--s4); margin-top:var(--s8); max-width:34rem; }
.cform__row{ display:grid; grid-template-columns:1fr 1fr; gap:var(--s4); }
@media (max-width:560px){ .cform__row{ grid-template-columns:1fr; } }
.cform .field{ display:grid; gap:6px; min-width:0; }
.cform .field > span{ font-size:13px; font-weight:550; color:var(--ink-2); }
.cform input,.cform textarea{
  width:100%; min-height:46px; padding:12px 13px;
  border:1px solid var(--line-2); border-radius:8px;
  background:#FFFFFF; color:var(--ink);
  font-family:var(--f); font-size:16px; line-height:1.45;
  transition:border-color 150ms var(--ease-ui), box-shadow 150ms var(--ease-ui);
}
.cform textarea{ resize:vertical; }
.cform input::placeholder,.cform textarea::placeholder{ color:var(--faint); }
.cform input:focus,.cform textarea:focus{
  outline:none; border-color:var(--ink); box-shadow:0 0 0 3px rgba(17,17,18,.12);
}
.cform .btn{ justify-self:start; }
.cform__note{ font-size:13px; color:var(--muted); }
.cform__note a{
  color:var(--ink); text-decoration:underline; text-underline-offset:2px;
  display:inline-block; min-height:44px; line-height:44px;
}
.cform__pot{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }

/* S33: the mock table cuts off on phones with no affordance on the cut edge */
@media (max-width:900px){
  .ui__tablewrap{
    -webkit-mask-image:linear-gradient(90deg,#000 84%,transparent 100%);
    mask-image:linear-gradient(90deg,#000 84%,transparent 100%);
  }
}

/* ------------------------------------------------------- FOOTER STACKING --
   The footer is outside <main>, so the "let the liquid through" rule that
   raised every section to z-index 1 never reached it, and the fixed liquid
   layer painted over the whole thing. Anything at the page level that must sit
   above the background needs to say so explicitly. */
.foot{ position:relative; z-index:1; }
.callbar{ position:fixed; z-index:var(--z-nav); }

/* ==========================================================================
   DENSITY, SHAPES AND CHOREOGRAPHY
   2026-07-26. Three notes from Journey in one pass: everything sat too far
   apart, the page needed moving parts and geometry rather than only the liquid,
   and sections needed to arrive rather than just appear.
   ========================================================================== */

/* ------------------------------------------------------------- DENSITY ----
   The band was clamp(64px, 7.5vw, 124px), which put a single idea on a whole
   1920x1080 screen. Journey's stated target is roughly one and a half to two
   things per screen. */
:root{
  --band:clamp(44px, 4.6vw, 80px);
  --s10:32px; --s12:38px; --s16:50px; --s20:62px; --s24:74px;
}
.hero{ padding:clamp(96px,13vh,150px) 0 clamp(36px,5vh,64px); }
.plain__row{ padding:clamp(15px,1.9vw,24px) 0; }
.plain{ margin-top:var(--s8); }
.stmt, .h2{ margin-bottom:var(--s4); }
.ledger__row{ padding:clamp(14px,1.8vw,22px) 0; }
.idx__panels{ gap:clamp(32px,5vw,72px); }
.docnum{ margin-bottom:var(--s4); }
.hero__center .lede{ margin-top:var(--s4); }
.hero__center .hero__cta{ margin-top:var(--s6); }

/* -------------------------------------------------------------- SHAPES ----
   Thin geometric figures drifting behind the content. Monochrome hairlines, so
   they read as drafting geometry rather than as decoration, and they give the
   background structure the liquid alone could not. Transform only. */
.shapes{
  position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden;
  opacity:.5;
}
.shapes i{
  position:absolute; display:block; border:1px solid rgba(17,17,18,.13);
  border-radius:50%; will-change:transform;
}
.shapes i:nth-child(1){ width:52vmin; height:52vmin; left:-14vmin; top:8vh;
  animation:sh1 46s linear infinite; }
.shapes i:nth-child(2){ width:34vmin; height:34vmin; right:-6vmin; top:38vh;
  animation:sh2 61s linear infinite; }
.shapes i:nth-child(3){ width:24vmin; height:24vmin; left:58vw; bottom:6vh;
  border-radius:22%; animation:sh3 53s linear infinite; }
.shapes i:nth-child(4){ width:15vmin; height:15vmin; left:16vw; bottom:22vh;
  border-radius:22%; animation:sh4 39s linear infinite; }
@keyframes sh1{ to{ transform:rotate(360deg) translate3d(2vmin,0,0); } }
@keyframes sh2{ to{ transform:rotate(-360deg) translate3d(-2vmin,0,0); } }
@keyframes sh3{ to{ transform:rotate(360deg); } }
@keyframes sh4{ to{ transform:rotate(-360deg); } }

/* inside a dark band the same figures flip to light hairlines */
.band--dark{ isolation:isolate; }
.band--dark::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background-image:
    linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
  background-size:78px 78px;
  mask-image:radial-gradient(90% 80% at 50% 50%, #000 20%, transparent 78%);
  -webkit-mask-image:radial-gradient(90% 80% at 50% 50%, #000 20%, transparent 78%);
  animation:gridDrift 34s linear infinite;
}
@keyframes gridDrift{ to{ transform:translate3d(78px, 78px, 0); } }

/* -------------------------------------------------------- CHOREOGRAPHY ----
   Sections arrive rather than appearing. One curve, one distance, staggered by
   role, so the page has a rhythm without every element doing the same 600ms
   fade. The hero is exempt because it is the LCP element. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .band:not(.hero) .docnum,
    .band:not(.hero) .stmt,
    .band:not(.hero) > .container > .h2,
    .plain__row,
    .ledger__row,
    .versus__col,
    .plan,
    .calc,
    .idx__panel{
      animation:arrive linear both;
      animation-timeline:view();
      animation-range:entry 8% cover 26%;
    }
    /* the staircase steps in sequence rather than as a block */
    .plain__row:nth-child(2){ animation-range:entry 4% cover 24%; }
    .plain__row:nth-child(3){ animation-range:entry 0% cover 22%; }
  }
}
@keyframes arrive{
  from{ opacity:0; transform:translate3d(0,18px,0); }
  to{ opacity:1; transform:none; }
}

@media (prefers-reduced-motion:reduce){
  .shapes{ display:none; }
  .band--dark::after{ animation:none; }
}
/* the shapes are a desktop flourish: on a phone they crowd a narrow column */
@media (max-width:700px){
  .shapes{ opacity:.32; }
  .shapes i:nth-child(3),.shapes i:nth-child(4){ display:none; }
}

/* ========================================================== PHONE PASS =====
   Two real bugs found by driving a genuine touch device rather than a narrow
   desktop window.
   ========================================================================== */

/* 1. The open menu covered its own close button again. --z-nav was 100 and
      --z-menu 900, so the overlay painted over the burger and the only way out
      was tapping a link. This is the same regression written up in the brain's
      field lessons, so it is fixed here at the token rather than on .menu, and
      the rule is: any full screen overlay toggled by a button must sit BELOW
      that button in z-order. */
:root{ --z-nav:950; }
.nav{ z-index:950; }
.menu{ z-index:900; }
.burger{ position:relative; z-index:2; }

/* 2. Two to four pixels of horizontal scroll on four of five pages. The
      measured guard from the responsive study, which also stops any future
      flex or grid child refusing to shrink from reintroducing it. clip rather
      than hidden, so position:sticky keeps working. */
html,body{ overflow-x:clip; }
*{ min-width:0; }
img,video,svg,canvas{ max-width:100%; }
/* the mock table is meant to scroll inside its own box, not the page */
.ui__tablewrap{ overflow-x:auto; -webkit-overflow-scrolling:touch; }

/* -------------------------------------------------------- TOUCH TARGETS --
   The footer column links and the nav phone link were 19px and 24px tall. They
   were missed before because the earlier rule keyed off class names and these
   anchors have none, and off a width breakpoint when the real signal is the
   input device. A mouse can hit 19px; a thumb cannot. */
@media (pointer: coarse){
  .foot__col a,
  .foot__brand,
  .nav__tel{
    display:inline-flex; align-items:center; min-height:44px;
  }
  .foot__col li{ line-height:1; }
}

/* ================================================= THE MOCK ASSEMBLES ======
   The product shot used to appear whole. It now builds the way a real
   dashboard loads. mock.js holds it in the armed state until it scrolls into
   view, then releases it and drives the counting, the drawing and the stagger.
   ========================================================================== */
.ui[data-armed="true"] .ui__nav,
.ui[data-armed="true"] .ui__seclbl,
.ui[data-armed="true"] .ui__head,
.ui[data-armed="true"] .ui__ctl,
.ui[data-armed="true"] .ui__kpi,
.ui[data-armed="true"] #uiRows tr{ opacity:0; }

.ui[data-playing="true"] .ui__seclbl,
.ui[data-playing="true"] .ui__nav{ animation:mockSlide .5s cubic-bezier(.23,1,.32,1) both; }
.ui[data-playing="true"] .ui__head{ animation:mockRise .55s cubic-bezier(.23,1,.32,1) both; }
.ui[data-playing="true"] .ui__ctl{ animation:mockPop .45s cubic-bezier(.23,1,.32,1) both; }
.ui[data-playing="true"] .ui__kpi{ animation:mockRise .6s cubic-bezier(.23,1,.32,1) both; }
.ui[data-playing="true"] #uiRows tr{ animation:mockRow .5s cubic-bezier(.23,1,.32,1) both; }

@keyframes mockSlide{ from{ opacity:0; transform:translate3d(-10px,0,0); } to{ opacity:1; transform:none; } }
@keyframes mockRise { from{ opacity:0; transform:translate3d(0,12px,0); }  to{ opacity:1; transform:none; } }
@keyframes mockPop  { from{ opacity:0; transform:scale(.94); }             to{ opacity:1; transform:none; } }
@keyframes mockRow  { from{ opacity:0; transform:translate3d(0,-7px,0); }  to{ opacity:1; transform:none; } }

/* the window itself lands first, so the chrome is there to build inside */
.ui{ animation:mockFrame .7s cubic-bezier(.23,1,.32,1) both; }
@keyframes mockFrame{
  from{ opacity:0; transform:translate3d(0,26px,0) scale(.985); }
  to{ opacity:1; transform:none; }
}

/* the live dot only starts pulsing once the thing is assembled */
.ui[data-armed="true"] .ui__live i{ animation:none; opacity:.25; }

/* ============================================== MORE BACKGROUND MOVEMENT ===
   The liquid was too polite on the first screen. The masses are bigger and
   travel further, a slow sweep crosses the hero, and the geometry drifts more
   noticeably. All transform and opacity.
   ========================================================================== */
.liquid__goo{ opacity:1; }
.liquid__blob{
  background:radial-gradient(circle at 50% 50%, #CFCFD8 0%, #CFCFD8 54%, rgba(207,207,216,0) 74%);
}
.liquid__blob:nth-child(1){ width:58vmax; height:58vmax; animation-duration:26s; }
.liquid__blob:nth-child(2){ width:46vmax; height:46vmax; animation-duration:31s; }
.liquid__blob:nth-child(3){ width:38vmax; height:38vmax; animation-duration:23s; }
.liquid__blob:nth-child(4){ width:32vmax; height:32vmax; animation-duration:35s; }
.liquid__pane{
  background:linear-gradient(180deg, rgba(251,251,250,.18), rgba(251,251,250,.46));
  backdrop-filter:blur(28px) saturate(0%);
  -webkit-backdrop-filter:blur(28px) saturate(0%);
}

/* a slow light sweep across the first screen, the way light moves over glass */
.hero::after{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  display:block !important;
  background:linear-gradient(104deg, transparent 34%, rgba(255,255,255,.55) 50%, transparent 66%);
  animation:sweepHero 13s ease-in-out infinite;
  will-change:transform;
}
@keyframes sweepHero{
  0%,100%{ transform:translate3d(-42%,0,0); }
  50%{ transform:translate3d(42%,0,0); }
}

.shapes{ opacity:.72; }
.shapes i{ border-color:rgba(17,17,18,.16); }
.shapes i:nth-child(1){ animation-duration:30s; }
.shapes i:nth-child(2){ animation-duration:38s; }
.shapes i:nth-child(3){ animation-duration:33s; }
.shapes i:nth-child(4){ animation-duration:25s; }

@media (prefers-reduced-motion:reduce){
  .hero::after{ animation:none; opacity:0; }
  .ui{ animation:none; }
}

/* the explicit confirmation that replaces the form on success */
.cform__done{ display:grid; gap:10px; justify-items:start; padding:var(--s6) 0; }
.cform__done svg{ width:26px; height:26px; color:var(--ink); }
.cform__done h3{ font-size:1.3rem; letter-spacing:-.024em; }
.cform__done p{ color:var(--muted); font-size:.97rem; max-width:44ch; }
.cform__done a{ color:var(--ink); text-decoration:underline; text-underline-offset:2px; }
