/* ════════════════════════════════════════════════════════════════════════════
   ZWIPE — design system for the merchant application and the applications CRM.

   EVERY VALUE IN THE BRAND BLOCK WAS MEASURED OFF zwipe.co, NOT INVENTED.
   The homepage ships its palette inline, so these are the site's own numbers:
     · #ff4a12 is the accent, and it is used 143 times on the homepage. Nothing
       else competes with it — the second headline line, the eyebrow, the button,
       the check marks and the hover state are all this one orange.
     · #fffaf5 is the page, #0b0b0b the text  (main class="bg-[#fffaf5] text-[#0b0b0b]").
     · rgba(38,20,8,·) is the shadow AND the hairline — a warm brown, never a
       neutral grey, which is what keeps the cream from reading as dirty white.
       The nav's own shadow is 0 14px 36px rgba(38,20,8,0.08) and it is reused
       here as --zw-shadow rather than re-guessed.
     · The pastel chip colours (#edf8ec, #fff7df, #f1e3ff, #ffe8e9) are the
       icon-tile tints from the hero's four benefit cards.

   TYPE. Headlines are Figtree, body is Inter.

   Degular Display was tried and REMOVED. It is what zwipe.co self-hosts, and
   set the way the live site sets it — font-black at -0.055em — it renders
   "Own your customer's wallet" as "Ownyour customer'swallet". Rendered side by
   side against Figtree, Inter, Plus Jakarta and Manrope at the same size, it
   was the worst of the five by a clear margin: cramped, dark, and hard to read
   at a glance. Matching a brand is not worth shipping type nobody can read, and
   Figtree shares Degular's warm geometric skeleton without the problem.

   The tracking scale below is deliberately GENTLE. zwipe.co runs -0.045em to
   -0.06em; that is a display-poster setting being used on running text, and it
   is the single biggest reason the old build read as cramped. Nothing here goes
   past -0.022em.

   ICONS are Lucide, 24×24, stroke 2, round caps — the same set the site uses.
   ════════════════════════════════════════════════════════════════════════════ */

/* No @font-face here: both faces come from Google Fonts, declared in each
   page head. Nothing licensed is redistributed with this build. */

:root{
  /* ─ THE BRAND ─ */
  --zw-orange:    #ff4a12;
  --zw-orange-d:  #ef3c05;
  --zw-orange-2:  #f56f0f;

  /* ── THE ACCESSIBILITY SPLIT, AND WHY IT EXISTS ────────────────────────
     Zwipe's measured brand orange #ff4a12 is 3.24:1 on the cream page and
     3.37:1 under white text. Both clear the 3:1 bar for large text and both
     FAIL the 4.5:1 bar WCAG 2.2 AA sets for body copy — which §30 commits this
     platform to. Measured, not assumed: tests/shots.mjs computes it on every
     run and will fail the build if these drift.

     So the brand orange keeps every job where it passes — large display type,
     fills, rules, icons, dots — and two derived tones carry the jobs where it
     does not. They are the same hue, a few steps darker, and at body size the
     difference is invisible next to the difference between readable and not.

     THIS IS A FINDING TO TAKE BACK TO THE CRO, not a decision made quietly:
     if brand insists on #ff4a12 for body text, that is a documented exception
     to §30 rather than an oversight. */
  --zw-orange-ink: #c2380b;   /* orange TEXT on a light ground — 5.1:1 on cream */
  --zw-orange-btn: #d63a0a;   /* button fill under WHITE text — 4.6:1 */
  --zw-peach:     #ffb293;
  --zw-peach-1:   #fff1e7;
  --zw-peach-2:   #fff3ea;
  --zw-peach-3:   #ffe7dc;

  --zw-paper:     #fffaf5;
  --zw-paper-2:   #fbf7f1;
  --zw-paper-3:   #f8f3ed;
  --zw-white:     #ffffff;

  --zw-ink:       #0b0b0b;
  --zw-ink-2:     #6b5a50;
  --zw-ink-3:     #7a6b60;   /* darkened from #98877c, which was 3.45:1 on white */

  --zw-line:      rgba(38,20,8,.08);
  --zw-line-2:    rgba(38,20,8,.16);
  --zw-line-3:    rgba(38,20,8,.28);
  --zw-shadow:    0 14px 36px rgba(38,20,8,.08);
  --zw-shadow-sm: 0 6px 18px rgba(38,20,8,.07);
  --zw-shadow-lg: 0 24px 60px rgba(38,20,8,.12);
  --zw-ring:      0 0 0 3px rgba(255,74,18,.18);

  /* pastel chips, from the hero's benefit tiles */
  --zw-mint:      #edf8ec;
  --zw-butter:    #fff7df;
  --zw-lilac:     #f1e3ff;
  --zw-blush:     #ffe8e9;

  /* #2f8f4e measured 3.81:1 on the section ground — it FAILED AA everywhere it
     carried text, which is every place it is used (deltas, "Resolved" pills,
     the prefilled badge). #25733e clears 4.5 on all four grounds this token
     lands on: mint 5.34, page 5.62, section 5.46, white 5.83. */
  --zw-good:      #25733e;
  --zw-warn:      #8f5600;   /* darkened from #b8700a, which was 3.92:1 on white */
  --zw-bad:       #b82c14;   /* darkened from #d1341a, which was 4.26:1 on the blush pill */

  --zw-r:      16px;
  --zw-r-sm:   12px;
  --zw-r-lg:   18px;
  --zw-r-xl:   24px;

  --zw-display: "Figtree", "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --zw-font:    "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --zw-mono:    ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --zw-wrap:    1560px;
}

*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
body{
  margin:0; background:var(--zw-paper); color:var(--zw-ink);
  font-family:var(--zw-font); font-size:16px; line-height:1.55;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
a{ color:var(--zw-orange-ink); text-decoration:none; }
a:hover{ text-decoration:underline; }
img{ max-width:100%; }
[hidden]{ display:none !important; }
:focus-visible{ outline:2px solid var(--zw-orange); outline-offset:2px; border-radius:8px; }
::selection{ background:var(--zw-peach-3); }

/* ═══ THE BACKGROUND ══════════════════════════════════════════════════════
   Warm paper with two soft colour pools — peach low-left, sage top-right —
   and a faint warm grid that fades before the fold. Fixed, behind everything,
   never a click target.

   NO FILTER AND NO ANIMATION, AND THAT IS A MEASURED DECISION.
   The first version drew the pools as two 44vw elements with filter:blur(70px),
   drifting on a 30-second loop. Measured at 4x CPU throttling that cost the
   whole site 33.4ms median frames and 66.7ms at p95 — roughly 30fps, dipping
   to 15 — on EVERY page, because .zw-bg is on every page. An animated blur is
   re-rasterised every frame at full size.

   Ablation, one change at a time (tests/perf.mjs and the run that produced it):
       baseline                     33.4ms median / 66.7ms p95
       blob animation paused        16.7ms / 16.7ms
       blobs removed                16.7ms / 16.8ms
       blur set to 0                16.7ms / 16.8ms
       header backdrop-filter off   49.9ms  ← NOT the cause
       grid mask removed            50.0ms  ← NOT the cause
   The two candidates that looked most suspicious were both innocent. The pools
   are radial gradients now: identical to look at, zero raster cost, 60fps.
   ═══════════════════════════════════════════════════════════════════════════ */
.zw-bg{ position:fixed; inset:0; z-index:-1; overflow:hidden; pointer-events:none;
  background:
    radial-gradient(42vw 42vw at 6% 74%,  rgba(255,74,18,.10), transparent 62%),
    radial-gradient(38vw 38vw at 96% 96%, rgba(210,222,205,.42), transparent 64%),
    radial-gradient(70% 55% at 88% -6%,   rgba(210,222,205,.55), transparent 62%),
    radial-gradient(64% 52% at 4% 2%,     rgba(255,178,147,.34), transparent 60%),
    linear-gradient(180deg, var(--zw-paper) 0%, var(--zw-paper-2) 58%, var(--zw-paper) 100%); }
.zw-bg .grid{ position:absolute; inset:0;
  background-image:linear-gradient(rgba(38,20,8,.05) 1px, transparent 1px),
                   linear-gradient(90deg, rgba(38,20,8,.05) 1px, transparent 1px);
  background-size:72px 72px;
  -webkit-mask-image:radial-gradient(120% 70% at 50% 8%, #000 8%, transparent 70%);
          mask-image:radial-gradient(120% 70% at 50% 8%, #000 8%, transparent 70%); }
/* The blob elements are kept in the markup and made inert, so no page has to
   change and nothing 404s if one is missed. */
.zw-bg .blob{ display:none; }

/* ═══ CHROME ══════════════════════════════════════════════════════════════
   The floating white pill nav, at the site's own geometry: 70px tall (84 on
   desktop), 16/18px radius, black/5 hairline, and its shadow. */
.zw-skip{ position:absolute; left:-9999px; }
.zw-skip:focus{ left:16px; top:16px; z-index:80; background:var(--zw-white); color:var(--zw-ink);
  padding:10px 16px; border-radius:var(--zw-r-sm); box-shadow:var(--zw-shadow); }

.zw-headwrap{ position:sticky; top:0; z-index:50; padding:8px 16px 0; }
@media (min-width:1024px){ .zw-headwrap{ padding-top:12px; } }
.zw-header{ max-width:var(--zw-wrap); margin:0 auto; height:70px; display:flex; align-items:center;
  gap:14px; padding:0 14px; background:var(--zw-white); border:1px solid var(--zw-line);
  border-radius:var(--zw-r); box-shadow:var(--zw-shadow); }
@media (min-width:1024px){ .zw-header{ height:84px; padding:0 30px; border-radius:var(--zw-r-lg); } }
.zw-header .logo{ display:inline-flex; align-items:center; flex:none; }
.zw-header .logo img{ height:30px; width:auto; }
@media (min-width:1024px){ .zw-header .logo img{ height:38px; } }
.zw-header nav{ display:none; margin-left:26px; gap:26px; align-items:center;
  font-size:16px; font-weight:600; }
@media (min-width:900px){ .zw-header nav{ display:flex; } }
.zw-header nav a{ color:var(--zw-ink); white-space:nowrap; transition:color .2s ease; }
.zw-header nav a:hover{ color:var(--zw-orange); text-decoration:none; }
.zw-header nav a[aria-current="page"]{ color:var(--zw-orange-ink); }
.zw-header .right{ margin-left:auto; display:flex; align-items:center; gap:10px; }
.zw-chip{ display:inline-flex; align-items:center; gap:6px; font-size:12px; font-weight:700;
  letter-spacing:.08em; text-transform:uppercase; color:var(--zw-orange-ink);
  background:var(--zw-peach-2); border-radius:999px; padding:5px 12px; }

.zw-wrap{ max-width:1200px; margin:0 auto; padding:clamp(24px,4vw,44px) clamp(16px,4vw,28px) 100px; }
.zw-wide{ max-width:var(--zw-wrap); }

/* ═══ TYPE ════════════════════════════════════════════════════════════════ */
/* ── HOW LINES BREAK ──────────────────────────────────────────────────────
   Two different jobs, two different properties.

   `balance` on headings makes the browser even the lines out instead of filling
   the first and dropping whatever is left onto the second. It is what stops a
   heading ending in one orphaned word — "A direct line to your / guests."

   `pretty` on body copy leaves the earlier lines alone but forbids a single-word
   final line, which is the same problem one size down.

   Both degrade to normal wrapping where unsupported, so nothing breaks; the
   text is just less tidy. */
h1,h2,h3,h4,.zw-display{ font-family:var(--zw-display); letter-spacing:-0.022em; line-height:1.08;
  margin:0 0 .4em; font-weight:700; text-wrap:balance; }
p,li,figcaption,dd,.zw-lede,.zw-muted,.zw-small,.zw-hint,.zw-label,.tile p{ text-wrap:pretty; }
/* A heading built from two statements balances each of them, not the pair. */
h1 > span, h2 > span, .ob-title > em{ text-wrap:balance; }

/* ── NO MID-PHRASE BREAKS ─────────────────────────────────────────────────
   A button, a pill, a stat label or a table heading that wraps onto two lines
   reads as two things. These are short by construction, so they never wrap. */
.zw-btn, .pill, .zw-chip, .unconfirmed, .zw-seg button,
.kpi span, .fig span, .col h4, .zw-table th, table.data th,
.walletpill, .trustbar span, .navdrop > button, .ob-rail li button{ white-space:nowrap; }
/* … except where a long value genuinely needs to. */
.zw-table td, table.data td, .kv .v, .rv-kv .v{ white-space:normal; }
/* 64px was a poster size being used as a page lead, and on any page whose
   column is not the full bleed it forced the headline to break mid-sentence.
   50px reads as large without needing a metre of line to sit on. */
h1{ font-size:clamp(32px,5vw,50px); }
h2{ font-size:clamp(24px,3.4vw,40px); }
h3{ font-size:clamp(18px,2vw,22px); line-height:1.2; }
h4{ font-size:17px; }
.zw-o{ color:var(--zw-orange); }
.zw-eyebrow{ font-size:13px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--zw-orange-ink); margin:0 0 14px; }
.zw-lede{ color:var(--zw-ink-2); font-size:clamp(16px,1.5vw,18px); max-width:62ch; line-height:1.6; }
.zw-muted{ color:var(--zw-ink-2); }
.zw-small{ font-size:13px; color:var(--zw-ink-3); }

/* ═══ SURFACES ════════════════════════════════════════════════════════════ */
.zw-card{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-lg);
  box-shadow:var(--zw-shadow); }
.zw-pad{ padding:clamp(20px,3.2vw,34px); }
.zw-tile{ width:40px; height:40px; border-radius:12px; display:grid; place-items:center; flex:none; }
.zw-tile.peach{ background:var(--zw-peach-1); color:var(--zw-orange); }
.zw-tile.mint{ background:var(--zw-mint); color:#2f7a45; }
.zw-tile.butter{ background:var(--zw-butter); color:#a97708; }
.zw-tile.lilac{ background:var(--zw-lilac); color:#7a45c2; }
.zw-tile svg{ width:20px; height:20px; }

/* ═══ BUTTONS — solid orange, 12px radius, the arrow slides on hover ══════ */
.zw-btn{ display:inline-flex; align-items:center; justify-content:center; gap:9px;
  font-family:inherit; font-weight:700; font-size:15px; line-height:1;
  padding:14px 22px; border-radius:var(--zw-r-sm); cursor:pointer;
  border:1px solid var(--zw-line-2); background:var(--zw-white); color:var(--zw-ink);
  transition:background .18s ease, color .18s ease, box-shadow .18s ease, transform .12s ease; }
.zw-btn svg{ width:18px; height:18px; transition:transform .28s ease; }
.zw-btn:hover{ text-decoration:none; box-shadow:var(--zw-shadow-sm); }
.zw-btn:hover svg{ transform:translateX(5px); }
.zw-btn:active{ transform:translateY(1px); }
.zw-btn[disabled]{ opacity:.42; cursor:not-allowed; box-shadow:none; }
.zw-btn.primary{ background:var(--zw-orange-btn); color:#fff; border-color:transparent;
  box-shadow:0 10px 26px rgba(255,74,18,.28); }
.zw-btn.primary:hover{ background:var(--zw-orange-d); box-shadow:0 14px 32px rgba(255,74,18,.34); }
.zw-btn.ghost{ background:transparent; border-color:var(--zw-line-2); }
.zw-btn.ghost:hover{ background:var(--zw-peach-2); color:var(--zw-orange-ink); }
.zw-btn.danger{ color:var(--zw-bad); border-color:rgba(209,52,26,.34); background:transparent; }
.zw-btn.danger:hover{ background:#fdeceb; }
.zw-btn.sm{ padding:8px 13px; font-size:13px; border-radius:10px; }
.zw-btn.sm svg{ width:15px; height:15px; }

/* ═══ FORM CONTROLS ═══════════════════════════════════════════════════════ */
.zw-field{ margin:0 0 18px; }
.zw-label{ display:block; font-weight:650; font-size:15px; margin-bottom:8px; color:var(--zw-ink);
  line-height:1.35; }
.zw-label .req{ color:var(--zw-orange); margin-left:4px; }
.zw-label .opt{ color:var(--zw-ink-3); font-weight:500; font-size:13px; margin-left:7px; }

.zw-in, .zw-sel, .zw-ta{
  width:100%; font-family:inherit; font-size:15.5px; color:var(--zw-ink);
  background:var(--zw-white); border:1px solid var(--zw-line-2); border-radius:var(--zw-r-sm);
  padding:12px 14px; transition:border-color .16s ease, box-shadow .16s ease; }
.zw-ta{ min-height:104px; resize:vertical; line-height:1.55; }
.zw-in::placeholder{ color:var(--zw-ink-3); }
.zw-in:focus, .zw-sel:focus, .zw-ta:focus{ outline:none; border-color:var(--zw-orange); box-shadow:var(--zw-ring); }
.zw-sel{ appearance:none; padding-right:40px; cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236b5a50' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; }
.zw-in[data-secret]{ font-family:var(--zw-mono); letter-spacing:.03em; }
/* Visually hidden, still announced. NOT .zw-secret — that is the password
   field wrapper with the peek button, and reusing the name put the literal
   words "Without:" and "With:" on screen in front of every comparison row. */
.zw-sr{ position:absolute!important; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0; }

.zw-secret{ position:relative; }
.zw-secret .peek{ position:absolute; right:9px; top:50%; transform:translateY(-50%);
  background:var(--zw-peach-2); border:0; color:var(--zw-orange-ink); font:inherit; font-size:12px;
  font-weight:700; cursor:pointer; padding:5px 9px; border-radius:8px; }
.zw-secret .peek:hover{ background:var(--zw-peach-3); }

/* Choice controls — the whole row is the target, not a 14px circle. */
.zw-choices{ display:grid; gap:9px; }
.zw-choice{ display:flex; align-items:flex-start; gap:12px; padding:13px 15px; cursor:pointer;
  border:1px solid var(--zw-line-2); border-radius:var(--zw-r-sm); background:var(--zw-white);
  transition:border-color .16s ease, background .16s ease, box-shadow .16s ease; }
.zw-choice:hover{ border-color:var(--zw-peach); background:var(--zw-peach-2); }
.zw-choice input{ accent-color:var(--zw-orange); margin:3px 0 0; width:17px; height:17px; flex:none; }
.zw-choice span{ font-size:15px; line-height:1.4; }
.zw-choice.on{ border-color:var(--zw-orange); background:var(--zw-peach-2); box-shadow:var(--zw-ring); }
@media (min-width:660px){ .zw-choices.two{ grid-template-columns:1fr 1fr; } }

.zw-grp{ border:1px solid var(--zw-line); border-radius:var(--zw-r); padding:20px 20px 4px;
  margin:0 0 20px; background:var(--zw-paper-2); }
.zw-grp > legend{ padding:0 10px; margin-left:-4px; font-size:12px; font-weight:750;
  letter-spacing:.12em; text-transform:uppercase; color:var(--zw-ink-2); }
.zw-row{ display:grid; gap:0 18px; }
@media (min-width:620px){ .zw-row.half{ grid-template-columns:1fr 1fr; } }

.zw-hint{ color:var(--zw-ink-3); font-size:13px; margin:7px 0 0; }
.zw-err{ display:block; margin-top:9px; font-size:14px; color:var(--zw-bad);
  background:#fdeceb; border:1px solid rgba(209,52,26,.26); border-radius:var(--zw-r-sm); padding:10px 13px; }
.zw-err .fix{ display:block; color:var(--zw-ink-2); font-weight:500; margin-top:3px; }
.zw-field.bad .zw-in, .zw-field.bad .zw-sel, .zw-field.bad .zw-ta{ border-color:var(--zw-bad); }

.zw-tipbtn{ width:18px; height:18px; border-radius:50%; border:1.5px solid var(--zw-line-3);
  background:transparent; color:var(--zw-ink-2); font-size:12px; font-weight:800; line-height:1;
  cursor:pointer; margin-left:8px; vertical-align:1px; padding:0; }
.zw-tipbtn:hover{ color:var(--zw-orange-ink); border-color:var(--zw-orange-ink); }
.zw-tip{ display:none; gap:13px; margin:9px 0 0; padding:13px 15px; border-radius:var(--zw-r-sm);
  background:var(--zw-peach-2); border:1px solid var(--zw-peach-3); font-size:14px;
  color:var(--zw-ink-2); line-height:1.5; }
.zw-tip.open{ display:flex; }
.zw-tip svg{ width:26px; height:26px; flex:none; color:var(--zw-orange-ink); margin-top:1px; }

/* ═══ ONBOARDING LAYOUT ═══════════════════════════════════════════════════ */
.ob-grid{ display:grid; gap:28px; align-items:start; }
@media (min-width:1020px){ .ob-grid{ grid-template-columns:266px minmax(0,1fr); } }

/* THE RAIL IS A DESKTOP AFFORDANCE AND IT IS HIDDEN ON A PHONE ON PURPOSE.
   Stacked above the form it put TWELVE list items between the page heading and
   the first question, so a phone had to scroll past the whole table of contents
   to answer anything. The information it carries is not lost: the card's own
   line says "Step 1 of 12 - Business type" and the bar above it fills, which is
   the same three facts in one line instead of twelve rows. */
.ob-rail{ position:sticky; top:104px; }
@media (max-width:1019px){ .ob-rail{ display:none; } }
.ob-rail ol{ list-style:none; margin:0; padding:0; display:grid; gap:2px; }
.ob-rail li button{ width:100%; display:flex; align-items:center; gap:12px; text-align:left;
  font:inherit; font-size:14px; font-weight:600; color:var(--zw-ink-3); background:transparent;
  border:0; border-radius:10px; padding:10px 12px; cursor:pointer; }
.ob-rail li button:hover{ background:var(--zw-peach-2); color:var(--zw-ink-2); }
.ob-rail li .n{ width:23px; height:23px; flex:none; border-radius:50%; display:grid; place-items:center;
  font-size:12px; font-weight:800; border:1.5px solid var(--zw-line-2); color:var(--zw-ink-3); }
.ob-rail li.done .n{ background:var(--zw-mint); border-color:transparent; color:var(--zw-good); }
.ob-rail li.now button{ color:var(--zw-ink); background:var(--zw-peach-2); }
.ob-rail li.now .n{ background:var(--zw-orange-btn); border-color:transparent; color:#fff; }

.ob-prog{ height:5px; border-radius:999px; background:var(--zw-peach-3); overflow:hidden; margin:0 0 22px; }
.ob-prog i{ display:block; height:100%; border-radius:999px; background:var(--zw-orange);
  transition:width .4s cubic-bezier(.2,.8,.2,1); }

.ob-meta{ font-size:13px; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  color:var(--zw-ink-3); margin-bottom:10px; }
.ob-meta b{ color:var(--zw-orange-ink); }
.ob-title{ font-family:var(--zw-display); font-size:clamp(26px,3.4vw,38px); font-weight:700;
  letter-spacing:-0.022em; line-height:1.1; margin:0 0 10px; }
.ob-title em{ font-style:normal; color:var(--zw-orange); }  /* display size — 3:1 applies */
.ob-scope{ color:var(--zw-ink-2); margin:0 0 24px; max-width:60ch; }
.ob-step.in{ animation:zwIn .34s cubic-bezier(.2,.8,.2,1) both; }
@keyframes zwIn{ from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
@media (prefers-reduced-motion:reduce){ .ob-step.in{ animation:none; } }

.ob-nav{ display:flex; gap:12px; align-items:center; margin-top:28px; padding-top:22px;
  border-top:1px solid var(--zw-line); flex-wrap:wrap; }
.ob-nav .spacer{ flex:1; }
.ob-count{ color:var(--zw-ink-3); font-size:13px; }

.ob-risk{ display:flex; gap:13px; padding:15px 17px; border-radius:var(--zw-r);
  border:1px solid #f3d9a8; background:var(--zw-butter); margin:0 0 22px; }
.ob-risk .dot{ width:9px; height:9px; border-radius:50%; background:var(--zw-warn); margin-top:7px; flex:none; }
.ob-risk b{ display:block; color:var(--zw-warn); font-size:15px; }
.ob-risk p{ margin:3px 0 0; color:var(--zw-ink-2); font-size:14px; }

.ob-resume{ display:flex; gap:12px; align-items:center; flex-wrap:wrap; padding:14px 18px;
  border-radius:var(--zw-r); background:var(--zw-peach-2); border:1px solid var(--zw-peach-3);
  margin-bottom:20px; font-size:14px; }
.ob-resume .spacer{ flex:1; }

.zw-drop{ border:1.5px dashed var(--zw-line-3); border-radius:var(--zw-r); padding:22px;
  text-align:center; background:var(--zw-paper-2); cursor:pointer; transition:.16s ease; }
.zw-drop:hover, .zw-drop.over{ border-color:var(--zw-orange); background:var(--zw-peach-2); }
.zw-drop b{ display:block; font-size:15px; }
.zw-drop span{ color:var(--zw-ink-3); font-size:13px; }
.zw-file{ display:flex; align-items:center; gap:12px; margin-top:10px; padding:12px 13px;
  border-radius:var(--zw-r-sm); background:var(--zw-mint); border:1px solid #cfe6cd; font-size:14px; }
.zw-file .ok{ color:var(--zw-good); font-weight:800; }
.zw-file .rm{ margin-left:auto; }

.zw-sign{ border:1px solid var(--zw-line-2); border-radius:var(--zw-r); background:#fff;
  touch-action:none; width:100%; height:190px; display:block; cursor:crosshair; }
.zw-signbar{ display:flex; gap:12px; align-items:center; margin-top:10px; }

.rv-card{ border:1px solid var(--zw-line); border-radius:var(--zw-r); margin:0 0 12px;
  overflow:hidden; background:var(--zw-white); }
.rv-card > h4{ margin:0; padding:12px 16px; background:var(--zw-paper-2); font-size:12px;
  font-family:var(--zw-font); font-weight:750; letter-spacing:.1em; text-transform:uppercase;
  color:var(--zw-ink-2); display:flex; align-items:center; gap:10px; }
.rv-card > h4 .edit{ margin-left:auto; text-transform:none; letter-spacing:0; }
.rv-kv > div{ display:grid; grid-template-columns:minmax(130px,36%) 1fr; gap:16px;
  padding:10px 16px; border-top:1px solid var(--zw-line); font-size:14px; }
.rv-kv .k{ color:var(--zw-ink-3); }
.rv-kv .v{ color:var(--zw-ink); word-break:break-word; }

/* ═══ CRM ═════════════════════════════════════════════════════════════════ */
.crm-head{ display:flex; align-items:flex-end; gap:18px; flex-wrap:wrap; margin-bottom:24px; }
.crm-head .right{ margin-left:auto; display:flex; gap:10px; flex-wrap:wrap; align-items:center; }
.zw-sel.f, .zw-in.f{ width:auto; padding:9px 12px; font-size:14px; border-radius:10px; background:var(--zw-white); }
.zw-sel.f{ min-width:158px; padding-right:36px; }
.zw-in.f{ min-width:230px; }
.zw-seg{ display:inline-flex; border:1px solid var(--zw-line-2); border-radius:10px;
  overflow:hidden; background:var(--zw-white); }
.zw-seg button{ font:inherit; font-size:14px; font-weight:700; padding:9px 15px; border:0;
  background:transparent; color:var(--zw-ink-2); cursor:pointer; }
.zw-seg button.on{ background:var(--zw-orange-btn); color:#fff; }

.kpis{ display:grid; gap:14px; grid-template-columns:repeat(auto-fit,minmax(168px,1fr)); margin-bottom:26px; }
.kpi{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  padding:16px 18px; box-shadow:var(--zw-shadow-sm); }
.kpi b{ display:block; font-family:var(--zw-display); font-size:30px; font-weight:700;
  letter-spacing:-0.022em; line-height:1.1; }
.kpi span{ color:var(--zw-ink-3); font-size:12px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; }
.kpi.accent b{ color:var(--zw-orange); }  /* 30px display — 3:1 applies */

/* A KANBAN BOARD IS ONE ROW THAT SCROLLS.
   This was a grid of six columns holding NINE stages, so three of them wrapped
   onto a second row underneath — which is what made the board look broken: two
   ragged rows of wildly different heights with a dead area beside them. A
   pipeline reads left to right through its stages; if they do not fit, the
   board scrolls, it does not fold. */
.board{
  display:flex; gap:14px; align-items:flex-start;
  overflow-x:auto; overscroll-behavior-x:contain;
  padding-bottom:12px; scroll-snap-type:x proximity;
}
.board > .col{ flex:0 0 268px; scroll-snap-align:start; }
/* A scrolling row needs to LOOK scrollable, or it reads as content that has
   been cut off. The right edge fades only while there is more to reach. */
.boardwrap{ position:relative; }
.boardwrap::after{
  content:""; position:absolute; inset:0 0 14px auto; width:56px; pointer-events:none;
  background:linear-gradient(90deg, rgba(255,250,245,0), var(--zw-paper));
  opacity:0; transition:opacity .2s ease;
}
.boardwrap[data-more="1"]::after{ opacity:1; }
.board::-webkit-scrollbar{ height:10px; }
.board::-webkit-scrollbar-thumb{ background:var(--zw-line-2); border-radius:999px; }
.board::-webkit-scrollbar-track{ background:transparent; }
.col{ background:var(--zw-paper-2); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  padding:13px; min-height:108px; }
.col.drag{ border-color:var(--zw-orange); background:var(--zw-peach-2); }
.col h4{ display:flex; align-items:center; gap:9px; margin:0 0 3px; font-family:var(--zw-font);
  font-size:13px; font-weight:750; letter-spacing:.07em; text-transform:uppercase; color:var(--zw-ink-2); }
.col h4 .dot{ width:9px; height:9px; border-radius:50%; flex:none; }
.col h4 .n{ margin-left:auto; color:var(--zw-ink-3); font-variant-numeric:tabular-nums; }
.col .sum{ font-size:13px; color:var(--zw-ink-3); margin-bottom:12px; }
.col .cards{ display:grid; gap:10px; }
.appcard{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-sm);
  padding:12px 13px; cursor:pointer; display:grid; gap:5px; box-shadow:var(--zw-shadow-sm);
  transition:border-color .16s ease, transform .12s ease; }
.appcard:hover{ border-color:var(--zw-orange); transform:translateY(-1px); }
.appcard b{ font-size:15px; line-height:1.3; }
.appcard .co{ color:var(--zw-ink-3); font-size:13px; }
.appcard .prog{ font-size:13px; font-weight:650; color:var(--zw-ink-2); }
.appcard .row{ display:flex; align-items:center; gap:9px; margin-top:4px; }
.appcard .vol{ font-weight:700; font-size:14px; }
.risk{ font-size:12px; font-weight:800; padding:3px 8px; border-radius:999px; margin-left:auto; }
.risk.lo{ color:var(--zw-good); background:var(--zw-mint); }
.risk.md{ color:var(--zw-warn); background:var(--zw-butter); }
.risk.hi{ color:var(--zw-bad);  background:var(--zw-blush); }
.appcard .flag{ font-size:12px; color:var(--zw-warn); font-weight:650; }
.empty{ color:var(--zw-ink-3); font-size:14px; text-align:center; padding:18px 6px; }

.tblwrap{ overflow-x:auto; border:1px solid var(--zw-line); border-radius:var(--zw-r);
  background:var(--zw-white); box-shadow:var(--zw-shadow-sm); }
/* min-width belongs to the SCROLLING wrapper's tables, not to every table.
   A two-column summary inside a tile inherited 900px and pushed its value
   column clean outside the card, so the limits read as blank rows. */
table.zw-table{ width:100%; border-collapse:collapse; font-size:14px; }
.tblwrap > table.zw-table{ min-width:900px; }
.tile > table.zw-table td{ padding:10px 0; }
.tile > table.zw-table td:last-child{ text-align:right; }
.zw-table th{ text-align:left; font-size:12px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--zw-ink-3); padding:12px 15px; border-bottom:1px solid var(--zw-line); white-space:nowrap; }
.zw-table td{ padding:12px 15px; border-bottom:1px solid var(--zw-line); }
.zw-table tr:last-child td{ border-bottom:0; }
.zw-table tbody tr{ cursor:pointer; }
.zw-table tbody tr:hover{ background:var(--zw-peach-2); }
.zw-table .num{ text-align:right; font-variant-numeric:tabular-nums; }

.pill{ display:inline-flex; align-items:center; gap:7px; font-size:12px; font-weight:700;
  padding:4px 10px; border-radius:999px; background:var(--zw-paper-2);
  border:1px solid var(--zw-line); color:var(--zw-ink-2); white-space:nowrap; }
.pill .dot{ width:7px; height:7px; border-radius:50%; }

.ovl{ position:fixed; inset:0; background:rgba(38,20,8,.38); backdrop-filter:blur(2px);
  opacity:0; pointer-events:none; transition:opacity .22s ease; z-index:60; }
.ovl.on{ opacity:1; pointer-events:auto; }
.drawer{ position:fixed; top:0; right:0; height:100dvh; width:min(580px,100vw); z-index:61;
  background:var(--zw-paper); border-left:1px solid var(--zw-line); transform:translateX(102%);
  transition:transform .3s cubic-bezier(.2,.8,.2,1); display:flex; flex-direction:column;
  box-shadow:-24px 0 60px rgba(38,20,8,.14); }
.drawer.on{ transform:none; }
.dh{ padding:20px 22px; border-bottom:1px solid var(--zw-line); display:flex; align-items:flex-start;
  gap:12px; background:var(--zw-white); }
.dh b{ font-family:var(--zw-display); font-size:21px; letter-spacing:-0.02em; }
.dh .co{ color:var(--zw-ink-3); font-size:13px; }
.dh .x{ margin-left:auto; flex:none; }
.db{ padding:20px 22px 48px; overflow-y:auto; flex:1; }
.db h5{ margin:24px 0 10px; font-size:12px; letter-spacing:.11em; text-transform:uppercase;
  color:var(--zw-ink-3); font-weight:750; }
.db h5:first-child{ margin-top:0; }
.acts{ display:flex; gap:9px; flex-wrap:wrap; }
.note{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-sm);
  padding:12px 13px; font-size:14px; margin-bottom:9px; }
.note .by{ color:var(--zw-ink-3); font-size:12px; margin-top:6px; }
.narea{ display:flex; gap:9px; margin-top:12px; }
.scorebar{ height:8px; border-radius:999px; background:var(--zw-paper-3); overflow:hidden; margin:8px 0 12px; }
.scorebar i{ display:block; height:100%; border-radius:999px; }
.why{ font-size:14px; color:var(--zw-ink-2); display:flex; gap:9px; padding:5px 0; }
.why .p{ font-weight:800; color:var(--zw-ink); font-variant-numeric:tabular-nums; flex:none; width:30px; }

/* ═══ LANDING ═════════════════════════════════════════════════════════════ */
/* PADDING-BLOCK, NOT A SHORTHAND. .hero sits on the same element as .zw-wrap,
   and `padding: X 0 Y` zeroed the wrap's side gutter — the headline ran into
   the left edge of the window at every width. Vertical padding on a shared
   element is always padding-block for exactly this reason. */
.hero{ padding-block:clamp(36px,7vw,84px) clamp(26px,4vw,48px); }
/* The art is the SECOND column and it is the one that goes when there is no room
   for both -- a product shot that squeezes a headline into four words per line on
   a phone has stopped being a benefit. */
.herogrid{ display:grid; gap:34px; align-items:center; }
@media (min-width:1040px){ .herogrid{ grid-template-columns:minmax(0,1fr) minmax(0,440px); } }
.heroart{ display:none; }
@media (min-width:1040px){ .heroart{ display:block; } }
.heroart img{ width:100%; height:auto; border-radius:20px; transform:rotate(-3deg);
  box-shadow:0 34px 70px rgba(38,20,8,.22); }
/* max-width:15ch guaranteed the split the brief is about: the lead clause is
   27 characters, so it could never fit and always broke mid-sentence. The
   measure now holds a full clause, and the size is the largest that still lets
   one fit the hero column — checked by counting rendered line boxes, not by
   eye. */
/* One measure rule for headings, instead of a max-width:NNch typed inline on
   every page — twenty of those existed, ranging 15ch to 22ch, and each one was
   a cap somebody guessed. They were all too tight: `ch` resolves against the
   heading's own font-size, so 22ch at 54px is ~590px, and the roi headline
   needs 1160px. The cap now only stops a heading running the full bleed; the
   container decides the rest. */
.hero h1, .sec-head h2, .sec-head h1{ max-width:min(100%, 46ch); }
.hero h1{ font-size:clamp(32px,4.6vw,54px); }
/* A headline sharing a row with something else gets a column, not a page. The
   hero's wide-left split is the exception — it is sized to hold its clause. */
.split:not(.wide-left) h1{ font-size:clamp(28px,3vw,36px); }
.hero .cta{ display:flex; gap:14px; flex-wrap:wrap; margin-top:30px; align-items:center; }
.trust{ display:flex; gap:22px; flex-wrap:wrap; margin-top:26px; color:var(--zw-ink-2);
  font-size:15px; font-weight:600; }
.trust span{ display:inline-flex; align-items:center; gap:9px; }
.trust svg{ width:20px; height:20px; color:var(--zw-orange); }
.steps3{ display:grid; gap:16px; grid-template-columns:repeat(auto-fit,minmax(236px,1fr)); margin-top:44px; }
.steps3 .s{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  padding:20px; box-shadow:var(--zw-shadow-sm); }
.steps3 .s h3{ margin:12px 0 6px; }
.steps3 .s p{ margin:0; color:var(--zw-ink-2); font-size:15px; }

.zw-foot{ border-top:1px solid var(--zw-line); color:var(--zw-ink-3); font-size:13px;
  padding:26px clamp(16px,4vw,34px); display:flex; gap:16px; flex-wrap:wrap; align-items:center;
  max-width:var(--zw-wrap); margin:0 auto; }
.zw-foot .right{ margin-left:auto; display:flex; gap:16px; }

.zw-toast{ position:fixed; left:50%; bottom:28px; transform:translate(-50%,16px); z-index:80;
  background:var(--zw-ink); color:#fff; border-radius:12px; padding:13px 20px; font-size:14px;
  box-shadow:var(--zw-shadow-lg); opacity:0; transition:opacity .2s ease, transform .2s ease;
  pointer-events:none; max-width:min(92vw,520px); }
.zw-toast.on{ opacity:1; transform:translate(-50%,0); }

/* The done panel */
.done{ text-align:center; padding:clamp(28px,5vw,56px); }
.done .tick{ width:68px; height:68px; border-radius:50%; background:var(--zw-mint);
  display:grid; place-items:center; margin:0 auto 20px; color:var(--zw-good); }
.done .tick svg{ width:34px; height:34px; }
.done .ref{ font-family:var(--zw-mono); font-size:26px; font-weight:700; letter-spacing:.06em;
  background:var(--zw-peach-2); border:1px dashed var(--zw-peach); border-radius:var(--zw-r-sm);
  padding:14px 20px; display:inline-block; margin:14px 0 6px; color:var(--zw-orange); }

/* ════════════════════════════════════════════════════════════════════════════
   SALES 2.0 — components added for the full platform.
   Everything below still reads the measured tokens at the top of this file.
   Nothing here introduces a colour.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── section rhythm ───────────────────────────────────────────────────────── */
/* 92px top AND bottom put 184px of nothing between every pair of sections,
   which on a page that alternates tints reads as a loading gap rather than as
   breathing room. 72px still separates them clearly at half the void. */
.sec{ padding:clamp(40px,5.6vw,72px) 0; }
.sec.tint{ background:var(--zw-paper-2); border-block:1px solid var(--zw-line); }
.sec.ink{ background:var(--zw-ink); color:#fff; }
.sec.ink h2, .sec.ink h3{ color:#fff; }
.sec.ink .zw-lede, .sec.ink p{ color:#d9d2cc; }
/* max-width:70ch looked like a sane measure and was not: `ch` resolves against
   THIS element's font-size (16px), so the cap came out at ~560px and every
   section heading was being squeezed to roughly half the width available to
   it. That is what broke "Restaurants don't have a customer problem." across
   two lines with 1120px of room. A heading measure has to be set in px, or in
   ch on the heading itself. */
.sec-head{ max-width:min(100%, 980px); margin-bottom:clamp(22px,3vw,38px); }
.sec-head.center{ margin-inline:auto; }
.sec-head .zw-lede{ max-width:70ch; }
.sec-head.center .zw-lede{ margin-inline:auto; }
.sec-head h2{ margin-bottom:10px; }

/* ── grids ────────────────────────────────────────────────────────────────── */
.g2{ display:grid; gap:clamp(16px,2.4vw,28px); }
.g3{ display:grid; gap:clamp(16px,2.4vw,24px); }
.g4{ display:grid; gap:14px; }
@media (min-width:760px){ .g2{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .g3{ grid-template-columns:repeat(3,minmax(0,1fr)); } .g4{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (min-width:1080px){ .g4{ grid-template-columns:repeat(4,minmax(0,1fr)); } }
.g5{ display:grid; gap:14px; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); }
.split{ display:grid; gap:clamp(24px,4vw,52px); align-items:center; }
@media (min-width:1000px){ .split{ grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
  .split.wide-left{ grid-template-columns:minmax(0,1.5fr) minmax(0,1fr); } }

/* ── tiles ────────────────────────────────────────────────────────────────── */
.tile{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  padding:clamp(18px,2.4vw,26px); box-shadow:var(--zw-shadow-sm); }
.tile h3{ margin:14px 0 8px; }
.tile p{ margin:0; color:var(--zw-ink-2); font-size:15px; }
.tile.flat{ box-shadow:none; background:var(--zw-paper-2); }
.sec.ink .tile{ background:#16110e; border-color:#2a211c; box-shadow:none; }
.sec.ink .tile p{ color:#bdb3aa; }

/* ── numbered steps ───────────────────────────────────────────────────────── */
.numstep{ display:flex; gap:16px; align-items:flex-start; }
.numstep .n{ width:34px; height:34px; flex:none; border-radius:12px; display:grid; place-items:center;
  font-family:var(--zw-display); font-weight:700; font-size:16px;
  /* white on the brand orange is 3.37:1 at this size; the button tone is 4.6:1 */
  background:var(--zw-orange-btn); color:#fff; }
.numstep h3{ margin:2px 0 6px; }
.numstep p{ margin:0; color:var(--zw-ink-2); font-size:15px; }

/* ── the loop strip: Load → Pay → Cash back → Return ─────────────────────── */
.loop{ display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); }
.loop .step{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  padding:18px; position:relative; }
.loop .step b{ display:block; font-family:var(--zw-display); font-size:22px; letter-spacing:-0.02em; }
.loop .step span{ color:var(--zw-ink-3); font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; }
.loop .step p{ margin:8px 0 0; font-size:14px; color:var(--zw-ink-2); }
.loop .step .amt{ color:var(--zw-orange); }  /* 22px display — 3:1 applies */

/* ── trust strip ──────────────────────────────────────────────────────────── */
.trustbar{ display:flex; gap:10px 26px; flex-wrap:wrap; align-items:center; padding:16px 0;
  color:var(--zw-ink-2); font-size:15px; font-weight:600; }
.trustbar span{ display:inline-flex; align-items:center; gap:9px; }
.trustbar svg{ width:19px; height:19px; color:var(--zw-orange); flex:none; }

/* ── the card preview (card builder) ─────────────────────────────────────── */
.cardwrap{ perspective:1400px; }
.cardface{ width:100%; max-width:420px; aspect-ratio:1.586/1; border-radius:18px; position:relative;
  padding:22px; color:#fff; display:flex; flex-direction:column; justify-content:space-between;
  box-shadow:0 26px 60px rgba(38,20,8,.30); overflow:hidden;
  background:linear-gradient(135deg, var(--card-bg,#ff4a12), color-mix(in srgb, var(--card-bg,#ff4a12) 68%, #000)); }
.cardface::after{ content:""; position:absolute; inset:0;
  background:radial-gradient(120% 90% at 85% 8%, rgba(255,255,255,.22), transparent 55%); pointer-events:none; }
.cardface .brand{ font-family:var(--zw-display); font-weight:700; font-size:clamp(20px,3.4vw,27px);
  letter-spacing:-0.02em; line-height:1.1; max-width:72%; word-break:break-word; }
.cardface .brandlogo{ max-height:46px; max-width:62%; object-fit:contain; }
.cardface .chip{ width:42px; height:32px; border-radius:6px;
  background:linear-gradient(140deg,#f6dd96,#c9a24a); }
.cardface .pan{ font-family:var(--zw-mono); font-size:clamp(13px,2.2vw,17px); letter-spacing:.14em; }
.cardface .foot{ display:flex; align-items:flex-end; justify-content:space-between; gap:12px; }
.cardface .foot small{ display:block; font-size:12px; letter-spacing:.14em; text-transform:uppercase; opacity:.8; }
.cardface .foot b{ font-size:13px; font-weight:700; }
.cardface .mc{ display:flex; align-items:center; flex:none; }
.cardface .mc i{ display:block; width:26px; height:26px; border-radius:50%; }
.cardface .mc i:first-child{ background:#eb001b; }
.cardface .mc i:last-child{ background:#f79e1b; margin-left:-12px; mix-blend-mode:screen; }
.cardface.dark{ color:#fff; }
.cardface.light{ color:#1a1208; }
.cardface.light .foot small{ opacity:.65; }
.cardnote{ font-size:13px; color:var(--zw-ink-3); margin-top:10px; }
.walletrow{ display:flex; gap:10px; flex-wrap:wrap; margin-top:14px; }
.walletpill{ display:inline-flex; align-items:center; gap:8px; background:var(--zw-ink); color:#fff;
  border-radius:10px; padding:9px 14px; font-size:13px; font-weight:600; }
.walletpill svg{ width:16px; height:16px; }

/* ── figures & data ───────────────────────────────────────────────────────── */
.fig{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r); padding:18px 20px; }
.fig b{ display:block; font-family:var(--zw-display); font-size:clamp(26px,3.6vw,36px); letter-spacing:-0.022em; line-height:1.05; }
.fig span{ display:block; color:var(--zw-ink-3); font-size:13px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; margin-top:6px; }
.fig.accent b{ color:var(--zw-orange); }  /* display size — 3:1 applies */
.fig small{ display:block; color:var(--zw-ink-3); font-size:13px; margin-top:8px; font-weight:500; letter-spacing:0; text-transform:none; }

table.data{ width:100%; border-collapse:collapse; font-size:15px; }
table.data th{ text-align:left; font-size:12px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--zw-ink-3); padding:10px 14px; border-bottom:1px solid var(--zw-line); }
table.data td{ padding:12px 14px; border-bottom:1px solid var(--zw-line); }
table.data tr:last-child td{ border-bottom:0; }
table.data .num{ text-align:right; font-variant-numeric:tabular-nums; }
table.data tr.total td{ font-weight:750; background:var(--zw-paper-2); }
table.data tr.neg .num{ color:var(--zw-bad); }
table.data caption{ caption-side:bottom; text-align:left; color:var(--zw-ink-3); font-size:13px; padding:10px 14px 0; }

/* ── calculator ───────────────────────────────────────────────────────────── */
.calcgrid{ display:grid; gap:clamp(18px,3vw,30px); align-items:start; }
@media (min-width:1040px){ .calcgrid{ grid-template-columns:minmax(0,340px) minmax(0,1fr); } }
.calcinputs{ position:sticky; top:104px; }
.slider{ width:100%; accent-color:var(--zw-orange); }
.inputrow{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.inputrow b{ font-family:var(--zw-mono); font-size:15px; }
.illus{ display:inline-block; font-size:13px; color:var(--zw-ink-3); border:1px dashed var(--zw-line-2);
  border-radius:999px; padding:5px 12px; margin-top:12px; }

/* ── FAQ ──────────────────────────────────────────────────────────────────── */
.faq details{ border:1px solid var(--zw-line); border-radius:var(--zw-r); background:var(--zw-white); margin-bottom:10px; }
.faq summary{ cursor:pointer; padding:16px 20px; font-weight:650; font-size:16px; list-style:none;
  display:flex; align-items:center; gap:12px; }
.faq summary::-webkit-details-marker{ display:none; }
.faq summary::after{ content:"+"; margin-left:auto; color:var(--zw-orange-ink); font-size:20px; font-weight:700; line-height:1; }
.faq details[open] summary::after{ content:"\2013"; }
.faq details p{ margin:0; padding:0 20px 18px; color:var(--zw-ink-2); font-size:15px; }

/* ── nav dropdown ─────────────────────────────────────────────────────────── */
.navdrop{ position:relative; }
.navdrop > button{ font:inherit; font-size:16px; font-weight:600; color:var(--zw-ink); background:none;
  border:0; cursor:pointer; padding:0; display:inline-flex; align-items:center; gap:6px; }
.navdrop > button:hover{ color:var(--zw-orange-ink); }
.navdrop > button svg{ width:15px; height:15px; transition:transform .2s ease; }
.navdrop.open > button svg{ transform:rotate(180deg); }
.navdrop .menu{ position:absolute; top:calc(100% + 14px); left:-16px; min-width:260px; z-index:60;
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  box-shadow:var(--zw-shadow-lg); padding:8px; display:none; }
.navdrop.open .menu{ display:block; }
.navdrop .menu a{ display:block; padding:10px 12px; border-radius:10px; color:var(--zw-ink);
  font-size:15px; font-weight:600; }
.navdrop .menu a:hover{ background:var(--zw-peach-2); color:var(--zw-orange-ink); text-decoration:none; }
.navdrop .menu a small{ display:block; font-weight:500; font-size:13px; color:var(--zw-ink-3); }

/* ── role switcher (demo affordance, clearly marked) ─────────────────────── */
.rolebar{ background:var(--zw-ink); color:#fff; font-size:13px; }
.rolebar .in{ max-width:var(--zw-wrap); margin:0 auto; padding:8px clamp(16px,4vw,34px);
  display:flex; gap:12px; align-items:center; flex-wrap:wrap; }
.rolebar b{ color:var(--zw-peach); }
.rolebar select{ font:inherit; font-size:13px; background:#1d1613; color:#fff; border:1px solid #33271f;
  border-radius:8px; padding:5px 9px; }
.rolebar .spacer{ flex:1; }
.rolebar a{ color:#fff; text-decoration:underline; }

/* ── banners ──────────────────────────────────────────────────────────────── */
.banner{ display:flex; gap:12px; padding:14px 16px; border-radius:var(--zw-r); margin:0 0 18px;
  font-size:14px; align-items:flex-start; }
/* Only the LEAD-IN is a block. This applied to every <b> in a banner, so an
   inline emphasised value mid-sentence ("came in via <b>direct</b>.") was
   forced onto its own line and left the full stop stranded on the next one. */
.banner > div > b:first-child{ display:block; }
.banner.info{ background:var(--zw-peach-2); border:1px solid var(--zw-peach-3); }
.banner.warn{ background:var(--zw-butter); border:1px solid #f3d9a8; }
.banner.open{ background:#eef4fb; border:1px solid #cfe0f1; }
.banner .ic{ width:20px; height:20px; flex:none; margin-top:2px; color:var(--zw-orange); }
.banner.warn .ic{ color:var(--zw-warn); }

/* an unconfirmed value from Appendix E, shown as unconfirmed */
.unconfirmed{ display:inline-flex; align-items:center; gap:6px; font-size:12px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; color:var(--zw-warn);
  background:var(--zw-butter); border:1px solid #f3d9a8; border-radius:999px; padding:3px 9px; }

/* ── portal / launch timeline ─────────────────────────────────────────────── */
.milestones{ display:grid; gap:0; }
.ms{ display:grid; grid-template-columns:34px minmax(0,1fr); gap:14px; position:relative; padding-bottom:22px; }
.ms::before{ content:""; position:absolute; left:16px; top:30px; bottom:0; width:2px; background:var(--zw-line); }
.ms:last-child{ padding-bottom:0; }
.ms:last-child::before{ display:none; }
.ms .dot{ width:34px; height:34px; border-radius:50%; display:grid; place-items:center; z-index:1;
  background:var(--zw-paper-2); border:2px solid var(--zw-line-2); color:var(--zw-ink-3);
  font-size:13px; font-weight:800; }
.ms.done .dot{ background:var(--zw-mint); border-color:transparent; color:var(--zw-good); }
.ms.now .dot{ background:var(--zw-orange-btn); border-color:transparent; color:#fff; }
.ms h4{ margin:5px 0 4px; font-family:var(--zw-font); font-size:15.5px; font-weight:700; }
.ms p{ margin:0; color:var(--zw-ink-2); font-size:14px; }
.ms .when{ color:var(--zw-ink-3); font-size:13px; margin-top:4px; }

/* ── needs-you ────────────────────────────────────────────────────────────── */
.needsyou{ border:1px solid var(--zw-peach); background:var(--zw-peach-2); border-radius:var(--zw-r); padding:18px 20px; }
.needsyou h3{ margin:0 0 6px; color:var(--zw-orange-ink); }
.needsyou ul{ margin:10px 0 0; padding-left:18px; color:var(--zw-ink-2); font-size:15px; }
.needsyou li{ margin-bottom:6px; }

/* ── directory ────────────────────────────────────────────────────────────── */
.dirgrid{ display:grid; gap:16px; grid-template-columns:repeat(auto-fill,minmax(260px,1fr)); }
.dircard{ background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  overflow:hidden; box-shadow:var(--zw-shadow-sm); display:flex; flex-direction:column; }
.dircard .art{ padding:18px 18px 0; }
.dircard .art .cardface{ max-width:100%; }
.dircard .body{ padding:16px 18px 18px; display:flex; flex-direction:column; gap:6px; flex:1; }
.dircard .body b{ font-size:16px; }
.dircard .body .meta{ color:var(--zw-ink-3); font-size:13px; }
.dircard .body .offer{ color:var(--zw-orange-ink); font-weight:700; font-size:14px; }
.dircard .body .zw-btn{ margin-top:auto; }

/* ── misc ─────────────────────────────────────────────────────────────────── */
.kv{ display:grid; gap:0; }
.kv > div{ display:grid; grid-template-columns:minmax(150px,38%) 1fr; gap:14px; padding:10px 0;
  border-top:1px solid var(--zw-line); font-size:15px; }
.kv > div:first-child{ border-top:0; }
.kv .k{ color:var(--zw-ink-3); }
.stack{ display:grid; gap:12px; }
.row{ display:flex; gap:12px; flex-wrap:wrap; align-items:center; }
.right{ margin-left:auto; }
.mono{ font-family:var(--zw-mono); }
.nowrap{ white-space:nowrap; }
.center{ text-align:center; }
.maxw{ max-width:66ch; }
hr.rule{ border:0; border-top:1px solid var(--zw-line); margin:clamp(28px,4vw,48px) 0; }

/* ── site footer (multi-column) ───────────────────────────────────────────── */
.zw-sitefoot{ border-top:1px solid var(--zw-line); background:var(--zw-paper-2); margin-top:clamp(40px,6vw,80px); }
.zw-sitefoot .in{ max-width:var(--zw-wrap); margin:0 auto; padding:clamp(30px,4vw,52px) clamp(16px,4vw,34px);
  display:grid; gap:26px; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); }
.zw-sitefoot h4{ font-family:var(--zw-font); font-size:12px; font-weight:750; letter-spacing:.11em;
  text-transform:uppercase; color:var(--zw-ink-3); margin:0 0 12px; }
.zw-sitefoot a{ display:block; color:var(--zw-ink-2); font-size:15px; padding:5px 0; }
.zw-sitefoot a:hover{ color:var(--zw-orange-ink); text-decoration:none; }
.zw-sitefoot .foot-base{ max-width:var(--zw-wrap); margin:0 auto; padding:18px clamp(16px,4vw,34px) 30px;
  border-top:1px solid var(--zw-line); display:flex; gap:16px; flex-wrap:wrap;
  color:var(--zw-ink-3); font-size:13px; }
.zw-sitefoot .foot-base .right{ margin-left:auto; }

/* ════════════════════════════════════════════════════════════════════════════
   SITE REBUILD — components measured off zwipe.co, 2026-09-27
   ════════════════════════════════════════════════════════════════════════════
   Every number below came out of the live build's class strings, not a
   screenshot. See docs/BRAND.md for the frequency counts that separate the
   real scale from one-off values.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── TRACKING IS A FUNCTION OF SIZE ──────────────────────────────────────────
   zwipe.co tightens tracking as type grows: -0.055em at 58px, -0.02em at 15px.
   Setting it per-heading by eye is how a rebuild ends up looking almost right. */
/* Why there is no word-spacing compensation here any more: it existed to undo
   the damage of -0.055em tracking, which closed the word gap from 9.63px to
   6.11px at 64px. The tracking is gone, so the gap is back on its own. */
.zw-wrap h1            { letter-spacing:-0.022em; line-height:1.14; }
.sec-head h2, .sec h2  { letter-spacing:-0.018em; line-height:1.18; }
.tile h3, .numstep h3  { letter-spacing:-0.012em; line-height:1.3; }

/* ── EYEBROW ─────────────────────────────────────────────────────────────────
   The only positive tracking in the brand, and the strongest structural signal
   on the page: every section opens with one. 13px, bold, +0.14em, uppercase. */
.zw-eyebrow{
  font-size:13px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--zw-orange-ink); margin:0 0 10px;
}
/* The 5px orange underline that sits beneath every centred section heading. */
.sec-head.center .rule, .rule{
  display:block; width:76px; height:5px; border-radius:999px;
  background:var(--zw-orange); margin:16px auto 0;
}

/* ── TWO-COLUMN COMPARISON ───────────────────────────────────────────────────
   The site never argues in prose; it argues in two columns. Traditional vs
   Zwipe, Without vs With. Same component, used three times. */
.vs{ display:grid; gap:18px; grid-template-columns:1fr 1fr; align-items:stretch; }
.vs > div{
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-lg);
  padding:26px 24px; box-shadow:var(--zw-shadow-sm);
}
.vs .col-b{ border-color:rgba(255,74,18,.28); box-shadow:0 14px 36px rgba(38,20,8,.1); }
.vs h3{ font-size:19px; margin:0 0 16px; letter-spacing:-0.02em; }
.vs .col-b h3{ color:var(--zw-orange-ink); }
.vs ul{ list-style:none; margin:0; padding:0; display:grid; gap:12px; }
.vs li{ display:grid; grid-template-columns:22px 1fr; gap:12px; align-items:start;
        font-size:15px; line-height:1.45; color:var(--zw-ink-2); }
.vs li b{ font-weight:600; color:var(--zw-ink); }
.vs .mk{ width:22px; height:22px; border-radius:999px; display:grid; place-items:center;
         font-size:13px; font-weight:700; line-height:1; }
/* #7a6b60 on this chip measures 4.48:1 — four hundredths under the 4.5 AA bar,
   which is the kind of miss no one sees and a contrast probe catches every
   time. #74655d is 4.88:1 and visually identical at 13px. */
.vs .col-a .mk{ background:#f3efea; color:#74655d; }
.vs .col-b .mk{ background:#fff3ea; color:var(--zw-orange-ink); }

/* ── PRODUCT CARDS ───────────────────────────────────────────────────────── */
.prodgrid{ display:grid; gap:20px; grid-template-columns:repeat(3,1fr); }
.prod{
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-xl);
  overflow:hidden; display:flex; flex-direction:column; box-shadow:var(--zw-shadow-sm);
  transition:transform .18s ease, box-shadow .18s ease;
}
/* Hover lifts the card and nothing else. No scale on the image, no filter —
   the measured cost of a filter on hover is a repaint of the whole subtree. */
.prod:hover{ transform:translateY(-3px); box-shadow:0 18px 46px rgba(38,20,8,.1); }
.prod .art{ background:linear-gradient(160deg,#fff3ea,#fbf7f1); padding:26px 22px 0; text-align:center; }
.prod .art img{ width:100%; max-width:260px; height:auto; display:inline-block; }
.prod .body{ padding:22px 24px 26px; display:flex; flex-direction:column; gap:12px; flex:1; }
.prod .n{ font:700 12px/1 var(--zw-mono); color:var(--zw-orange-ink); letter-spacing:.12em; }
.prod h3{ font-size:22px; margin:0; letter-spacing:-0.022em; }
.prod .tag{ font-size:13px; font-weight:600; color:var(--zw-orange-ink); margin:-6px 0 0; }
.prod p{ font-size:15px; line-height:1.5; color:var(--zw-ink-2); margin:0; }
/* margin-top:auto pinned these lists to the bottom of an equal-height card, so
   the card with less copy showed a hole in its middle. Let them sit under the
   paragraph; the grid can carry the leftover height at the bottom, where it
   reads as spacing rather than as a missing element. */
.prod .cols{ display:grid; gap:14px; margin-top:2px; padding-top:6px; }
.prod .cols h4{ font-size:12px; letter-spacing:.1em; text-transform:uppercase;
                color:var(--zw-ink-3); margin:0 0 7px; font-weight:700; }
.prod .cols ul{ list-style:none; margin:0; padding:0; display:grid; gap:6px; }
.prod .cols li{ font-size:14px; color:var(--zw-ink-2); padding-left:15px; position:relative; }
.prod .cols li::before{ content:""; position:absolute; left:0; top:8px; width:5px; height:5px;
                        border-radius:999px; background:var(--zw-orange); }

/* ── BADGE STRIP ─────────────────────────────────────────────────────────── */
.badges{ display:flex; flex-wrap:wrap; gap:10px; justify-content:center; margin-top:26px; }
.badges span{
  display:inline-flex; align-items:center; gap:8px; white-space:nowrap;
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:999px;
  padding:10px 18px; font-size:14px; font-weight:600; box-shadow:var(--zw-shadow-sm);
}
.badges img{ height:18px; width:auto; }

/* ── MEMBERSHIP MODELS ───────────────────────────────────────────────────── */
.models{ display:grid; gap:14px; grid-template-columns:repeat(4,1fr); }
.model{
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-lg);
  padding:22px 20px; box-shadow:var(--zw-shadow-sm);
}
.model .zw-tile{ margin-bottom:14px; }
.model h3{ font-size:17px; margin:0 0 6px; letter-spacing:-0.02em; }
.model p{ font-size:14px; line-height:1.45; color:var(--zw-ink-2); margin:0; }

/* ── THE FIVE STEPS ──────────────────────────────────────────────────────── */
.steps5{ display:grid; gap:18px; grid-template-columns:repeat(5,1fr); }
.step5{ text-align:center; }
.step5 .shot{
  background:linear-gradient(170deg,#fff3ea,#fbf7f1); border:1px solid var(--zw-line);
  border-radius:var(--zw-r-lg); padding:18px; margin-bottom:16px;
}
.step5 .shot img{ width:100%; height:auto; display:block; }
/* White on the brand orange is 3.37:1 — fine for a 30px display numeral, and
   NOT fine for this one, which is 14px and therefore body text under WCAG.
   --zw-orange-btn is the derived tone that exists for exactly this case. */
.step5 .n{
  display:inline-grid; place-items:center; width:30px; height:30px; border-radius:999px;
  background:var(--zw-orange-btn); color:#fff; font:700 14px/1 var(--zw-display); margin-bottom:9px;
}
.step5 h3{ font-size:16px; margin:0 0 6px; letter-spacing:-0.02em; }
.step5 p{ font-size:14px; line-height:1.45; color:var(--zw-ink-2); margin:0; }

/* ── PLATFORM PANELS ─────────────────────────────────────────────────────── */
.panels{ display:grid; gap:18px; grid-template-columns:repeat(2,1fr); }
/* Equal-height panels stretch SOMETHING. Left to itself the grid stretched the
   bullet list, so one panel's three bullets drifted apart while its neighbour's
   stayed tight and the difference read as a bug. Pinning the first two rows to
   auto makes the demo box absorb the slack instead, which is the row that can
   afford it. */
.panel{
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-xl);
  padding:26px 24px; box-shadow:var(--zw-shadow-sm);
  display:grid; gap:18px; grid-template-rows:auto auto 1fr;
}
.panel ul{ align-content:start; }
.panel .demo{ display:flex; flex-direction:column; justify-content:center; }
.panel h3{ font-size:20px; margin:0; letter-spacing:-0.022em; }
.panel ul{ list-style:none; margin:0; padding:0; display:grid; gap:8px; }
.panel li{ font-size:15px; color:var(--zw-ink-2); padding-left:16px; position:relative; }
.panel li::before{ content:""; position:absolute; left:0; top:9px; width:5px; height:5px;
                   border-radius:999px; background:var(--zw-orange); }
.panel .demo{ background:var(--zw-paper-2); border:1px solid var(--zw-line); border-radius:var(--zw-r);
              padding:18px; }
.panel .demo .lab{ font-size:12px; letter-spacing:.08em; text-transform:uppercase;
                   color:var(--zw-ink-3); font-weight:700; }
.panel .demo .val{ font:700 30px/1.05 var(--zw-display); letter-spacing:-0.022em; margin-top:6px; }
/* letter-spacing inherits as an ABSOLUTE length, so this 13px badge was
   inheriting the -0.9px its 30px parent computes — that is -0.069em at this
   size, tight enough to overlap its own glyphs. A child at a different size
   must reset tracking, never inherit it. */
.panel .demo .dlt{ font-size:13px; font-weight:700; color:var(--zw-good); margin-left:8px;
  letter-spacing:normal; word-spacing:normal; }
.chat{ display:grid; gap:9px; }
.chat .bub{ font-size:14px; line-height:1.4; padding:10px 14px; border-radius:16px; max-width:88%; }
.chat .them{ background:var(--zw-white); border:1px solid var(--zw-line); border-bottom-left-radius:5px; }
.chat .me{ background:var(--zw-orange-btn); color:#fff; margin-left:auto; border-bottom-right-radius:5px; }

/* ── BRAND MARQUEE ───────────────────────────────────────────────────────────
   The only looping animation on the page. A transform on one w-max flex row —
   no per-logo animation, no filter — which is why it costs nothing to run.
   It stops for anyone who has asked their system to reduce motion. */
.marquee{
  overflow:hidden; background:#121d23; border-block:1px solid var(--zw-orange);
  border-radius:2px; box-shadow:0 14px 36px rgba(18,29,35,.18);
}
.marquee .row{ display:flex; width:max-content; gap:0; animation:zwMarquee 38s linear infinite;
               padding-block:28px; }
.marquee:hover .row, .marquee:focus-within .row{ animation-play-state:paused; }
.marquee .cell{
  flex:0 0 auto; width:205px; height:72px; display:grid; place-items:center;
  padding-inline:22px; border-right:1px solid rgba(255,255,255,.12);
}
.marquee img{ max-height:46px; max-width:175px; width:auto; height:auto; object-fit:contain;
              opacity:.95; filter:brightness(0) invert(1); }
@keyframes zwMarquee{ from{ transform:translate3d(0,0,0); } to{ transform:translate3d(-50%,0,0); } }
@media (prefers-reduced-motion:reduce){
  .marquee .row{ animation:none; }
  .marquee{ overflow-x:auto; }
}
.kicker{ display:flex; align-items:center; gap:26px; justify-content:center; margin-top:34px;
         flex-wrap:wrap; text-align:center; }
.kicker .ic{ width:72px; height:72px; border-radius:999px; background:rgba(255,255,255,.8);
             color:var(--zw-orange); display:grid; place-items:center;
             box-shadow:0 12px 30px rgba(38,20,8,.07); flex:0 0 auto; }
.kicker p{ font:800 27px/1.16 var(--zw-display); letter-spacing:-0.022em; margin:0; }

/* ── PRESS ───────────────────────────────────────────────────────────────── */
.presslist{ display:grid; gap:0; border-top:1px solid var(--zw-line); }
.pressrow{
  display:grid; grid-template-columns:190px 1fr auto; gap:20px; align-items:baseline;
  padding:20px 4px; border-bottom:1px solid var(--zw-line); text-decoration:none; color:inherit;
  transition:background .14s ease;
}
.pressrow:hover{ background:var(--zw-paper-2); }
.pressrow .outlet{ font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
                   color:var(--zw-ink-3); }
.pressrow h3{ font-size:17px; font-weight:600; margin:0; letter-spacing:-0.02em; line-height:1.35; }
.pressrow:hover h3{ color:var(--zw-orange-ink); }
.pressrow time{ font-size:13px; color:var(--zw-ink-3); white-space:nowrap; }
.pressrow .era{ font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
                color:var(--zw-ink-3); background:var(--zw-paper-3); border-radius:999px;
                padding:3px 9px; margin-left:9px; white-space:nowrap; }

/* ── RESPONSIVE ──────────────────────────────────────────────────────────────
   One breakpoint ladder for every new component, so a column count is never
   left behind at a width nobody tested. */
@media (max-width:1080px){
  .prodgrid{ grid-template-columns:1fr; max-width:520px; margin-inline:auto; }
  .models{ grid-template-columns:repeat(2,1fr); }
  .steps5{ grid-template-columns:repeat(2,1fr); }
  .panels{ grid-template-columns:1fr; }
  .pressrow{ grid-template-columns:1fr auto; }
  .pressrow .outlet{ grid-column:1/-1; }
}
@media (max-width:640px){
  .vs{ grid-template-columns:1fr; }
  .models{ grid-template-columns:1fr; }
  .steps5{ grid-template-columns:1fr; max-width:360px; margin-inline:auto; }
  .kicker p{ font-size:21px; }
  .kicker .ic{ width:56px; height:56px; }
  .marquee .cell{ width:150px; height:58px; padding-inline:16px; }
  .marquee img{ max-height:34px; max-width:120px; }
  .pressrow{ grid-template-columns:1fr; gap:6px; }
}


/* ════════════════════════════════════════════════════════════════════════════
   READABILITY PASS — "font is ugly, text too close, text too small, single
   sentences going into double lanes"
   ════════════════════════════════════════════════════════════════════════════ */

/* ── ONE CLAUSE, ONE LANE ────────────────────────────────────────────────────
   Every headline on this site is two clauses with the second one orange. Run
   inline they share lines, so a clause breaks in the middle and the eye reads
   half a sentence per row — which is exactly the "single sentence in two lanes"
   complaint. Giving the orange clause its own line means a break can only ever
   happen BETWEEN sentences, never inside one. It is also how zwipe.co sets its
   own headings. */
h1 .zw-o, h2 .zw-o { display:block; }

/* balance lets the browser even out the lines it does need, instead of leaving
   one word stranded on the last one */
h1, h2, h3, .zw-lede, .sec-head p { text-wrap:balance; }
p, li, dd, .zw-small { text-wrap:pretty; }

/* ── LOOSER, NOT JUST BIGGER ─────────────────────────────────────────────────
   "Too close" was two separate things: the tracking, fixed above, and leading
   set for display type and then used on running text. */
body, p, li, td, .zw-small, .zw-hint { line-height:1.62; }
.zw-lede { line-height:1.58; }
.tile p, .model p, .prod p, .panel li, .step5 p { line-height:1.58; }
.zw-small, .zw-hint, .cardnote, .illus { font-size:13px; }

/* ── COLUMNS WIDE ENOUGH TO HOLD A SENTENCE ──────────────────────────────────
   A 7-word sentence cannot fit one line in a 190px column at any readable size,
   so the fix is the column, not the copy. Five across was too many at this
   content width; four gives every caption ~60 characters, which is a line.  */
.steps5{ grid-template-columns:repeat(3,1fr); gap:24px; max-width:1040px; margin-inline:auto; }
/* Never five. Five across this container is ~205px a column, and a seven-word
   caption needs about 320px at 15px — so five columns guarantees the split the
   brief is asking me to remove. Four is the most that still holds a sentence. */
@media (min-width:1240px){ .steps5{ grid-template-columns:repeat(4,1fr); max-width:1180px; } }

/* Where a caption genuinely cannot fit one line, the two lines should be even.
   Left to itself the browser fills line one and strands the remainder — the
   measured worst case was 228px then 93px, which reads as a mistake. Balance
   makes it ~160/160, which reads as a choice. */
.tile p, .model p, .step5 p, .panel li, .prod p, .numstep p, .zw-hint { text-wrap:balance; }

/* the outlet column was 190px and wrapped three publication names */
.pressrow{ grid-template-columns:220px 1fr auto; }

/* pills must never break: they are labels, not sentences */
.badges span, .pill, .walletpill, .zw-btn, .zw-chip { white-space:nowrap; }

/* ── MINIMUM 12px, ENFORCED ──────────────────────────────────────────────────
   The eyebrow, table headers, footer headings and the card face were all set
   between 9.5px and 11.8px. Nothing on this site is smaller than 12px now. */
.zw-eyebrow{ font-size:13px; letter-spacing:.12em; }
.cardface .lab, .cardface small{ font-size:12px; }
.zw-sitefoot h4, .zw-table th, table.data th, .db h5{ font-size:12px; }
.pressrow .outlet, .pressrow .era, .unconfirmed, .pill, .risk{ font-size:12px; }

/* The generic .split turns two-column at 1000px, which for the HERO leaves a
   text column too narrow for its own headline — measured as one line at 1280px
   and 820px, but two at 1024px. The hero therefore keeps its own, later,
   breakpoint. On a phone a 27-character sentence cannot fit at any readable
   size, so there it wraps to two balanced lines, which is the right answer
   rather than a shrunken one. */
@media (max-width:1139px){
  .hero .split.wide-left{ grid-template-columns:minmax(0,1fr); }
  .hero .cardwrap{ max-width:460px; }
}

/* Belt and braces for the 1330px checkmark: even if an icon is ever emitted
   without its width/height attributes again, no inline icon may exceed a line.
   The components that want a bigger glyph say so by name. */
svg{ max-width:100%; }
p svg, li svg, td svg, span:not([class]) svg{ width:1.05em; height:1.05em; vertical-align:-0.16em; }

/* ════════════════════════════════════════════════════════════════════════════
   APP CHROME — one bar, one account control, a real toolbar
   ════════════════════════════════════════════════════════════════════════════
   What this replaces: a black "Demo role switch" strip stacked above the nav,
   carrying a role <select>, a paragraph of caveat, "Signed in as X" and a
   "Sign out" link — while the nav itself carried a role chip and a "Switch
   role" button. Five controls for one concept, across two full-width bars, on
   every screen.
   ════════════════════════════════════════════════════════════════════════════ */

.zw-header.app{ padding-block:10px; }
.zw-header.app nav{ gap:4px; }
.zw-header.app nav a{
  padding:9px 14px; border-radius:999px; font-size:15px; font-weight:600;
  color:var(--zw-ink-2); white-space:nowrap;
}
.zw-header.app nav a:hover{ background:var(--zw-paper-2); color:var(--zw-ink); text-decoration:none; }
.zw-header.app nav a[aria-current="page"]{ background:var(--zw-ink); color:#fff; }

/* ── ACCOUNT MENU ────────────────────────────────────────────────────────── */
.acct{ position:relative; }
.acct > button{
  display:flex; align-items:center; gap:10px; cursor:pointer;
  background:var(--zw-white); border:1px solid var(--zw-line-2); border-radius:999px;
  padding:7px 12px 7px 16px; font:inherit; color:inherit; text-align:left; line-height:1.15;
}
.acct > button:hover{ border-color:var(--zw-ink-3); }
.acct .who{ font-size:14px; font-weight:650; display:block; }
.acct .rol{ font-size:12px; color:var(--zw-ink-3); display:block; }
.acct > button svg{ width:14px; height:14px; color:var(--zw-ink-3); transition:transform .2s ease; }
.acct.open > button svg{ transform:rotate(180deg); }
.acct .menu{
  display:none; position:absolute; right:0; top:calc(100% + 8px); z-index:60;
  min-width:290px; max-height:min(70vh, 560px); overflow:auto;
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  box-shadow:0 18px 48px rgba(38,20,8,.14); padding:8px;
}
.acct.open .menu{ display:block; }
.acct .menu .hd{
  margin:4px 8px 6px; font-size:12px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--zw-ink-3);
}
.acct .menu button{
  display:block; width:100%; text-align:left; background:none; border:0; cursor:pointer;
  padding:8px 10px; border-radius:9px; font:inherit; font-size:14px; color:var(--zw-ink-2);
}
.acct .menu button:hover{ background:var(--zw-paper-2); color:var(--zw-ink); }
.acct .menu button[aria-current="true"]{ background:var(--zw-peach-2); color:var(--zw-orange-ink); font-weight:650; }
.acct .menu .nb{
  margin:10px 10px 8px; padding-top:10px; border-top:1px solid var(--zw-line);
  font-size:12px; line-height:1.5; color:var(--zw-ink-3);
}
.acct .menu .out{ display:block; padding:9px 10px; border-radius:9px; font-size:14px; font-weight:600; }
.acct .menu .out:hover{ background:var(--zw-paper-2); text-decoration:none; }

/* ── PAGE HEAD + TOOLBAR ─────────────────────────────────────────────────────
   Section tabs and filters belong on their own full-width row under the title,
   not floated to the right of a description paragraph in the middle of the
   page with nothing aligned to them. */
.app-head{ margin-bottom:22px; }
.app-head .ttl h1{ margin:0; font-size:clamp(26px,3vw,34px); }
.app-head .ttl .zw-lede{ margin-top:8px; font-size:16px; max-width:78ch; }
.app-head .toolbar{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  margin-top:18px; padding-top:14px; border-top:1px solid var(--zw-line);
}
.app-head .toolbar .tools{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-left:auto; }
.subnav{ display:flex; gap:2px; flex-wrap:wrap; }
.subnav a{
  padding:8px 14px; border-radius:999px; font-size:14px; font-weight:600;
  color:var(--zw-ink-2); white-space:nowrap;
}
.subnav a:hover{ background:var(--zw-paper-2); color:var(--zw-ink); text-decoration:none; }
.subnav a[aria-current="page"]{ background:var(--zw-peach-2); color:var(--zw-orange-ink); }

/* ── APP FOOTER ──────────────────────────────────────────────────────────── */
.zw-appfoot{
  border-top:1px solid var(--zw-line); margin-top:clamp(32px,5vw,60px);
  padding:16px clamp(16px,4vw,34px); display:flex; align-items:center; gap:18px; flex-wrap:wrap;
  font-size:13px; color:var(--zw-ink-3);
}
.zw-appfoot .env{ display:inline-flex; align-items:center; gap:7px; font-weight:600; }
.zw-appfoot .env.on{ color:var(--zw-good); }
.zw-appfoot nav{ display:flex; gap:16px; margin-left:auto; flex-wrap:wrap; }
.zw-appfoot a{ color:var(--zw-ink-3); }

@media (max-width:860px){
  .zw-header.app nav{ order:3; width:100%; overflow-x:auto; padding-top:8px; }
  .app-head .toolbar .tools{ margin-left:0; width:100%; }
}

/* ── SIGN IN ─────────────────────────────────────────────────────────────────
   Two panes: what this door is, and the door. The previous version listed
   thirteen role buttons, which is a directory rather than a sign-in. */
.signin{ display:grid; gap:clamp(24px,4vw,48px); align-items:start; }
@media (min-width:900px){ .signin{ grid-template-columns:minmax(0,1fr) minmax(0,400px); } }
.signin .card{
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r-lg);
  padding:clamp(22px,3vw,30px); box-shadow:var(--zw-shadow); display:grid; gap:14px;
}
.signin .sep{ display:flex; align-items:center; gap:12px; margin:4px 0 0; }
.signin .sep::before, .signin .sep::after{ content:""; flex:1; height:1px; background:var(--zw-line); }
.signin .sep span{ font-size:12px; font-weight:650; letter-spacing:.06em; text-transform:uppercase; color:var(--zw-ink-3); }

/* The sign-in headline shares its row with the form, so it gets a column size
   rather than a page size — at 50px its second clause could not hold one line
   in a 490px pane. */
.signin h1{ font-size:clamp(27px,3.2vw,36px); }

/* The search field was truncating its own placeholder. In a toolbar the search
   is the control people reach for first, so it gets the room. */
.app-head .tools #q{ min-width:min(340px, 46vw); }
.app-head .tools .zw-sel{ min-width:150px; }

/* ── LAUNCH LADDER ───────────────────────────────────────────────────────────
   Its own component rather than a reuse of .milestones/.rv-kv. Reusing those
   put a stage with no checks in a flex row that pushed its own title to the
   middle of the page, and rendered each check's "how to fix it" hard against
   the end of its label with no gap at all. */
.ladder{ display:grid; gap:0; position:relative; text-align:left; }
.lstep{ display:grid; grid-template-columns:34px minmax(0,1fr); gap:16px;
  padding:16px 0 18px; position:relative; }
.lstep + .lstep{ border-top:1px solid var(--zw-line); }
.lstep > .dot{
  width:34px; height:34px; border-radius:50%; display:grid; place-items:center;
  font:700 14px/1 var(--zw-display); background:var(--zw-paper-2);
  border:1px solid var(--zw-line-2); color:var(--zw-ink-3); flex:none;
}
.lstep.is-done > .dot{ background:var(--zw-mint); border-color:transparent; color:var(--zw-good); }
.lstep.is-now > .dot{ background:var(--zw-orange-btn); border-color:transparent; color:#fff; }
.lstep > .bd{ min-width:0; }
.lstep > .bd > b{ font:700 17px/1.3 var(--zw-display); letter-spacing:-0.012em; }
.lstep.is-now > .bd > b{ color:var(--zw-orange-ink); }

.lchecks{ list-style:none; margin:10px 0 0; padding:0; display:grid; gap:9px; }
.lchecks li{
  display:grid; grid-template-columns:18px minmax(0,auto) minmax(0,1fr); gap:10px;
  align-items:baseline; font-size:15px;
}
.lchecks .mk{ font-size:13px; line-height:1.4; }
.lchecks .met .mk{ color:var(--zw-good); }
.lchecks .unmet .mk{ color:var(--zw-ink-3); }
.lchecks .lb{ color:var(--zw-ink); }
.lchecks .unmet .lb{ color:var(--zw-ink-2); }
/* The fix is guidance, not a second label: smaller, muted, and clearly apart. */
.lchecks .fx{ font-size:13px; line-height:1.5; color:var(--zw-ink-3); }
@media (max-width:720px){
  .lchecks li{ grid-template-columns:18px minmax(0,1fr); }
  .lchecks .fx{ grid-column:2; }
}

/* ════════════════════════════════════════════════════════════════════════════
   BACK-OFFICE SHELL — top bar + left rail
   ════════════════════════════════════════════════════════════════════════════
   Replaces a seven-item horizontal nav that had already run out of room, with
   a second row of sub-tabs appearing under each page title. A rail has space,
   shows the whole structure at once, and keeps your position visible while you
   work. The top bar holds only what is global: search, environment, identity.
   ════════════════════════════════════════════════════════════════════════════ */

:root{ --zw-rail: 252px; --zw-topbar: 56px; }

body.zw-app{ background:var(--zw-paper-2); }
/* The shell is fixed and the page scrolls inside it, so the rail does not
   scroll away from somebody halfway down a long table. */
body.zw-app .zw-bg{ display:none; }

.zw-top{
  position:fixed; inset:0 0 auto 0; height:var(--zw-topbar); z-index:70;
  display:flex; align-items:center; gap:14px; padding-inline:14px;
  background:var(--zw-white); border-bottom:1px solid var(--zw-line);
}
.zw-top .logo{ display:flex; align-items:center; flex:none; }
.zw-top .logo img{ display:block; height:26px; width:auto; }

/* ── GLOBAL SEARCH ───────────────────────────────────────────────────────── */
.zw-top .search{ position:relative; flex:1; max-width:620px; margin-inline:auto; }
.zw-top .search > svg{
  position:absolute; left:12px; top:50%; transform:translateY(-50%);
  width:16px; height:16px; color:var(--zw-ink-3); pointer-events:none;
}
.zw-top .search input{
  width:100%; height:36px; padding:0 14px 0 36px; font:inherit; font-size:14px;
  background:var(--zw-paper-2); border:1px solid var(--zw-line); border-radius:9px; color:var(--zw-ink);
}
.zw-top .search input:focus{ outline:none; background:var(--zw-white); border-color:var(--zw-orange);
  box-shadow:0 0 0 3px rgba(255,74,18,.14); }
.zw-top .results{
  position:absolute; top:calc(100% + 7px); left:0; right:0; z-index:80;
  background:var(--zw-white); border:1px solid var(--zw-line); border-radius:var(--zw-r);
  box-shadow:0 18px 48px rgba(38,20,8,.16); padding:6px; max-height:min(64vh,520px); overflow:auto;
}
.zw-top .results .grp{ font-size:12px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--zw-ink-3); padding:9px 10px 5px; }
.zw-top .results a{ display:grid; grid-template-columns:1fr auto; gap:12px; align-items:baseline;
  padding:9px 10px; border-radius:8px; color:var(--zw-ink); font-size:14px; }
.zw-top .results a:hover, .zw-top .results a.sel{ background:var(--zw-paper-2); text-decoration:none; }
.zw-top .results a small{ color:var(--zw-ink-3); font-size:12.5px; }
.zw-top .results .none{ padding:14px 10px; color:var(--zw-ink-3); font-size:14px; }

.zw-top .tright{ display:flex; align-items:center; gap:10px; flex:none; margin-left:auto; }
.envpill{ display:inline-flex; align-items:center; gap:7px; font-size:12px; font-weight:650;
  padding:6px 11px; border-radius:999px; background:var(--zw-butter); color:#7a5200;
  border:1px solid #f3d9a8; white-space:nowrap; }
.envpill.live{ background:var(--zw-mint); color:var(--zw-good); border-color:#cfe6cd; }

/* the hamburger only exists below the rail breakpoint */
.railtoggle{ display:none; width:38px; height:38px; border:1px solid var(--zw-line-2); border-radius:9px;
  background:var(--zw-white); cursor:pointer; padding:0; flex-direction:column; gap:4px;
  align-items:center; justify-content:center; flex:none; }
.railtoggle span{ display:block; width:16px; height:2px; background:var(--zw-ink); border-radius:2px; }

/* ── THE RAIL ────────────────────────────────────────────────────────────── */
.zw-rail{
  position:fixed; top:var(--zw-topbar); bottom:0; left:0; width:var(--zw-rail); z-index:60;
  background:var(--zw-white); border-right:1px solid var(--zw-line);
  display:flex; flex-direction:column; overflow-y:auto; padding:12px 10px;
}
.zw-rail .rtop{ flex:1; display:grid; gap:2px; align-content:start; }
.zw-rail .rfoot{ display:grid; gap:2px; border-top:1px solid var(--zw-line); padding-top:10px; margin-top:12px; }

.zw-rail .rg{
  display:flex; align-items:center; gap:11px; padding:9px 11px; border-radius:9px;
  font-size:14.5px; font-weight:600; color:var(--zw-ink-2); cursor:pointer; list-style:none;
}
.zw-rail .rg::-webkit-details-marker{ display:none; }
.zw-rail .rg:hover{ background:var(--zw-paper-2); color:var(--zw-ink); text-decoration:none; }
.zw-rail .rg > svg{ width:18px; height:18px; flex:none; color:var(--zw-ink-3); }
.zw-rail .rg > span{ flex:1; min-width:0; }
.zw-rail .rg .cv{ width:14px; height:14px; transition:transform .2s ease; }
.zw-rail details[open] > .rg .cv{ transform:rotate(180deg); }
/* Current page: the same treatment everywhere, so it is never ambiguous. */
.zw-rail .rg.on, .zw-rail .rg.act{ background:var(--zw-peach-2); color:var(--zw-orange-ink); }
.zw-rail .rg.on > svg, .zw-rail .rg.act > svg{ color:var(--zw-orange-ink); }

.zw-rail .rsub{ display:grid; gap:1px; margin:2px 0 6px 30px;
  border-left:1px solid var(--zw-line); padding-left:10px; }
.zw-rail .ri{ padding:7px 10px; border-radius:8px; font-size:14px; color:var(--zw-ink-2); }
.zw-rail .ri:hover{ background:var(--zw-paper-2); color:var(--zw-ink); text-decoration:none; }
.zw-rail .ri.on{ background:var(--zw-ink); color:#fff; font-weight:600; }

/* ── THE CONTENT COLUMN ──────────────────────────────────────────────────── */
body.zw-app main{
  margin-left:var(--zw-rail); padding-top:calc(var(--zw-topbar) + 22px);
  padding-inline:clamp(16px,2.6vw,32px); padding-bottom:40px;
  max-width:none; min-height:100vh; background:var(--zw-paper-2);
}
body.zw-app .zw-appfoot{ margin-left:var(--zw-rail); }
body.zw-app .zw-sitefoot{ margin-left:var(--zw-rail); }

/* The page head no longer carries navigation, so it is just a title. */
body.zw-app .app-head .toolbar{ border-top:0; padding-top:0; margin-top:14px; }

@media (max-width:1040px){
  :root{ --zw-rail: 0px; }
  .railtoggle{ display:flex; }
  .zw-top .search{ margin-inline:0; }
  .zw-rail{
    width:262px; transform:translateX(-100%); transition:transform .22s ease;
    box-shadow:0 18px 48px rgba(38,20,8,.16);
  }
  body.zw-app.rail-open .zw-rail{ transform:none; }
  body.zw-app main{ margin-left:0; }
  body.zw-app .zw-appfoot, body.zw-app .zw-sitefoot{ margin-left:0; }
  body.zw-app.rail-open::after{
    content:""; position:fixed; inset:var(--zw-topbar) 0 0 0; background:rgba(11,11,11,.32); z-index:55;
  }
}
@media (max-width:640px){
  .zw-top .search input::placeholder{ font-size:13px; }
  .zw-top .tright .envpill{ display:none; }
}
@media (prefers-reduced-motion:reduce){ .zw-rail{ transition:none; } }

/* ── "WHAT NEEDS YOU" CARDS ──────────────────────────────────────────────────
   The first question on opening an operations tool. Each one is a link to the
   work it counts, because a figure you cannot click is a figure you then have
   to go and find. */
.needs{ display:grid; gap:14px; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); }
.needcard{
  display:block; background:var(--zw-white); border:1px solid var(--zw-line);
  border-radius:var(--zw-r); padding:18px 18px 16px; color:inherit;
  box-shadow:var(--zw-shadow-sm); transition:transform .16s ease, box-shadow .16s ease;
}
.needcard:hover{ transform:translateY(-2px); box-shadow:0 14px 34px rgba(38,20,8,.1); text-decoration:none; }
.needcard b{ display:block; font:700 32px/1 var(--zw-display); letter-spacing:-0.02em; }
.needcard .lb{ display:block; margin-top:6px; font-size:14px; font-weight:650; }
.needcard .wy{ display:block; margin-top:6px; font-size:12.5px; line-height:1.5; color:var(--zw-ink-3); }
/* Tone is about consequence, not count: "in review" is work waiting, "blocked"
   is work that has stopped. Zero of either is deliberately plain. */
.needcard.act b{ color:var(--zw-orange-ink); }
.needcard.act{ border-color:rgba(255,74,18,.3); }
.needcard.warn b{ color:var(--zw-warn); }
.needcard.warn{ border-color:#f3d9a8; }

/* visually hidden label for the search box */
.zw-secret-label{ position:absolute!important; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0; }

/* A KPI label longer than its figure was running to the card edge and touching
   the next one. Let it wrap rather than clip. */
.kpi span{ display:block; white-space:normal; line-height:1.35; }
.kpi{ min-width:0; }

/* ── MARKETING MENU ON A PHONE ───────────────────────────────────────────────
   Below 900px the nav was display:none with nothing in its place — twenty-one
   links simply unreachable on a phone. */
.navburger{
  display:none; width:42px; height:42px; flex:none; padding:0; cursor:pointer;
  background:var(--zw-white); border:1px solid var(--zw-line-2); border-radius:11px;
  flex-direction:column; align-items:center; justify-content:center; gap:4px;
}
.navburger span{ display:block; width:17px; height:2px; background:var(--zw-ink); border-radius:2px;
  transition:transform .2s ease, opacity .2s ease; }
.navburger[aria-expanded="true"] span:nth-child(1){ transform:translateY(6px) rotate(45deg); }
.navburger[aria-expanded="true"] span:nth-child(2){ opacity:0; }
.navburger[aria-expanded="true"] span:nth-child(3){ transform:translateY(-6px) rotate(-45deg); }

.navsheet{
  position:fixed; inset:calc(var(--zw-headh,86px)) 0 0 0; z-index:65; overflow-y:auto;
  background:var(--zw-paper); padding:18px clamp(16px,5vw,26px) 40px;
  display:grid; gap:22px; align-content:start;
}
.navsheet section h4{
  font-size:12px; font-weight:700; letter-spacing:.11em; text-transform:uppercase;
  color:var(--zw-ink-3); margin:0 0 8px;
}
.navsheet section a{
  display:block; padding:11px 2px; font-size:17px; font-weight:600; color:var(--zw-ink);
  border-bottom:1px solid var(--zw-line);
}
.navsheet section a small{ display:block; font-size:13px; font-weight:400; color:var(--zw-ink-3); margin-top:2px; }
.navsheet .acts{ display:grid; gap:10px; margin-top:6px; }
.navsheet .acts .zw-btn{ justify-content:center; }
body.nav-open{ overflow:hidden; }

@media (max-width:899px){
  .navburger{ display:flex; }
  /* The ghost "Sign in" duplicates a link inside the sheet and crowds the bar. */
  .zw-header .right .zw-btn.ghost.sm{ display:none; }
}
@media (min-width:900px){ .navsheet{ display:none!important; } }
@media (prefers-reduced-motion:reduce){ .navburger span{ transition:none; } }
