
/* round ten (Sergey, 2026-09-06): one typeface on every platform - Inter, self-hosted from this
   origin (site/fonts/, SIL OFL 1.1, the latin subset, one variable file for every weight), first in
   the stack so an Android or Windows visitor sees the headings his iPhone showed him. No outside
   request: the file ships with the site (build_deploy copies fonts/). */
@font-face{font-family:"Inter";font-style:normal;font-weight:100 900;font-display:swap;
  src:url(/fonts/inter-latin-wght-normal.woff2) format("woff2-variations"),url(/fonts/inter-latin-wght-normal.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}
html body,html button,html input,html select,html textarea{font-family:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
/* ============================================================================
   THEME + MOBILE-FIRST LAYER  (source: site/theme-template.html, spliced by
   patch_theme.py into every built page as the LAST block in <head>).
   Sergey, 2026-09-04: the site goes dark - not pure black - and is built for the
   phone first. Every rule here is prefixed with `html` so it outranks the
   template rules of equal specificity wherever they sit, including the pricing
   and mobile-runtime blocks that are spliced into <body> after this one.
   The six-assistant demo shows each assistant in its own dark mode (palettes read off
   the live apps, see patch_demo_dark.py) inside a dark browser window. The 30-day
   monitor demo was retired on 2026-09-05 (afternoon) for two charts in #charts, and
   #charts itself in the evening (round six); the gauge and the funnel card live on as
   the pictures of steps 2 and 3.
   All pairs below were checked against WCAG AA: muted on paper 7.4:1, accent
   on paper 8.5:1, button text on button 8.8:1, ink on paper 16:1.
   ============================================================================ */
:root{
  --paper:#12161c; --soft:#181d25; --soft2:#1f2530; --line:#2e3642;
  --ink:#eef1f6; --muted:#9ba6b7;
  --accent:#8fb0ff; --accent-deep:#3358b8; --accent-soft:#1b2440;
  --btn-ink:#0c1020; --btn-bg:#ffffff; --ghost-bg:#262b34;
  --ok:#63c29c; --warn:#e3ad5f; --bad:#ff9478; --bad-ink:#ffb39c; --bad-soft:#3b201b;
}
/* Round thirty (Sergey, his screenshot of three screens on grey): "give us the same background,
   almost black or absolutely black, the one used OUTSIDE the coloured plates." The page's ground
   was --paper (#12161c) while every cinematic screen stands on #0A0A0A, so the reading sections
   sat on a lighter grey than the plates did. One ground now; --paper stays the colour of the
   things that stand ON it (the header, a card, a table). */
html{background:var(--cs-ground,#0A0A0A);color-scheme:dark;-webkit-text-size-adjust:100%;
  -webkit-tap-highlight-color:rgba(143,176,255,.22)}
html body{background:var(--cs-ground,#0A0A0A);color:var(--ink)}
html ::selection{background:#3358b8;color:#fff}

/* ---- buttons: the one bright object on the page ---- */
html .btn{background:var(--btn-bg);border-color:var(--btn-bg);color:var(--btn-ink)}
html .btn:hover{background:#e3e8f3;border-color:#e3e8f3;color:var(--btn-ink)}
html .btn.ghost{background:var(--ghost-bg);color:#fff;border-color:var(--ghost-bg)}
html .btn.ghost:hover{background:#333947;border-color:#333947;color:#fff}
html header .btn,html header .btn.ghost,html #stickyScan .btn{background:var(--btn-bg);border-color:var(--btn-bg);color:var(--btn-ink)}
html header .btn.ghost:hover{background:#e3e8f3;border-color:#e3e8f3;color:var(--btn-ink)}
html .skip{background:var(--btn-bg);color:var(--btn-ink)}
html :focus-visible{outline:3px solid var(--accent);outline-offset:3px}

/* ---- page chrome that carried a light literal ---- */
html .kicker{border-color:var(--line)}
html .receipt{background:var(--soft)}
html .receipt figcaption,html .receipt .rnote,html .targets .teye,html .targets .tn{color:var(--muted)}
html .targets .tlead{color:var(--ink)}
html .targets li{border-top-color:var(--line)}
html .targets .ta,html .indGroup a i{color:var(--ok)}
html .tag{color:var(--muted)}
html .hfact{border-color:var(--line)}
html .hasked{background:var(--soft)}
html .ind,html .indPanel{background:var(--soft)}
html .indPanel{box-shadow:0 18px 44px rgba(0,0,0,.55);border:1px solid var(--line)}
html .ind:hover{box-shadow:0 6px 18px rgba(0,0,0,.45)}
html .measured{background:var(--accent-soft)}
html pre.file{background:var(--soft);color:var(--ink)}
html pre,html code{color:var(--ink)}
html table{border-color:var(--line)}
html th,html td{border-color:var(--line)}

/* ---- forms ---- */
html .field input,html .field select,html .field textarea,html .indFilter{
  background:var(--soft2);border:1px solid #3a4453;color:var(--ink)}
html .field input::placeholder,html .indFilter::placeholder{color:#8b96a7}
html .field input:focus,html .field select:focus,html .indFilter:focus{
  background:#232a35;border-color:var(--accent)}
html .field input.known,html .field select.known{background:var(--soft);color:var(--muted)}
html .field input.known:focus,html .field select.known:focus{background:#232a35;color:var(--ink)}
html .field select option{background:var(--soft2);color:var(--ink)}
html .intake .mclose:hover{background:var(--soft2);color:var(--ink)}
html .intake .confirm{background:var(--accent-soft)}
html .note.prefill{background:var(--accent-soft)}
html .ok{background:var(--accent-soft);border-color:var(--accent)}
html .ok.err,html .formStatus[data-kind=error]{background:var(--bad-soft);border-color:var(--bad);color:var(--bad-ink)}
html .formStatus[data-kind=ok]{background:var(--accent-soft);border-color:var(--accent)}
html .formStatus[data-kind=busy]{background:var(--soft);border-color:var(--line)}
html .intake.js-steps.step-open .step2{background:rgba(0,0,0,.62)}
html .intake.js-steps.step-open .step2inner{background:var(--soft);border:1px solid var(--line);
  box-shadow:0 18px 50px rgba(0,0,0,.6)}

/* ---- sticky bars spliced into <body> (mobile runtime, pricing switch) ----
   Sergey, 2026-09-05: inverted - the bar that pins to the top is white, its controls are
   black with white text, so it reads as a different object from the dark page under it. */
html #stickyScan .lockup,html #stickyScan .lockup b,html #stickyScan .lockup span{color:var(--btn-ink)}
html #stickyScan .lockup span{border-left-color:rgba(12,16,32,.75)}
html #stickyScan .lockup{font-size:18px;text-decoration:none;min-height:36px;position:relative}   /* a link is a tap target (44px through its ::before, below); round forty-nine: the bar a fifth lower */
/* round forty-seven: no backdrop blur on the bar. At 96% white the blur was invisible, and a fixed
   element with a backdrop filter makes iOS re-render everything under it on every scroll frame - the
   one thing on the screen through every move on a phone. */
html #stickyScan{background:rgba(255,255,255,.97);
  border-bottom:1px solid #cfd6e0;box-shadow:0 3px 14px rgba(0,0,0,.35)}
/* round twelve: the yearly switch belongs to the monitoring screen and rides inside its pinned
   heading, so it is a plain control, not a white bar of its own (it used to pin at the top on its
   own and, on the new monitoring screen, covered the heading it was sitting under) */
html #pricing .pz-billing{background:transparent;border:0;box-shadow:none;padding:0;position:static}
html #pricing .pz-billing label{color:var(--ink)}
html #pricing .pz-billing .pz-save{color:var(--accent)}
html #pricing .pz-billing .pz-sw{background:var(--line)}
html #pricing .pz-billing .pz-sw[aria-checked="true"]{background:var(--accent)}
html #stickyScan p{color:var(--btn-ink)}
html #stickyScan .btn{background:var(--btn-ink);border-color:var(--btn-ink);color:#fff}
html #stickyScan .btn:hover{background:#1c2340;border-color:#1c2340;color:#fff}
html #pricing .pz-billing .pz-sw::after{background:#fff}
html #pricing .pz-billing .pz-sw:focus-visible{outline-color:var(--btn-ink)}
html #pricing .pz-badge{color:var(--btn-ink)}

/* ---- the hero phone stays a light screenshot inside a dark frame ---- */
html .phone{background:var(--soft);border-color:var(--line)}
html .screen{background:#fff;color:#14171c;border-color:#e3e6ea}
html .screen .ask{background:#eef2fb;color:#14171c}
html .screen .label,html .screen .firm span{color:#5c6673}
html .screen .firm,html .screen .miss{border-top-color:#e3e6ea}
html .screen .miss{color:#a33c17}

/* ---- hero: one centred column, the question as big as the screen allows ---- */
html .hero{display:flex;flex-direction:column;justify-content:center;max-width:1080px;margin:0 auto;text-align:center;
  padding:clamp(40px,7vw,96px) 0 clamp(40px,5vw,72px);box-sizing:border-box;
  min-height:min(calc(100vh - 55px),900px);min-height:min(calc(100svh - 55px),900px)}
html .hero > div{max-width:none;width:100%}
html .hero h1,html .hq-h1,html .hq-box,html section > .wrap > h2,html .gnf-h2,html #scan .wrap > h2,
html main > .wrap > h2{font-size:clamp(40px,5.6vw,76px);line-height:1.06;letter-spacing:-.035em;font-weight:800}   /* round nine: the closing scene's weight and tracking everywhere */
html .hq-box{margin-bottom:14px}
/* /pricing/ (build_pricing.py): the block's own head is the page head, its h2 an h1 */
html #pricing .pz-head h1,html #pricing .pz-head h2{font-size:clamp(40px,5.6vw,76px);line-height:1.06;letter-spacing:-.035em;font-weight:800;margin:0 0 14px}
html #pricing .pz-head{max-width:none}
html .closer{padding:clamp(56px,9vw,120px) 0}
html .hero .hq-row{justify-content:center}
html .hero .eyebrow,html .hero .lead,html .hero .hasked,html .hero-cta,html .hero .caption{text-align:center}
html .hero .lead{margin-left:auto;margin-right:auto;max-width:44ch;font-size:clamp(17px,1.5vw,21px)}
html .hero-cta{justify-content:center;align-items:center}
html .hero .hfacts{max-width:640px;margin-left:auto;margin-right:auto;text-align:left}

/* ---- header: white and black only - no accent in the brand, no grey links ---- */
html .brand,html .brand b{color:#fff}
/* ---- the logo (Sergey, 2026-09-05 late evening): concept 39 of LOGO_CONCEPTS_2026-09-05,
   "split by a rule" - a heavy AI, a hairline, then the phrase; type only, no separate mark.
   patch_theme.py writes the same markup into every header and footer; the box carries it
   in SVG (patch_mobile_blocks.py, part 5). 19px in the header, as the concept sheet set. ---- */
html .lockup{display:inline-flex;align-items:center;font-weight:400;letter-spacing:-.01em;color:#fff;text-decoration:none;white-space:nowrap}
html .lockup b{font-weight:800;letter-spacing:-.04em;color:#fff}
html .lockup span{display:inline-block;border-left:1px solid rgba(255,255,255,.92);margin-left:.44em;padding-left:.44em;line-height:1.05;font-weight:400;color:#fff}
html header .brand.lockup{font-size:19px;min-height:44px}
html footer .lockup{font-size:16px}
/* ---- round fourteen (Sergey, 2026-09-06): "the header must be the same on every page" - the
   markup is (site_nav.py), and from here so is its shape, which used to live in the stylesheet of
   three pages only. Round fifteen took the Industries dropdown out of the header altogether, so
   the rules that shaped it went with it; what stays is the row itself. ---- */
html header .wrap{display:flex;align-items:center;gap:24px;min-height:68px;position:relative;
  width:min(1040px,calc(100% - 40px));margin-left:auto;margin-right:auto}   /* /thanks/ had a 760px header of its own */
html header nav{margin-left:auto;display:flex;gap:22px}
html header nav a,html header .brand,html header .lockup,html header .indMenu>summary{text-decoration:none}
/* the header brand is a link like any other: 44px to hit, measured at 33 before this */
html header .brand{display:inline-flex;align-items:center;min-height:44px}
/* the same skip link everywhere: on /thanks/ it had no rule of its own and read as the first line of the page */
html .skip{position:absolute;left:-9999px;top:0;z-index:100;padding:10px 14px;background:var(--accent);color:#0c1020;font-weight:650}
html .skip:focus{left:0}
html nav a,html .indMenu>summary{color:var(--ink)}
html nav a:hover,html .indMenu>summary:hover,html .indMenu[open]>summary{color:#fff;text-decoration:underline;text-underline-offset:4px}
html .hq-burger i{background:#fff}

/* ---- header: Profound's shape on phones - brand, white button, hamburger ---- */
/* the hamburger takes over at the width the root template hides its nav (820px); the nav is
   hidden here too, so pages built on the lighter service stylesheet (/pricing/) match */
html .hq-burger{display:none;width:44px;height:44px;border:0;background:transparent;cursor:pointer;
  padding:10px;flex-direction:column;justify-content:center;gap:5px;border-radius:8px}
html .hq-burger i{display:block;height:2px;background:var(--ink);border-radius:2px;transition:transform .2s,opacity .2s}
html.hq-open .hq-burger i:nth-child(1){transform:translateY(7px) rotate(45deg)}
html.hq-open .hq-burger i:nth-child(2){opacity:0}
html.hq-open .hq-burger i:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
html .hq-menu{display:none}
@media (max-width:820px){
  html .hq-burger{display:flex;flex:none;margin-right:-10px;margin-top:-2px;margin-bottom:-2px}
  html header .wrap{gap:8px}
  html header .brand{flex:none}
  html header .indMenu,html header nav{display:none}
  html header .wrap > .btn{margin-left:auto;flex:none;border-radius:9px;padding-left:16px;padding-right:16px}
  html header .btn.ghost{background:var(--btn-bg);border-color:var(--btn-bg);color:var(--btn-ink)}
  html header .btn.ghost:hover{background:#e3e8f3;border-color:#e3e8f3;color:var(--btn-ink)}
  html.hq-open{overflow:hidden}
  html.hq-open .hq-menu{display:block;position:fixed;left:0;right:0;top:55px;bottom:0;z-index:70;
    background:var(--paper);padding:8px 20px 40px;overflow:auto;border-top:1px solid var(--line)}
  html .hq-menu nav{display:flex;flex-direction:column;gap:0;margin:0}
  html .hq-menu nav a{display:flex;align-items:center;min-height:58px;padding:0;font-size:22px;
    font-weight:650;color:var(--ink);border-bottom:1px solid var(--line);letter-spacing:-.01em}
}

/* ---- the six-assistant demo: the browser alone, the assistant in the heading ---- */
html #geo-nf .nf-grid{grid-template-columns:1fr;grid-template-areas:"browser"}
/* a dark browser window (Chrome's dark frame: #202124 / #35363a / #e8eaed / #9aa0a6) */
html #geo-nf .browser{background:#202124;border-color:#3c4043;
  box-shadow:0 23px 52px -19px rgba(0,0,0,.75),0 3px 8px rgba(0,0,0,.35)}
html #geo-nf .br-tab{background:rgba(255,255,255,.06);color:#9aa0a6}
html #geo-nf .br-tab:hover{background:rgba(255,255,255,.11)}
html #geo-nf .br-tab[aria-current="true"]{background:#35363a;color:#e8eaed;box-shadow:none}
html #geo-nf .br-tab .fav{color:#e8eaed}
html #geo-nf .br-tab .x,html #geo-nf .br-plus,html #geo-nf .br-nav,html #geo-nf .br-acts{color:#9aa0a6}
html #geo-nf .br-url{background:#35363a}
html #geo-nf .br-omni{background:#202124;color:#e8eaed}
html #geo-nf .br-omni .lock,html #geo-nf .br-omni .u i{color:#9aa0a6}
html #geo-nf .br-view{background:#131313}
html #geo-nf .res .n{color:var(--mu)}
/* the window leaves a tenth of the screen free on each side (Sergey); the "Not found"
   verdict lands in the middle of the window, not along its bottom edge, and is wiped
   the moment the next assistant opens */
html #geo-nf .nf-grid{width:min(100%,80vw);margin:0 auto}
html #geo-nf .nf-ov{inset:0;margin:auto;width:min(80%,300px);height:fit-content;
  flex-direction:column;justify-content:center;text-align:center;gap:0;padding:14px 16px;border-radius:14px;
  box-shadow:0 26px 60px rgba(0,0,0,.6),inset 0 0 0 1px rgba(255,255,255,.18);transform:scale(.88);opacity:0}
html #geo-nf .ov-x,html #geo-nf .ov-tag{display:none}
html #geo-nf .is-live .nf-ov{animation:gnfCentre .42s cubic-bezier(.2,.9,.3,1.04) var(--verdict-delay,1980ms) forwards}
@keyframes gnfCentre{from{transform:scale(.88);opacity:0}to{transform:none;opacity:1}}
html #geo-nf .ov-txt{white-space:normal;font-size:16px;line-height:1.35;font-weight:650}
@media (prefers-reduced-motion:reduce){html #geo-nf .is-live .nf-ov{animation:none;opacity:1;transform:none}}
html #geo-nf .nf-below,html #geo-nf .nf-panel,html #geo-nf .nf-rail{display:none}
html .gnf-h2{text-align:center}
html #evidence > .wrap > .eyebrow,html #evidence > .wrap > .lead,html #evidence > .wrap > h2{text-align:center}
html #evidence > .wrap > .lead{margin-left:auto;margin-right:auto;max-width:60ch}
html .gnf-who,html .gnf-rest{display:block}
html .gnf-who{white-space:nowrap;height:1.15em;line-height:1.15;color:var(--ink)}
html .gw-mk{display:inline-block;height:1em;width:1em;vertical-align:-.1em;margin-right:.12em;
  opacity:0;transform:translateY(.4em);transition:opacity .28s ease,transform .44s cubic-bezier(.2,.72,.28,1)}
html .gw-mk svg{display:block;width:100%;height:100%}
html .gw-mk svg [fill]:not([fill="none"]){fill:currentColor}
html .gw-mk svg [stroke]{stroke:currentColor}
html .gw-l{display:inline-block;opacity:0;transform:translateY(.4em);
  transition:opacity .28s ease,transform .44s cubic-bezier(.2,.72,.28,1)}
html .gnf-who.on .gw-l{opacity:1;transform:none;transition-delay:calc(var(--i) * 36ms)}
html .gnf-who.on .gw-mk{opacity:1;transform:none}

/* ---- the radial gauge and the funnel card: the two 21st.dev elements ported on 2026-09-05,
   drawn as inline SVG by charts-js below. They stood in #charts for an afternoon; since
   round six they are the pictures of steps 2 and 3 in "How it works". Dark ground, site tokens. ---- */
html .gauge{display:block;margin:0;width:100%;max-width:var(--gauge-max,300px)}
html .gauge svg{display:block;width:100%;height:auto;overflow:visible}
html .gauge .gauge-fallback{margin:0;font-size:15px;color:var(--muted);text-align:center}
html .gauge .gauge-fallback b{color:var(--ink);font-size:22px}
html .fcard{position:relative;margin:0;background:var(--soft);border:1px solid var(--line);border-radius:14px;padding:18px 18px 16px;
  width:100%;max-width:400px;color:var(--ink);box-sizing:border-box;text-align:left}
html .fcard-top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin:0}
html .fcard-title{font-size:14px;font-weight:500;color:var(--muted);margin:0;text-align:left}
html .fcard-hero{display:flex;align-items:center;gap:10px;margin-top:4px}
html .fcard-hero .v{font-size:30px;font-weight:700;letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums}
html .fcard-pill{font-size:12px;font-weight:600;border-radius:999px;padding:3px 9px;line-height:1.3}
html .fcard-pill.up{color:var(--ok);background:rgba(99,194,156,.14)}
html .fcard-pill.down{color:var(--bad);background:rgba(255,148,120,.14)}
html .fcard-btn{font:inherit;font-size:14px;font-weight:600;color:var(--ink);background:var(--ghost-bg);border:1px solid var(--line);
  border-radius:9px;padding:9px 14px;min-height:44px;cursor:pointer;flex:none}
html .fcard-btn:hover{background:#333947}
html .fcard-rows{list-style:none;margin:14px 0 0;padding:0;display:grid;gap:7px}
html .fcard-rows li{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:8px;font-size:14px}
html .fcard-rows .fchip{width:9px;height:9px;border-radius:3px;flex:none;display:block}
html .fcard-rows .lab{color:var(--muted);min-width:0}
html .fcard-rows .num{font-weight:600;font-variant-numeric:tabular-nums}
html .fcard-rows .d{font-size:14px;font-weight:600;font-variant-numeric:tabular-nums;min-width:52px;text-align:right}
html .fcard-rows .d.up{color:var(--ok)}
html .fcard-rows .d.down{color:var(--bad)}
html .fcard-plot{position:relative;margin-top:14px}
html .fcard-plot svg{display:block;width:100%;height:auto}
html .fcard-tip{position:absolute;pointer-events:none;opacity:0;transition:opacity .12s;background:var(--soft2);border:1px solid var(--line);
  border-radius:8px;padding:8px 10px;font-size:14px;line-height:1.45;white-space:nowrap;box-shadow:0 6px 18px rgba(0,0,0,.45);z-index:2}
html .fcard-tip .t{color:var(--muted);font-size:14px;letter-spacing:.06em;text-transform:uppercase;margin-bottom:2px}
html .fcard-tip .r{display:flex;align-items:center;gap:6px;font-variant-numeric:tabular-nums;font-weight:600}
html .fcard-tip .r i{width:8px;height:8px;border-radius:2px;display:block;flex:none}
html .fcard-plot:hover .fcard-tip.on{opacity:1}
html .fcard-table{margin-top:12px;max-height:190px;overflow:auto;border:1px solid var(--line);border-radius:8px}
html .fcard-table table{border-collapse:collapse;width:100%;font-size:14px;font-variant-numeric:tabular-nums;display:table}
html .fcard-table th,html .fcard-table td{padding:5px 10px;text-align:right;border-bottom:1px solid var(--line);white-space:nowrap}
html .fcard-table th{position:sticky;top:0;background:var(--soft2);color:var(--muted);font-weight:600;text-align:right}
html .fcard-table th:first-child,html .fcard-table td:first-child{text-align:left}
html .fcard-table td{color:#c9d4e4}
@media (prefers-reduced-motion:reduce){html .fcard-tip{transition:none}}
@media (max-width:640px){
  html .fcard{padding:14px 14px 12px}
  html #evidence{padding-top:64px;padding-bottom:28px}   /* round eleven: the eyebrow stood under the pinned bar */
  html #scan .sec-head > .lead,html #scan .wrap.grid2 > div:first-child{display:none}
  html #scan .intake .step1 > .btn{margin-top:18px}   /* round nine: air between the hint and the button */
  html #evidence > .wrap > .lead{display:none}
  html #geo-nf .br-view{height:344px}
  @media (max-height:700px){   /* round eleven, iPhone SE (375x667): the demo window on one screen - measured 639px */
    html #evidence{padding-top:62px;padding-bottom:10px}
    html #evidence > .wrap > .eyebrow{display:none}
    html #evidence .gnf-h2{font-size:34px}   /* outranks the phone heading rule below (same selector, later) */
    html #geo-nf{margin-top:18px}
  }
}

/* ---- #analyze "We analyze data 24/7": the 21st.dev "bucket" (open box) ported on 2026-09-05,
   greys probed off the original; the brand printed low on the body in the flaps' grey; the cards
   that fall in are the questions people put to the assistants (a hub uses its own measured questions). ---- */
html #analyze .an-stage{display:flex;justify-content:center;margin-top:26px}
html .bucket{--bw:440px;position:relative;width:var(--bw);max-width:100%;height:calc(var(--bw) * 265 / 344);margin:0 auto}
html .bucket > svg{position:absolute;inset:0;width:100%;height:100%;display:block}
html .bucket .bk-back{z-index:1;filter:drop-shadow(0 0 calc(var(--bw)*0.03) rgba(140,160,220,.10))}
html .bucket .bk-front{z-index:3;pointer-events:none}
html .bucket .bk-cards{position:absolute;inset:0;z-index:2;overflow:hidden}
html .bcard{position:absolute;left:11%;top:2.5%;width:78%;height:19%;box-sizing:border-box;
  display:flex;align-items:center;gap:calc(var(--bw) * .026);
  padding-left:calc(var(--bw) * .016);padding-right:calc(var(--bw) * .04);
  background:#1b1b1b;border:1px solid rgba(255,255,255,.26);border-radius:999px;
  box-shadow:0 calc(var(--bw)*.014) calc(var(--bw)*.045) rgba(0,0,0,.55);opacity:0}
/* ten questions, 1.8s apart (round six: a third faster than the 2.6s of round five): the loop is
   18s and the animation starts only once the box is in view */
html .bucket.on .bcard{animation:bkcard 18s linear infinite;animation-delay:calc(var(--i) * 1.8s)}
html .bcard .ic{flex:none;width:calc(var(--bw) * .0837);height:calc(var(--bw) * .0837);border-radius:50%;
  background:#262626;display:flex;align-items:center;justify-content:center;color:#e8e8e8}
html .bcard .ic svg{width:58%;height:58%;display:block}
html .bcard .ic svg [fill]:not([fill="none"]){fill:currentColor}
html .bcard .ic svg [stroke]{stroke:currentColor}
html .bcard .tx{min-width:0;line-height:1.28;text-align:left}
html .bcard .tt{display:block;color:#fafafa;font-weight:700;font-size:max(14px,calc(var(--bw) * .032));letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
html .bcard .ss{display:block;color:#a8a8a8;font-weight:400;font-size:max(12px,calc(var(--bw) * .026));white-space:nowrap}
@keyframes bkcard{
  0%    {opacity:0;transform:translateY(-58%) scale(.94)}
  2.8%  {opacity:1;transform:translateY(0) scale(1)}
  7.6%  {opacity:1;transform:translateY(0) scale(1)}
  10%   {opacity:0;transform:translateY(230%) scale(.97)}
  100%  {opacity:0;transform:translateY(230%) scale(.97)}
}
html #analyze .an-n{display:inline-block;font-variant-numeric:tabular-nums}
/* round ten: the brand on the box lights up white as each question drops in and fades back - one
   drop every 1.8s, the drop itself at 1.37-1.8s of a card's cycle, so the flash runs on the same
   clock, 1.5s behind the first card */
html .bucket.on .bk-brand text,html .bucket.on .bk-brand rect{animation:bkflash 1.8s linear infinite;animation-delay:1.5s}
@keyframes bkflash{0%{fill:#fff}8%{fill:#fff}45%{fill:#9c9c9c}100%{fill:#9c9c9c}}
html .bucket .bk-brand{font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;letter-spacing:-.01em}
@media (prefers-reduced-motion:reduce){
  html .bucket.on .bk-brand text,html .bucket.on .bk-brand rect{animation:none}
  html .bucket.on .bcard{animation:none;opacity:0}
  html .bucket.on .bcard[style*="--i:0"]{opacity:1}
}
@media (max-width:640px){
  html #analyze{padding-top:24px;padding-bottom:24px}
  html #analyze > .wrap > .lead{display:none}
  html .bucket{--bw:340px}
  html #analyze .an-stage{margin-top:18px}
}
@media (max-width:360px){html .bucket{--bw:300px}}

/* ---- pricing cards (Sergey, rounds four to six): each card with its own outline. On a PHONE -
   narrow AND no taller than 1000px; a tall narrow desktop window gets the plain column, because
   the sticky track left a screen of nothing under the card there (round six) - the three follow
   the scroll exactly like the step cards: the plans block is a track three screens tall, the
   yearly switch pinned at the top, the deck pinned under it. Round six: the buttons are white
   with black text on every card and narrower than the card; the deck arrives leaning back and
   straightens as it rises (--pz-in, written by the block's script: 0 with the deck's top at half
   the screen, 1 at 12% - the 21st.dev "container scroll" in plain CSS). ---- */
html #pricing .pz-swipe{display:none}
html #pricing .pz-build h2{font-size:clamp(40px,5.6vw,76px);line-height:1.06;letter-spacing:-.035em;font-weight:800;margin:0 0 12px}
html #pricing .pz-bhead{max-width:none}   /* round nine: the heading may run the width of the wrap; the lead keeps a measure */
html #pricing .pz-blead{max-width:52ch;margin-left:auto;margin-right:auto}
html #pricing .pz-card .btn,html #pricing .pz-card .btn.ghost,html #pricing .pz-out .btn{width:auto;min-width:72%;max-width:100%;
  align-self:center;margin-left:auto;margin-right:auto;padding-left:28px;padding-right:28px;
  background:#fff;color:#0c1020;border-color:#fff}
html #pricing .pz-card .btn:hover,html #pricing .pz-out .btn:hover{background:#e9edf3;border-color:#e9edf3;color:#0c1020}
html #pricing .pz-plans{--pz-in:1}
/* how much room the pinned free-scan bar takes above a pricing deck: 60px where the bar can come up,
   nothing on /pricing/, which never shows it (round eleven) and is told apart by its missing head stop */
html #pricing{--pzbar:60px}
html #pricing:not(:has(.pz-hstop)){--pzbar:0px}
@media (max-width:640px){
  html #pricing .pz-build h2{font-size:clamp(36px,10.4vw,47px)}
  html #pricing .pz-card{border-width:2px;border-radius:18px}
  html #pricing #plan-free{border-color:#6b7789}
  html #pricing #plan-report{border-color:var(--accent)}
  html #pricing #plan-monitoring{border-color:var(--ok)}
  html #pricing .pz-card .btn{margin-top:auto}
}
/* the plan cards' titles: a real heading on each (round nine: "the titles do not read") */
html #pricing .pz-name{font-size:24px;letter-spacing:-.025em;text-transform:none;font-weight:800;color:var(--ink);margin:0 0 12px;line-height:1.1}
html #pricing .pz-pop .pz-name{color:var(--ink)}
/* round eight: the stack on every narrow screen again (his tall narrow window included - round six
   had switched it off there because the card sat at the top with a screen of nothing under it);
   the card now sits in the MIDDLE of the pinned deck, like a step card in its sticky viewport, and
   is taller (68svh, up to 600px). First the deck arrives leaning and straightens (--pz-in), then
   the cards take each other's place along the track. Round nine: every card leans in the same way
   when it takes its turn (from lying back to upright), a snap stop per card makes one swipe show
   exactly one card, and the done-for-you block is a second track of two cards (.pz-two). */
@media (max-width:640px){
  html #pricing .pz-swipe{display:block;text-align:center;font-size:14px;color:var(--muted);margin:0 0 6px}
  /* round eleven (Sergey: "a scroll skips past a card on /pricing/"): measured, a fling could end anywhere
     in the last third of a track (the card pinned, nothing changing) and the section itself, taller than
     the screen, was a snap area of its own - inside it any position counted as snapped, so nothing pulled
     the page onto a stop. Now a track is exactly as long as its stops (one stop spacing per card change,
     the last card pinned until the next block begins), the stops are the only snap points in the block,
     and a page that lands on a card holds for a moment like every other screen. */
  html #pricing .pz-plans{--pzs:66.7vh;--pzs:66.7svh;position:relative;height:calc(100vh + 2 * var(--pzs));height:calc(100svh + 2 * var(--pzs))}
  html #pricing .pz-plans.pz-two{height:calc(100vh + var(--pzs));height:calc(100svh + var(--pzs))}
  /* one card: the deck alone is the track, so the block is one screen and the gap to the next
     block's first stop stays a normal one (a full extra screen here left a swipe short of it) */
  html #pricing .pz-plans.pz-one{height:auto}
  html #pricing .pz-stop{position:absolute;left:0;width:1px;height:1px;top:calc(var(--k) * var(--pzs));scroll-snap-align:start;scroll-snap-stop:always}
  html #pricing{position:relative}
  html #pricing .pz-hstop{position:absolute;left:0;top:0;width:1px;height:1px;scroll-snap-align:start;scroll-snap-stop:always}   /* a hub: the block's heading is a stop of its own */
  html #pricing:has(.pz-hstop) .pz-report{padding-top:68px}   /* ...and its eyebrow clears the pinned bar (59px) there; /pricing/ has neither the stop nor the bar */
  html #pricing .pz-cards{position:sticky;top:var(--pzbar);display:block;height:calc(100vh - var(--pzbar) - 8px);height:calc(100svh - var(--pzbar) - 8px);margin:0;padding:0;
    transform-origin:50% 50%}
  /* round twelve (Sergey's screenshot: at the foot of /pricing/ the heading and the button drew over
     the card's own text): the card is as tall as what is in it and sits in the middle of the deck -
     it was a fixed 68svh box, and the tallest card's content ran out of it. */
  html #pricing .pz-card{position:absolute;left:0;right:0;top:0;bottom:0;height:-moz-fit-content;height:fit-content;max-height:100%;margin:auto 0;min-height:0;
    box-sizing:border-box;opacity:0;pointer-events:none;transform-origin:50% 100%;
    transform:perspective(1100px) rotateX(18deg) translateY(14%) scale(.94);transition:transform 1.24s cubic-bezier(.2,.72,.28,1),opacity .9s ease}
  html #pricing .pz-card.is-cur{opacity:1;transform:none;pointer-events:auto}
  html #pricing .pz-card.is-past{opacity:0;transform:translateY(-10%) scale(.94)}
}
html #pricing .pz-stop,html #pricing .pz-hstop,html #pricing .pz-endstop,html #pricing .pz-bstop{display:none}
/* round sixteen: after the last card's stop a hub's pricing block still runs a screen and a half - the
   deck scrolling away plus the section's tail - and the next snap point is #mechanism. Under mandatory
   snapping that gap is a dead end (measured on /med-spa/ at 375x667: 58 wheels, no movement at
   11,959px). This is the point that splits it, one screen above the block's own end. */
html #pricing{position:relative}
/* ...and the heading of the site-work block is a stop of its own. The block's inner stops sit inside
   its DECK, so its heading - 237px at 375x667 - had no snap position at all, and from the far edge of
   the monitoring block the next one was 904px away, a screen and a third: measured on /dentists/ at
   375x667, eight flings, no movement at 10,383px. */
@media (max-width:640px){
  html #pricing .pz-build{position:relative}
  html #pricing .pz-bstop{display:block;position:absolute;left:0;top:0;width:1px;height:1px;
    scroll-snap-align:start;scroll-snap-stop:always}
  html #pricing .pz-stop,html #pricing .pz-hstop{display:block}
  html #pricing:not(.pz-scenes) .pz-endstop{display:block;position:absolute;left:0;bottom:0;width:1px;height:1px;
    scroll-snap-align:end;scroll-snap-stop:normal}
}
@media (max-width:640px),(min-width:961px){
  html #pricing .pz-cards{transform:perspective(1100px) rotateX(calc((1 - var(--pz-in)) * 20deg)) scale(calc(.92 + var(--pz-in) * .08))
    translateY(calc((1 - var(--pz-in)) * 48px))}
}
@media (prefers-reduced-motion:reduce){html #pricing .pz-card{transition:none} html #pricing .pz-cards{transform:none}}

/* ---- round fourteen (Sergey, 2026-09-06): /pricing/ is three cinematic screens, not three stacked
   decks. Each screen reads its heading first; scrolling takes the heading back the way the home
   page's hero leaves, and a coloured plate rises out of the black with that screen's cards on it -
   blue for the report, green for monitoring, purple for the site work, the last one the plate the
   form already stands on. build_pricing.py wraps the three blocks (.pzs) and adds .pz-scenes to
   the section; the block's own script stands down where that class is, and the driver below writes
   --h (the heading leaving), --cd (the plate rising) and --ct (the cards arriving).

   The layout here is the one a page gets with no script at all: heading, then the plate with the
   cards on it, in flow. The scroll-driven scene is added on top of it, on a wide screen, only once
   the driver has taken over (.pzs-live) - so a phone, an old browser and prefers-reduced-motion
   all get the same readable page, and nothing can leave a screen blank. ---- */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes{--cs-ground:#0A0A0A;background:var(--cs-ground);padding:0;min-height:0;display:block}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes > .wrap{width:auto;max-width:none;padding:0;display:block}
/* Round fifteen (Sergey): "the black monitoring screen slips past - we are supposed to land on the
   next screen and brake there until the next scroll." Two attempts are recorded here because the
   second one shipped and then turned out to be worse than the problem.

   Attempt one: a 1px snap stop at the top of each track with the scene itself no longer a snap area.
   MEASURED at 1280x800: twelve 400px wheels moved the page from 1 to 1 - mandatory snapping with the
   next allowed position 2,400px away refuses to move at all.

   Attempt two (round fifteen, shipped): the scene keeps its oversized area and gains a snap area
   exactly one screen tall at its top, so the page lands on the heading. That worked at his window
   size and FROZE the page above it. MEASURED at 1280x1000, 1280x1080 and 768x1024: six wheel bursts
   of 1,200px each moved /pricing/ from 56 to 56, six times - because an area exactly as tall as the
   viewport has exactly one valid resting position, and it fought the oversized area around it.
   Below 900px of viewport the same page scrolled normally, which is why a laptop never showed it.

   What ships: no snap trickery at all. The scene is an ordinary oversized snap area - free to scroll
   inside, snapping to its top on the way in - and the LANDING is theme-js's job: a scene that arrives
   is seated at its top and the page is parked there for a beat, the same brake the step cards and the
   verdict use. The stop below is only the marker that names that top. */
/* Round seventeen: a scene is a TRACK, not a screen - three viewports of animation on a wide window,
   two stacked screens on a phone. It carried an alignment of its own from the snapping years, and as
   one area three screens tall it swallowed both of its own rests: every position inside it read as
   seated, so the seat had nothing to do on /pricing/ (measured at 1440x900: fourteen rests, eleven of
   them anywhere at all). The rests are named one by one below. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs{--h:0;--cd:1;--ct:1;position:relative;padding:0;min-height:0;display:block;
  scroll-snap-align:none}
/* the phone's two screens ARE the rests (the head screen and the plate screen) */
@media (max-width:760px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head{scroll-snap-align:start;scroll-snap-stop:always}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body{scroll-snap-align:start;scroll-snap-stop:always}
  /* the FIRST screen is the one the page opens on, with the header standing above it in the flow
     rather than over it - so it carries no allowance for the header (Sergey's screenshot at 375x667:
     the heading sat a third of a screen too low) */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs:first-of-type .pzs-head{padding-top:18px;min-height:calc(100vh - var(--hdr,72px));min-height:calc(100svh - var(--hdr,72px))}
}
/* ...and on a wide window the scene is one long shot with two places worth standing in: the heading,
   at the top of the track, and the moment the plate and its cards have fully arrived on it. The
   second one is a marker, because it is a phase of the animation and not a box on the page: --ct
   finishes at p = .80 of a track that runs 200vh, so it stands 164vh below the track's top. */
@media (min-width:761px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-track{scroll-snap-align:none}
  /* the heading, at the top of the track... */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-stop{top:0;bottom:auto;scroll-snap-align:start;scroll-snap-stop:always}
  /* ...and the moment the plate and its cards have arrived on it */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-seat{display:block;position:absolute;left:0;top:164vh;top:164svh;
    width:1px;height:1px;pointer-events:none;scroll-snap-align:start;scroll-snap-stop:always}
}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-seat{display:none}
/* ...and the marker earns its keep by standing in the hole. A scene three screens tall is a snap area
   whose resting range ends one screen before the scene does, so between two scenes there is exactly
   one screen with no resting position in it. Under mandatory snapping that hole is crossed by a
   gesture that gets past its middle and refused by one that does not - measured at 768x1024, a
   1,200px wheel burst oscillated between 5,176 and 5,574 and fell back, over and over. This point
   sits in the middle of the hole, so each half is half a screen. */
/* the hole-splitter of round sixteen: it existed because mandatory snapping could refuse to cross a
   gap. Nothing refuses now, and a rest in the middle of a scene's tail is a rest on nothing, so it
   keeps its box and gives up its alignment. */
/* Round nineteen (Sergey: "from the header, Pricing lands me at the END of the pricing page"):
   before the scene driver has run there was no rest anywhere near the top of /pricing/ - the
   scene's rests only exist once it is live - and the only aligned thing on the page was the footer,
   so the browser's first snap took the page to it. The heading's rest is there from the first
   paint, at every width. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-stop{position:absolute;left:0;top:0;width:1px;height:1px;
  pointer-events:none;scroll-snap-align:start;scroll-snap-stop:always}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-track{position:relative;height:auto}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-stage{position:static;height:auto;display:block;padding:0}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head{position:static;width:auto;max-width:min(92vw,900px);margin:0 auto;text-align:center;
  min-height:100vh;min-height:100svh;display:flex;flex-direction:column;justify-content:center;
  padding:calc(var(--hdr,56px) + 18px) 0 18px;box-sizing:border-box;   /* the header's allowance at the top: the sticky header covers the first 56-72px of a screen that has snapped in */
  transform:none;opacity:1;filter:none;pointer-events:none}
/* ...and the last line has room for its own descenders. background-clip:text paints only the glyph
   boxes, so a line box tight enough to cut a g cuts it from the picture as well as from the layout -
   Sergey's screenshot of "how far to go." on the blue screen. 1.12 and a hair of padding is the fix;
   the tracking keeps the block reading as one. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head h1,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head h2{font-weight:800;font-size:clamp(34px,6vw,72px);
  line-height:1.12;padding-bottom:.06em;letter-spacing:-.035em;margin:0 auto;max-width:16ch;
  background-image:linear-gradient(180deg,#FAFAFA 0%,rgba(250,250,250,.42) 100%);-webkit-background-clip:text;background-clip:text;color:transparent}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head .eyebrow{color:#7c8798;margin-bottom:14px}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head .lead,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head .pz-blead{color:#A1A1AA;margin:22px auto 0;
  max-width:52ch;font-size:clamp(15px,1.6vw,19px);line-height:1.5}
/* Round seventeen (Sergey, 2026-09-07): "on the home page the black heading is one whole screen,
   you scroll, the animation runs, and the coloured plate is the next whole screen - /pricing/ has
   the heading and the plate stuck together on one screen instead." So on a phone each scene is two
   screens, exactly like #scan on the home page: a section one viewport tall, its content centred,
   with the plate standing inside it and black around its edges. The plate is sized by the FRAME
   now, not by the body - the body is the screen, the frame is what the plate covers. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body{position:relative;width:auto;margin:0;display:grid;place-items:center;
  min-height:100vh;min-height:100svh;padding:calc(var(--hdr,56px) + 18px) 4vw 18px;box-sizing:border-box}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-frame{position:relative;width:min(92vw,1064px);max-width:100%}
@media (max-width:760px){
  /* Round twenty (Sergey, three screenshots at 375x667): the plates did not fit the screen and sat
     under a block of black. Measured: blue 1,088px, green 795, purple 747 on a 667px screen, with
     90px of header allowance above each - and on /pricing/ the header hides as you scroll, so that
     allowance was black. A plate is one screen here: the allowance goes, the caption keeps its
     kicker and heading and gives up its line, the card gives up its footnote and tightens, and in a
     two-card scene the SECOND card - the free scan, which every page's form already offers; the new
     site, which is a quote - is a row: name, price, button, no list. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body{padding-top:12px;padding-bottom:12px;align-content:center}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap p:not(.eyebrow){display:none}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-badge{display:none}   /* it sat across the card's name once the card was tight */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap{margin-bottom:12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap .eyebrow{margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h2,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h3{font-size:clamp(22px,6.4vw,28px);line-height:1.1;max-width:22ch}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body .pzs-deck{padding:12px 10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card{padding:14px 14px 12px;gap:0;justify-content:flex-start}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-cards{display:grid;gap:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-fine{display:none}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-name{font-size:19px;margin-bottom:4px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-price{margin:2px 0}
  /* the price LINE carries the size now (both figures are 1em of it), and on a phone it keeps the
     line box the number used to give it - the one plate size is measured off it. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-price{font-size:32px;line-height:1.1}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-cycle{margin:2px 0 8px;font-size:11px}
  /* round forty-nine (Sergey, the purple card on his phone: "the lines are squeezed - there is room
     above and below the card, give the description more air"): 1.25 -> 1.45 and a wider gap */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat{gap:8px;margin-bottom:10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat li,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat span{font-size:13.5px;line-height:1.5}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat svg{width:14px;height:14px;margin-top:2px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-price{margin:0}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-cycle{margin:0 0 6px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-billing{margin:0 0 10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .btn{padding:10px 14px;font-size:15px;margin-top:6px}
  /* Round twenty-one (Sergey, two screenshots at 375x667): "you put two cards on one screen - I do
     not want that. One card per screen: the plate rises with the first card, you scroll, the plate
     rises again and the second card is on it." So round twenty's row-shaped second card is a whole
     card again - it has a screen of its own now - and the extra screen is built by the scene driver
     (pzScenes: split), not written into the page: one card, one price, one id, moved onto a plate
     of its own on a phone and moved back onto the shared plate on a wide window. */
  /* ...and every plate is the green one's size - almost the whole screen (Sergey, the green plate
     beside the blue one: "the blue plate must be the same size as the green, almost the full
     screen"). The frame is a screen less its margins, whatever stands on it, and what stands on it
     is centred with more air between the heading and the card. min-height, not height: a plate
     whose content outgrows the screen grows with it rather than clipping it. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-frame{min-height:var(--plate-h);display:flex;flex-direction:column;justify-content:flex-start}
  /* ...and the same places on every plate (Sergey, the three side by side): the heading stands at
     the top of the plate on all five, and the card is centred in what is left - the same air
     between the heading and the card as between the card and the plate's end. (He first asked for
     the buttons on one line too, then took that back: "the headings on one level, the cards
     centred so the distance to the heading above and to the plate's end below is the same".) */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body .pzs-deck{flex:1;display:flex;flex-direction:column}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body .pzs-cap{margin-bottom:12px}   /* the deck's foot is 12px too, so the two gaps around the card are equal; .pzs-body because the caption's own margin rule below has the same weight and comes later */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap .eyebrow{margin-bottom:12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body .pz-billing{margin:0 0 12px}   /* the yearly switch is part of the heading block: the same 12px under it */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body .pz-plans{margin-top:auto;margin-bottom:auto}
}
/* round fifteen: the phone arrival is the home page's order - the coloured plate first, the card on it
   after - and it moves in pixels, not in screens. It used to rise 20vh, which on a 667px phone put the
   glass deck 133px lower than its own box: over the footer, which then showed through it (his screenshot
   at 375x667). The travel is now shorter than the padding it starts inside, so nothing can leave the box. */
/* background-clip: the background painted under the translucent border while the inset bottom
   shadow darkened only what is inside it, leaving a light hairline along the two bottom corners
   (Sergey saw it on the turquoise plate, where the contrast is highest; it is the same plate). */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-plate{position:absolute;inset:0;display:block;border-radius:32px;border:1px solid rgba(255,255,255,.04);background-clip:padding-box;
  box-shadow:0 40px 100px -20px rgba(0,0,0,.9),0 20px 40px -20px rgba(0,0,0,.8),inset 0 1px 2px rgba(255,255,255,.2),inset 0 -2px 4px rgba(0,0,0,.8);
  transform:translate3d(0,calc((1 - var(--cd)) * 26px),0) scale(calc(.955 + var(--cd) * .045));opacity:var(--cd);
  /* Round twenty-eight (Sergey, 2026-09-07): "take that screen as the absolute reference - black, a
     pause, then the purple ground, then what stands on it. Repeat exactly those pauses everywhere,
     desktop and mobile." These are #scan's own numbers, to the hundredth. */
  transition:transform 1.4s cubic-bezier(.2,.72,.28,1),opacity 1.1s ease}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-deck{position:relative;padding:clamp(24px,4vw,46px);
  transform:translate3d(0,calc((1 - var(--ct)) * 22px),0);opacity:var(--ct);
  transition:transform 1.05s cubic-bezier(.2,.72,.28,1) .5s,opacity .8s ease .5s}
/* round fifteen (Sergey, 2026-09-06): every plate says what it is, the way the purple one under the
   form does - a kicker, a heading and one explaining line above the cards. */
/* round sixteen (Sergey, 2026-09-06): "you did not reproduce the same sizes for the heading and the
   hint on the coloured plates." Measured on the purple plate under the form, which is the reference:
   eyebrow 13px uppercase at .09em, heading clamp(40px,5.6vw,76px) at 800 and -.035em, lead 19px.
   Those are the numbers below. The kicker and the lead are centred at every width - a phone rule
   (html #pricing p{text-align:left}) was pulling them to the left edge. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap{text-align:center;max-width:none;margin:0 auto clamp(22px,3vw,34px)}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap .eyebrow,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap p{text-align:center}
/* Round eighteen (Sergey, 2026-09-07): "REPORT at the top is not centred - and it is not the only
   place." The kicker is a <p>, so the caption's own paragraph rule (max-width:56ch) was sizing its
   box to 459px inside a 920px column, and margin:0 0 14px pinned that box to the left edge. The text
   was centred inside a box that was not. Auto side margins centre the box. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap .eyebrow{color:rgba(255,255,255,.66);margin:0 auto 14px;font-size:13px;
  letter-spacing:.09em;text-transform:uppercase;font-weight:400}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h2,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h3{margin:0 auto;color:#fff;
  font-weight:800;letter-spacing:-.035em;line-height:1.06;max-width:19ch;
  /* the reference's scale, held back by the height as well: his headings run to three lines where the
     home page's runs to one, and a screen has to hold the heading, the line under it and the cards */
  font-size:clamp(28px,min(4.6vw,5.2vh),62px)}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap p{margin:16px auto 0;max-width:56ch;color:rgba(255,255,255,.78);
  font-size:clamp(15px,min(1.5vw,2.1vh),19px);line-height:1.5}
/* background-IMAGE, not the background shorthand: the shorthand resets background-clip, and the
   plate above sets it to padding-box so the gradient stops at the border instead of showing
   through it (that hairline is what Sergey saw at the plate's two bottom corners). */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-blue .pzs-plate{background-image:linear-gradient(145deg,#162C6D 0%,#0A101D 100%)}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-green .pzs-plate{background-image:linear-gradient(145deg,#0B5B3A 0%,#07160F 100%)}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-purple .pzs-plate{background-image:linear-gradient(145deg,#3D1178 0%,#150A20 100%)}
/* the fourth plate colour (the badge pages, 2026-09-08): teal, at the same angle as the other three */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-teal .pzs-plate{background-image:linear-gradient(145deg,#0B5B5B 0%,#07161A 100%)}
/* the deck machinery of a hub's block has no part here: no track, no sticky deck, no lean, no stops */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-plans{position:static;height:auto;--pz-in:1}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-cards{position:static;height:auto;transform:none;margin:0;padding:0;overflow:visible}
/* ...the hub's phone rule for the site-work and monitoring decks (a sticky deck the height of the
   screen minus its heading) outranks the line above by coming later, and was giving the scene's
   cards a 509px box to stretch into - 56px of empty card under the button on the purple plate
   (round twenty, measured at 375x667) */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-build .pz-cards,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-mon .pz-cards{position:static;height:auto;top:auto;transform:none}
/* relative, not static: the "Where most start" badge is absolutely placed on its card's corner, and a
   static card is not a containing block - the badge escaped to the plate and floated in its top right
   (round fourteen put position:static here to undo the phone rule; relative undoes it just as well) */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card{position:relative;opacity:1;transform:none;pointer-events:auto;max-height:none;margin:0;height:auto;min-height:0}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-swipe,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-stop,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-hstop{display:none}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-report,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-mon,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-build{
  min-height:0;display:block;margin:0;border:0;border-radius:0;background:none;padding:0;
  /* these three ARE the scenes, and a scene is a track, not a screen. Aligned - which is what round
     eleven's lesson asked for while the browser did the holding - the track counted as seated at
     every position inside itself, and the rests inside it (the heading, the plate) could never be
     reached: measured at 1440x900, eleven of fourteen rests landed nowhere in particular. */
  scroll-snap-align:none}
/* the cards stand on a coloured plate now, so they are glass on it, not paper on paper */
/* Round sixteen (Sergey, his screenshot at 375x667 again): the deck was still being drawn OVER the
   footer on a phone. Round fifteen measured the geometry and found it clean - the deck's bottom
   never passed the section's - and that measurement was right, because nothing was mis-positioned:
   backdrop-filter was PAINTING it there. A blurred backdrop samples whatever is behind the element,
   and on a card that is also a moving, will-change'd compositing layer the sample it gets can be a
   different part of the page - here, the footer, which then showed through the glass. The plate
   underneath already gives the card its colour, so the card is a solid translucent panel now: no
   backdrop to sample, nothing to mis-sample, and one less expensive layer per card on a phone. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card{border:1px solid rgba(255,255,255,.14);border-radius:20px;
  background:rgba(255,255,255,.07);-webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:0 25px 50px -12px rgba(0,0,0,.55),inset 0 1px 1px rgba(255,255,255,.16);color:#E2E8F0}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card.pz-pop{border-color:rgba(147,197,253,.5);background:rgba(59,130,246,.16)}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-name,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-per,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-cycle,
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-fine,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .note{color:#A1A1AA}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-num,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-pop .pz-num{color:#FAFAFA}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat li{color:#E2E8F0}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-blue .pz-feat svg{stroke:#93C5FD}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-pop .pz-name{color:#93C5FD}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-green .pz-feat svg{stroke:#6EE7B7}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-purple .pz-feat svg{stroke:#C4B5FD}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-teal .pz-feat svg{stroke:#7DD3D8}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-badge{background:#3B82F6;color:#fff}
/* a phone rule (html #pricing p{text-align:left}) was leaving the card's name and cycle hanging on
   the left while the price above them sat in the middle; on a plate the card reads as one column */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card > p{text-align:center}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-billing{margin:0 0 20px}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-billing label{color:#E2E8F0}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-billing .pz-save{color:#6EE7B7}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-sw{background:rgba(255,255,255,.18)}
/* the yearly switch draws as a 48x28 toggle, which is the whole point of it, so its hit area is
   extended to 44px with a transparent box rather than by growing the thing you see (::after is the
   knob; ::before was free). The audit measured it at 27px, the only control under the site's 44. */
html #pricing .pz-sw{position:relative}
html #pricing .pz-sw::before{content:"";position:absolute;left:-4px;right:-4px;top:-8px;bottom:-8px}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-sw[aria-checked="true"]{background:#34D399}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .btn,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .btn.ghost{background:#fff;color:#0c1020;border-color:#fff}
@media (max-width:760px){
  /* nothing inside a scene is sticky at this width, so the scene can clip - and then a plate or a
     deck cannot be painted outside it whatever the compositor decides. On a wide screen the sticky
     stage already clips, and clipping the track there kills the pin: measured at 1280x800, the
     stage ran to -2,345px instead of holding at 0. */
  /* Round nineteen (Sergey: "on the phone one scroll on /pricing/ goes straight to the bottom"):
     overflow:hidden makes the scene a SCROLL CONTAINER, and every snap area inside it - the two
     screens of each scene - then snaps to the scene, not to the page. On the page there was nothing
     left to snap to but the header and the footer, so a fling from the top went to the footer.
     Measured: scrollTo(900) on /pricing/ at 390x844 came to rest at 0. clip clips without becoming
     a container. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs{overflow:clip}
}
@media (max-width:560px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-deck{padding:20px 14px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-plate{border-radius:26px}
}
/* the scene itself: a wide screen, and only once the driver is running */
@media (min-width:761px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-track{height:300vh;height:calc(300svh / var(--z,1))}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-stage{position:sticky;top:0;height:100vh;height:calc(100svh / var(--z,1));overflow:hidden;
    display:grid;place-items:center;padding:0;background:var(--cs-ground)}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-stage::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.5;
    background-image:linear-gradient(to right,rgba(250,250,250,.05) 1px,transparent 1px),linear-gradient(to bottom,rgba(250,250,250,.05) 1px,transparent 1px);
    background-size:60px 60px,60px 60px;
    -webkit-mask-image:radial-gradient(ellipse 70% 60% at 50% 50%,#000 0%,transparent 75%);mask-image:radial-gradient(ellipse 70% 60% at 50% 50%,#000 0%,transparent 75%)}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-head{position:absolute;z-index:30;margin:0;padding:0 24px;
    transform:translate3d(0,calc(var(--h) * -13vh),0) scale(calc(1 - var(--h) * .16));
    opacity:calc(1 - var(--h));filter:blur(calc(var(--h) * 9px));will-change:transform,opacity,filter}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-body{position:absolute;inset:0;z-index:10;display:grid;place-items:center;
    width:auto;margin:0;min-height:0;padding:0}
  /* Round seventeen (Sergey): the plate filled the window edge to edge - "it should be a plate,
     almost the size of the screen, with its edges showing", the way the purple plate under the form
     does on the home page. The frame is that plate's box: it stretches to whatever stands on it and
     stops short of the window on every side. */
  /* Round eighteen (Sergey, with the blue plate of the first screen beside the pricing one): every
     coloured plate on the site is that plate. Its size is the cinematic card's - width min(1064px,
     92vw), height min(1096px, 84vh) - and the purple plate under the form already carries it. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-frame{position:relative;display:grid;place-items:center;
    width:min(1064px,92vw);height:auto;min-height:var(--plate-h);max-width:92vw}
  /* the plate is the size of what stands on it: the deck defines the grid cell and the plate stretches
     to it, with a floor so a short screen still reads as a plate. Round sixteen: with the caption at
     the reference's size the deck outgrew a fixed 84vh plate, and the kicker and the card hung off
     its top and bottom edges (measured at 1280x900 on the green screen). */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-plate{grid-area:1/1;position:relative;inset:auto;
    justify-self:stretch;align-self:stretch;width:auto;height:auto;
    min-width:0;min-height:0;border-radius:40px;
    transition:transform 1.4s cubic-bezier(.2,.72,.28,1),opacity 1.1s ease;will-change:transform,opacity;
    transform:translate3d(0,calc((1 - var(--cd)) * 26vh),0) scale(calc(.92 + var(--cd) * .08))}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-deck{grid-area:1/1;position:relative;width:100%;max-width:min(1000px,86vw);
    padding:clamp(26px,4vh,52px) clamp(16px,3vw,40px);transition:transform 1.05s cubic-bezier(.2,.72,.28,1) .5s,opacity .8s ease .5s;will-change:transform,opacity;
    transform:translate3d(0,calc((1 - var(--ct)) * 22px),0)}
  /* round forty-seven: leaving a scene upward, the plate and what stands on it go in a third of a
     second, so the heading never shows through them (the arrival keeps its own long transitions) */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-away .pzs-plate{transition:transform .3s ease-in,opacity .25s ease-in}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-away .pzs-deck{transition:transform .3s ease-in,opacity .2s ease-in}
  /* Round twenty-two (Sergey, 2026-09-07, the pricing card beside the referral one: "the headings
     on /pricing/ start at one level and on /referral/ at another"). Measured at 1280x800 with the
     arrival transforms neutralised: the plate is the frame - 672px - and a deck SHORTER than it was
     centred inside it by the frame's place-items, so the kicker sat 105/153/95px from the plate's
     top on /referral/ against 34-58px on /pricing/, whose decks happen to fill their plates. The
     deck now stretches to the plate on a wide screen exactly as it already does on a phone: the
     caption is pinned to the top on every plate of both pages, and the block under it takes the
     room that is left with the same air above it as below (auto margins), which is the rule Sergey
     set for the phone in round twenty-one. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-deck{align-self:stretch;
    display:flex;flex-direction:column;justify-content:flex-start;box-sizing:border-box}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-cap{flex:0 0 auto}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-billing{flex:0 0 auto}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-plans{margin-top:auto;margin-bottom:auto}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-two .pz-cards{max-width:820px;margin:0 auto}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-card{padding:24px 22px 20px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-price{font-size:40px}
}
/* a short wide screen - a laptop at 1024x768, a 1280x800 - has to hold the same heading, the same line
   and the same cards on one screen. Measured before this: the monitoring deck was 777px inside a 768px
   window, so its plate hung off the bottom. The card gives up the room, never the caption. */
/* Round twenty-seven (Sergey, 2026-09-07, his screenshots at 1663x852 and 819x851 - he browses
   at 150% zoom, which makes his viewport 852 CSS pixels tall): this block missed his window by
   eleven pixels, so the tightening a short screen needs never applied and the monitoring deck
   stood 167px taller than its plate. Measured at 1663x852, 1440x900, 1280x800, 1024x768. */
@media (min-width:761px) and (max-height:900px){
  /* the plate takes more of a short screen - the room has to come from somewhere, and black
     margin is the cheapest thing on it (measured: the monitoring deck needed 100px at 1280x800) */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-frame{height:auto;min-height:var(--plate-h)}
  /* the stage centres the plate in the whole window, so a taller plate slid under the sticky
     header (measured: its top edge at 34px with a 65px header). The header's room comes off
     the top of the stage, and the plate centres in what is left. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-body{padding-top:var(--hdr,55px);box-sizing:border-box}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-cap{margin-bottom:14px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-billing{margin-bottom:10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat{gap:6px;margin-bottom:10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .note,
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .pz-fine{margin-top:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-deck{padding-top:12px;padding-bottom:12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-cap{margin-bottom:14px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-cap p{margin-top:10px}
  /* Round fifty-one (Sergey, 2026-09-09): the heading was held to 19ch on a plate with room for
     thirty, so it broke to three lines and pushed the monitoring plate 76px past the one plate size
     (measured at 1280x800: 709px against the token's 633). It uses the width it has on a short
     screen; the type keeps its size, which is his rule of round twenty-seven. */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h2,
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h3{max-width:30ch}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap .eyebrow{margin-bottom:10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-card{padding:18px 18px 16px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-price{font-size:34px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-name{font-size:20px;margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-cycle{margin:6px 0 12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-feat{gap:8px;margin-bottom:14px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-billing{margin-bottom:10px}
}
/* Round fifty-one: the same room at every desktop height. The rule above lived inside the
   short-screen block, so a tall window (1710x975, 1920x1000 measured) centred the plate in the
   WHOLE window and the sticky header covered its first 16px. */
@media (min-width:761px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-body{padding-top:var(--hdr,55px);box-sizing:border-box}
}
/* a 320x568 phone (an iPhone SE of the first kind) is the smallest screen we test, and a plate
   there ran 55px past its screen. The room comes from padding and from the price, never from a
   feature line - measured 2026-09-07 on /pricing/, /referral/ and /r/. */
/* Round thirty: the free-scan screen on a small phone. Measured on a hub at 375x667 the section
   stood 688px in a 667px screen and at 320x568 it stood 722 - the heading block and the card each
   give a little, and the promise line under the button is never what goes. */
@media (max-width:760px) and (max-height:700px){
  html #scan > .wrap.sec-head > h2{font-size:clamp(26px,7.4vw,32px)}
  html #scan > .wrap.sec-head > .lead{margin-bottom:6px;font-size:14px}
  html #scan > .wrap.grid2{margin-top:6px}
  html #scan .form{padding:14px 12px}
  html #scan .form .fx-logo{margin-bottom:6px}
  html #scan .form > .note{margin-bottom:8px}
  html #scan .form .fx-field{margin-bottom:8px}
}
@media (max-width:360px){
  html #scan .form{zoom:.94}
}
/* a 320x568 phone: the smallest screen we test. The heading keeps its words and gives up its
   size, the card is drawn a tenth smaller - nothing is cut, and the promise line stays. */
@media (max-width:760px) and (max-height:600px){
  html #scan > .wrap.sec-head > h2{font-size:24px}
  html #scan > .wrap.sec-head > .eyebrow{margin-bottom:4px}
  html #scan > .wrap.sec-head > .lead{display:none}
  html #scan .form{zoom:.88;padding:12px 10px}
}
@media (max-width:360px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body .pzs-deck{padding:6px 8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-frame{min-height:var(--plate-h)}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-body .pzs-cap{margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap .eyebrow{margin-bottom:6px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card{padding:10px 12px 10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-price{font-size:28px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat{gap:8px;margin-bottom:8px}   /* round forty-nine: the same air as wider phones - his 336px layout lands here */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .btn{padding:9px 12px;font-size:14px;margin-top:4px}
  /* ...and a hub carries the same cards outside the scenes, in its own sticky track */
  html #pricing .pz-card{padding:10px 12px 10px}
  html #pricing .pz-price{font-size:28px}
  html #pricing .pz-name{font-size:17px;margin-bottom:2px}
  html #pricing .pz-cycle{margin:0 0 4px}
  html #pricing .pz-feat{gap:3px;margin-bottom:6px}
  html #pricing .pz-card .btn{padding:9px 12px;font-size:14px;margin-top:4px}
}
/* a 1024x768 laptop is shorter still, and the room comes from spacing rather than from type -
   Sergey, 2026-09-07: "keep to this size of type everywhere". Measured: 31px short at 768. */
@media (min-width:761px) and (max-height:820px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-deck{padding-top:12px;padding-bottom:12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-cap{margin-bottom:10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card{padding:14px 16px 12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-cycle{margin:2px 0 6px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat{gap:4px;margin-bottom:6px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .note,
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .pz-fine{margin-top:5px;font-size:12px;line-height:1.4}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-name{margin-bottom:2px}
  /* the last of it, still from spacing: the badge line under the price, the button's own padding
     and the switch's foot (measured at 1280x800: the monitoring plate 651 against the token 633) */
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-bline{margin:-4px 0 10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .btn{padding:10px 16px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-billing{margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-cap p{margin-top:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-frame{height:auto;min-height:var(--plate-h)}
}
/* Round fifty-one (Sergey, 2026-09-09, his MacBook Air screen after unplugging the monitor): the
   scale stopped at 820px of height, and a window ~650px tall was drawn with the 820px values - so
   the monitoring plate stood 683px inside a 652px window: its kicker was cut off under the header
   and the cards' last lines ran past the bottom edge. Measured at 1000x652, 1100x700 and 1180x720.
   The room comes from spacing and from the heading's WIDTH (it was held to 19ch, which put three
   lines where the plate had room for two) - never from a line of copy. */
@media (min-width:761px) and (max-height:780px){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h2,
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap h3{max-width:30ch;font-size:clamp(24px,min(4.6vw,4.6vh),62px)}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap .eyebrow{margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-cap p{margin-top:8px;font-size:clamp(14px,min(1.5vw,2.1vh),19px);line-height:1.45}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-cap{margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pzs-deck{padding-top:10px;padding-bottom:10px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-billing{margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card{padding:14px 16px 12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-card{padding:14px 16px 12px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-name{font-size:19px;margin-bottom:2px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-name{font-size:19px;margin-bottom:2px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-price{font-size:30px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-price{font-size:30px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-cycle{margin:2px 0 6px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-cycle{margin:2px 0 6px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-bline{margin:-2px 0 8px;font-size:12.5px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat{gap:4px;margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes.pzs-live .pz-feat{gap:4px;margin-bottom:8px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-feat li{font-size:14px;line-height:1.4}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .btn{padding:9px 16px;font-size:15px}
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .note,
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pz-card .pz-fine{margin-top:5px;font-size:11.5px;line-height:1.4}
  /* the badge and referral plates carry prose and a card rather than two price cards */
  html :is(#badge,#badgeme) .bd-para{font-size:clamp(14px,min(1.5vw,2vh),19px);line-height:1.5}
  html :is(#badge,#badgeme) .bd-card{padding:16px 16px 14px;gap:10px}
  html :is(#badge,#badgeme) .bd-offer{padding:18px 18px 16px}
  html :is(#badge,#badgeme) .bd-rate{font-size:30px}
  html :is(#badge,#badgeme) .bd-rows{gap:10px}
  html :is(#badge,#badgeme) .bd-note{margin-top:10px;font-size:14px}
  html :is(#badge,#badgeme) .bd-prev{min-height:104px;padding:18px}
}
@media (prefers-reduced-motion:reduce){
  html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-plate,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-deck{transition:none}
}

/* ---- screens (Sergey, 2026-09-05 late evening, round seven): every block of the home page and
   of a hub is one screen - the height of the first two (a full viewport, capped at 900px on tall
   windows, as round three settled), its content centred - and the page snaps from screen to
   screen: scroll and you stop on the next one until you scroll again. Blocks taller than the
   screen (the step track on phones, the plans track, a long desktop block) scroll freely inside
   their area; the footer snaps to the bottom so the page end stays reachable. /pricing/ and a hub's
   pricing block: the plans are the first screen, "Do you want us to do it for you?" the second. ---- */
/* Round seventeen (Sergey, 2026-09-07): "on the desktop the braking is gone - I scroll straight
   through several screens." Round sixteen had taken mandatory snapping off wherever a wheel drives
   the page, because a wheel notch cannot cross a screen and the browser put every notch back; that
   cured the dead ends and cost the seat. Both are the same mistake: asking the BROWSER to hold the
   page while the gesture is still running. So the alignments below stay - they are the map of what
   a screen is, and AICY_SEAT reads them - but nothing snaps while a finger or a wheel is moving.
   The seat happens after the gesture ends, it always moves toward a screen, and any new gesture
   wins over it, so it can brake without ever being able to refuse. */
html.aicy-screens{scroll-snap-type:y mandatory}   /* the home page, a hub, /pricing/, /referral/ - not the reading pages (round forty-six: a class, no root :has()) */
/* Round forty-two (Sergey's fourth trace, iPhone): with the finger held off the page and one native
   smooth scroll per swipe, the only thing still moving the page was WebKit's own snap engine - it
   put a finished smooth scroll back on the point it remembered (3343 after landing on 4028; 4107
   after landing on 5476), and each time snapping was switched back on it re-snapped to a stale
   point. On a touch screen the swipe driver lands on a rest of the page's own map every time, so the
   browser's snapping has nothing to add there and everything to break: it is off. The alignments
   below stay - they ARE the map the driver reads. The desktop keeps mandatory snapping untouched. */
@media (hover:none) and (pointer:coarse){
  html.aicy-screens{scroll-snap-type:none}
  /* Round forty-four: the panning itself is taken from the browser on these pages. Round thirty-nine
     wrote that touch-action on the root does nothing on iOS; every one of the six traces since
     records the root's computed touch-action as 'auto' - the rule below (as html.aicy-swipe, a class
     nothing sets) was never in force on the phone, so that was never measured. The driver already
     prevents every touchmove; what this adds is the one case preventDefault cannot reach - a flick
     so fast (38ms, 63ms in the sixth trace) that WebKit stops waiting for the page and starts its own
     scroll, non-cancelable from then on. If WebKit honours this, that scroll never starts; if it
     ignores it, nothing changes. Pinch-zoom is never taken away; the intake dialog scrolls itself. */
  html.aicy-screens:not(.scan-locked):not(.hq-open){touch-action:pinch-zoom}
  html.aicy-screens:not(.scan-locked):not(.hq-open) body{touch-action:inherit}   /* Safari reads it from the body as well */
  html .fcard-table{touch-action:pan-y}   /* the one box on the site that scrolls inside itself */
}
/* round thirteen (Sergey: "from the bottom of the page a scroll up carries me to the very top by
   itself", and "on a phone the logo at the foot only takes me back to the third step"): the opening
   scene is a scroll TRACK four screens tall, and round eleven's lesson applies to it exactly as it
   applied to the pricing block. Two things were wrong, and only one of them was the alignment.
   scroll-snap-stop:ALWAYS on a track four screens tall says "a scroll may not pass this area
   without stopping in it", so a 200px wheel at the foot of the page was answered by a jump into
   the opening: measured at 1280x900, 8290 -> 1745 -> 0. The track keeps its alignment (an oversized
   area is what lets the scene scroll freely inside it - round eleven) and gives up the forced stop.
   The sticky header gives up its alignment altogether: its box travels with the viewport, so it can
   be "reached" from anywhere on the page. */
/* Round thirty-two (Sergey, 2026-09-08): "I tried hard swipes on the phone and the first screen
   throws me across several screens. That must be forbidden - we agreed: a swipe takes you to the
   screen above or the screen below, depending on which way you swiped. Check that law everywhere,
   not only on the home page."

   Measured at 390x844 with real touch events: rapid flicks left the page at 76 and at 3083 -
   positions no screen owns. AICY_SWIPE calls preventDefault on every touchmove, but that only
   holds while the event is CANCELABLE, and on a quick second flick Chrome has already begun its
   own scroll, so the first moves of the gesture went to the browser and the carry started from
   wherever they had left the page. touch-action takes the gesture away from the browser before it
   can begin, so the swipe driver is the only thing that ever moves the page and one swipe is
   always exactly one screen.

   Set from script, so a page with no scripting still scrolls normally; lifted while the intake
   dialog is up, because that dialog does its own scrolling. Pinch-zoom is never taken away. */
/* (round thirty-nine: the class below is no longer set - the phone's trace showed touch-action on the
   root does nothing on iOS, every touchmove arrives non-cancelable, and the page scrolls natively
   from the first move whatever is declared here. The rules stay for the record.) */
html.aicy-swipe:not(.scan-locked):not(.hq-open){touch-action:pinch-zoom}
html.aicy-swipe body{touch-action:inherit}   /* Safari reads it from the body as well */
/* Round thirty-three (Sergey, 2026-09-08): "the second swipe, the one that grows the red message and
   takes you to the screen with the three cards, does it in a jerk, not smoothly." Traced frame by
   frame at 390x844: the move ran 3050 -> 3600 in even 13-14px steps and then covered the last 844px
   in ONE frame. 3600 is the far edge of the opening scene's own snap area, and under
   scroll-snap-type:mandatory the browser put every scrollTo past that edge back on it - the move and
   the snap engine were pulling against each other for the whole second half, and the jump was the
   final frame landing on a position the browser accepted. A move driven by script already knows
   where it is going and always ends on a screen, so the browser's snapping stands down while one is
   running - the same reason round eighteen took the holding of the page out of the browser's hands
   during a gesture. */
html.aicy-moving{scroll-snap-type:none!important}   /* !important: the rule it must beat was
   html:has(#how){scroll-snap-type:y mandatory}, which carried the id's specificity; it is
   html.aicy-screens now (round forty-six) and the !important simply stays */
html.aicy-swipe .fcard-table{touch-action:pan-y}   /* the one box on the site that scrolls inside itself */
html footer{scroll-snap-align:end}
/* ...but where the header is NOT sticky - every phone - the top of the document has to be a snap
   position of its own, or the first stop below it becomes the highest the page can rest and the
   brand, the menu and the page's own heading cannot be reached again without a reload. */
@media (max-width:820px){html header{scroll-snap-align:start}}
html #evidence,html #how,html #analyze,html #scan,html #mechanism,html #faq,html #closer,
html #pricing:not(.pz-scenes) .pz-report,html #pricing:not(.pz-scenes) .pz-mon,html #pricing:not(.pz-scenes) .pz-build{scroll-snap-align:start;scroll-snap-stop:always;scroll-margin-top:0}
/* ...on /pricing/ those three classes are the SCENES, which are tracks three screens tall - aligned,
   they swallowed their own rests whole (round seventeen, measured at 1440x900) */
html #opening{scroll-snap-align:start;scroll-snap-stop:normal}
/* round fifteen (Sergey's round-fifteen sweep, found by measurement not by report): a hub's #hook is
   1,687px of page with no snap alignment at all, sitting between the opening track and #how. Under
   mandatory snapping that is a dead end: from the far edge of the opening's own area (3,415px at
   1280x800) the next snap position is 2,487px away, and a 500px wheel is answered by a snap back.
   Measured on /dentists/: the page could not be scrolled past 3,415 - fifty-one wheels, no movement,
   on every one of the 46 hub pages. Aligned like every other oversized screen, it scrolls freely. */
html #hook{scroll-snap-align:start;scroll-snap-stop:normal}
@media (max-width:640px){html #pricing .pz-report,html #pricing .pz-mon,html #pricing .pz-build{scroll-snap-align:none;scroll-snap-stop:normal}}   /* round eleven: on a phone the stops inside the block are its only snap points (a section taller than the screen made every position inside it count as snapped) */
/* ...except the monitoring block, which on a phone is not a track: it is one heading and one card,
   as tall as they come out, and its single stop sits at its top. Measured at 390x844 it stands
   1,085px tall - taller than the screen - so the next resting place after its top is the block after
   it, and a fling could not cross the gap (stalled at 12,073px on /dentists/). It has no inner stops
   to protect, so it takes round eleven's other half: an area taller than the screen counts as
   snapped at every position inside it, and the block scrolls through freely. */
@media (max-width:640px){
  html #pricing .pz-mon{scroll-snap-align:start;scroll-snap-stop:always}
  html #pricing .pz-mon .pz-stop{display:none}
}
/* Round sixteen, from the audit, and the other half of Sergey's "it shakes and cannot get through".
   Every window 900px and taller could not be scrolled through the site's screens with a mouse wheel.
   The screens are one viewport each, so consecutive snap positions are one viewport apart, and a
   gesture that does not carry past the halfway point is put back where it started. MEASURED on
   /pricing/: at 1280x800 a 1,200px wheel burst moved the page 878px; at 1280x900, 1280x1000,
   1280x1080 and 768x1024 the same burst moved it nothing at all, six bursts running - and at 768x1024
   the trace shows the page oscillating forward and being pulled back, frame after frame, which is
   what "shakes and cannot get through" looks like from the outside.

   Proximity was tried and is not enough: its threshold is about a viewport, so on a tall screen it
   pulls back too (measured: 5,566 back to 5,380). Half-screen snap points were considered and
   rejected - they would let a screen come to rest halfway, which is the design gone.

   So above the height where it is measured to work, the page simply scrolls. Everything the screens
   do is driven by scroll position and by theme-js, not by snapping: the scenes still seat and brake,
   the step cards still hold for their pictures, the closing sentence still leaves. What is lost on a
   tall window is the crisp screen-to-screen click - and what is gained is a page that moves. */
/* round sixteen's second audit measured that a wheel notch cannot cross a screen under mandatory
   snapping (/dentists/ dead at 5,991px of 12,968 at 1280x800, at 6,493 of 12,542 at 1024x768 and at
   8,548 of 18,043 at 390x844) and lifted the snapping under a fine pointer. Round seventeen lifts it
   everywhere and gives the seat to AICY_SEAT instead, so this rule has nothing left to say. */
html{--screen:min(100vh,900px);--screen:min(100svh,900px)}
html #evidence,html #analyze,html #scan,html #mechanism,html #faq,
html #pricing .pz-report,html #pricing .pz-mon,html #pricing .pz-build{min-height:var(--screen);display:flex;flex-direction:column;justify-content:center;box-sizing:border-box}
/* the cinematic closing block (round eight, patch_closer.py) is a scroll track with a sticky stage; its
   call to action is the last screen. The section itself is not centred or padded. */
html #closer,html #opening{padding:0;min-height:0;display:block}
/* round fourteen (Sergey, 2026-09-06): no rule between the dark screens - the section divider the
   light layout drew there is a bright hairline across a black page */
html #opening,html #closer,html #scan{border-top:0}
/* ---- round twelve (Sergey, 2026-09-06): the cinematic scene is the FIRST screen. The hero is its
   headline - it fades back and the blue card rises out of it, the choreography the closing block
   had, one screen earlier. What is left at the end is the closing sentence as a still screen, and
   the form after it. The six-assistant demo window is hidden, not deleted. ---- */
html #evidence[hidden]{display:none!important}
/* the hero inside the stage: the scene's headline, so it gives up the page-level layout it had */
html #opening .cs-headline.hero{min-height:0;padding:0;width:min(92vw,var(--wrapw,1120px));max-width:none;margin:0;
  padding-left:max(0px,env(safe-area-inset-left));padding-right:max(0px,env(safe-area-inset-right))}
html #opening .cs-headline.hero > div{width:100%}
html #opening .hero .eyebrow,html #opening .hero h1,html #opening .hero .lead,html #opening .hero .hq-box,
html #opening .hero-cta{text-align:center}
html #opening .hero .hq-row{justify-content:center}
html #opening .hero-cta{display:flex;flex-direction:column;align-items:center;gap:12px;margin-top:26px}
html #opening .hero .lead{margin-left:auto;margin-right:auto;max-width:46ch;color:var(--cs-muted)}
/* Round forty-nine (Sergey, the first screen on his monitor: "everything is pressed into the centre -
   there is room above and below; give the blocks a little more air, in proportions, so nothing
   breaks on a phone"). From 821px up the gaps grow with the window's height and stop at a cap;
   below that width the phone keeps its own spacing. */
@media (min-width:821px){
  html #opening .hero .eyebrow{margin-bottom:clamp(8px,2svh,28px)}
  html #opening .hero .hq-box{margin-bottom:clamp(2px,1svh,14px)}
  html #opening .hero .lead{margin-top:clamp(24px,4.2svh,56px)}
  html #opening .hero-cta{margin-top:clamp(28px,4.8svh,64px);gap:clamp(12px,2.2svh,26px)}
}
html #opening .hero .eyebrow{color:var(--cs-dim)}
html #opening .hero .hero-cta .note{color:var(--cs-muted)}
/* the closing screen is still: no track, no sticky stage, the sentence centred on one screen */
/* the closing screen is a short track with a sticky stage, so its sentence has real scroll distance
   to leave over - one screen of reading, one of leaving, then the form */
html #closer .cs-track.cs-shorttrack{position:relative;height:100vh;height:100svh}   /* round fifteen: exactly one screen - see patch_closer.py */
html #closer .cs-stage.cs-still{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:center;padding:64px 24px;box-sizing:border-box}
/* round fourteen (Sergey): the closing sentence must leave the way the hero leaves the first screen -
   the same fade, the same blur, the same drift back. cs-js drives --h from how far this screen has
   scrolled past, exactly as the opening track drives it from its own progress. */
html #closer .cs-still .cs-headline{position:relative;width:min(92vw,900px);margin:0;
  transform:translate3d(0,calc(var(--h,0) * -13vh),0) scale(calc(1 - var(--h,0) * .16));
  opacity:calc(1 - var(--h,0));filter:blur(calc(var(--h,0) * 9px));will-change:transform,opacity,filter}
html #closer .cs-still .cs-h2{margin-left:auto;margin-right:auto}
html #closer .cs-still .cs-hint{opacity:1}
/* round eleven: the honesty caption of the mocks is one footnote in the footer (patch_mobile_blocks part 8) */
html footer .fineprint{flex-basis:100%;margin:6px 0 0;font-size:14px;line-height:1.5;color:var(--muted);max-width:none}
/* round ten: the form (#scan) is the last screen of the page, in the closing scene's place; its button
   is the big white pill he liked there ("Run my free scan") */
html #scan .intake .step1 > .btn{display:block;width:auto;max-width:100%;margin:22px auto 0;border:0;font-weight:700;font-size:clamp(17px,2.2vw,22px);letter-spacing:-.01em;line-height:1.2;
  color:#0f172a;background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);padding:19px 40px;border-radius:20px;box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45);transition:transform .16s ease,filter .16s ease}
html #scan .intake .step1 > .btn:hover{transform:translateY(-2px);filter:brightness(1.04);background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);color:#0f172a}
html #scan .intake .step1 > .btn:active{transform:none}
/* ---- round eleven (Sergey, 2026-09-06): the form card is the 21st.dev "sign-in-card-2" (jatin-yadav05),
   ported to plain CSS and a few lines of script: a black ground with the purple gradient, a grain, a glow
   above and below and two soft spots; a glass card (black at 40% over a blurred backdrop, a hairline, a faint
   diagonal weave) with four light beams travelling along its edges and a spark in each corner, a glow that
   breathes; dark-glass fields with an icon that lights up on focus; the card tilts toward the pointer and
   rises in when the screen arrives. The left column is gone, the card stands centred (max 384px, the
   reference's). Kept ours: the fonts, the labels, 48px fields with 16px type (no zoom on iOS), the big white
   button (round ten) - with the reference's arrow, glow and press. The glass and the tilt live on layers and
   are lifted while step two is open: a blurred or transformed ancestor would pin the fixed dialog to the card. */
/* round thirteen (Sergey, 2026-09-06): "at the end of the home page, make it not a purple ground
   but a purple CARD the size of the blue one at the top - the same motion, another colour". So the
   last screen repeats the opening: the ground is the scene's near-black, and a card rises out of it
   with the form standing on it, exactly where the phone stands on the blue one. */
html #scan{position:relative;background:#0A0A0A;isolation:isolate;overflow:hidden}
/* the ground is the opening scene's ground, down to its grid - nothing purple on it. Every purple
   thing belongs to the card (Sergey, 2026-09-06: "the ground down there is not black, it has a
   rusty cast to it - it should be black, and the purple card appears on it"). */
html #scan::before{content:"";position:absolute;inset:0;z-index:-2;opacity:.5;pointer-events:none;
  background-image:linear-gradient(to right,rgba(250,250,250,.05) 1px,transparent 1px),linear-gradient(to bottom,rgba(250,250,250,.05) 1px,transparent 1px);
  background-size:60px 60px,60px 60px;
  -webkit-mask-image:radial-gradient(ellipse 70% 60% at 50% 50%,#000 0%,transparent 75%);mask-image:radial-gradient(ellipse 70% 60% at 50% 50%,#000 0%,transparent 75%)}
html #scan .fx-plate{position:absolute;left:50%;top:50%;z-index:-1;pointer-events:none;overflow:hidden;
  width:min(1064px,92vw);height:var(--plate-h);border-radius:40px;border:1px solid rgba(255,255,255,.04);
  background:linear-gradient(145deg,#3D1178 0%,#150A20 100%);
  box-shadow:0 40px 100px -20px rgba(0,0,0,.9),0 20px 40px -20px rgba(0,0,0,.8),inset 0 1px 2px rgba(255,255,255,.2),inset 0 -2px 4px rgba(0,0,0,.8);
  transform:translate(-50%,-50%) translate3d(0,26vh,0) scale(.92);opacity:0;will-change:transform,opacity;
  transition:transform 1.4s cubic-bezier(.2,.72,.28,1),opacity 1.1s ease}
html #scan.plate-in .fx-plate{transform:translate(-50%,-50%);opacity:1}
/* Round nineteen (Sergey, 2026-09-07): "after the last screen, scrolling down, the purple plate
   should appear FIRST - it does not: the form and the text come first, and only then the plate."
   The first screen's order is plate, then what stands on it. So the content of this screen waits
   for the plate: it is held back and comes up out of the plate half a second after the plate has
   started rising, on the same easing, and drops back with it when the screen is left. */
/* ...and no will-change:transform here: it makes the block a containing block for position:fixed,
   and the step-two dialog inside the form IS position:fixed - it opened cut in half, scrolling
   inside a box the size of this block (Sergey's two screenshots, round twenty). The transform
   itself is gone once the block has risen (transform:none below), so the dialog, which opens
   after that, is laid out against the viewport as it should be. */
html #scan > .wrap{opacity:0;transform:translate3d(0,22px,0);
  transition:transform 1.05s cubic-bezier(.2,.72,.28,1) .5s,opacity .8s ease .5s}
html #scan.plate-in > .wrap{opacity:1;transform:none}
html #scan:not(.plate-in) > .wrap{transition-delay:0s}
@media (prefers-reduced-motion:reduce){html #scan > .wrap{transition:none;opacity:1;transform:none}}
/* Round nineteen (Sergey, his screenshot at 375x667): black above "STEP ONE", and the foot of the
   card cut off below. A screen snaps in UNDER the sticky header (scroll-padding-top), so what shows
   of a one-viewport section is its top part minus the header: its content has to be centred in
   that, not in the whole box, and its paddings have to be small enough for the card to fit. The
   header's allowance goes at the TOP of the box, under the header (measured: the screen snaps in with
   its top at the viewport's top and the sticky header covers the first 55px - scroll-padding does
   not move it). */
@media (max-width:760px){
  html #scan{min-height:100vh;min-height:100svh;display:flex;flex-direction:column;justify-content:center;box-sizing:border-box;
    padding-top:calc(var(--hdr,55px) + 12px);padding-bottom:12px}
  html #scan .fx-plate{width:94vw;height:calc(100vh - var(--hdr,55px) - 22px);height:calc(100svh - var(--hdr,55px) - 22px);border-radius:32px;
    top:calc(50% + var(--hdr,55px) / 2)}
  html #scan.plate-in .fx-plate{transform:translate(-50%,-50%)}
}
@media (prefers-reduced-motion:reduce){html #scan .fx-plate{transition:none;transform:translate(-50%,-50%);opacity:1}}
html #scan .fx-scene{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
html #scan .fx-scene > i{position:absolute;display:block}
html #scan .fx-noise{inset:0;opacity:.03;mix-blend-mode:soft-light;background-size:200px 200px;
  background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
html #scan .fx-top{top:0;left:50%;transform:translateX(-50%);width:120vh;height:60vh;border-radius:0 0 50% 50%;background:rgba(192,132,252,.22);filter:blur(80px)}
html #scan .fx-top2{top:0;left:50%;width:100vh;height:60vh;border-radius:0 0 9999px 9999px;background:rgba(216,180,254,.2);filter:blur(60px);opacity:.15;transform:translateX(-50%) scale(.98);animation:fxTop 8s ease-in-out infinite alternate}
html #scan .fx-bottom{bottom:0;left:50%;width:90vh;height:90vh;border-radius:9999px 9999px 0 0;background:rgba(192,132,252,.22);filter:blur(60px);opacity:.3;transform:translateX(-50%);animation:fxBottom 6s ease-in-out 1s infinite alternate}
html #scan .fx-spot{width:384px;height:384px;border-radius:50%;background:rgba(255,255,255,.05);filter:blur(100px);animation:fxPulse 2s cubic-bezier(.4,0,.6,1) infinite}
html #scan .fx-spot1{left:25%;top:25%}
html #scan .fx-spot2{right:25%;bottom:25%;animation-delay:1s}
@keyframes fxTop{from{opacity:.15;transform:translateX(-50%) scale(.98)}to{opacity:.3;transform:translateX(-50%) scale(1.02)}}
@keyframes fxBottom{from{opacity:.3;transform:translateX(-50%) scale(1)}to{opacity:.5;transform:translateX(-50%) scale(1.1)}}
@keyframes fxPulse{0%,100%{opacity:1}50%{opacity:.5}}
html #scan .wrap.grid2{grid-template-columns:minmax(0,384px);justify-content:center;gap:0}
html #scan .wrap.grid2{display:grid}   /* /contact/ uses the service-page stylesheet, which has no .grid2 of its own */   /* no perspective here: it would be a containing block for the fixed step-two dialog; the tilt carries its own */
html #scan .wrap.grid2 > div:first-child{display:none}
html #scan .form{position:relative;isolation:isolate;background:transparent;border:1px solid rgba(255,255,255,.05);border-radius:16px;padding:24px;box-shadow:0 25px 50px -12px rgba(0,0,0,.25);transform:none}
html #scan .form.fx-wait{opacity:0;transform:translateY(20px)}
html #scan .form.fx-in{opacity:1;transform:none;transition:opacity .8s ease,transform .8s ease}
html #scan .form.fx-tilt{transition:none}
html #scan .form.fx-back{transition:transform .5s cubic-bezier(.2,.72,.28,1)}
html #scan .form:has(.step-open){transform:none!important;transition:none}
html #scan .fx-card > i,html #scan .fx-card > span{position:absolute;display:block;pointer-events:none}
html #scan .fx-glass{inset:0;z-index:-1;border-radius:16px;background:rgba(0,0,0,.4);-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);overflow:hidden}
html #scan .form:has(.step-open) > .fx-card .fx-glass{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(0,0,0,.55)}
html #scan .fx-weave{inset:0;z-index:-1;border-radius:16px;opacity:.03;background-image:linear-gradient(135deg,#fff .5px,transparent .5px),linear-gradient(45deg,#fff .5px,transparent .5px);background-size:30px 30px}
html #scan .fx-glow{inset:-1px;border-radius:16px;opacity:.2;animation:fxGlow 4s ease-in-out infinite alternate;transition:opacity .7s}
html #scan .form:hover .fx-glow{opacity:.7}
@keyframes fxGlow{from{box-shadow:0 0 10px 2px rgba(255,255,255,.03);opacity:.2}to{box-shadow:0 0 15px 5px rgba(255,255,255,.05);opacity:.4}}
html #scan .fx-ring{inset:-.5px;border-radius:16px;background:linear-gradient(90deg,rgba(255,255,255,.03),rgba(255,255,255,.07),rgba(255,255,255,.03));opacity:0;transition:opacity .5s}
html #scan .form:hover .fx-ring{opacity:.7}
html #scan .fx-clip{inset:-1px;border-radius:16px;overflow:hidden}
html #scan .fx-clip > i{position:absolute;display:block;opacity:.7}
html #scan .fx-bt{top:0;left:-50%;height:3px;width:50%;background:linear-gradient(90deg,transparent,#fff,transparent);animation:fxBeamX 3.5s ease-in-out infinite,fxBeamO 1.2s ease-in-out infinite alternate,fxBeamB 1.5s ease-in-out infinite alternate}
html #scan .fx-br{right:0;top:-50%;width:3px;height:50%;background:linear-gradient(180deg,transparent,#fff,transparent);animation:fxBeamY 3.5s ease-in-out .6s infinite,fxBeamO 1.2s ease-in-out .6s infinite alternate,fxBeamB 1.5s ease-in-out .6s infinite alternate}
html #scan .fx-bb{bottom:0;right:-50%;height:3px;width:50%;background:linear-gradient(90deg,transparent,#fff,transparent);animation:fxBeamXr 3.5s ease-in-out 1.2s infinite,fxBeamO 1.2s ease-in-out 1.2s infinite alternate,fxBeamB 1.5s ease-in-out 1.2s infinite alternate}
html #scan .fx-bl{left:0;bottom:-50%;width:3px;height:50%;background:linear-gradient(180deg,transparent,#fff,transparent);animation:fxBeamYr 3.5s ease-in-out 1.8s infinite,fxBeamO 1.2s ease-in-out 1.8s infinite alternate,fxBeamB 1.5s ease-in-out 1.8s infinite alternate}
@keyframes fxBeamX{0%{left:-50%}71.4%{left:100%}100%{left:100%}}       /* 2.5s across, then a 1s rest, as the reference's repeatDelay */
@keyframes fxBeamXr{0%{right:-50%}71.4%{right:100%}100%{right:100%}}
@keyframes fxBeamY{0%{top:-50%}71.4%{top:100%}100%{top:100%}}
@keyframes fxBeamYr{0%{bottom:-50%}71.4%{bottom:100%}100%{bottom:100%}}
@keyframes fxBeamO{from{opacity:.3}to{opacity:.7}}
@keyframes fxBeamB{from{filter:blur(1px)}to{filter:blur(2.5px)}}
html #scan .fx-clip > .fx-dot{border-radius:50%;opacity:.2;animation:fxDot 2s ease-in-out infinite alternate}
html #scan .fx-d1{top:0;left:0;width:5px;height:5px;background:rgba(255,255,255,.4);filter:blur(1px)}
html #scan .fx-d2{top:0;right:0;width:8px;height:8px;background:rgba(255,255,255,.6);filter:blur(2px);animation-duration:2.4s;animation-delay:.5s}
html #scan .fx-d3{bottom:0;right:0;width:8px;height:8px;background:rgba(255,255,255,.6);filter:blur(2px);animation-duration:2.2s;animation-delay:1s}
html #scan .fx-d4{bottom:0;left:0;width:5px;height:5px;background:rgba(255,255,255,.4);filter:blur(1px);animation-duration:2.3s;animation-delay:1.5s}
@keyframes fxDot{from{opacity:.2}to{opacity:.4}}
/* the head of the card: the company's own lockup (round twelve), the title in the reference's gradient */
html #scan .fx-logo{position:relative;display:flex;align-items:center;justify-content:center;
  width:min(100%,240px);margin:0 auto 16px;padding-bottom:12px;border-bottom:1px solid rgba(255,255,255,.14);
  transform:scale(.92);opacity:0;transition:transform .8s cubic-bezier(.34,1.56,.64,1),opacity .4s}
html #scan .fx-in .fx-logo,html #scan .step2inner .fx-logo{transform:none;opacity:1}
html #scan .fx-logo .lockup{font-size:19px}
html #scan .form > h3,html #scan .form > h1{text-align:center;font-size:20px;line-height:1.3;font-weight:800;letter-spacing:-.02em;margin:0 0 4px;background:linear-gradient(180deg,#fff,rgba(255,255,255,.8));-webkit-background-clip:text;background-clip:text;color:transparent}
html #scan .form > .note{text-align:center;color:rgba(255,255,255,.6)}
/* the fields: dark glass, an icon at the left that lights up on focus, a hairline that shows while the pointer is on the card */
html #scan .field .lab label{color:rgba(255,255,255,.6);font-size:14px}
html #scan .fx-field{position:relative;display:block;border-radius:8px}
html #scan .fx-field[hidden]{display:none}
html #scan .fx-field::before{content:"";position:absolute;inset:-.5px;border-radius:8px;background:linear-gradient(90deg,rgba(255,255,255,.1),rgba(255,255,255,.05),rgba(255,255,255,.1));opacity:0;transition:opacity .3s;pointer-events:none}
html #scan .form:hover .fx-field::before{opacity:1}
html #scan .fx-field .fx-ic{position:absolute;left:12px;top:50%;width:16px;height:16px;margin-top:-8px;color:rgba(255,255,255,.4);transition:color .3s;pointer-events:none;z-index:1}
html #scan .fx-field .fx-ic svg{display:block;width:16px;height:16px}
html #scan .fx-field:focus-within .fx-ic{color:#fff}
html #scan .fx-field input,html #scan .fx-field select{position:relative;width:100%;box-sizing:border-box;background:rgba(255,255,255,.05);border:1px solid transparent;border-radius:8px;color:#fff;padding-left:40px;transition:background .3s,border-color .3s,transform .25s cubic-bezier(.2,.72,.28,1)}
html #scan .fx-field input:hover,html #scan .fx-field select:hover{transform:scale(1.01)}
html #scan .fx-field input:focus,html #scan .fx-field select:focus{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2);outline:none;transform:scale(1.02)}
html #scan .fx-field input::placeholder{color:rgba(255,255,255,.3)}
html #scan .fx-field input.known,html #scan .fx-field select.known{background:rgba(255,255,255,.03);color:rgba(255,255,255,.6)}
html #scan .fx-field select option{background:#0b0b10;color:#fff}
html #scan .intake .hint,html #scan .intake .s1note,html #scan .intake .privacy,html #scan .nosite{color:rgba(255,255,255,.6)}
/* the write-to-us card on /contact/ (round thirteen): the same card, one message box and one
   address. Nothing is posted from it - the visitor's own mail app sends the message, so the one
   mailbox is never written on the page as text. */
html #scan .wform .privacy{color:rgba(255,255,255,.6)}
html #scan .wform textarea{width:100%;box-sizing:border-box;min-height:132px;resize:vertical;
  background:rgba(255,255,255,.05);border:1px solid transparent;border-radius:8px;color:#fff;padding:12px 14px;
  font:inherit;font-size:16px;line-height:1.5;transition:background .3s,border-color .3s}
html #scan .wform textarea::placeholder{color:rgba(255,255,255,.3)}
html #scan .wform textarea:focus{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2);outline:none}
html #scan .wform .tag{color:rgba(255,255,255,.45);font-variant-numeric:tabular-nums}
html #scan .wform .tag.over{color:#f0a58a}
html #scan .wform > .btn{position:relative;display:flex;align-items:center;justify-content:center;gap:8px;
  width:auto;max-width:100%;margin:22px auto 0;border:0;font-weight:700;font-size:clamp(17px,2.2vw,20px);letter-spacing:-.01em;line-height:1.2;
  color:#0f172a;background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);padding:17px 34px;border-radius:20px;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45);
  transition:transform .2s cubic-bezier(.2,.72,.28,1),box-shadow .3s,filter .16s}
html #scan .wform > .btn:hover{transform:scale(1.02);background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);color:#0f172a;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45),0 0 28px 6px rgba(255,255,255,.18)}
html #scan .wform > .btn:active{transform:scale(.98)}
/* the "No website yet" row: a label rule (.field label{display:block}) had stacked the box over its text and the 48px
   field rule had stretched the box to 13x48 (seen while restyling the card; older than this round) */
html #scan .field label.nosite{display:flex;align-items:center;gap:10px;font-weight:500;margin:10px 0 0}
html #scan .field .nosite input[type=checkbox]{min-height:0;width:20px;height:20px;margin:0;padding:0;accent-color:#fff}
/* the button: the big white pill of round ten, with the reference's arrow, glow and press */
html #scan .intake .step1 > .btn{position:relative;display:flex;align-items:center;justify-content:center;gap:8px;transition:transform .2s cubic-bezier(.2,.72,.28,1),box-shadow .3s,filter .16s}
html #scan .intake .step1 > .btn:hover{transform:scale(1.02);box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45),0 0 28px 6px rgba(255,255,255,.18)}
html #scan .intake .step1 > .btn:active{transform:scale(.98)}
html #scan .intake .step1 > .btn .fx-arrow{display:inline-block;width:.6em;height:.6em;transition:transform .3s}
html #scan .intake .step1 > .btn .fx-arrow svg{display:block;width:100%;height:100%}
html #scan .intake .step1 > .btn:hover .fx-arrow{transform:translateX(4px)}
/* step two (round twelve, Sergey 2026-09-06): the same card as step one - the same glass, the same
   beams and sparks, the same logo at its head, the same rise-in, the same white pill. It opened in a
   design of its own before, which is what he saw. */
/* round thirteen (Sergey): "the background goes a darker purple - it should not, it is just another
   form". No scrim and no blur: the scene stays exactly as it was, and the card underneath steps aside
   so there is one card on the screen, not two. */
html #scan .intake.js-steps.step-open .step2{background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}
/* the dialog is fixed inside #scan, and #scan is its own stacking context (isolation:isolate), so
   the dialog's z-index counts inside the section - and the sticky header, z-index 60 at the root,
   painted over the dialog's own lockup and its close button (round twenty, 375x667). While a step
   is open the section stands above the header. */
html #scan:has(.step-open){z-index:70}
/* the screen steps aside while the modal is up - the scene stays exactly as it was and one card
   stands on it, instead of a second card and a heading showing through the first */
html #scan:has(.step-open) > .wrap{visibility:hidden}
html #scan:has(.step-open) .step2,html #scan:has(.step-open) .step2 *{visibility:visible}
/* three steps (round thirteen): one pane at a time inside the modal; with no JavaScript both stand inline */
html #scan .intake.js-steps.step-open .spane{display:none}
html #scan .intake.js-steps.step-open.pane-2 #scanPane2{display:block}
html #scan .intake.js-steps.step-open.pane-3 #scanPane3{display:block}
html #scan .intake .step2inner > .btn,html #scan .intake .spane > .btn{position:relative;display:flex;align-items:center;justify-content:center;gap:8px;
  width:auto;max-width:100%;margin:22px auto 0;border:0;font-weight:700;font-size:clamp(17px,2.2vw,20px);letter-spacing:-.01em;line-height:1.2;
  color:#0f172a;background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);padding:17px 34px;border-radius:20px;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45);
  transition:transform .2s cubic-bezier(.2,.72,.28,1),box-shadow .3s,filter .16s}
html #scan .intake .step2inner > .btn:hover,html #scan .intake .spane > .btn:hover{transform:scale(1.02);background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);color:#0f172a;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45),0 0 28px 6px rgba(255,255,255,.18)}
html #scan .intake .step2inner > .btn:active,html #scan .intake .spane > .btn:active{transform:scale(.98)}
html #scan .intake.js-steps.step-open .step2inner{position:relative;isolation:isolate;width:min(384px,100%);
  background:transparent;border:1px solid rgba(255,255,255,.05);border-radius:16px;padding:24px;
  box-shadow:0 25px 50px -12px rgba(0,0,0,.5);animation:fxRise .8s cubic-bezier(.2,.72,.28,1) both}
@keyframes fxRise{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
html #scan .step2inner .fx-glow{opacity:.35}
html #scan .step2inner:hover .fx-glow,html #scan .step2inner:hover .fx-ring{opacity:.7}
html #scan .step2inner:hover .fx-field::before{opacity:1}
html #scan .intake .mhead{padding-right:0;text-align:center}
html #scan .intake .mtitle{text-align:center;font-size:20px;line-height:1.3;font-weight:800;letter-spacing:-.02em;margin:0 0 4px;
  background:linear-gradient(180deg,#fff,rgba(255,255,255,.8));-webkit-background-clip:text;background-clip:text;color:transparent}
html #scan .intake .mhead .note{text-align:center;color:rgba(255,255,255,.6)}
html #scan .intake .mclose{top:-10px;right:-10px;color:rgba(255,255,255,.5)}
html #scan .intake .mclose:hover{background:rgba(255,255,255,.08);color:#fff}
html #scan .intake .confirm{color:#fff;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08)}
html #scan .intake .confirm button{color:#fff}
/* the modal's button is step one's white pill, with the same arrow, glow and press */
html #scan .intake .step2inner > .btn[type=submit]{position:relative;display:flex;align-items:center;justify-content:center;gap:8px;
  width:auto;max-width:100%;margin:22px auto 0;border:0;font-weight:700;font-size:clamp(17px,2.2vw,20px);letter-spacing:-.01em;line-height:1.2;
  color:#0f172a;background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);padding:17px 34px;border-radius:20px;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45);
  transition:transform .2s cubic-bezier(.2,.72,.28,1),box-shadow .3s,filter .16s}
html #scan .intake .step2inner > .btn[type=submit]:hover{transform:scale(1.02);background:linear-gradient(180deg,#FFFFFF 0%,#F1F5F9 100%);color:#0f172a;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 10px 30px rgba(0,0,0,.45),0 0 28px 6px rgba(255,255,255,.18)}
html #scan .intake .step2inner > .btn[type=submit]:active{transform:scale(.98)}
html #scan .intake .step2inner > .btn .fx-arrow{display:inline-block;width:.6em;height:.6em;transition:transform .3s}
html #scan .intake .step2inner > .btn .fx-arrow svg{display:block;width:100%;height:100%}
html #scan .intake .step2inner > .btn:hover .fx-arrow{transform:translateX(4px)}
/* round thirteen: Sergey took item 8 back - the bright business-name label "took all the attention".
   It reads like every other label again. */
@media (prefers-reduced-motion:reduce){
  html #scan .intake.js-steps.step-open .step2inner{animation:none}
  html #scan .fx-scene > i,html #scan .fx-clip > i,html #scan .fx-dot,html #scan .fx-glow{animation:none}
  html #scan .form.fx-wait{opacity:1;transform:none}
  html #scan .fx-logo{transform:none;opacity:1;transition:none}
  html #scan .form.fx-in,html #scan .fx-field input,html #scan .fx-field select,html #scan .intake .step1 > .btn{transition:none}
}
@media (max-width:640px){
  html #scan .fx-top,html #scan .fx-top2,html #scan .fx-bottom,html #scan .fx-spot{filter:blur(40px)}   /* a phone: half the blur radius, the same picture */
  html #scan .form{padding:20px 16px}
}
/* round eight (Sergey, on his Mac): the header stays while the page scrolls; a screen is 88% of the
   viewport so the start of the next one shows under it (what he liked at 125% zoom); on displays
   wider than 2048px the whole page is zoomed like his browser was, in steps */
@media (min-width:821px){
  html{--screen:min(88vh,900px);--screen:min(88svh,900px);scroll-padding-top:55px}
  html header{position:sticky;top:0;z-index:60;background:var(--paper)}
  html .hero{min-height:min(calc(88vh - 55px),900px);min-height:min(calc(88svh - 55px),900px)}
  html #how{min-height:var(--screen);display:flex;flex-direction:column;justify-content:center;box-sizing:border-box}
  /* "<Assistant> chooses others. What about you?" on one line: the line may run past the wrap, and
     shrinks a little below 1550px so it never wraps (measured: 1,283px at the full 76px) */
  html .gnf-h2{white-space:nowrap;width:max-content;max-width:calc(100vw - 40px);position:relative;left:50%;transform:translateX(-50%);
    font-size:min(clamp(40px,5.6vw,76px),4.9vw)}
}
/* Round twenty-seven: the zoom above is a real browser zoom, and a browser zoom does NOT scale the
   viewport units - so at 2049px every full-screen box (a sticky stage, a scene track, a plate) came
   out 1.25x taller than the window it was meant to fill. Measured at 2490x1282: #closer stood 1603px
   in a 1282px window, and the hero's floating chips left the page 311px wider than the screen.
   --z carries the zoom so those boxes can divide by it; it is 1 everywhere else, so this changes
   nothing on an ordinary display. */
/* Round thirty (Sergey, 2026-09-07, with the purple screen beside the referral ones): "look at the
   SIZE of that purple plate. That size is to be used everywhere, on every other coloured plate. Only
   if one plate has too much on it may it grow a little - in no other case. Then there will be none of
   this ugliness where the middle and the bottom are empty." Measured at 1663x852: the reference plate
   is 685px and the scene plates were 784 - a hundred pixels of nothing, which is exactly the void he
   photographed. One token now, read from the reference's own arithmetic (the screen, less the header,
   less the black frame), and every plate is a MIN height so a fuller deck may still grow. */
html{--z:1;--plate-h:min(1096px,calc(100svh / var(--z,1) - var(--hdr,55px) - 112px))}
@media (max-width:760px){html{--plate-h:calc(100svh - var(--hdr,55px) - 22px)}}
/* a genuinely short desktop - a 1024x768 or a 900x700 laptop - needs more than tighter margins:
   the step card's illustration is a fixed 230px box and the form is padded for a tall window.
   Both give room by height here, and nothing above 820px is touched (Sergey browses at 852). */
@media (min-width:761px) and (max-height:820px){
  html #how .hw-art{height:clamp(120px,22svh,230px)}
  html #how .hw-card{padding:14px 16px 16px}
  html #scan .form{padding:16px 14px}
  html #scan > .wrap.grid2{margin-top:10px}
  html :is(#scan,#how,#mechanism) > .wrap > h2{font-size:min(clamp(40px,5.6vw,76px),8.4vh)}
}
/* ...and a 700px-tall desktop window, which is the shortest we test, takes the last of it */
@media (min-width:761px) and (max-height:760px){
  html #scan .form{padding:12px 12px}
  /* the form's own head: the lockup, the title and the promise line, packed (measured: 22px short
     on a hub at 900x700, and the promise line is never the thing that goes) */
  html #scan .form .fx-logo{margin-bottom:4px}
  html #scan .form > .note{margin-bottom:6px}
  html #scan{padding-top:var(--hdr,55px)}
  html #scan > .wrap.grid2{margin-top:4px}
  /* the last ten pixels on a 700px window: the card keeps every field and every line and is
     drawn a twentieth smaller, which is a scale rather than a cut. */
  html #scan .form{zoom:.95}
  html :is(#scan,#how,#mechanism) > .wrap > h2{font-size:min(clamp(40px,5.6vw,76px),7.4vh)}
}
@media (min-width:2049px){html{zoom:1.25;--z:1.25;--screen:min(calc(88svh / 1.25),900px)}}
@media (min-width:2700px){html{zoom:1.5;--z:1.5;--screen:min(calc(88svh / 1.5),900px)}}
@media (min-width:3300px){html{zoom:1.8;--z:1.8;--screen:min(calc(88svh / 1.8),900px)}}
html .cs .cs-stage,html #closer .cs-stage.cs-still{height:calc(100svh / var(--z,1))}
/* Round fifty-three (Sergey): the reader plays the picture themselves now, so the ONLY thing that
   sets its speed is how much scrolling it takes. 520 -> 1040 (half speed), then 900 with the
   phases re-cut: the run to the red message is a fifth shorter than at 1040, and what follows it
   - the message growing, then the plate and the phone leaving - is a screen of scroll each, so
   the way out of the scene reads like the move between any other two screens rather than a blink. */
html .cs .cs-track{height:calc(740svh / var(--z,1))}
html #closer .cs-track.cs-shorttrack{height:calc(100svh / var(--z,1))}
html .hero{min-height:min(calc(88svh / var(--z,1) - 55px),900px)}
/* and nothing may make the page wider than the screen, at any width: clip, not hidden, so the
   sticky stages keep sticking. */
/* the pair to the aicy-js class set in the head script: once scripting is known to be running, a scene's plate and deck
   start hidden - the driver is about to say so anyway, and this way it says it before the first
   paint rather than a beat after it. */
/* Round thirty-one (Sergey, 2026-09-08): "on every first black screen the animation we run on the
   home page's first screen must play." The black heading screen simply stood there while every other
   screen on the site now arrives. Its own box keeps the --h transform that carries it away as you
   scroll on; what arrives is what is written on it - kicker, heading, line - on the reference's own
   curve and one beat apart, so the screen reads as arriving rather than as already being there. */
html.aicy-js :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head > * > *{opacity:0;transform:translate3d(0,22px,0);
  transition:transform 1.05s cubic-bezier(.2,.72,.28,1),opacity .8s ease}
html.aicy-js :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head > * > * + *{transition-delay:.18s}
html.aicy-js :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head > * > * + * + *{transition-delay:.36s}
html.aicy-js :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs.pzs-headin .pzs-head > * > *{opacity:1;transform:none}
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes:not(.pzs-ready) .pzs-head > * > *{transition:none}
html.aicy-js :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-plate{opacity:var(--cd,0)}
html.aicy-js :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-deck{opacity:var(--ct,0)}
html.aicy-js :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head{opacity:calc(1 - var(--h,0))}
/* ...and nothing transitions until the driver has painted once, so the very first value is a
   starting point and not something to animate away from. */
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes:not(.pzs-ready) .pzs-plate,
html :is(#pricing,#referral,#badge,#badgeme).pz-scenes:not(.pzs-ready) .pzs-deck{transition:none}

html,html body{overflow-x:clip}
/* every heading centred, as the first two screens have theirs; #scan carries its heading in a block
   of its own above the grid (patch_mobile_blocks part 6; #report and #boundaries are pages since round eleven) */
html #how > .wrap > .eyebrow,html #how > .wrap > h2,html #how > .wrap > .lead,
html #analyze > .wrap > .eyebrow,html #analyze > .wrap > h2,html #analyze > .wrap > .lead,
html #mechanism > .wrap > .eyebrow,html #mechanism > .wrap > h2,html #mechanism > .wrap > .lead,
html #faq > .wrap > .eyebrow,html #faq > .wrap > h2,html #faq > .wrap > .lead,
html #closer > .wrap > .eyebrow,html #closer > .wrap > h2,html #closer > .wrap > .lead,
html .sec-head > .eyebrow,html .sec-head > h2,html .sec-head > .lead{text-align:center}
html #how > .wrap > .lead,html #analyze > .wrap > .lead,html #mechanism > .wrap > .lead,html #faq > .wrap > .lead,
html #closer > .wrap > .lead,html .sec-head > .lead{margin-left:auto;margin-right:auto;max-width:60ch}
html .sec-head + .wrap.grid2{margin-top:28px}
/* the done-for-you block (round nine): the heading centred, then two cards - fix my site, build a
   new site - laid out like the plan cards: a row on the desktop, the stack on phones. Not a box but
   a screen of its own, parted from the plans by the same line the home page draws between screens. */
html #pricing .pz-build,html #pricing .pz-mon{position:relative;border:0;border-radius:0;background:transparent;padding-left:0;padding-right:0;margin-top:0;
  min-height:var(--screen)}
html #pricing .pz-build::before,html #pricing .pz-mon::before{content:"";position:absolute;top:0;left:50%;width:100vw;height:1px;background:var(--line);transform:translateX(-50%)}
html #pricing .pz-bhead > .eyebrow,html #pricing .pz-bhead > h2,html #pricing .pz-bhead > p{text-align:center}
/* round thirteen (Sergey's screenshot: "THE REPORT" sits left of centre - "and that is not the only
   place"): a centred block centres its TEXT, not its box, and the site's paragraph measure (a max-width
   in ch) left every eyebrow's box at the left edge of its parent. Measured at 1280: 200-238px off centre
   on /llms-txt/, /report/, /what-decides-it/, /what-this-is-not/, /faq/, /log/, /research/, /privacy/
   and the pricing head. An eyebrow is a label, not prose: it takes the width it is given, and then
   text-align decides where its text sits - centred where the block is centred, left where it is not. */
html .eyebrow{max-width:none;margin-left:0;margin-right:0}
/* ...and wherever a heading block is centred, its kicker's BOX is centred too, not just the text
   inside it. Any narrower box left at the block's left edge reads as a stray label. */
html .sec-head > .eyebrow,html #pricing .pz-bhead > .eyebrow,html .hero .eyebrow,
html #evidence > .wrap > .eyebrow,html :is(#pricing,#referral,#badge,#badgeme).pz-scenes .pzs-head .eyebrow{margin-left:auto;margin-right:auto}
html #pricing .pz-head > *,html #pricing .pz-bhead > *{margin-left:auto;margin-right:auto}
html #pricing .pz-one .pz-cards{grid-template-columns:minmax(0,380px);justify-content:center}
/* Round thirty-four (Sergey): the referral card is the monitoring price crossed out. The old figure
   stays legible - it is the point of the card - so it keeps the number's own weight and sits on the
   new one's baseline, in the muted ink every secondary figure on the page uses. */
html #pricing .pz-was{display:inline-block;margin-left:.28em;margin-right:0;font-weight:600;font-size:.78em;
  color:var(--muted);text-decoration:line-through;text-decoration-thickness:.07em;
  text-underline-offset:0;letter-spacing:-.02em;
  width:0;overflow:visible;white-space:nowrap;text-align:left}
@media (min-width:641px){   /* round ten: on phones the two cards lean in exactly like the plan cards (the rule below had switched it off there) */
  html #pricing .pz-two .pz-cards{grid-template-columns:repeat(2,minmax(0,1fr));max-width:760px;margin:0 auto}
  html #pricing .pz-two .pz-card{transform:none}
  html #pricing .pz-two .pz-card:hover{transform:translateY(-4px)}
}
@media (max-width:640px){
  /* round ten: the done-for-you heading is pinned above its deck (the bar over it, the deck under it),
     so the heading is never covered and never scrolls away while the cards take their turns. Round
     twelve: monitoring is headed the same way, and the offsets are 0 on /pricing/, which has no bar
     (they were 60px there, which is what pushed the last card's button over its own text). */
  html #pricing .pz-build,html #pricing .pz-mon{padding-top:calc(var(--pzbar) + 8px)}
  html #pricing .pz-bhead{position:sticky;top:var(--pzbar);z-index:2;margin-bottom:0}
  html #pricing .pz-build .pz-cards,html #pricing .pz-mon .pz-cards{top:calc(var(--pzbar) + var(--bh,150px));
    height:calc(100vh - var(--pzbar) - 8px - var(--bh,150px));height:calc(100svh - var(--pzbar) - 8px - var(--bh,150px))}
  /* the monitoring screen holds ONE card, so it is not a track: the heading and the card simply stand
     on one screen. A sticky deck inside a block exactly its own height can never pin, and the card
     slid up under the heading - measured at 390x844 (round twelve). */
  html #pricing .pz-mon{position:relative}
  html #pricing .pz-mon .pz-bhead{position:static}
  html #pricing .pz-mon .pz-cards{position:static;height:auto;transform:none}
  html #pricing .pz-mon .pz-card{position:static;opacity:1;pointer-events:auto;transform:none;max-height:none;margin:0;height:auto}
  html #pricing .pz-mon .pz-stop{top:0}
}

/* ============================================================================
   MOBILE FIRST. The phone is the primary screen; the desktop inherits.
   ============================================================================ */
html img,html svg,html video{max-width:100%;height:auto}
html pre{overflow-x:auto;max-width:100%}
html table{display:block;overflow-x:auto;max-width:100%}
html section[id],html [id]{scroll-margin-top:72px}
html .wrap{padding-left:max(0px,env(safe-area-inset-left));padding-right:max(0px,env(safe-area-inset-right))}

/* every control is at least a thumb high */
html .btn{min-height:48px;padding-top:12px;padding-bottom:12px;font-family:inherit;font-size:17px;font-weight:650}
html .brand{display:inline-flex;align-items:center;min-height:44px}
html .ladder a{display:inline-flex;align-items:center;min-height:44px}
html nav a,html footer a{padding-left:8px;padding-right:8px}
/* Sergey, 2026-09-05 (round four): the header a fifth lower - 54px instead of 68, its button
   38px instead of 47. The thumb still gets 44px: a ::before extends the hit area invisibly. */
html header .wrap{min-height:54px}
html header .btn{min-height:38px!important;padding-top:6px!important;padding-bottom:6px!important;font-size:14px;position:relative}
html header .btn::before{content:"";position:absolute;inset:-3px 0}
html .top .btn{min-height:44px;font-size:15px}
html nav a,html footer a,html .svc a,html .indFoot a{display:inline-flex;align-items:center;min-height:44px}
html .indGroup a,html .indx a{display:flex;align-items:center;min-height:44px}
/* round forty-nine (Sergey): the phone bar a fifth lower - 59px to 45. The button and the lockup
   are 36px tall; as with the header, a ::before extends each hit area to 44px invisibly. */
html #stickyScan .btn{min-height:36px;font-size:15px;padding:6px 18px;position:relative}
html #stickyScan .btn::before,html #stickyScan .lockup::before{content:"";position:absolute;inset:-4px 0}
html #stickyScan p{font-size:15px}
/* the yearly switch keeps its 48x28 pill; its hit area grows to a thumb without moving a pixel */
html #pricing .pz-sw{position:relative}
html #pricing .pz-sw::before{content:"";position:absolute;inset:-10px -6px}
html summary{min-height:44px;display:flex;align-items:center;cursor:pointer}
html .tag button,html .intake .confirm button,html .intake .mclose{min-height:44px;min-width:44px}
html .field input,html .field select,html .field textarea,html .indFilter{min-height:48px;font-size:16px}
html label{min-height:auto}

/* small type that the audit found under 14px on phones */
html .caption,html .hasked,html .hero-cta .note,html .note,html .tag,html .field .hint,html .intake .hint,
html .receipt figcaption,html .receipt .rnote,html .indGroupLabel,html p.indGroupLabel{font-size:14px}
html .eyebrow{font-size:13px}
html .hfact .hl{font-size:14px}
html .targets .teye{font-size:14px}
html #pricing .pz-badge{font-size:12px}
html .md{font-size:13px}
html .targets .turl{font-size:14px}
html .indGroup .indGroupLabel{font-size:13px}
html .indGroup a{font-size:15px}
html .indGroup a i{font-size:11px}

@media (max-width:640px){
  html body{font-size:17px;line-height:1.55}
  html .hero{padding-top:40px;padding-bottom:48px}
  html .hero-cta{flex-direction:column;align-items:center;margin-top:30px}
  html .hero-cta .btn{width:auto;min-width:0;padding-left:30px;padding-right:30px;justify-content:center;font-size:17px}
  html .hero .lead{margin-top:22px}
  html .hero-cta .note{text-align:center}
  html h1{text-wrap:balance}
  html .hero h1,html .hq-h1,html .hq-box,html section > .wrap > h2,html .gnf-h2,html #scan .wrap > h2,
  html main > .wrap > h2{font-size:clamp(36px,10.4vw,47px);line-height:1.06}
  html #pricing .pz-head h1,html #pricing .pz-head h2{font-size:clamp(36px,10.4vw,47px)}
  html h2{text-wrap:balance}
  html .lead{font-size:17px}
  html .indGroup a{font-size:16px}
  html .card,html .receipt{padding-left:16px;padding-right:16px}

  /* Sergey, 2026-09-04: on the phone nothing sits ragged. Headings, eyebrows, leads,
     the question and its assistants, the CTA and its promise line are centred; running
     prose is justified with hyphenation; lists, cards, forms, receipts and the demo
     screens stay left-aligned because they are scanned, not read. */
  html .hero > div:first-child,html .hero .eyebrow,html .hero h1,html .hero .hq-box,
  html .hero .lead,html .hero-cta,html .hero .caption,html .hero .hasked,html .hero .hero-cta .note{
    text-align:center}
  html .hero .hq-row{justify-content:center}
  html .hero-cta{align-items:center}
  html .hero .hfacts,html .hero .hfact{text-align:left}
  html section > .wrap > .eyebrow,html section > .wrap > h2,html section > .wrap > h3,
  html section > .wrap > .lead,html section > .wrap > .svc-lead,html main > .wrap > .eyebrow,
  html main > .wrap > h1,html main > .wrap > h2,html main > .wrap > .lead,
  html #scan .wrap > h2,html #scan .wrap > .lead,html #pricing .wrap > h2,html #pricing .wrap > .lead,
  html .thanks h1,html .thanks .lead{text-align:center}
  html main p{text-align:justify;text-justify:inter-word;hyphens:auto;-webkit-hyphens:auto}
  html main .eyebrow,html main .lead,html main .note,html main .caption,html main .hasked,
  html .intake p,html .field p,html #stickyScan p,html #pricing p,html .screen p,html #geo-nf p,
  html #geo-mon p,html .receipt p,html .receipt figcaption,html .hfact p,html .targets p,
  html .card p,html li p,html .mteaser,html .indPanel p,html footer p{
    text-align:inherit;hyphens:manual;-webkit-hyphens:manual}
  html main .eyebrow,html main .lead{text-align:center}
  html .card p,html .receipt p,html .intake p,html .field p,html .hfact p,html .targets p,
  html li p,html .indPanel p,html #stickyScan p,html #pricing p{text-align:left}
  html #pricing .pz-bhead > p{text-align:center}
  html #pricing .pz-head p{text-align:center}
}
@media (max-width:360px){
  /* the narrowest phones: brand + white button + hamburger must still fit on one line */
  html header .wrap > .btn{padding-left:12px!important;padding-right:12px!important;font-size:14px}
  html header .brand.lockup{font-size:16px}
  html header .lockup span{margin-left:.32em;padding-left:.32em}
}
/* round twelve: while the page is held, a new touch gesture must not scroll it at all */
html.aicy-hold{touch-action:none}
@media (prefers-reduced-motion:reduce){
  html *{scroll-behavior:auto}
}

/* ---- the footer (round twelve, Sergey 2026-09-06): column groups with headings, the same
   on every page of the site. site_footer.py writes the markup; patch_theme.apply() puts it
   on every page on every build, so no page can carry a footer of its own. ---- */
/* round sixteen (Sergey): a little more black between the purple plate and the footer. The room is
   added to BOTH ends of the screen, because the plate and the form card are centred on it - extra
   at the bottom alone slides the plate down and gains nothing. Above the plate the extra black is
   the closing screen's own, so only the gap under it shows. */
html #scan{padding-top:calc(48px + 6vh);padding-top:calc(48px + 6svh / var(--z,1));
  padding-bottom:calc(48px + 6vh);padding-bottom:calc(48px + 6svh / var(--z,1))}
/* Round twenty-seven (Sergey, three screenshots from his wide monitor at 1663x852): "the screen
   with our three steps - the bottom of the plate does not fit, because you left a lot of black
   at the top", and "you scroll down and simply land on a black screen", and the purple one sits
   wrong. One cause for all three: a screen's box is padded for a TALL window (64px top and
   bottom, and 64px + 8svh on #scan) while the sticky header already eats the first 55px, so at
   852px #how measured 874 and #scan 945 - both past the fold, and landing on #scan's top showed
   its black padding with the plate still below. On a short desktop the room goes where it is
   needed: the header's height at the top, a small foot, and the content centred in the rest. */
@media (min-width:761px) and (max-height:1100px){
  /* the budget is the SCREEN LESS THE HEADER, not the screen: scroll-padding-top parks a snapped
     screen 55px down, under the sticky header, so a section exactly one viewport tall ends 55px
     past the fold. Measured at the landing, 1663x852: #how stood at top 52 and its last card's
     bottom at 860. The header's height comes off the box - it is not padding inside it. */
  html #evidence,html #how,html #analyze,html #scan,html #mechanism,html #faq{
    padding-top:12px;padding-bottom:12px;
    min-height:calc(100vh - var(--hdr,55px) - 2px);min-height:calc(100svh - var(--hdr,55px) - 2px);
    max-height:none;box-sizing:border-box;
    display:flex;flex-direction:column;justify-content:center}
  /* the heading block gives up its air before the cards give up their bottoms (measured on a hub at
     1280x800: 832px of section in an 800px window, and 801 in 768) */
  html :is(#evidence,#how,#analyze,#scan,#mechanism,#faq) > .wrap > .eyebrow{margin-bottom:8px}
  html :is(#evidence,#how,#analyze,#scan,#mechanism,#faq) > .wrap > h2{margin-bottom:8px}
  html :is(#evidence,#how,#analyze,#scan,#mechanism,#faq) > .wrap > .lead{margin-bottom:8px}
  html #how > .wrap > .hw{margin-top:10px}
  html #mechanism > .wrap > .grid3{margin-top:20px}
  html #mechanism > .wrap > .kicker{margin-top:20px}
  html #scan > .wrap.grid2{margin-top:14px}
  /* Sergey, 2026-09-07: "the purple plate is the whole screen, and you know it should have
     limits". Its 84vh was written for a tall window; on a short one it left 40px of black and
     read as edge-to-edge. It is the screen less a black frame now, and the frame is the same
     above and below (measured at 1663x852: 55px each, with the form still inside the plate). */
}
/* ...and on a phone the room is the header's, at the foot, and nothing more: the card has to fit
   (round nineteen - this rule sits after the one above, which had been winning over the phone's) */
@media (max-width:760px){
  html #scan{padding-top:calc(var(--hdr,55px) + 12px);padding-bottom:12px}
  html #scan > .wrap{margin-top:0;margin-bottom:0}
}
/* 2026-09-07 (Sergey, his screenshot of the footer under the purple plate): "the gradient runs into
   grey, not black - make it the same black as the band between the footer and the plate above it."
   That band is the cinematic ground, #0A0A0A, which every last screen on the site stands on (#scan
   and the pricing and referral scenes all set it), so the footer stands on it too and the glow
   fades into black instead of into the page's lighter paper. */
html footer{position:relative;overflow:hidden;border-top:0;padding:76px 0 30px;color:var(--muted);font-size:15px;
  background:#0A0A0A}
/* round fourteen (Sergey, 2026-09-06): the 21st.dev "footer-section" he picked - the same content in
   another shape. A glow rises out of the top edge, a hairline is drawn across it and blurred, the
   brand and the copyright stand together on the left with the four columns to their right, and the
   columns arrive one after another when the footer comes into view (theme-js: fArrive). */
html footer .fglow{position:absolute;top:0;left:50%;transform:translateX(-50%);width:min(1180px,140%);height:340px;
  pointer-events:none;z-index:0;
  background:radial-gradient(ellipse 60% 100% at 50% 0%,rgba(143,176,255,.20) 0%,rgba(143,176,255,.07) 42%,transparent 72%)}
html footer .frule{position:absolute;top:0;left:0;right:0;height:1px;pointer-events:none;z-index:1;
  background:linear-gradient(90deg,transparent 0%,rgba(143,176,255,.55) 28%,rgba(238,241,246,.7) 50%,rgba(143,176,255,.55) 72%,transparent 100%);
  filter:blur(.6px)}
html footer .wrap{display:block;position:relative;z-index:2}
/* round fifteen (Sergey, 2026-09-06): the reference stacks it - the company's mark first, the
   rights line under it, and only then the row of link columns. */
html footer .fcols{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:34px 24px;align-items:start}
html footer .fbrand{grid-column:1 / -1;display:flex;flex-direction:column;align-items:flex-start;gap:10px;margin:0 0 6px}
/* round sixteen: the mark sat 18px in from the left edge everything under it lines up on - a footer
   link rule was giving it 8px of padding and the tap target another 10 - and it is 15% larger now */
html footer .fbrand .lockup{font-size:21px;padding:0;margin:0;align-self:flex-start;
  min-height:44px}   /* left-aligned and larger, but still a 44px target - the audit caught it at 33 */
html footer .fgroup{display:flex;flex-direction:column;align-items:flex-start}
html footer .fhead{margin:0 0 6px;font-size:13px;letter-spacing:.09em;text-transform:uppercase;font-weight:700;color:var(--ink)}
html footer .fgroup a{display:flex;align-items:center;min-height:44px;margin:0;padding:0;color:var(--muted);text-decoration:none;line-height:1.35}   /* 44px to hit, like every other link on the site */
html footer .fgroup a:hover{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
html footer .fbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:8px 18px;
  margin-top:40px;padding-top:18px;border-top:1px solid var(--line);font-size:14px}
html footer .fcopy{margin:0;font-size:14px;line-height:1.5;color:var(--muted)}
html footer .flegal{margin:0;display:flex;flex-wrap:wrap;gap:0 4px}
html footer .flegal a{display:inline-flex;align-items:center;min-height:36px;margin:0;padding:0 8px;color:var(--muted);text-decoration:none}
html footer .flegal a:hover{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
html footer .fineprint{margin:14px 0 0;font-size:13.5px;line-height:1.5;color:var(--muted);max-width:none}
/* 2026-09-09 (Sergey): the bottom row - our own badge, its text form, the payment names as
   card marks. The badge is the customer's image at its own size (200x64); the marks are the two
   card brands in colour on their own white tiles (2026-09-09: Sergey chose colour, and Stripe
   came off - we do not take cards through Stripe yet). */
html footer .ftrust{display:flex;flex-wrap:wrap;align-items:center;gap:16px 28px;margin-top:22px;padding-top:18px;border-top:1px solid var(--line)}
/* Round fifty-one (Sergey, 2026-09-09): the badge in the footer leads to /badge/ - it always did,
   but nothing on it said so. It carries a link's ring and a link's cursor now. */
html footer .fbadge{display:inline-flex;flex:0 0 auto;line-height:0;border-radius:10px;cursor:pointer;
  outline:1px solid transparent;outline-offset:3px;transition:outline-color .15s ease,opacity .15s ease}
html footer .fbadge svg{width:200px;height:64px;display:block}
html footer .fbadge:hover{opacity:1;outline-color:var(--line)}
html footer .fbadge:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
html footer .ftrust-text{flex:1 1 320px;min-width:0}
html footer .ftrust-line{margin:0 0 4px;font-size:13.5px;line-height:1.5;color:var(--muted)}
html footer .ftrust-tline{margin:0;font-size:14px;line-height:1.5;color:var(--ink)}
html footer .ftrust-tline a{display:inline;min-height:0;margin:0;padding:0;color:var(--ink);font-weight:600;text-decoration:none;border-bottom:1px solid currentColor}
html footer .fpay{margin:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px;flex:0 0 auto}
html footer .fpay span{font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);margin-right:2px}
html footer .fpay img{display:block;width:44px;height:28px;border-radius:6px}
@media (max-width:640px){html footer .ftrust{gap:14px 20px} html footer .fpay{flex-basis:100%}}
/* the arrival: each column blurred and a little low, clearing in turn. Written so the page without
   the script is the finished footer - theme-js puts the columns down first, then lets them up. */
html footer .fcols > *{transition:opacity .8s ease,transform .8s cubic-bezier(.2,.72,.28,1),filter .8s ease}
html footer.f-wait .fcols > *{opacity:0;transform:translateY(16px);filter:blur(7px)}
html footer.f-in .fcols > *{opacity:1;transform:none;filter:none}
html footer .fcols > *:nth-child(2){transition-delay:.08s}
html footer .fcols > *:nth-child(3){transition-delay:.16s}
html footer .fcols > *:nth-child(4){transition-delay:.24s}
html footer .fcols > *:nth-child(5){transition-delay:.32s}
@media (prefers-reduced-motion:reduce){
  html footer .fcols > *{transition:none}
  html footer.f-wait .fcols > *{opacity:1;transform:none;filter:none}
}
@media (max-width:900px){
  html footer{padding-top:52px}
  html footer .fcols{grid-template-columns:repeat(2,minmax(0,1fr));gap:28px 20px}
}
@media (max-width:420px){
  html footer .fgroup a{font-size:14.5px}
}
/* the page end must stay reachable: the footer is taller than a phone screen, and a snap area
   taller than the viewport counts as snapped wherever you are inside it (round eleven's lesson),
   so its top is the stop and the rest scrolls freely under it. */
html footer{scroll-snap-align:start}
