/* The two brand faces, served from here rather than from Google (#4221).
   WHY. They were two <link>s to fonts.googleapis.com and fonts.gstatic.com: two third-party origins,
   each needing DNS, TCP and TLS before a single glyph could be asked for, and the second one is not
   even known until the first has answered with the stylesheet. `display=swap` then does exactly what
   it says and repaints the page in a fallback face while that happens. Same origin as the page, and
   preloaded from the head, the faces arrive with the stylesheet instead of two round trips behind it.

   THREE FILES, NOT TEN. Google's css2 answer offers Nunito at 400/600/700/800 per subset, and every
   one of those URLs is the SAME variable font: md5 166202cc... for all four latin entries, ffdc8b0c...
   for all four latin-ext. So it is declared once here with a weight RANGE, which is what a variable
   font is for, and the browser fetches 39 KB instead of the same 39 KB four times.
   Cabin Sketch 400 was dropped outright: every rule that reaches for var(--disp) sets
   font-weight:700, so the 400 face is 79 KB nothing on this site can ask for.

   The unicode-range values are Google's own, kept verbatim, so latin-ext is still only fetched by a
   page that actually contains one of those characters. */
@font-face{font-family:'Nunito';font-style:normal;font-weight:400 800;font-display:swap;
  src:url('/assets/fonts/nunito-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Nunito';font-style:normal;font-weight:400 800;font-display:swap;
  src:url('/assets/fonts/nunito-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Cabin Sketch';font-style:normal;font-weight:700;font-display:swap;
  src:url('/assets/fonts/cabin-sketch-700-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
:root{
  --board:#1e1d22;--board-2:#26252b;--board-3:#2f2e35;--chalk:#f1ede4;--dim:#ded9cf;--line:rgba(241,237,228,.28);--line-soft:rgba(241,237,228,.16);
  --coral:#e9573f;                 /* brand accent — text, underline, small marks */
  --coral-btn:#d76350;--coral-btn-600:#c4543f;   /* softer coral for button fills (matches mockup) */
  --yellow:#e8b84b;--blue:#6fa8d6;--orange:#e0863c;--green:#8ab86e;--teal:#7fb0c4;--purple:#b18fd0;
  --disp:'Cabin Sketch',cursive;   /* chalky, hand-drawn — all display + logo */
  --body:'Nunito',system-ui,sans-serif;
}
*{box-sizing:border-box} html{scroll-behavior:smooth}
body{margin:0;font-family:var(--body);color:var(--chalk);line-height:1.6;
  /* The board was a 779 KB file and the page showed itself as flat colour until it arrived (#4221).
     It was also a JPEG named .png, so nginx served it as image/png from the extension alone.
     Same picture, 1376x768: webp 54 KB, jpeg 94 KB. The plain url() below is what a browser
     without image-set support takes; image-set upgrades it to webp for everyone else. Quality 72
     is generous here rather than tight: body::before lays a 40-50% dark gradient over the whole
     thing, and cover scales it past its own resolution on any wide screen. */
  background:#191820 url("/assets/chalkboard.jpg") center top/cover fixed;
  background-image:image-set(url("/assets/chalkboard.webp") type("image/webp"),
                             url("/assets/chalkboard.jpg") type("image/jpeg"));}
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(1200px 700px at 82% -6%,rgba(233,87,63,.09),transparent 60%),
    radial-gradient(1000px 620px at -6% 108%,rgba(111,168,214,.07),transparent 60%),
    linear-gradient(rgba(20,19,26,.40),rgba(20,19,26,.5));}
.wrap{max-width:1541px;margin:0 auto;padding:0 32px;position:relative}
a{color:inherit;text-decoration:none}
.coral{color:var(--coral)}
/* hand-drawn coral underline sits just below "ink" */
.ul{position:relative;white-space:nowrap}
.ul::after{content:"";position:absolute;left:0;right:-1px;bottom:-2px;height:7px;background:no-repeat center/100% 7px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='7'%3E%3Cpath d='M2 4.5 C 22 2,46 6,70 3.5 S 108 2,118 4.5' stroke='%23e9573f' stroke-width='3' fill='none' stroke-linecap='round'/%3E%3C/svg%3E")}

/* buttons — flat matte, softer coral, no gloss, no glow */
.btn{display:inline-flex;align-items:center;gap:9px;font-family:var(--body);font-weight:800;border-radius:40px;padding:15px 32px;font-size:18px;cursor:pointer;transition:background .15s,box-shadow .15s;border:0;letter-spacing:.01em;white-space:nowrap}
.btn-primary{background:var(--coral-btn);color:#fff} .btn-primary:hover{background:var(--coral-btn-600)}
.btn-ghost{background:transparent;color:var(--chalk);box-shadow:inset 0 0 0 2px var(--line)} .btn-ghost:hover{box-shadow:inset 0 0 0 2px var(--chalk)}
.btn-sm{padding:10px 22px;font-size:16px}

/* nav */
nav{position:sticky;top:0;z-index:20;backdrop-filter:blur(7px);background:rgba(25,24,32,.66);border-bottom:1px solid var(--line-soft)}
nav .wrap{display:flex;align-items:center;gap:22px;height:70px}
.brand{font-family:var(--disp);font-weight:700;font-size:34px;letter-spacing:.5px;line-height:1}
nav .links{margin-left:auto;display:flex;align-items:center;gap:26px;color:var(--chalk);font-weight:700;font-size:18px}
nav .links a{opacity:.82} nav .links a:hover{opacity:1} nav .links a.on{opacity:1;color:var(--coral)}
/* hamburger — mobile only */
.navtoggle{display:none;margin-left:auto;flex-direction:column;justify-content:center;gap:5px;width:44px;height:44px;padding:10px;background:transparent;border:0;cursor:pointer}
.navtoggle span{display:block;height:2.5px;border-radius:3px;background:var(--chalk);transition:transform .2s,opacity .2s}
@media(max-width:820px){
  .navtoggle{display:flex}
  nav .links{position:absolute;top:70px;left:0;right:0;margin:0;flex-direction:column;align-items:stretch;gap:0;
    background:rgba(22,21,28,.98);border-bottom:1px solid var(--line-soft);padding:8px 0 16px;display:none}
  nav.open .links{display:flex}
  nav .links a{padding:14px 32px;font-size:19px;opacity:.92}
  nav .links a.btn{margin:12px 32px 2px;justify-content:center;font-size:17px}
  nav.open .navtoggle span:nth-child(1){transform:translateY(7.5px) rotate(45deg)}
  nav.open .navtoggle span:nth-child(2){opacity:0}
  nav.open .navtoggle span:nth-child(3){transform:translateY(-7.5px) rotate(-45deg)}
}

/* section scaffolding — big chalk titles, no small eyebrows (match mockup) */
section{padding:104px 0;position:relative}
h2.h{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:clamp(34px,4.6vw,54px);line-height:1;margin:0 auto 14px;text-align:center;max-width:22ch;text-wrap:balance;letter-spacing:.01em}
.sub{color:var(--dim);max-width:54ch;margin:0 auto 60px;text-align:center;font-size:18px}
.doodle{position:absolute;pointer-events:none;opacity:.9;z-index:0}
@media(max-width:820px){section{padding:76px 0}.doodle{display:none}}

/* hero — text + 16:9 video player */
.hero{padding:72px 0 64px}
.hero .grid{display:grid;grid-template-columns:1.3fr 1fr;gap:60px;align-items:center}
.hero h1{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:clamp(38px,4.4vw,56px);line-height:1.02;margin:0 0 18px;letter-spacing:.01em;white-space:nowrap}
.hero p.lead{font-size:18px;color:var(--chalk);max-width:42ch;margin:0 0 26px}
.hero .note{color:var(--dim);font-size:18px;margin-top:16px}
.player{position:relative;width:100%;aspect-ratio:16/9;border-radius:14px;overflow:hidden;background:#26262a;
  box-shadow:0 26px 56px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.05)}
.player .poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 46%;background:#26262a}
.player .veil{position:absolute;inset:0;background:radial-gradient(120% 120% at 50% 40%,transparent 55%,rgba(0,0,0,.28))}
.player .play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:86px;height:86px;border-radius:50%;
  background:var(--coral-btn);display:grid;place-items:center;cursor:pointer;border:0;box-shadow:0 12px 30px rgba(0,0,0,.45);transition:transform .15s,background .15s}
.player .play:hover{transform:translate(-50%,-50%) scale(1.06);background:var(--coral-btn-600)}
.player .play svg{width:32px;height:32px;fill:#fff;margin-left:5px}
.player .bar{position:absolute;left:16px;right:16px;bottom:16px;height:5px;border-radius:4px;background:rgba(255,255,255,.26)}
.player .bar span{position:absolute;left:0;top:0;height:100%;width:32%;border-radius:4px;background:var(--coral-btn)}
.player .chip{position:absolute;top:13px;right:14px;font-family:var(--body);font-size:12px;font-weight:800;color:#fff;background:rgba(0,0,0,.5);padding:3px 9px;border-radius:7px;letter-spacing:.02em}
.player .pvideo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;background:#26262a;display:block}
.player .sound{position:absolute;bottom:14px;right:14px;width:46px;height:46px;border-radius:50%;border:0;background:rgba(0,0,0,.5);display:grid;place-items:center;cursor:pointer;z-index:3;transition:background .15s}
.player .sound:hover{background:rgba(0,0,0,.72)}
.player .sound svg{width:22px;height:22px;fill:#fff}
@media(max-width:900px){
  .hero .grid{grid-template-columns:1fr;text-align:center;gap:30px}
  .hero p.lead{margin-left:auto;margin-right:auto}
  .hero .artcol{order:-1;max-width:520px;margin:0 auto;width:100%}
}

/* stats + share proof */
.stats{padding:56px 0 4px}
.statgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:24px;max-width:1040px;margin:0 auto}
@media(max-width:760px){.statgrid{grid-template-columns:repeat(2,1fr)}}
.stat{text-align:center;padding:26px 14px;border:1px solid var(--line);border-radius:18px;background:rgba(255,255,255,.015)}
.stat .num{font-family:var(--disp);font-weight:700;font-size:clamp(36px,4.6vw,52px);line-height:1;color:var(--coral);font-variant-numeric:tabular-nums}
.stat .lbl{margin-top:8px;color:var(--dim);font-size:16px;font-weight:700}
/* Sat between the big stat cards and the next big heading at 26px and read as an
   afterthought. Sized up so the row is a deliberate element rather than debris. */
.sharerow{display:flex;align-items:center;justify-content:center;gap:26px;flex-wrap:wrap;margin:44px auto 0;color:var(--dim)}
.sharerow .lead{font-size:20px;font-weight:700}
.sharerow svg{width:56px;height:56px;fill:currentColor;opacity:.9;transition:opacity .15s,transform .15s}
.sharerow span[role=img]{display:inline-flex;line-height:0}
@media(max-width:640px){
  .sharerow{gap:18px;margin-top:32px}
  .sharerow .lead{font-size:17px}
  .sharerow svg{width:42px;height:42px}
}

/* how it works — clean chalk-line step icons */
.steps{position:relative;display:grid;grid-template-columns:repeat(3,1fr);gap:64px;max-width:none;margin:0 auto}
.step{text-align:center;position:relative;padding:0 10px}
.step .ic{height:200px;display:flex;align-items:center;justify-content:center;margin-bottom:10px}
.step .ic img{height:200px;width:200px;object-fit:contain}
.step h3{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:25px;margin:0 0 4px;letter-spacing:.01em}
.step .n{color:var(--coral)}
.step p{color:var(--dim);margin:0 auto;font-size:18px;max-width:26ch}
.sarrow{position:absolute;top:66px;width:70px;height:34px;color:var(--coral);opacity:.9;z-index:2;fill:none;stroke:currentColor;stroke-width:3.2;stroke-linecap:round;stroke-linejoin:round}
.sarrow.s1{left:calc(33.33% - 34px)} .sarrow.s2{left:calc(66.66% - 36px)}
@media(max-width:820px){
  .steps{grid-template-columns:1fr;gap:40px;max-width:320px}
  .sarrow{position:static;width:40px;margin:-26px auto -4px;transform:rotate(90deg)}
  .sarrow.s1,.sarrow.s2{left:auto}
}

/* explore styles — animated marquee carousel */
.marquee{position:relative;overflow:hidden;padding:10px 0;border-radius:8px}
.marquee::before,.marquee::after{content:"";position:absolute;top:0;bottom:0;width:80px;z-index:2;pointer-events:none}
.marquee::before{left:0;background:linear-gradient(90deg,#191820,rgba(25,24,32,0))}
.marquee::after{right:0;background:linear-gradient(270deg,#191820,rgba(25,24,32,0))}
.mtrack{display:flex;gap:32px;width:max-content;animation:scroll 70s linear infinite}
.marquee:hover .mtrack{animation-play-state:paused}
@keyframes scroll{from{transform:translateX(0)}to{transform:translateX(calc(-50% - 16px))}}
.scard{flex:0 0 auto;width:440px;text-align:center;color:inherit}
.scard .thumb{border-radius:16px;overflow:hidden;aspect-ratio:16/9;box-shadow:0 16px 34px rgba(0,0,0,.42);transition:transform .2s,box-shadow .2s;border:1px solid var(--line-soft)}
.scard:hover .thumb{transform:translateY(-5px);box-shadow:0 22px 44px rgba(0,0,0,.5)}
.scard img{width:100%;height:100%;object-fit:cover;display:block}
.scard .ct{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:22px;margin:15px 0 0;letter-spacing:.01em}
.scard span{color:var(--coral);font-size:18px;font-weight:700}
@media(prefers-reduced-motion:reduce){.mtrack{animation:none}.marquee{overflow-x:auto}}
@media(max-width:640px){.scard{width:300px}}

/* pricing — clean bordered cards */
/* The free minute above the pack grid. Not a card: it is not bought, it is begun, and as a
   column it competed with the packs while asking a different question. */
.freeline{display:flex;align-items:center;justify-content:center;gap:16px;flex-wrap:wrap;
  text-align:center;margin:0 auto 34px;padding:16px 22px;max-width:760px;font-size:17px;
  color:var(--dim);border:1px dashed var(--line);border-radius:16px}
.freeline strong{color:var(--chalk)}
.freeline .btn{flex:0 0 auto}
.plans{display:grid;grid-template-columns:repeat(4,1fr);gap:24px;max-width:none;margin:0 auto;align-items:stretch}
@media(max-width:1040px){.plans{grid-template-columns:repeat(2,1fr)}}@media(max-width:560px){.plans{grid-template-columns:1fr;max-width:380px}}
.plan{position:relative;display:flex;flex-direction:column;padding:40px 34px;text-align:center;border:2px solid var(--line);border-radius:20px;background:rgba(255,255,255,.015)}
.plan.hot{border-color:var(--coral);box-shadow:0 18px 40px rgba(233,87,63,.12)}
/* The cards did not react to the cursor at all. Deliberately nothing MOVES: the border brightens
   and a soft glow appears, which is enough to say "this is yours to click" without the page
   jumping about. */
.plan{transition:box-shadow .2s ease,border-color .2s ease}
.plan:hover{border-color:rgba(241,237,228,.5);box-shadow:0 0 0 1px rgba(241,237,228,.12),0 20px 44px rgba(0,0,0,.34)}
.plan.hot:hover{box-shadow:0 0 0 1px rgba(233,87,63,.35),0 22px 50px rgba(233,87,63,.18)}

.plan .tagpop{position:absolute;top:0;left:50%;transform:translate(-50%,-50%);text-align:center;line-height:1.25;background:var(--coral);color:#fff;font-family:var(--body);font-weight:800;font-size:11px;letter-spacing:.08em;text-transform:uppercase;padding:4px 13px;border-radius:40px}.tagpop.soon{background:rgba(255,255,255,.08);color:#b7b3ab}
/* fixed zones so titles / prices / buttons line up across all three cards (no jumping) */
.p-head{padding-bottom:20px;border-bottom:1px dashed var(--line)}
.plan .nm{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:26px;color:var(--coral);letter-spacing:.01em}
.plan .pr{font-family:var(--disp);font-weight:700;font-size:46px;margin:6px 0 0;font-variant-numeric:tabular-nums} .plan .pr small{font-family:var(--body);font-size:18px;font-weight:700;color:var(--dim)}
.p-body{flex:1 1 auto;list-style:none;padding:0;margin:22px auto;color:var(--dim);font-size:18px;text-align:left;max-width:270px}
.p-body li{padding:9px 0 9px 26px;position:relative}
.p-body li::before{content:"";position:absolute;left:2px;top:17px;width:8px;height:8px;border-radius:50%;background:var(--coral);box-shadow:0 0 0 3px rgba(233,87,63,.14)}
.p-foot{padding-top:20px;border-top:1px dashed var(--line)}
.p-foot .btn{width:100%;justify-content:center}
/* The buttons declared a transition and had nothing to transition to. */
.btn{transition:background .18s ease,box-shadow .18s ease,border-color .18s ease,color .18s ease}
.btn-primary:hover{box-shadow:0 8px 22px rgba(233,87,63,.34)}
.btn-ghost:hover{border-color:var(--chalk);color:var(--chalk);background:rgba(241,237,228,.06)}
nav .links a:hover{color:var(--chalk)}
.freeline .btn:hover{border-color:var(--chalk);color:var(--chalk)}

.p-head .cr{margin-top:12px;color:var(--dim);font-size:15px;font-weight:700}
/* The saving was a pale pill that read as a footnote. It is the reason to take the bigger pack,
   so it is a sticker now: yellow chalk on the board, tilted, sitting slightly proud of the line
   it belongs to. Yellow rather than coral because coral is already the price and the buttons, and
   a saving competing with the call to action in the same colour reads as noise. */
.bonus{display:inline-block;margin-left:8px;font-family:var(--disp);font-size:15px;font-weight:700;
  letter-spacing:.02em;color:#1e1d22;background:var(--yellow);padding:3px 11px 2px;border-radius:4px;
  transform:rotate(-3deg);vertical-align:middle;box-shadow:0 3px 10px rgba(0,0,0,.35);
  text-transform:uppercase;white-space:nowrap}
.plan.hot .bonus{transform:rotate(-3deg) scale(1.04)}
.pricenote{text-align:center;color:var(--dim);margin:34px auto 0;max-width:68ch;font-size:16px}
.pricenote b{color:var(--chalk)}

/* final cta */
.final{text-align:center;padding:86px 0 94px}
.final h2{margin-bottom:12px}

/* footer */
footer{border-top:1px dashed var(--line-soft);padding:34px 0;margin-top:8px}
footer .wrap{display:flex;gap:20px;align-items:center;flex-wrap:wrap}
footer .brand{font-size:26px}
footer .cpy{color:var(--dim);font-size:18px}
footer .flinks{display:flex;gap:18px;font-weight:700;font-size:18px;color:var(--chalk)}
footer .flinks a{opacity:.72} footer .flinks a:hover{opacity:1}
footer .social{margin-left:auto;display:flex;gap:16px}
footer .social a{color:var(--dim);transition:color .15s} footer .social a:hover{color:var(--chalk)}
footer .social svg{width:26px;height:26px;fill:currentColor;display:block}
@media(max-width:640px){footer .social{margin-left:0;width:100%}}

/* waitlist modal */
.wl{position:fixed;inset:0;z-index:60;display:none;align-items:center;justify-content:center;padding:24px;background:rgba(12,11,16,.86);backdrop-filter:blur(4px)}
.wl.open{display:flex}
.wl .wlbox{position:relative;width:min(460px,100%);background:var(--board-2);border:1px solid var(--line);border-radius:20px;padding:38px 34px 34px;text-align:center;box-shadow:0 30px 70px rgba(0,0,0,.6)}
.wl .wlclose{position:absolute;top:14px;right:16px;width:38px;height:38px;border-radius:50%;border:0;background:transparent;color:var(--dim);font-size:26px;line-height:1;cursor:pointer;transition:color .15s}
.wl .wlclose:hover{color:var(--chalk)}
.wl h2{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:30px;margin:0 0 10px;letter-spacing:.01em}
.wl p{color:var(--dim);font-size:16px;margin:0 auto 22px;max-width:34ch}
.wl form{display:flex;flex-direction:column;gap:12px}
.wl input{width:100%;padding:15px 18px;border-radius:12px;border:1px solid var(--line);background:rgba(255,255,255,.03);color:var(--chalk);font-family:var(--body);font-size:16px;font-weight:600;text-align:center}
.wl input:focus{outline:0;border-color:var(--coral)}
.wl input::placeholder{color:var(--dim)}
.wl form .btn{width:100%;justify-content:center}
.wl .wlmsg{margin-top:16px;font-weight:700;font-size:15px;min-height:1px}
.wl .wlmsg.ok{color:var(--green)} .wl .wlmsg.err{color:var(--coral)}
.wl .wldone{display:none} .wl.done .wlform{display:none} .wl.done .wldone{display:block}
.wl .wldone .tick{width:64px;height:64px;margin:0 auto 14px;border-radius:50%;background:rgba(138,184,110,.16);display:grid;place-items:center}
.wl .wldone .tick svg{width:32px;height:32px;fill:none;stroke:var(--green);stroke-width:3;stroke-linecap:round;stroke-linejoin:round}

/* ===== content pages (styles / use cases / input methods) =====
   Shared page furniture so every family view inherits the same hero, body
   copy and card treatment instead of re-inventing inline styles per view. */
.phero{padding:56px 0 0}
.phero .in{display:grid;grid-template-columns:1.05fr .95fr;gap:52px;align-items:center}
.phero .eyebrow{color:var(--coral);font-weight:800;margin:0 0 10px;font-size:16px;text-transform:uppercase;letter-spacing:.04em}
.phero h1{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:clamp(34px,4.4vw,52px);line-height:1.02;margin:0 0 16px;letter-spacing:.01em}
.phero p.lead{font-size:18px;color:var(--chalk);max-width:44ch;margin:0 0 26px}
.phero img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:14px;border:1px solid var(--line-soft);box-shadow:0 22px 48px rgba(0,0,0,.45)}
@media(max-width:900px){.phero .in{grid-template-columns:1fr;gap:32px}.phero p.lead{max-width:none}}

.prose{max-width:720px;margin:56px auto 0;color:var(--dim);font-size:18px}
.prose h2{font-family:var(--disp);font-weight:700;text-transform:uppercase;color:var(--chalk);font-size:28px;line-height:1.1;margin:38px 0 10px;letter-spacing:.01em}
.prose h3{font-family:var(--disp);font-weight:700;text-transform:uppercase;color:var(--chalk);font-size:22px;margin:28px 0 8px}
.prose p{margin:0 0 16px}
.prose ul,.prose ol{padding-left:22px;margin:0 0 16px}
.prose li{margin:7px 0}
.prose strong{color:var(--chalk)}
.prose a{color:var(--coral);font-weight:700}
.prose a:hover{text-decoration:underline}

.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:30px}
@media(max-width:900px){.grid3{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.grid3{grid-template-columns:1fr}}

/* text card -- cards with no artwork (use cases, input methods, link lists) */
.tcard{display:block;padding:30px 28px;border:2px solid var(--line);border-radius:20px;background:rgba(255,255,255,.015);color:inherit;transition:border-color .15s,transform .2s,box-shadow .2s}
/* .tcard has no hover on purpose: the cards contain no link, and a hover state would promise a click that does nothing. */
.tcard .ct{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:24px;margin:0 0 8px;letter-spacing:.01em}
.tcard p{color:var(--dim);margin:0;font-size:17px}

.backlink{text-align:center;margin-top:46px}
.backlink a{color:var(--dim);font-weight:700}
.backlink a:hover{color:var(--chalk)}

/* ===== mega-menu nav + 4-column footer (Stage B) ===== */
nav .links{gap:24px}
nav .links a.signin{font-weight:700}  /* a menu item, deliberately not a button: the one button in the header is the one action */
/* Opens the chat, which runs in modal mode and has no floating bubble of its own.
   Deliberately a link and not a button: the header already carries the one action
   the page exists for. */


.drop{position:relative;display:flex;align-items:center}
.drop>.dtoggle{display:inline-flex;align-items:center;gap:8px;padding:0;border:0;background:none;color:var(--chalk);font-family:var(--body);font-weight:700;font-size:18px;line-height:1;cursor:pointer;opacity:.82}
.drop>.dtoggle:hover{opacity:1}
.drop>.dtoggle svg{width:12px;height:8px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform .18s}
.drop:hover>.dtoggle{opacity:1}
.drop:hover>.dtoggle svg{transform:rotate(180deg)}
/* invisible bridge: keeps :hover alive across the gap between button and panel */
.drop::after{content:"";position:absolute;left:0;right:0;top:100%;height:20px}
.dpanel{position:absolute;top:calc(100% + 18px);left:-20px;min-width:342px;padding:12px;border:1px solid var(--line);border-radius:18px;background:rgba(30,29,34,.985);box-shadow:0 26px 60px rgba(0,0,0,.55);display:none;z-index:30}
.drop:hover .dpanel,.drop:focus-within .dpanel{display:block}
.dpanel a{display:block;padding:11px 14px;border-radius:12px;opacity:1;transition:background .15s}
.dpanel a:hover{background:rgba(255,255,255,.06)}
.dpanel b{display:block;font-size:17px;font-weight:800;line-height:1.25}
.dpanel span{display:block;margin-top:2px;color:var(--dim);font-size:14.5px;font-weight:600;line-height:1.35}

@media(max-width:820px){
  .drop{display:block;width:100%}
  .drop::after{display:none}
  .drop>.dtoggle{width:100%;justify-content:space-between;padding:14px 32px;font-size:19px;opacity:.92}
  .drop.open>.dtoggle svg{transform:rotate(180deg)}
  .dpanel,.drop:hover .dpanel,.drop:focus-within .dpanel{display:none}
  .drop.open .dpanel{display:block;position:static;min-width:0;margin:0;padding:0 0 10px;border:0;border-radius:0;background:transparent;box-shadow:none}
  .dpanel a{padding:9px 32px 9px 44px}
  .dpanel span{display:none}
}

/* footer -- link columns above the original brand/copyright/social bar */
footer{padding:52px 0 34px}
footer .wrap{display:block}
.fgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:32px;padding-bottom:38px;margin-bottom:26px;border-bottom:1px dashed var(--line-soft)}
.fcol h5{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:20px;letter-spacing:.02em;margin:0 0 14px;color:var(--chalk)}
.fcol a{display:block;color:var(--dim);font-weight:600;font-size:17px;padding:5px 0;opacity:.86}
.fcol a:hover{opacity:1;color:var(--chalk)}
.fbot{display:flex;gap:20px;align-items:center;flex-wrap:wrap}
/* PeerPush badge. It sits between the copyright and the social bar; footer
   .social already claims the right edge with margin-left:auto, so no ordering
   rule is needed. Slightly dimmed at rest so a white card does not outshout
   the brand on a dark board. */
.ppbadge{display:block;line-height:0}
.ppbadge img{width:160px;height:auto;display:block;border-radius:10px;opacity:.88;transition:opacity .15s}
.ppbadge:hover img{opacity:1}
/* There's An AI For That badge, homepage only (see partials/footer.php).
   Sized to the PeerPush badge's height instead of TAAFT's stock 300px so the
   two cards read as one row; aspect-ratio holds the box before the image lands. */
.taaft{display:block;line-height:0}
.taaft img{width:200px;height:auto;aspect-ratio:599/125;display:block;border-radius:10px;opacity:.88;transition:opacity .15s}
.taaft:hover img{opacity:1}
@media(max-width:820px){.fgrid{grid-template-columns:repeat(2,1fr);gap:26px}}
@media(max-width:480px){.fgrid{grid-template-columns:1fr}}

/* ===== blog (Stage E): article head, hero, listing cards ===== */
.ahead{max-width:780px;margin:0 auto;text-align:center}
.ahead .eyebrow{margin-bottom:12px}
.ahead h1{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:clamp(32px,4.2vw,50px);line-height:1.04;margin:0 0 14px;letter-spacing:.01em;text-wrap:balance}
.ameta{color:var(--dim);font-size:16px;font-weight:700;margin:0}
.ahero{display:block;width:100%;max-width:980px;margin:44px auto 0;aspect-ratio:16/9;object-fit:cover;border-radius:16px;border:1px solid var(--line-soft);box-shadow:0 22px 48px rgba(0,0,0,.45)}
.tcard .date{display:block;color:var(--coral);font-size:14px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;margin-bottom:8px}
.prose blockquote{margin:22px 0;padding:2px 0 2px 20px;border-left:3px solid var(--coral);color:var(--chalk)}
.prose code{font-size:.92em;background:rgba(255,255,255,.06);padding:2px 6px;border-radius:6px}
.prose h2:first-child{margin-top:0}

/* ===== ported legal pages (Stage F) ===== */
.prose.legal{max-width:800px}
.prose .note{background:var(--board-2);border:1px solid var(--line);border-radius:12px;padding:14px 18px;margin:20px 0;font-size:16px;color:var(--dim)}
.prose table{width:100%;border-collapse:collapse;margin:18px 0;font-size:16px}
.prose th,.prose td{border:1px solid var(--line);padding:9px 12px;text-align:left;vertical-align:top}
.prose th{color:var(--chalk);font-weight:700}

/* ===== gallery page (Stage F: lifted from the static page) ===== */
/* header */
.ghead{text-align:center;padding:78px 0 8px}
.ghead h1{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:clamp(38px,5vw,60px);line-height:1;margin:0 0 16px;letter-spacing:.01em}
.ghead p{color:var(--dim);max-width:56ch;margin:0 auto;font-size:19px}
.ghead .tag{display:inline-block;margin-bottom:18px;font-weight:800;font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--coral);border:1px solid rgba(233,87,63,.4);border-radius:40px;padding:6px 16px}

/* grid */
.gsec{padding:44px 0 96px}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:32px}
@media(max-width:520px){.grid{grid-template-columns:1fr}}
.card{text-align:left;cursor:pointer;background:none;border:0;padding:0;color:inherit;font:inherit}
.card .thumb{position:relative;border-radius:16px;overflow:hidden;aspect-ratio:16/9;box-shadow:0 16px 34px rgba(0,0,0,.42);border:1px solid var(--line-soft);transition:transform .2s,box-shadow .2s;background:#26262a}
.card:hover .thumb,.card:focus-visible .thumb{transform:translateY(-5px);box-shadow:0 24px 46px rgba(0,0,0,.55)}
.card img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.card .thumb video.tile{width:100%;height:100%;object-fit:cover;display:block;background:#26262a;pointer-events:none}
.card .veil{position:absolute;inset:0;background:radial-gradient(120% 120% at 50% 42%,transparent 52%,rgba(0,0,0,.30))}
.card .chip{position:absolute;top:12px;left:12px;font-size:12px;font-weight:800;color:#fff;background:rgba(0,0,0,.5);padding:4px 10px;border-radius:8px;letter-spacing:.02em}
.card .ct{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:22px;margin:15px 2px 0;letter-spacing:.01em;line-height:1.05}
.card .style{color:var(--coral);font-size:16px;font-weight:700;margin:3px 2px 0}

/* lightbox */
.lb{position:fixed;inset:0;z-index:50;display:none;align-items:center;justify-content:center;padding:24px;background:rgba(12,11,16,.86);backdrop-filter:blur(4px)}
.lb.open{display:flex}
.lb .lbwrap{position:relative;width:min(1040px,100%)}
.lb .box{position:relative;width:100%;aspect-ratio:16/9;border-radius:14px;overflow:hidden;background:#000;box-shadow:0 30px 70px rgba(0,0,0,.6)}
.lb video{width:100%;height:100%;display:block;background:#000}
.lb .close{position:absolute;top:-18px;right:-18px;width:46px;height:46px;border-radius:50%;border:0;background:var(--coral-btn);color:#fff;font-size:24px;font-weight:800;cursor:pointer;display:grid;place-items:center;box-shadow:0 8px 20px rgba(0,0,0,.5);z-index:3;transition:background .15s}
.lb .close:hover{background:var(--coral-btn-600)}
.lb .lbtitle{display:block;text-align:center;margin-top:16px;font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:22px;color:var(--chalk);letter-spacing:.01em}
@media(max-width:560px){.lb{padding:16px}.lb .close{top:-14px;right:-6px}.lb .lbtitle{font-size:19px;margin-top:12px}}

/* cta strip */
/* 14px of top padding left this sitting on the block above it. The same closing section
   on the homepage (.final) uses 86, and this one needs the same room. */
.gcta{text-align:center;padding:78px 0 90px}
.gcta h2{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:clamp(30px,4vw,46px);margin:0 0 10px}
.gcta p{color:var(--dim);margin:0 auto 24px;max-width:52ch;font-size:18px}

/* ===== standards pass (task #2861 remediation) ===== */
/* Index pages must carry exactly one H1 and it is the page title, so the chalk
   title treatment has to work on h1 as well as h2. */
h1.h{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:clamp(34px,4.6vw,54px);line-height:1;margin:0 auto 14px;text-align:center;max-width:22ch;text-wrap:balance;letter-spacing:.01em}

/* answer-first lede block: visible, quotable, 40-60 words */
.answer{max-width:760px;margin:34px auto 0;padding:18px 22px;border:1px solid var(--line);border-left:3px solid var(--coral);border-radius:12px;background:rgba(255,255,255,.02);color:var(--chalk);font-size:18px;line-height:1.55}
.answer strong{color:var(--coral)}
.ahead + .answer{margin-top:26px}

/* FAQ block (the partial also emits its own FAQPage JSON-LD) */
.faq{max-width:800px;margin:0 auto;display:grid;gap:18px}
.faqitem{border:1px solid var(--line);border-radius:16px;padding:22px 24px;background:rgba(255,255,255,.015)}
.faqitem h3{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:21px;line-height:1.15;margin:0 0 8px;letter-spacing:.01em}
.faqitem p{color:var(--dim);margin:0;font-size:17px}

/* Footer column titles stop being h5: sitting after an h2 they broke the heading
   hierarchy on all 41 pages (auditor U12). Same look, no heading level. */
.fcol .fh{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:20px;letter-spacing:.02em;margin:0 0 14px;color:var(--chalk)}
.aauthor{color:var(--chalk)}

/* ===== layout system (task #2862) =====
   The theme grew one block at a time and each block brought its own width and
   its own margins, so a reader crossing the site met five different content
   widths (720 / 760 / 780 / 800 / 1541) and vertical gaps that ranged from
   104px to zero depending on which view happened to override them inline.
   Everything below is expressed as tokens; per-block numbers are gone. */
:root{
  --wrap:1440px;        /* outer container, one value */
  --gutter:32px;
  --measure:760px;      /* the single reading width for any text column */
  --sp-section:104px;   /* rhythm between sections */
  --sp-block:56px;      /* gap between blocks inside a section */
  --sp-tight:28px;
}
@media(max-width:1024px){:root{--sp-section:84px;--gutter:24px}}
@media(max-width:820px){:root{--sp-section:68px;--sp-block:40px;--sp-tight:20px;--gutter:20px}}

.wrap{max-width:var(--wrap);padding:0 var(--gutter)}
section{padding:var(--sp-section) 0}
/* A section that continues the one above it, instead of an inline padding-top:0
   sprinkled through the views. */

/* One reading width, everywhere text is read as a column. */
.prose,.prose.legal,.answer,.ahead,.faq,.pricenote{max-width:var(--measure)}
.prose{margin:var(--sp-block) auto 0}
.answer{margin:var(--sp-block) auto 0}
.faq{margin:0 auto}
.pricenote{margin-left:auto;margin-right:auto}
.ahero{margin:var(--sp-block) auto 0}
.backlink{margin-top:var(--sp-block)}
.answer + h2.h,.ahead + .grid3{margin-top:var(--sp-block)}
.sub{margin-bottom:var(--sp-block)}
.phero{padding:var(--sp-section) 0 0}

/* Cards fill their grid cell; the width lived as an inline style before. */
.grid3 .scard{width:auto}
.cta-row{text-align:center;margin-top:var(--sp-block)}
.pagelinks{text-align:center;margin-top:var(--sp-block)}
.pagelinks a{padding:0 10px;color:var(--dim);font-weight:700}
.pagelinks a.on{color:var(--coral)}
.searchform{max-width:520px;margin:0 auto var(--sp-block);display:flex;gap:12px}
.searchform input{flex:1;padding:14px 18px;border-radius:12px;border:1px solid var(--line);background:rgba(255,255,255,.03);color:var(--chalk);font-family:var(--body);font-size:16px;font-weight:600}
.searchform input:focus{outline:0;border-color:var(--coral)}

/* Responsive: the grids collapse on the same breakpoints as the type scale, so
   nothing changes shape halfway between two of them. */
@media(max-width:1024px){.grid3{gap:24px}}
@media(max-width:900px){.grid3{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.grid3{grid-template-columns:1fr}}
@media(max-width:560px){.searchform{flex-direction:column}}

/* ===== fill balance (owner review of /use-cases/education) =====
   The complaint: the container fills unevenly. Card grids ran the full width
   while the text column and the FAQ sat as a narrow strip in the middle.
   Two sides of the fix, because a text line cannot simply be stretched: at this
   size a 1280px line is unreadable, the eye loses the start of the next line.
   So the container comes in, the measure goes out, and the FAQ uses the width
   it was wasting. */
:root{--wrap:1280px;--measure:820px}
@media(max-width:1024px){:root{--gutter:24px}}

/* The FAQ is a list, not a stack of cards. Two columns on desktop so it fills
   the container, and hairline rules instead of borders so the page has two
   textures rather than the same rounded box repeated to the footer. */
.faq{max-width:none;display:grid;grid-template-columns:repeat(2,1fr);gap:0 40px}
.faqitem{border:0;border-top:1px solid var(--line);border-radius:0;background:none;padding:22px 0 24px}
.faqitem h3{font-size:20px;margin:0 0 6px}
@media(max-width:900px){.faq{grid-template-columns:1fr;gap:0}}

/* Hero header of a content page: same centred pattern as articles and /pricing,
   so a visitor never meets two alignment axes on one page. */
.ahead p.lead{max-width:58ch;margin:0 auto 22px;font-size:18px;color:var(--chalk)}
.ahead .ameta{margin-bottom:22px}
.ahead .btn{margin-top:4px}
.phero .ahero{margin-top:44px}

/* ===== content pages fill the container top to bottom =====
   Owner review, second pass: the top of the page was narrower than the bottom.
   The reading column stays at --measure because a 1280px line is unreadable,
   so the space next to it now carries the rail, and hero art spans the
   container. Result: hero band, two-column body, wide sections, all the same
   width. */
.ahero{max-width:none;width:100%;margin-top:40px}
.phero .ahead{margin-top:8px}

.pbody{display:grid;grid-template-columns:minmax(0,var(--measure)) 320px;gap:48px;align-items:start;justify-content:center;margin-top:var(--sp-block)}
.pbody .pmain{min-width:0}
.pbody .pmain .prose,.pbody .pmain .answer{max-width:none;margin-left:0;margin-right:0}
.pbody .pmain .answer{margin-top:0}
.pbody .pmain .prose{margin-top:32px}

.prail{position:sticky;top:96px;display:grid;gap:16px}
.railcard{border:1px solid var(--line);border-radius:16px;padding:22px 24px;background:rgba(255,255,255,.015)}
.railcard-cta{border-color:rgba(233,87,63,.45)}
.railcard .rt{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:19px;letter-spacing:.01em;margin-bottom:8px}
.railcard p{color:var(--dim);font-size:16px;margin:0 0 14px}
.railcard .btn{width:100%;justify-content:center}
.rlist{list-style:none;padding:0;margin:0;display:grid;gap:9px}
.rlist a{color:var(--dim);font-weight:700;font-size:16px}
.rlist a:hover{color:var(--chalk)}
.rmore{color:var(--coral);font-weight:800;font-size:16px}

@media(max-width:1024px){
  .pbody{grid-template-columns:1fr;max-width:var(--measure);margin-left:auto;margin-right:auto;gap:36px}
  .prail{position:static;grid-template-columns:repeat(2,1fr)}
  .railcard-cta{grid-column:1 / -1}
}
@media(max-width:640px){.prail{grid-template-columns:1fr}}

/* ===== one gap between any two sections =====
   Reported: the gaps above and below the "More use cases" block differ. They
   did. .phero carried padding-bottom:0 while the section after it carried
   padding-top:0, so that boundary collapsed to nothing, while the next
   boundary still had a full --sp-section from the block above it.

   The rhythm is now a rule rather than a per-block decision: every section
   pads top and bottom, and a section that follows another drops its top
   padding. Every boundary is then exactly one --sp-section, from the section
   above. .sec-join stays only so existing markup keeps working; it no longer
   decides anything. */
section{padding:var(--sp-section) 0}
.phero{padding:var(--sp-section) 0}

/* ===== section rhythm, one-sided =====
   The previous attempt used `section + section { padding-top: 0 }`. That breaks
   whenever something sits between two sections in the markup: the FAQ partial
   emits its FAQPage JSON-LD as a <script> right after its section, and a script
   is an element, so the adjacent-sibling rule stopped matching and the next
   section kept a top padding that added to the previous section's bottom one.
   Result: a double gap in some places and none in others.

   One-sided rhythm instead: a section only ever pads its top, so the gap
   between any two sections is exactly one --sp-section no matter what sits
   between them in the source. The last section pads its bottom so the footer
   is not glued to it. Nothing here depends on sibling order. */
section{padding:var(--sp-section) 0 0}
.phero{padding:var(--sp-section) 0 0}
.faqsec{padding-top:var(--sp-section)}
/* neutralised: gaps are no longer decided per block */

/* ===== rhythm belongs to the heading (owner call) =====
   Sections no longer decide their own spacing. One unit --sp-h: the gap above a
   section heading is 1x, the gap below the heading block (heading, or heading
   plus its subtitle) is 2x. Sections keep only that 1x on top so a section
   without a heading still breathes, and the last one pads its bottom so the
   footer is not glued to it.
   This replaces the earlier --sp-section padding, which produced a gap that
   depended on which blocks happened to be neighbours. */
:root{--sp-h:52px}
@media(max-width:1024px){:root{--sp-h:44px}}
@media(max-width:820px){:root{--sp-h:34px}}

section{padding:var(--sp-h) 0 0}

h1.h,h2.h{margin-top:0;margin-bottom:calc(var(--sp-h) * 2)}
/* when a subtitle follows the heading, the pair is the block: the heading sits
   tight to its subtitle and the subtitle carries the 2x below */
h1.h:has(+ .sub),h2.h:has(+ .sub){margin-bottom:12px}
.sub{margin-bottom:calc(var(--sp-h) * 2)}

/* the body grid and the article head follow the same unit */
.pbody{margin-top:calc(var(--sp-h) * 1.2)}
.ahero{margin-top:calc(var(--sp-h) * 0.8)}
.backlink,.cta-row,.pagelinks{margin-top:calc(var(--sp-h) * 1.2)}

/* ===== headings, one style everywhere (owner call) =====
   Two kinds of heading, two jobs.

   1. Section headings (h1.h, h2.h, the .ahead h1 on content pages) open a
      section. The section already gives them 1x above, so they carry no top
      margin of their own and a single --sp-h below. If a subtitle, byline or
      lede follows, the heading sits tight to it and that element carries the
      single gap instead, because the pair is one block.

   2. Headings inside body copy (.prose h2/h3) have no section boundary above
      them, so they keep 1x on top and sit tight to the paragraph they
      introduce. Removing the top gap there would glue them to the paragraph
      above, which is the one place the rule has to differ. */
h1.h,h2.h,.ahead h1{margin-top:0;margin-bottom:var(--sp-h)}
h1.h:has(+ .sub),h2.h:has(+ .sub),.ahead h1:has(+ .ameta),.ahead h1:has(+ .lead){margin-bottom:12px}
.sub,.ahead .lead,.ahead .ameta{margin-bottom:var(--sp-h)}
.ahead .eyebrow{margin-bottom:12px}
.ahead .lead:has(+ .ameta){margin-bottom:12px}

.prose h2{margin:var(--sp-h) 0 10px}
.prose h3{margin:calc(var(--sp-h) * 0.6) 0 8px}
.prose > :first-child{margin-top:0}
.prose h2:first-child,.prose h3:first-child{margin-top:0}

/* card, rail and FAQ titles are labels, not section headings: they stay tight */
.tcard .ct,.scard .ct,.card .ct{margin-bottom:8px}
.railcard .rt{margin-bottom:8px}
.faqitem h3{margin:0 0 6px}

/* ===== the tight gap scales with the heading =====
   12px under an h1 set at ~50px reads as no gap at all, which is what the owner
   saw on /use-cases/education. The pair-tight value is not one number: it is
   proportional to the type it sits under. */
.ahead h1:has(+ .lead),.ahead h1:has(+ .ameta),.ahead h1:has(+ .answer){margin-bottom:var(--gap-h1)}
h1.h:has(+ .sub),h2.h:has(+ .sub){margin-bottom:16px}
.ahead .lead:has(+ .ameta){margin-bottom:16px}
.ahead .eyebrow{margin-bottom:14px}

:root{--gap-h1:30px}
@media(max-width:820px){:root{--gap-h1:22px}}

/* =============================================================
   SPACING POLICY -- the single source for vertical space.
   Supersedes every spacing rule above it in this file.

   The bug it fixes: blocks such as .answer set their own bottom margin (or
   none), so a block could sit flush against the next section. Individual
   elements must not decide their own gaps.

   Model, two levels only:
     1. SECTION rhythm: a section pads its top with --s5. The last section pads
        its bottom too, so the footer is not glued to it. Nothing else.
     2. FLOW inside a section: a block gets its gap from the sibling above it,
        not from itself. `.wrap > * + *` carries --s4. Two exceptions, because
        a heading and its subtitle are one block: after a heading or an eyebrow
        the gap is --s2, and the heading block ends with a normal --s4.

   Consequences to keep in mind when adding markup:
     - Do not write margin or padding on a block. Put it in the flow.
     - A new direct child of `section > .wrap` is spaced automatically.
     - Text inside .prose keeps its own typographic margins; that is copy, not
       layout.
   ============================================================= */
:root{
  --s1:12px;   /* inside a line: label to value */
  --s2:20px;   /* inside a block: heading to its subtitle */
  --s3:32px;   /* inside a block: secondary gap */
  --s4:52px;   /* between blocks in a section */
  --s5:88px;   /* between sections */
}
@media(max-width:1024px){:root{--s4:44px;--s5:72px}}
@media(max-width:820px){:root{--s2:16px;--s3:24px;--s4:34px;--s5:56px}}

/* 1. section rhythm */
section,.phero,.sec-join,.faqsec{padding:var(--s5) 0 0}
section:last-of-type{padding-bottom:var(--s5)}

/* 2. flow: the gap belongs to the sibling above, never to the block itself */
section > .wrap > *{margin-top:0;margin-bottom:0}
section > .wrap > * + *{margin-top:var(--s4)}
section > .wrap > .eyebrow + *,
section > .wrap > h1 + *,
section > .wrap > h2 + *{margin-top:var(--s2)}

/* the page header block uses the same flow at its own scale */
.ahead > *{margin-top:0;margin-bottom:0}
.ahead > * + *{margin-top:var(--s2)}
.ahead > .lead + *,.ahead > .ameta + *{margin-top:var(--s3)}

/* blocks that used to carry their own margins are now silent */
.answer,.prose,.pbody,.grid3,.faq,.ahero,.cta-row,.backlink,.pagelinks,.searchform,.pricenote,.sub,.steps,.plans,.marquee{margin-top:0;margin-bottom:0}
.answer,.prose{margin-left:auto;margin-right:auto}
.pbody .pmain .prose{margin-left:0;margin-right:0;margin-top:var(--s3)}
.pbody .pmain .vgrid{margin-top:var(--s3)}

/* copy inside .prose keeps typographic spacing: that is text, not layout */
.prose p{margin:0 0 16px}
.prose h2{margin:var(--s4) 0 var(--s1)}
.prose h3{margin:var(--s3) 0 var(--s1)}
.prose > :first-child{margin-top:0}
.prose > :last-child{margin-bottom:0}

/* ===== the heading block ends with the same gap that opens the section =====
   With the section gap at --s5, a heading followed by only --s4 read as
   top-heavy: more air above the title than under it. The rule now is simple to
   state and to keep: whatever opens a section closes its heading block.

     section top      --s5
     heading -> sub   --s2   (one block, stays tight)
     heading block -> content   --s5
     block -> block   --s4

   Only the gap under the heading block changes; blocks inside a section still
   sit --s4 apart, so the section does not turn into a list of islands. */
section > .wrap > h1 + :not(.sub),
section > .wrap > h2 + :not(.sub),
section > .wrap > .sub + *{margin-top:var(--s5)}

/* the page header block follows the same shape one step down the scale */
.ahead > .lead + *,.ahead > .ameta + *{margin-top:var(--s4)}

/* how-it-works walkthrough: the player under the three steps. Narrower than the step row on purpose,
   so the steps stay the widest thing in the section and the film reads as their footnote, not as a
   second hero. */
.howfilm{max-width:760px;margin:52px auto 0}
@media (max-width:760px){.howfilm{margin-top:36px}}

/* four-up video proof grid (homepage). Same breakpoints as .plans: 4 up, 2x2 from 1040px,
   one column from 560px. The shared .grid is auto-fill and would orphan the fourth card. */
.vgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:40px;max-width:1300px;margin:0 auto}
@media(max-width:760px){.vgrid{grid-template-columns:1fr;max-width:520px;gap:32px}}

/* the script a style card was made from, shown verbatim under the video */
.scriptbox{margin:26px 0 6px;border:1px solid var(--line-soft);border-radius:14px;background:rgba(0,0,0,.22);overflow:hidden}
.scriptbox .schead{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;border-bottom:1px solid var(--line-soft)}
.scriptbox .sctitle{font-family:var(--disp);font-weight:700;text-transform:uppercase;font-size:15px;letter-spacing:.02em}
.scriptbox .scopy{border:1px solid var(--line-soft);background:transparent;color:inherit;font:inherit;font-size:13px;padding:5px 14px;border-radius:8px;cursor:pointer;transition:background .15s,border-color .15s}
.scriptbox .scopy:hover{background:var(--coral-btn);border-color:var(--coral-btn);color:#fff}
/* the brief is long: give it its own scroll so it never stretches the page sideways */
.scriptbox pre{margin:0;padding:16px;max-height:340px;overflow:auto;white-space:pre-wrap;word-break:break-word;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.55;color:var(--chalk)}
.scriptbox .scnote{margin:0;padding:12px 16px;border-top:1px solid var(--line-soft);font-size:14px;color:rgba(241,237,228,.62)}
@media(max-width:560px){.scriptbox .schead{padding:10px 12px}.scriptbox pre{padding:12px;font-size:12px;max-height:260px}}

/* the style chooser plays its cards; the clip must never take the click away from the card's link */
.scard .thumb{position:relative}
.scard .thumb video.tile{width:100%;height:100%;object-fit:cover;display:block;background:#26262a;pointer-events:none}


/* The highlighted pack. The card itself stays exactly like its neighbours, translucent over the
   board: an opaque fill was only ever needed because the first attempt clipped the gradient to the
   border box, and a see-through card let it through. Here the gradient lives on a pseudo-element
   that is masked down to a 2px ring, so nothing shows through the middle and the interior is not
   tinted at all. Anyone who asked for less motion gets the same ring, standing still. */
.plan.hot{
  border-color:transparent;
  background:rgba(255,255,255,.015);
}
.plan.hot::before{
  content:"";
  position:absolute; inset:0; border-radius:20px; padding:2px; pointer-events:none;
  background:linear-gradient(90deg,var(--coral),var(--yellow),var(--coral),var(--yellow),var(--coral));
  background-size:300% 100%;
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  animation:plan-edge 7s linear infinite;
}
@keyframes plan-edge{ from{background-position:0% 50%} to{background-position:300% 50%} }
@media (prefers-reduced-motion: reduce){ .plan.hot::before{animation:none} }

/* visually hidden, still read aloud */
.vh{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}


/* Chat, as a floating button rather than a menu item: it is a service, not a destination, and in
   the header it competed with the navigation for a place it did not need. Deliberately not the
   widget's stock round bubble - dark and translucent like the rest of the board, with a thin
   gradient edge on a masked ring, the same one the highlighted pack and the buttons use. */
.askfab{
  position:fixed;right:22px;bottom:22px;z-index:30;
  display:inline-flex;align-items:center;gap:9px;
  padding:12px 18px 12px 15px;border:1px solid transparent;border-radius:14px;
  background:rgba(25,24,32,.82);backdrop-filter:blur(7px);
  color:var(--chalk);font-family:var(--body);font-weight:800;font-size:16px;cursor:pointer;
  box-shadow:0 12px 30px rgba(0,0,0,.42);transition:background .18s ease,transform .18s ease}
.askfab:hover{background:rgba(38,37,43,.92)}
.askfab svg{width:22px;height:22px;fill:currentColor;flex:0 0 auto}
.askfab::before{
  content:"";position:absolute;inset:0;border-radius:14px;padding:1.5px;pointer-events:none;
  background:linear-gradient(90deg,var(--coral),var(--yellow),var(--coral),var(--yellow),var(--coral));
  background-size:300% 100%;
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  animation:plan-edge 7s linear infinite}
@media (prefers-reduced-motion: reduce){ .askfab::before{animation:none} }
@media(max-width:640px){ .askfab{right:14px;bottom:14px;padding:11px 14px} .askfab span{display:none} }

/* ==========================================================================
   PAID LANDINGS (/lp/*) -- the whiteboard mode of this brand
   ==========================================================================
   WHY LIGHT. The site is a dark chalkboard and it should stay one. But these pages advertise a
   WHITE board, and on the dark ground the product video reads as a bright hole punched in a wall
   rather than as the thing being sold. The brand kit already answers this: whiteboard/light is a
   MODE of explain.ink, not a second brand. So the wordmark, the coral, the button shape, Cabin
   Sketch and Nunito all stay exactly as they are; only the ground and the ink swap.

   WHY EVERY RULE IS UNDER .lp. layouts/base.php puts that class on <body> and only for
   $chrome === 'lp'. Nothing here can reach a page that did not ask for it, which is what makes
   this safe to append to a stylesheet shared by forty other pages.
   ========================================================================== */
.lp{
  --paper:#f7f4ec;      /* brand light ground */
  --paper-2:#ffffff;    /* cards, the video well */
  --ink:#211e1a;        /* brand light ink */
  --ink-dim:#5f584f;
  --rule:rgba(33,30,26,.14);
  color:var(--ink);
  /* The dark board is a fixed background-image on <body>; overriding the shorthand is what takes
     the picture off, not just the colour behind it. */
  background:var(--paper);
  background-image:none;
}
/* body::before paints the whole dark vignette over everything, including this page. */
.lp::before{display:none}
.lp ::selection{background:rgba(233,87,63,.22)}

.lpwrap{max-width:1080px;margin:0 auto;padding:0 24px;position:relative}

/* --- top bar: a wordmark and one link out, and nothing else --------------- */
.lpbar{border-bottom:1px solid var(--rule);background:var(--paper)}
.lpbar .lpwrap{display:flex;align-items:center;height:72px}
.lp .brand{font-family:var(--disp);font-weight:700;font-size:32px;letter-spacing:.5px;line-height:1;color:var(--ink)}
.lplogin{margin-left:auto;font-weight:700;font-size:16px;color:var(--ink-dim)}
.lplogin:hover{color:var(--ink)}

/* --- hero ---------------------------------------------------------------- */
/* The vertical budget here is not taste. A 1280x720 laptop shows about 610px of page under the
   browser chrome, and the video has to start inside that: it is the only proof on the page, and a
   headline plus a button with nothing behind them is what every one of these tools looks like.
   So the type is set to wrap in two lines rather than three, and the air is spent on the video. */
.lphero{padding:44px 0 60px;text-align:center}
.lphero h1{font-family:var(--disp);font-weight:700;
  font-size:clamp(32px,4.6vw,54px);line-height:1.04;letter-spacing:.01em;
  margin:0 auto 16px;max-width:21ch;text-wrap:balance}
.lpsub{font-size:clamp(17px,2vw,20px);color:var(--ink-dim);
  max-width:52ch;margin:0 auto 26px;line-height:1.5;text-wrap:balance}

.lpact{display:flex;flex-direction:column;align-items:center;gap:10px;margin:0 0 34px}
.btn-lg{padding:18px 42px;font-size:20px}
/* .btn-primary already carries the coral fill and white text from the shared button rules; it
   needs nothing here, which is the whole argument for calling this a mode. */
.lpnote{font-size:15px;color:var(--ink-dim)}

/* --- the video ----------------------------------------------------------- */
.lpvid{margin:0}
.lpvwrap{position:relative;width:100%;max-width:920px;margin:0 auto}
.lpvid video{display:block;width:100%;
  aspect-ratio:16/9;height:auto;background:var(--paper-2);
  border:1px solid var(--rule);border-radius:14px;
  box-shadow:0 18px 44px rgba(33,30,26,.13)}
.lpvid figcaption{margin:16px auto 0;max-width:56ch;font-size:15px;color:var(--ink-dim)}

/* Sits on the video rather than beside it: the press has to be where the eye already is. */
.lpsound{position:absolute;left:50%;transform:translateX(-50%);bottom:16px;
  display:inline-flex;align-items:center;gap:9px;cursor:pointer;
  font-family:var(--body);font-weight:800;font-size:15px;
  padding:11px 22px;border:0;border-radius:40px;
  color:var(--ink);background:rgba(255,255,255,.93);
  box-shadow:0 4px 16px rgba(33,30,26,.22)}
.lpsound:hover{background:#fff}
.lpsound-i{color:var(--coral);font-size:12px;line-height:1}
.lpsound[hidden]{display:none}

/* --- four doubts, answered under the player ------------------------------ */
.lpfeat{list-style:none;margin:30px auto 0;padding:0;max-width:920px;
  display:grid;grid-template-columns:repeat(4,1fr);gap:22px;text-align:left}
/* align-content:start matters: a shorter item sits in the same row as a taller one, and its own
   grid rows would otherwise stretch to the row height and push its title down out of line. */
.lpfeat li{display:grid;grid-template-columns:26px 1fr;column-gap:12px;row-gap:3px;align-items:start;align-content:start}
.lpfeat svg{grid-row:span 2;color:var(--coral);margin-top:1px}
.lpfeat b{font-size:16px;line-height:1.3}
.lpfeat span{font-size:14px;line-height:1.45;color:var(--ink-dim)}

/* --- them and us --------------------------------------------------------- */
.lpvs{padding:8px 0 64px}
.lpvsgrid{display:grid;grid-template-columns:1fr 1fr;gap:20px;max-width:920px;margin:0 auto}
.lpvscol{padding:26px 28px;border-radius:14px;border:1px solid var(--rule);background:var(--paper-2)}
.lpvscol p{margin:0;font-size:16px;line-height:1.55;color:var(--ink-dim)}
.lpvsh{font-family:var(--disp);font-weight:700;font-size:23px;line-height:1.15;margin-bottom:11px}
/* The other column is not dimmed. It used to be (opacity .78), which is the page grading them;
   content rule 3 wants the trade-off told in both directions, so both columns read at full ink and
   only the coral outline says which one is ours. */
.lpvsold{background:transparent}
.lpvsnew{box-shadow:inset 0 0 0 2px var(--coral);border-color:transparent}
.lpvsnew .lpvsh{color:var(--coral)}

/* --- three steps --------------------------------------------------------- */
.lpsteps{padding:0 0 72px}
.lpstepgrid{list-style:none;margin:0 auto;padding:0;max-width:920px;
  display:grid;grid-template-columns:repeat(3,1fr);gap:26px}
.lpstepgrid li{text-align:left}
.lpnum{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;
  border-radius:50%;background:var(--coral);color:#fff;
  font-family:var(--disp);font-weight:700;font-size:19px;margin-bottom:12px}
.lpstepgrid b{display:block;font-size:18px;margin-bottom:6px}
.lpstepgrid p{margin:0;font-size:16px;line-height:1.55;color:var(--ink-dim)}

/* --- drawing in on scroll (armed by the script in views/lp.php) ------------- */
/* Nothing here hides anything on its own. The script measures each stroke, hides it, and only then
   adds .is-armed, so without JS or with reduced motion these rules never match and the icons and
   numbers are simply there. --d is each item's stagger, set per <li> by the same script. */
.lpnum{position:relative}
.lpnum svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.lpnum circle{fill:none;stroke:var(--coral);stroke-width:2}
.is-armed svg path,.is-armed svg rect,.is-armed svg circle{
  transition:stroke-dashoffset .7s cubic-bezier(.4,0,.2,1) var(--d,0s)}
.lpstepgrid.is-armed .lpnum{background:transparent;color:transparent}
/* The fill lands once the ring has closed: outline first, then ink, the order a hand would do it. */
.lpstepgrid.is-drawn .lpnum{background:var(--coral);color:#fff;
  transition:background-color .25s ease calc(var(--d,0s) + .5s),color .25s ease calc(var(--d,0s) + .5s)}

/* --- short FAQ ---------------------------------------------------------- */
/* Its own closing rule and air: the closing section's border runs full width, so leaning on it
   left the last question touching a line wider than the list it belonged to. */
.lpfaq{padding:0 0 64px}
.lpfaq .lpwrap{max-width:760px}
.lpfaq details{border-top:1px solid var(--rule)}
.lpfaq details:last-child{border-bottom:1px solid var(--rule)}
.lpfaq summary{cursor:pointer;list-style:none;position:relative;
  padding:20px 40px 20px 0;font-weight:800;font-size:18px;line-height:1.35}
.lpfaq summary::-webkit-details-marker{display:none}
.lpfaq summary::after{content:"+";position:absolute;right:6px;top:50%;transform:translateY(-50%);
  font-size:26px;font-weight:700;line-height:1;color:var(--coral)}
.lpfaq details[open] summary::after{content:"\2212"}
.lpfaq p{margin:-4px 0 22px;font-size:16px;line-height:1.6;color:var(--ink-dim)}

/* --- closing ------------------------------------------------------------- */
.lpend{padding:0 0 84px;text-align:center;border-top:1px solid var(--rule);padding-top:64px}
.lpend h2{font-family:var(--disp);font-weight:700;font-size:clamp(28px,4vw,44px);
  line-height:1.05;margin:0 0 26px}
.lpend .lpact{margin-bottom:0}

/* --- footer: legal only -------------------------------------------------- */
.lpfoot{border-top:1px solid var(--rule);padding:26px 0 40px}
.lpfoot .lpwrap{display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  font-size:14px;color:var(--ink-dim)}
.lpfoot .brand{font-size:24px}
.lplegal{margin-left:auto;display:flex;gap:18px}
.lplegal a:hover{color:var(--ink)}

/* --- phone --------------------------------------------------------------- */
@media(max-width:760px){
  /* The CTA must be reachable without a scroll, so the hero loses its top air first. */
  .lphero{padding:34px 0 48px}
  .lphero h1{max-width:none}
  .lpact{margin-bottom:32px}
  .btn-lg{padding:17px 30px;font-size:18px;width:100%;justify-content:center;max-width:340px}
  /* Full-bleed player: on a 390px screen a 24px gutter each side is 12% of the only proof on
     the page. The radius goes with the gutter, since a rounded edge against the screen edge
     reads as a rendering fault rather than as a card. */
  .lpvwrap{width:100vw;max-width:100vw;margin-left:calc(50% - 50vw)}
  .lpvid video{border-radius:0;border-left:0;border-right:0;box-shadow:none}
  .lpvid figcaption{padding:0 4px}
  .lpvsgrid,.lpstepgrid{grid-template-columns:1fr;gap:16px}
  /* Two by two rather than a column of four: stacked, the row would push the comparison a
     full screen further down for four short lines. */
  .lpfeat{grid-template-columns:1fr 1fr;gap:20px 14px;padding:0 4px}
  .lpfeat li{grid-template-columns:1fr}
  .lpfeat svg{grid-row:auto}
  .lpfaq summary{font-size:17px}
  /* The vertical cut fills the phone like a Reel, but never taller than most of the screen, so the
     top of the next block still shows under it. min() with svh is dropped whole by a browser that
     lacks svh, which falls back to the full-bleed width above. */
  .lpvwrap.has-vertical{width:min(100vw,calc(82svh * 9 / 16));margin-left:50%;transform:translateX(-50%)}
  .lpvwrap.has-vertical video{aspect-ratio:9/16}
  /* One column on a phone reads as a centred stack; left-aligned it looked like a layout that had
     lost its other columns (owner, 2026-09-13). Comparison paragraphs stay left, they are prose. */
  .lpfeat li{justify-items:center;text-align:center}
  .lpstepgrid li{text-align:center}
  .lpfoot .lpwrap{justify-content:center;text-align:center}
  .lplegal{justify-content:center}
  .lpend{padding-top:48px;padding-bottom:60px}
  .lpfoot .lpwrap{gap:12px}
  .lplegal{margin-left:0;width:100%}
}

/* --- wide tables on a narrow screen --------------------------------------- */
/* A table is the one block in .prose whose minimum width comes from its content rather than from
   its container, so width:100% is simply ignored once the columns cannot fit. The comparison table
   on /whiteboard-animation has four columns of prose, and on a phone it pushed the WHOLE PAGE into
   a horizontal scroll (owner, 2026-09-13) -- the body moving sideways reads as a broken layout,
   while a table that scrolls on its own reads as a table.
   display:block is what gives it its own overflow context; max-content stops the columns collapsing
   to one word per line the moment scrolling is allowed; max-width:100% is what keeps it off the
   body. Desktop is untouched: above the breakpoint the table still stretches to the column. */
@media(max-width:820px){
  .prose table{display:block;width:max-content;max-width:100%;overflow-x:auto;
    -webkit-overflow-scrolling:touch}
  /* AND THE CELLS NEED A FLOOR. Without one, max-width:100% squeezes the table back to the width of
     the screen and the columns wrap to two words a line: technically no page scroll, but nobody can
     read it. A floor makes the table genuinely wider than the phone, which is what the sideways
     scroll is there for. A two-column table stays under the screen width and never scrolls at all. */
  .prose th,.prose td{min-width:10rem}
}
