/* ZDNetworking v2 — "Sol Editorial" design system
   DNA: docs/superpowers/plans/v2-design-dna.json (D1 structure × D3 warmth; D2 excluded)
   Terracotta is the only accent — max 3 uses per page. */

/* Body/UI face: Libre Franklin, NOT Geist (swapped 2026-08-11).
   Geist is Vercel's own typeface and a default in v0/shadcn-generated output,
   which makes it a recognisable "an AI tool built this" tell in exactly the
   SaaS/startup context ZDN competes in. Libre Franklin is a 1912 Franklin
   Gothic interpretation: an American editorial grotesque, so it pairs with
   Fraunces the way a newspaper pairs its display serif with its text face.
   Both subsets verified rendering á é í ó ú ü ñ Ñ ¿ ¡ before the swap - a
   font that silently drops Spanish glyphs would be fatal on a bilingual site.
   See docs/design/ for the full standard and the do-not-default font list. */
@font-face{font-family:'LibreFranklin';font-style:normal;font-display:swap;font-weight:400 700;src:url(/fonts/librefranklin-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212}
@font-face{font-family:'LibreFranklin';font-style:normal;font-display:swap;font-weight:400 700;src:url(/fonts/librefranklin-latin-ext.woff2) format('woff2');unicode-range:U+0100-02AF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0}
@font-face{font-family:'Fraunces';font-style:normal;font-display:swap;font-weight:300 900;src:url(/fonts/fraunces-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212}
@font-face{font-family:'Fraunces';font-style:normal;font-display:swap;font-weight:300 900;src:url(/fonts/fraunces-latin-ext.woff2) format('woff2');unicode-range:U+0100-02AF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0}

:root{
  --paper:#FAF8F2;
  --sand:#F5ECDC;
  --sand-deep:#EDDFC5;
  --ink:#1C1812;
  --ink-soft:#4A4336;
  /* V2-10 QA: was #8A8171, which measured 3.62:1 on --paper and 3.28:1 on
     --sand — under the 4.5:1 body-contrast rule and WCAG AA, on 25 usages
     (captions, footnotes, honesty lines: the small print people most need to
     be able to read). Darkened along its own hue to the first value that
     clears 4.5:1 against --sand, the harder of the two grounds: 4.57:1 there,
     5.04:1 on --paper. */
  --ink-faint:#716A5D;
  --terra:#D5572E;
  --terra-deep:#B8441F;
  --card-ink:#231D14;
  --hairline:rgba(28,24,18,.14);
  --hairline-soft:rgba(28,24,18,.08);
  --font-display:'Fraunces',Georgia,serif;
  --font-body:'LibreFranklin',-apple-system,BlinkMacSystemFont,'SF Pro Text',Arial,sans-serif;
  --sp-1:4px;--sp-2:8px;--sp-3:16px;--sp-4:24px;--sp-5:32px;--sp-6:48px;--sp-7:64px;--sp-8:96px;
  --r-card:20px;--r-tile:12px;--r-input:12px;
  --dur-micro:.45s;--dur-in:.8s;--dur-draw:1.2s;
  --ease:cubic-bezier(.22,1,.36,1);
  --max:1240px;
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  font-family:var(--font-body);font-size:16.5px;line-height:1.65;
  color:var(--ink);background:var(--paper);
  -webkit-font-smoothing:antialiased;min-height:100dvh;
}
img,svg,video{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font-family:var(--font-body);cursor:pointer}
::selection{background:rgba(213,87,46,.18)}

/* ── type ── */
.t-display{font-family:var(--font-display);font-weight:640;font-size:clamp(40px,6.5vw,68px);line-height:1.04;letter-spacing:-.025em}
.t-h2{font-family:var(--font-display);font-weight:600;font-size:clamp(28px,4vw,40px);line-height:1.12;letter-spacing:-.02em}
.t-h3{font-weight:700;font-size:20px;line-height:1.3}
.t-small{font-size:13.5px;line-height:1.55;color:var(--ink-soft)}
.t-stat{font-family:var(--font-display);font-weight:640;font-size:clamp(56px,9vw,104px);line-height:1;letter-spacing:-.02em}
/* terra-deep, not terra: at 12px this is normal-size text, so it needs 4.5:1.
   --terra measures 3.78:1 on --paper; --terra-deep clears at 5.09:1. Same
   accent family, so the one-accent rule is untouched. */
.t-eyebrow{font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--terra-deep)}

/* ── layout primitives ── */
.wrap{max-width:var(--max);margin:0 auto;padding:0 var(--sp-4)}
.section{padding:var(--sp-8) 0}
.section--sand{background:var(--sand)}
.rule{border:0;border-top:1px solid var(--hairline)}
@media(max-width:700px){.section{padding:var(--sp-6) 0}}

/* ── buttons ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 var(--sp-5);border-radius:100px;font-size:16px;font-weight:600;border:1px solid transparent;transition:transform var(--dur-micro) var(--ease),background var(--dur-micro) var(--ease),border-color var(--dur-micro) var(--ease)}
.btn:active{transform:scale(.98)}
.btn--primary{background:var(--terra);color:#FFF8F0}
.btn--primary:hover{background:var(--terra-deep)}
.btn--quiet{border-color:var(--hairline);color:var(--ink);background:transparent}
.btn--quiet:hover{border-color:var(--ink-soft)}

/* ── nav ── */
.nav{position:sticky;top:0;z-index:50;background:rgba(250,248,242,.94);border-bottom:1px solid var(--hairline-soft)}
.nav-in{max-width:var(--max);margin:0 auto;padding:0 var(--sp-4);height:68px;display:flex;align-items:center;gap:var(--sp-5)}
.nav-wordmark{font-family:var(--font-display);font-weight:640;font-size:21px;letter-spacing:-.02em;display:flex;align-items:baseline}
.nav-wordmark .dot{color:var(--terra)}
.nav-links{display:flex;gap:var(--sp-4);margin-left:auto}
.nav-links a{font-size:15px;font-weight:500;color:var(--ink-soft)}
.nav-links a:hover{color:var(--ink)}
.nav-lang{display:flex;border:1px solid var(--hairline);border-radius:100px;overflow:hidden;flex-shrink:0}
.nav-lang button{position:relative;background:transparent;border:0;padding:var(--sp-2) 12px;font-size:12.5px;font-weight:700;color:var(--ink-faint)}
.nav-lang button::before{content:'';position:absolute;inset:-9px -3px}
.nav-lang button.on{background:var(--ink);color:var(--paper)}
.nav-cta{flex-shrink:0}
.nav-burger-box,.nav-burger,.nav-menu{display:none}
@media(max-width:680px){
  .nav-menu{display:block}
  .nav-in{gap:var(--sp-3)}
  /* 2026-08-24 audit fix: .nav-lang used to be in this hide-list too, with a
     second copy duplicated inside .nav-menu-in as the only reachable
     instance — same bug as the app shell's nav (docs/handoff/2026-08-24-
     auth-interaction-audit.md): the EN|ES pill was invisible until the
     hamburger opened (.nav-menu is max-height:0 until #nav-burger:checked),
     so tapping where it looked like it should be did nothing. Now there is
     exactly one instance, kept visible and pushed into the bar next to the
     wordmark; margin-right clears the absolutely-positioned burger. */
  .nav-links,.nav-cta{display:none}
  .nav-lang{margin-left:auto;margin-right:calc(48px + var(--sp-3))}
  .nav-burger-box{display:block;position:absolute;top:0;right:var(--sp-3);width:48px;height:68px;margin:0;opacity:0;cursor:pointer;z-index:3}
  .nav-burger{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:var(--sp-1);position:absolute;top:0;right:var(--sp-3);width:48px;height:68px;pointer-events:none}
  .nav-burger span{width:20px;height:2px;border-radius:2px;background:var(--ink);transition:transform var(--dur-micro) var(--ease),opacity var(--dur-micro) var(--ease)}
  #nav-burger:checked~.nav-burger span:nth-child(1){transform:translateY(7px) rotate(45deg)}
  #nav-burger:checked~.nav-burger span:nth-child(2){opacity:0}
  #nav-burger:checked~.nav-burger span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
  .nav-menu{position:absolute;top:100%;left:0;right:0;background:var(--paper);border-bottom:1px solid var(--hairline);max-height:0;overflow:hidden;transition:max-height var(--dur-micro) var(--ease)}
  #nav-burger:checked~.nav-menu{max-height:340px}
  .nav-menu-in{padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-3)}
  .nav-menu-in a{font-size:17px;font-weight:600;min-height:44px;display:flex;align-items:center}
  .nav-menu-in .btn{width:100%}
}
/* 320px-class phones: wordmark + pill + burger no longer fit the bar without
   overlap (measured via getBoundingClientRect, not eyeballed — the pill's
   hit-slop pseudo-element made it worse than it looked). Shrink both the
   wordmark and the pill rather than just one, matching the app shell's
   equivalent narrow-phone rule. */
@media(max-width:374px){
  .nav-wordmark{font-size:18px}
  .nav-lang button{padding:6px 9px;font-size:11.5px}
}

/* ── deco geometry (draw with restraint: max one per viewport) ── */
.deco-arch{position:absolute;pointer-events:none;z-index:0}
.deco-arch path{fill:none;stroke:var(--ink);stroke-opacity:.1;stroke-width:1.5}
.deco-arch .terra-ring{stroke:var(--terra);stroke-opacity:.55}
.deco-steps{position:absolute;pointer-events:none;z-index:0;opacity:.6}
.deco-steps rect{fill:var(--sand-deep)}

/* ── placeholder blocks (skeleton phase only; removed as sections land) ── */
.ph{border:1px dashed var(--hairline);border-radius:var(--r-tile);padding:var(--sp-7) var(--sp-4);text-align:center;color:var(--ink-faint);font-size:14px;letter-spacing:.04em;margin:var(--sp-4) 0}

/* ── footer ── */
.footer{border-top:1px solid var(--hairline);padding:var(--sp-6) 0;background:var(--sand)}
.footer-in{max-width:var(--max);margin:0 auto;padding:0 var(--sp-4);display:flex;flex-wrap:wrap;gap:var(--sp-4);align-items:center;justify-content:space-between}
.footer-legal{display:flex;flex-wrap:wrap;gap:var(--sp-3)}.footer-social{display:flex;align-items:center;gap:var(--sp-3)}.footer-social a{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;color:var(--ink-faint);transition:color .2s var(--ease),background .2s var(--ease)}.footer-social a:hover{color:var(--terra);background:rgba(213,87,46,.08)}.footer-social a:focus-visible{outline:2px solid var(--terra);outline-offset:2px}.footer-social svg{width:19px;height:19px;fill:currentColor;display:block}
/* min-height 44px, not the 24px WCAG 2.2 AA floor: these measured 22px on a
   390px viewport, which fails SC 2.5.8 outright, and they are the privacy /
   terms / data links — the ones a compliance-minded visitor goes looking for
   on a phone. inline-flex so the padding becomes real touch area rather than
   just leading. */
.footer-legal a{display:inline-flex;align-items:center;min-height:44px;font-size:13.5px;color:var(--ink-soft);text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--hairline)}
.footer-legal a:hover{color:var(--ink)}
.footer-note{font-size:13.5px;color:var(--ink-faint)}

/* ── styleguide (dev reference, hidden behind <details>) ── */

/* ── hero (V2-2) ── */
.hero{padding-top:var(--sp-7);overflow:hidden}
.hero-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-7)}
@media(min-width:900px){
  .hero-grid{grid-template-columns:minmax(0,45%) minmax(0,55%);align-items:center;gap:var(--sp-6)}
}

.hero-copy{display:flex;flex-direction:column;gap:var(--sp-4);max-width:560px}
.hero-h1{color:var(--ink)}
.hero-word{position:relative;display:inline-block}
.hero-flourish{position:absolute;left:0;right:0;bottom:-.12em;width:100%;height:.32em;overflow:visible}
.hero-flourish path{fill:none;stroke:var(--terra);stroke-width:3;stroke-linecap:round;stroke-dasharray:140;stroke-dashoffset:0}
.hero-flourish.is-drawing path{stroke-dashoffset:140}
.hero-sub{font-size:17px;line-height:1.6;color:var(--ink-soft);max-width:48ch}
.hero-ctas{display:flex;flex-wrap:wrap;gap:var(--sp-3)}
.hero-reassure{color:var(--ink-faint)}

.hero-builder{position:relative;background:var(--sand);border:1px solid var(--hairline);border-radius:var(--r-tile);padding:var(--sp-5);display:flex;flex-direction:column;align-items:center;gap:var(--sp-4);isolation:isolate}

.sun-disc-wrap{position:absolute;top:50%;left:50%;width:min(560px,150%);aspect-ratio:1/1;transform:translate(-50%,-50%);pointer-events:none;z-index:0}
.sun-disc{width:100%;height:100%;
  --ray:rgba(28,24,18,.08);
  background:repeating-conic-gradient(from 0deg,var(--ray) 0deg .6deg,transparent .6deg 12deg);
  border-radius:50%;
  -webkit-mask:radial-gradient(circle,#000 62%,transparent 100%);mask:radial-gradient(circle,#000 62%,transparent 100%);
}

.hero-card-stage{position:relative;z-index:1;width:100%;max-width:300px;display:flex;justify-content:center}
.hero-card{width:100%;aspect-ratio:9/13.5;border-radius:var(--r-card);padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-2);box-shadow:0 24px 48px -20px rgba(28,24,18,.28);opacity:0;transform:translateY(24px) scale(.98)}
.hero-card.is-settled{opacity:1;transform:none;transition:opacity var(--dur-in) var(--ease),transform var(--dur-in) var(--ease)}
@media(prefers-reduced-motion:reduce){.hero-card{opacity:1;transform:none}}
.hero-card-top{display:flex}
.hero-card-monogram{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-weight:640;font-size:22px;border:1px solid currentColor;opacity:.9}
.hero-card-name{font-family:var(--font-display);font-weight:640;font-size:22px;letter-spacing:-.01em;margin-top:auto}
.hero-card-role{font-size:14px;opacity:.72}
.hero-card-contact{display:flex;align-items:center;gap:8px;font-size:13.5px;opacity:.85;padding-top:var(--sp-2);border-top:1px solid currentColor;border-top-color:rgba(0,0,0,0);position:relative}
.hero-card-contact::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;background:currentColor;opacity:.18}
.hero-card-phone{width:16px;height:16px;fill:currentColor}
.hero-card-qr{display:flex;align-items:center;gap:var(--sp-2);margin-top:var(--sp-2)}
#v2-qr-glyph{width:34px;height:34px;fill:currentColor}
.hero-card-qr-caption{opacity:.7;color:inherit}

.hero-card[data-theme="ink"]{background:#2B2013;color:#FAF8F2}
.hero-card[data-theme="sand"]{background:#F5ECDC;color:#1C1812}
.hero-card[data-theme="green"]{background:#1F3B2C;color:#F2ECDC}
.hero-card[data-theme="white"]{background:#FFFDF8;color:#1C1812;box-shadow:0 24px 48px -20px rgba(28,24,18,.2),0 0 0 1px var(--hairline-soft)}
.hero-card[data-theme="terra"]{background:#D5572E;color:#FFF8F0}

.hero-builder-form{position:relative;z-index:1;width:100%;max-width:300px;display:flex;flex-direction:column;gap:var(--sp-3)}
.hero-field{display:flex;flex-direction:column;gap:var(--sp-2)}
.hero-field span{color:var(--ink-faint);font-weight:600;letter-spacing:.02em}
.hero-field input{height:44px;border-radius:var(--r-input);border:1px solid var(--hairline);background:var(--paper);padding:0 var(--sp-3);font-family:var(--font-body);font-size:15px;color:var(--ink);transition:border-color var(--dur-micro) var(--ease)}
.hero-field input:focus{outline:none;border-color:var(--terra)}
.hero-theme-row{display:flex;gap:var(--sp-2);align-items:center}
.hero-theme-swatch{width:44px;height:44px;border-radius:50%;border:1px solid var(--hairline);background:transparent;display:flex;align-items:center;justify-content:center;padding:0}
.hero-theme-swatch::after{content:'';width:22px;height:22px;border-radius:50%;background:var(--sw);border:1px solid rgba(28,24,18,.12)}
.hero-theme-swatch.is-active{border-color:var(--ink)}
.hero-theme-swatch.is-active::after{box-shadow:0 0 0 2px var(--paper),0 0 0 3px var(--ink)}

.hero-builder-claim{position:relative;z-index:1;font-size:14.5px;font-weight:600;color:var(--terra-deep);text-underline-offset:3px;text-decoration:underline;text-decoration-color:rgba(213,87,46,.35)}
/* Base is already --terra-deep, so hover can't lighten to --terra (3.78:1,
   under AA). Feedback moves to the underline instead: same colour, fuller
   decoration. */
.hero-builder-claim:hover{text-decoration-color:var(--terra-deep)}
.hero-honesty{position:relative;z-index:1;color:var(--ink-faint);text-align:center}

@media(max-width:520px){.hero-card-stage,.hero-builder-form{max-width:260px}}

/* ── problem stats (V2-3): D3 giant-numeral treatment on D1's asymmetric grid ── */
.problem{position:relative;overflow:hidden}
.problem-grid{position:relative;z-index:1;display:grid;grid-template-columns:1fr;gap:var(--sp-6);padding-bottom:var(--sp-6)}
.problem-stat{max-width:420px}
.problem-stat--1{justify-self:start;text-align:left}
.problem-stat--2{justify-self:start;text-align:left}
.stat-num{display:flex;align-items:baseline;gap:var(--sp-2);color:var(--ink)}
.stat-num-value{font-family:var(--font-display);font-weight:640;font-size:clamp(56px,9vw,104px);line-height:1;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.stat-num-suffix{font-family:var(--font-display);font-weight:600;font-size:clamp(22px,3vw,32px);color:var(--ink-soft)}
.stat-caption{margin-top:var(--sp-2);font-size:17px;line-height:1.55;color:var(--ink-soft);max-width:34ch}
.problem-foot{grid-column:1/-1;color:var(--ink-faint)}
.problem-steps{left:0;right:0;bottom:0;width:100%;height:clamp(64px,12vw,120px);opacity:1}
.problem-steps path{fill:var(--sand-deep)}
@media(min-width:900px){
  .problem-grid{grid-template-columns:1fr 1fr;column-gap:var(--sp-6);align-items:start}
  .problem-stat--1{grid-column:1;grid-row:1}
  .problem-stat--2{grid-column:2;grid-row:1;justify-self:end;text-align:right;margin-top:var(--sp-7)}
  .problem-stat--2 .stat-num{justify-content:flex-end}
  .problem-foot{grid-column:2;justify-self:end;margin-top:calc(-1 * var(--sp-2))}
}

/* ── how it works (V2-3): 3 numbered steps, lazy footage slots ── */
.how-head{display:flex;flex-direction:column;gap:var(--sp-2);margin-bottom:var(--sp-6);max-width:640px}
.how-head .t-eyebrow{color:var(--ink-faint)} /* terracotta budget spent in hero; this page's eyebrow stays ink */
.how-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-6)}
@media(min-width:900px){.how-grid{grid-template-columns:repeat(3,1fr);column-gap:var(--sp-5)}}
.how-step{display:flex;flex-direction:column;gap:var(--sp-3)}
.how-step-num{font-family:var(--font-display);font-weight:640;font-size:clamp(32px,4vw,44px);color:var(--ink-faint);letter-spacing:-.01em}
.how-step p{color:var(--ink-soft);max-width:34ch}
.how-media{border-radius:var(--r-tile);overflow:hidden;background:var(--sand);aspect-ratio:16/10}
.how-media video,.how-media-img{width:100%;height:100%;object-fit:cover;display:block}
/* editorial asymmetry: alternate numeral position + vertical rhythm per column */
.how-step--b{margin-top:0}
@media(min-width:900px){
  .how-step--b{margin-top:var(--sp-6)}
  .how-step--a .how-step-num,.how-step--c .how-step-num{align-self:flex-start}
  .how-step--b .how-step-num{align-self:flex-end;font-size:clamp(40px,5vw,56px)}
}

/* ── proof + founding counter (V2-4): editorial, no deco element in this
   section (hero + problem already used the viewport's deco budget). The
   terracotta budget's THIRD and final use lives in .proof-counter-num. ── */
.proof-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-6)}
@media(min-width:900px){.proof-grid{grid-template-columns:1fr 1fr;gap:var(--sp-7);align-items:start}}
.proof-copy{display:flex;flex-direction:column;gap:var(--sp-3);max-width:480px}
.proof-counter{font-family:var(--font-display);font-weight:600;font-size:clamp(19px,2.3vw,23px);line-height:1.4;color:var(--ink);letter-spacing:-.01em}
.proof-counter-num{color:var(--terra-deep);border-bottom:2px solid var(--terra);padding-bottom:1px;font-variant-numeric:tabular-nums}
.proof-miami{color:var(--ink-faint);margin-top:var(--sp-1)}
.proof-ladder{display:flex;flex-direction:column;gap:var(--sp-4)}
.ladder-list{list-style:none;display:flex;flex-direction:column;border:1px solid var(--hairline);border-radius:var(--r-tile);padding:var(--sp-2) var(--sp-4);background:var(--paper)}
.ladder-item{display:flex;align-items:baseline;gap:var(--sp-2);font-size:15px;padding:var(--sp-3) 0;border-bottom:1px solid var(--hairline-soft)}
.ladder-item:last-child{border-bottom:0}
.ladder-wave{font-weight:700;min-width:60px}
.ladder-price{font-family:var(--font-display);font-weight:640;font-size:17px}
.ladder-dot{color:var(--ink-faint)}
.ladder-seats{color:var(--ink-soft);margin-left:auto}
.ladder-item--then{color:var(--ink-faint);font-size:13.5px}
.proof-kept{color:var(--ink-soft)}

/* ── hidden testimonial shells (V2-4): styled only for the future moment the
   `hidden` attribute is removed. The :not([hidden]) guard matters: a bare
   `.testimonials{display:grid}` would out-cascade the browser's default
   `[hidden]{display:none}` (author rule beats UA rule regardless of
   specificity) and make the "nothing renders until real quotes exist" empty
   boxes visible right now. ── */
.testimonials:not([hidden]){display:grid;grid-template-columns:1fr;gap:var(--sp-5);margin-top:var(--sp-6)}
@media(min-width:900px){.testimonials:not([hidden]){grid-template-columns:repeat(3,1fr)}}
.testimonial{border:1px solid var(--hairline);border-radius:var(--r-tile);padding:var(--sp-4);background:var(--paper)}

/* ── bilingual + WhatsApp (V2-5): paper ground, zero terracotta (budget
   already spent: H1 flourish, hero CTA, founding counter). Reuses
   .hero-card/.hero-card-* (demo card) and .nav-lang (EN|ES flip pill) from
   the hero/nav modules above — nothing here duplicates that CSS. ── */
.bilingual-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-7)}
@media(min-width:900px){
  .bilingual-grid{grid-template-columns:minmax(0,54%) minmax(0,38%);column-gap:var(--sp-8);align-items:start}
  .bilingual-demo{justify-self:end;margin-top:var(--sp-7)}
}
.bilingual-copy{display:flex;flex-direction:column;gap:var(--sp-4);max-width:560px}
.bilingual-whatsapp{display:flex;align-items:center;gap:var(--sp-3);margin-top:var(--sp-1)}
.whatsapp-glyph{width:28px;height:28px;flex-shrink:0}
.whatsapp-glyph path{fill:none;stroke:var(--ink);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.bilingual-whatsapp p{font-size:16.5px;color:var(--ink-soft)}
.bilingual-stat{max-width:44ch}
.bilingual-demo{display:flex;flex-direction:column;align-items:center;gap:var(--sp-4);width:100%;max-width:300px}
/* Deliberately its own small ruleset, NOT a reuse of .nav-lang: that class
   is also the selector i18n.js's page-toggle wiring queries generically
   (`.nav-lang button`), so sharing the literal class name would wire the
   page-language click handler onto these demo buttons too. Visually
   identical pill, functionally isolated. */
.bilingual-flip{display:flex;border:1px solid var(--hairline);border-radius:100px;overflow:hidden;flex-shrink:0}
.bilingual-flip button{background:transparent;border:0;padding:var(--sp-2) var(--sp-3);min-height:44px;font-size:12.5px;font-weight:700;color:var(--ink-faint)}
.bilingual-flip button.on{background:var(--ink);color:var(--paper)}
/* crossfade for the demo card's independently-swapped text nodes; both
   properties already carry a resting opacity (.72 / .7) for the dimmed
   card-copy look, so the transition doubles as the flip's fade-out/in */
.hero-card-role,.hero-card-qr-caption{transition:opacity var(--dur-micro) var(--ease)}
.hero-card-role.is-flipping,.hero-card-qr-caption.is-flipping{opacity:0}
@media(prefers-reduced-motion:reduce){.hero-card-role,.hero-card-qr-caption{transition:none}}

/* ── pricing page (V2-6): terracotta budget here is TWO uses only —
   the pre-selected Pro card's accent border and the primary CTA color
   (already .btn--primary). The badge pill and the honest counter number
   both use ink, not terra, to stay inside budget. ── */
.pricing-hero{position:relative;overflow:hidden;padding-bottom:var(--sp-7)}
.pricing-hero-in{display:flex;flex-direction:column;gap:var(--sp-2);max-width:640px}
.pricing-hero-steps{left:0;right:0;bottom:0;width:100%;height:clamp(48px,9vw,88px);opacity:1}
.pricing-hero-steps path{fill:var(--sand-deep)}

/* Round-2: founding-ladder banner, now ABOVE the tier grid. Reuses the
   homepage proof section's .proof-grid/.proof-ladder/.ladder-list rules
   (same visual language, one source of truth) inside its own wrapper so the
   page's section spacing stays this page's own. */
.pricing-banner{padding:var(--sp-5) var(--sp-5);border:1px solid var(--hairline);border-radius:var(--r-card);background:var(--paper);margin-bottom:var(--sp-5)}
.pricing-banner .pricing-proof-line{font-family:var(--font-display);font-weight:600;font-size:19px;color:var(--ink)}
.pricing-banner .pricing-proof-num{font-variant-numeric:tabular-nums;color:var(--ink);border-bottom:2px solid var(--hairline);padding-bottom:1px}

/* Billing toggle: its own isolated pill, deliberately not .nav-lang (that
   selector is i18n.js's generic page-language click handler — see the
   identical note on .bilingual-flip above). Ink only, terracotta budget
   for this page stays at its existing 2 uses. */
.billing-toggle{display:flex;justify-content:center;border:1px solid var(--hairline);border-radius:100px;overflow:hidden;width:fit-content;margin:0 auto var(--sp-5)}
.billing-toggle button{background:transparent;border:0;padding:var(--sp-2) var(--sp-3);min-height:44px;font-size:13px;font-weight:700;color:var(--ink-faint);cursor:pointer}
.billing-toggle button.on{background:var(--ink);color:var(--paper)}

.pricing-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-5);align-items:start}
@media(min-width:900px){.pricing-grid{grid-template-columns:1fr 1.08fr 1fr;gap:var(--sp-4)}}

.pricing-card{position:relative;display:flex;flex-direction:column;gap:var(--sp-3);background:var(--paper);border:1px solid var(--hairline);border-radius:var(--r-card);padding:var(--sp-5)}
/* Neutral ink shadow, not a terracotta glow: a tinted shadow is the ban-list's
   "fake depth" tell, and it was carrying no information the customer needs —
   the 2px terracotta border, the "Most popular" badge, and the desktop lift
   already mark this as the recommended plan three times over. The shadow now
   just supports that real lift, in the same ink family as every other raised
   surface here. */
.pricing-card--pro{border:2px solid var(--terra);box-shadow:0 24px 48px -28px rgba(28,24,18,.28)}
@media(min-width:900px){.pricing-card--pro{padding:calc(var(--sp-5) + var(--sp-2)) var(--sp-5);transform:translateY(calc(-1 * var(--sp-2)))}}
.pricing-badge{position:absolute;top:calc(-1 * var(--sp-3));left:var(--sp-5);background:var(--ink);color:var(--paper);font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:var(--sp-1) 12px;border-radius:100px}
.pricing-card-price{display:flex;align-items:baseline;gap:4px;font-family:var(--font-display)}
.pricing-price-num{font-weight:640;font-size:clamp(36px,5vw,48px);letter-spacing:-.02em;color:var(--ink);font-variant-numeric:tabular-nums}
.pricing-price-unit{color:var(--ink-faint)}
.pricing-card-cap{font-weight:600;color:var(--ink-soft)}
.pricing-ladder{color:var(--ink-soft)}
.pricing-kept{color:var(--ink-faint)}
.pricing-annual-note{color:var(--ink-faint)}
.pricing-roi-inline{color:var(--ink-soft);font-weight:600}
.pricing-features{list-style:none;display:flex;flex-direction:column;gap:var(--sp-2);border-top:1px solid var(--hairline-soft);padding-top:var(--sp-3)}
.pricing-features li{position:relative;padding-left:16px;color:var(--ink-soft);font-size:15px;line-height:1.5}
.pricing-features li::before{content:'';position:absolute;left:0;top:9px;width:6px;height:6px;border-radius:50%;background:var(--ink-faint)}
.pricing-card-note{color:var(--ink-faint)}
.pricing-card-cta{margin-top:auto;width:100%}

/* Enterprise slim text row (LOCKED layout item 1): a row, not a 4th card —
   a 4th equal card would dilute the Ariely decoy target on the 3-card grid. */
.pricing-enterprise-row{text-align:center;margin-top:var(--sp-4)}
.pricing-enterprise-row a{color:var(--ink-soft);font-weight:600;border-bottom:1px solid var(--hairline)}

.pricing-roi{max-width:60ch;margin:var(--sp-6) auto 0;text-align:center}

/* Workflow-tool anchoring strip: quiet, small, sits beside the ROI line.
   Never anchors against card apps (Popl/Blinq) per the research brief's
   explicit ban — solo-agent workflow tools only. */
.pricing-anchor{max-width:60ch;margin:var(--sp-2) auto 0;text-align:center;color:var(--ink-faint)}

.trust-strip{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--sp-4) var(--sp-6);margin-top:var(--sp-6);padding-top:var(--sp-5);border-top:1px solid var(--hairline)}
.trust-strip p{font-size:13.5px;color:var(--ink-soft);max-width:26ch;text-align:center}

.pricing-proof-line{font-family:var(--font-display);font-weight:600;font-size:17px;color:var(--ink)}
.pricing-proof-num{font-variant-numeric:tabular-nums;color:var(--ink);border-bottom:2px solid var(--hairline);padding-bottom:1px}
.pricing-proof-note{color:var(--ink-faint);margin-top:var(--sp-1)}

/* ── homepage pricing teaser (V2-6): compact 3-card mini-grid, Pro leads visually ── */
.teaser-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-4)}
@media(min-width:900px){.teaser-grid{grid-template-columns:repeat(3,1fr)}}
.teaser-card{border:1px solid var(--hairline);border-radius:var(--r-tile);padding:var(--sp-4);background:var(--paper);display:flex;flex-direction:column;gap:var(--sp-2)}
.teaser-card--pro{border-color:var(--ink);border-width:2px}
.teaser-card-badge{align-self:flex-start;background:var(--ink);color:var(--paper);font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:var(--sp-1) var(--sp-2);border-radius:100px}
.teaser-card-name{font-weight:700}
.teaser-card-price{font-family:var(--font-display);font-weight:640;font-size:24px;color:var(--ink)}
.teaser-card-line{color:var(--ink-soft);font-size:14.5px}
.teaser-foot{display:flex;justify-content:center;margin-top:var(--sp-5)}

/* ── objections (V2-7): native <details>/<summary> accordion.
   The native open/close IS the failsafe — content is reachable and readable
   with zero JS or with animation dead (browser default toggling, no
   transition, still fully readable). initObjectionsAccordion in v2.js only
   layers a max-height transition on top when motion is allowed; it never
   leaves a persistent max-height on the element, so a stalled JS transition
   can never clip content — see the module comment in v2.js. ── */
.objections .wrap{display:flex;flex-direction:column;gap:var(--sp-5)}
.objections-h2{max-width:640px}
.objections-list{display:flex;flex-direction:column}
.objection{border-top:1px solid var(--hairline)}
.objection:last-child{border-bottom:1px solid var(--hairline)}
.objection summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);min-height:44px;padding:var(--sp-4) 0;font-weight:700;font-size:16.5px;color:var(--ink)}
.objection summary::-webkit-details-marker{display:none}
.objection summary::after{content:'+';flex:0 0 auto;font-family:var(--font-body);font-weight:400;font-size:22px;line-height:1;color:var(--ink-faint);transition:transform var(--dur-micro) var(--ease)}
.objection[open] summary::after{transform:rotate(45deg)}
.objection-body{overflow:hidden;transition:max-height var(--dur-micro) var(--ease)}
.objection-body p{padding-bottom:var(--sp-4);color:var(--ink-soft);max-width:68ch}
@media(prefers-reduced-motion:reduce){.objection summary::after,.objection-body{transition:none}}

/* ── final CTA (V2-7): the page's closing echo of the hero sun-disc.
   ONE deco element (sun-arch), hairline ink rings only — no terra ring here,
   the DNA's "one ring may be terra" clause is scoped to the arch that
   anchors the founding counter (.proof section), not this one, so the
   terracotta budget stays exactly spent on the H1 flourish / founding
   counter / primary CTA. The primary CTA button below reuses .btn--primary,
   same category as every other instance on the page (nav/hero/teaser). ── */
.final-cta-in{position:relative;padding-top:var(--sp-6)}
.final-cta-arch{position:absolute;top:-8px;left:50%;transform:translateX(-50%);width:min(520px,92%);height:auto;z-index:0;pointer-events:none}
.final-cta-content{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--sp-4);max-width:640px;margin:0 auto}
.final-cta-sub{max-width:46ch}
.final-cta-ladder{color:var(--ink-faint)}

/* ── sticky mobile CTA (V2-7): thumb-zone bar, <=768px only.
   Visibility is owned by initStickyCta in v2.js (IntersectionObserver on
   #v2-hero-ctas / #v2-pricing-teaser / #v2-final / #v2-footer) — CSS only
   owns the slide transform + the <=768px gate. Default state (no .is-visible)
   is translateY(100%), matching the JS's own default-hidden assumption
   while the hero CTA is in view on load, so there's no visible flash. ── */
.sticky-cta{display:none;position:fixed;left:0;right:0;bottom:var(--cookie-banner-h,0px);z-index:60;padding:var(--sp-3) var(--sp-4) calc(var(--sp-3) + env(safe-area-inset-bottom,0px));background:rgba(250,248,242,.96);border-top:1px solid var(--hairline);transform:translateY(100%);transition:transform .25s var(--ease),bottom .25s var(--ease)}
.sticky-cta.is-visible{transform:translateY(0)}
.sticky-cta-btn{width:100%;min-height:48px}
@media(max-width:768px){.sticky-cta{display:block}}
@media(prefers-reduced-motion:reduce){.sticky-cta{transition:none}}

/* Cookie consent banner (V2-9). z-index above .sticky-cta (60) so it's never
   hidden underneath; .sticky-cta reads --cookie-banner-h (set by JS to the
   banner's real height) to sit above it instead of overlapping. */
.v2-cookie-banner{position:fixed;left:0;right:0;bottom:0;z-index:70;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-3) var(--sp-4) calc(var(--sp-3) + env(safe-area-inset-bottom,0px));background:var(--paper);border-top:1px solid var(--hairline);box-shadow:0 -4px 20px rgba(28,24,18,.08)}
.v2-cookie-banner[hidden]{display:none}
.v2-cookie-banner p{flex:1 1 240px;font-size:14px;color:var(--ink-soft)}
.v2-cookie-actions{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.v2-cookie-actions .btn{padding:0 var(--sp-4);min-height:44px;font-size:14px}

/* ── motion base: elements opt in via data-reveal; JS failsafe forces .is-in ── */
[data-reveal]{opacity:0;transform:translateY(24px);transition:opacity var(--dur-in) var(--ease),transform var(--dur-in) var(--ease)}
[data-reveal].is-in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){[data-reveal]{opacity:1;transform:none;transition:none}}
