/* UserGuard — Daylight.
   Generated from the approved concept. Edit the concept, re-run
   scratchpad/build-css.mjs; do not hand-edit this file. */
/* ═══════════════ faces ═══════════════
   Self-hosted, same as the rest of the site. A cookie-compliance company
   loading its own pages' fonts from a third-party CDN would be quoted back
   at us, and it would be a request we cannot gate behind consent because
   the page cannot render without it. */
@font-face{
  font-family:'Inter';
  src:url('/assets/fonts/InterVariable.woff2') format('woff2');
  font-weight:100 900;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'IBM Plex Mono';
  src:url('/assets/fonts/IBMPlexMono-500.woff2') format('woff2');
  font-weight:500;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'IBM Plex Mono';
  src:url('/assets/fonts/IBMPlexMono-600.woff2') format('woff2');
  font-weight:600;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'IBM Plex Mono';
  src:url('/assets/fonts/IBMPlexMono-700.woff2') format('woff2');
  font-weight:700;font-style:normal;font-display:swap;
}

/* ═══════════════ Daylight v2 · UserGuard multi-page concept ═══════════════
   Tokens mirror apps/web/app/globals.css so the drawn app surfaces and the
   marketing skin are one system. Green is the only accent; amber is
   needs-attention only. ────────────────────────────────────────────────── */
:root{
  --paper:#ffffff;
  --card:#ffffff;
  --sunken:#f4f4f3;
  --ink:#101711;
  --ink-2:#3d4c41;
  --ink-3:#5b6a5e;
  --ink-4:#636f66;
  --line:#dfe8dc;
  --line-2:#eaf1e7;
  --edge:#869686;
  --card-edge:rgb(16 23 17 / .055);
  --brand:#077410;
  --brand-hi:#0a8210;
  --brand-lo:#066210;
  --brand-soft:#bff0c2;
  --brand-wash:#eef8ee;
  --green-text:#077a0d;
  --green-deep:#0a5d10;
  --lead-wash:#f6fbf5;
  --lead-edge:#cfe6cf;
  --green-btn:#0a6b12;
  --green-btn-hi:#0a7a13;
  --warn:#8a5a00;
  --warn-wash:#fdf4e3;
  --font:'Inter',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',SFMono-Regular,Menlo,Consolas,monospace;
  --maxw:1320px;
  --maxw-wide:1420px;
  --radius-card:16px;
  --shadow-card:0 1px 1px rgb(16 23 17 / .03),0 4px 10px rgb(16 23 17 / .05),0 16px 40px rgb(16 23 17 / .07);
  --shadow-soft:0 1px 2px rgb(16 23 17 / .04),0 8px 24px rgb(16 23 17 / .06);
  --shadow-float:0 1px 2px rgb(16 23 17 / .05),0 10px 28px rgb(16 23 17 / .07),0 44px 90px -24px rgb(16 23 17 / .16);
  --ease:cubic-bezier(.22,.7,.3,1);
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:var(--font);color:var(--ink);background:var(--paper);
  line-height:1.65;font-size:16.5px;overflow-x:hidden;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
img{max-width:100%;height:auto;display:block}
a{color:inherit;text-decoration:none}
i,em.n{font-style:normal}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
h1,h2{font-weight:800;letter-spacing:-.042em;line-height:1.04;text-wrap:balance}
h1{font-size:clamp(2.5rem,1.3rem + 4.6vw,4.5rem)}
h2{font-size:clamp(1.8rem,1.28rem + 2.1vw,2.7rem);letter-spacing:-.036em;line-height:1.08}
h3{font-size:1.18rem;font-weight:700;letter-spacing:-.02em;line-height:1.28}
h1 em,h2 em{color:var(--green-text);font-style:normal}
p{text-wrap:pretty;overflow-wrap:break-word}
.tnum{font-variant-numeric:tabular-nums}
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ─────────── shared bits ─────────── */
.kicker{
  font-family:var(--mono);font-size:.72rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--green-text);
  display:inline-flex;align-items:center;gap:10px;
}
.kicker::before{content:"";width:22px;height:2px;background:currentColor;border-radius:2px}
.kicker--c::after{content:"";width:22px;height:2px;background:currentColor;border-radius:2px}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px;width:100%}
.wrap--wide{max-width:var(--maxw-wide)}
.wrap--tight{max-width:1040px}
/* The rhythm is a variable so that breakpoints can change the SIZE without
   re-declaring `padding`. They used to: `@media (max-width:900px){.section
   {padding:88px 0}}` sits 900 lines below `.section--top0{padding-top:0}` at
   the same specificity, so the shorthand quietly rewrote padding-top and the
   modifier — whose whole job is welding a continuation section to the one
   above it — was dead on every phone. Continuation joins got 88+88px instead
   of 88, which is why the gaps GREW as the screen shrank: 120px at 1440,
   176px at 375. Change --sec-y, never `padding`, and the modifier survives. */
.section{--sec-y:120px;padding:var(--sec-y) 0}
.section--top0{padding-top:0}
.sectionHead{max-width:720px;margin:0 auto 56px;text-align:center}
.sectionHead h2{margin-top:16px}
.sectionHead .sub{margin-top:18px;color:var(--ink-2);font-size:1.06rem}
.sectionHead--left{margin-left:0;text-align:left}
.hedge{max-width:74ch;margin:38px auto 0;text-align:center;font-size:.86rem;color:var(--ink-4);line-height:1.65}

.btn{
  display:inline-flex;align-items:center;gap:8px;justify-content:center;
  border-radius:999px;font-weight:600;font-size:.95rem;line-height:1;
  padding:14px 26px;border:1px solid transparent;cursor:pointer;white-space:nowrap;
  transition:background-color .15s,border-color .15s,transform .12s,box-shadow .15s,color .15s;
}
.btn--primary{background:var(--green-btn);color:#fff;box-shadow:inset 0 1px 0 rgb(255 255 255 / .14),0 1px 2.5px rgb(7 116 16 / .24)}
.btn--primary:hover{background:var(--green-btn-hi)}
.btn--ghost{background:#fff;border-color:var(--edge);color:var(--ink-2)}
.btn--ghost:hover{border-color:var(--ink-4);color:var(--ink)}
.btn--white{background:#fff;color:#0b3d10}
.btn--white:hover{background:var(--brand-wash)}
.btn--lg{padding:16px 30px;font-size:1rem}
.btn:active{transform:translateY(.5px)}
.btn .arr{font-weight:700;translate:0 -1px}

.chips{display:flex;flex-wrap:wrap;gap:9px;margin-top:26px}
.chip{
  font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--brand-lo);background:var(--brand-wash);border-radius:999px;padding:7px 14px;
}
.ticks{display:grid;gap:12px;margin-top:26px;list-style:none}
.ticks li{display:flex;gap:12px;align-items:flex-start;color:var(--ink-2);font-size:.98rem;line-height:1.55}
.ticks svg{color:var(--green-text);flex:none;margin-top:4px}

.card{
  border:1px solid var(--line);border-radius:20px;background:#fff;
  box-shadow:var(--shadow-soft);padding:28px 26px;
  transition:transform .2s var(--ease),box-shadow .2s var(--ease),border-color .2s;
}
.motion .lift:hover{transform:translateY(-4px);box-shadow:var(--shadow-float);border-color:var(--line-2)}
.card h3{margin-bottom:10px}
.card p{color:var(--ink-2);font-size:.95rem;line-height:1.62}
.grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:20px}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.split{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);gap:64px;align-items:center}

/* ─────────── floating pill nav ─────────── */
.navSpacer{height:16px}
.navZone{position:sticky;top:16px;z-index:70;padding:0 16px}
.nav{
  max-width:1120px;margin:0 auto;min-height:62px;
  display:flex;align-items:center;gap:14px;
  padding:0 10px 0 22px;border-radius:999px;
  background:rgb(255 255 255 / .86);border:1px solid var(--line);
  box-shadow:0 1px 2px rgb(16 23 17 / .04),0 12px 32px rgb(16 23 17 / .07);
  -webkit-backdrop-filter:blur(14px) saturate(150%);backdrop-filter:blur(14px) saturate(150%);
}
.nav__logo img{width:148px;height:auto}
.nav__links{display:flex;align-items:center;gap:2px;margin-left:6px}
.navlink,.menu__btn{
  display:inline-flex;align-items:center;gap:6px;
  font-size:.92rem;font-weight:500;color:var(--ink-2);
  padding:9px 14px;border-radius:999px;transition:background-color .15s,color .15s;
}
.navlink:hover,.menu__btn:hover{background:var(--brand-wash);color:var(--ink)}
.navlink.on,.menu__btn.on{background:var(--brand-wash);color:var(--brand-lo);font-weight:600}
.menu{position:relative}
.menu__btn svg{transition:transform .2s var(--ease);color:var(--ink-4)}
.menu.open .menu__btn svg{transform:rotate(180deg)}
.menu__panel{
  position:absolute;top:calc(100% + 12px);left:-8px;width:340px;
  background:#fff;border:1px solid var(--line);border-radius:18px;
  box-shadow:var(--shadow-float);padding:8px;z-index:80;
}
.js .menu__panel{opacity:0;visibility:hidden;transform:translateY(-8px) scale(.985);transform-origin:top left;transition:opacity .18s var(--ease),transform .18s var(--ease),visibility .18s}
.js .menu:hover .menu__panel,.js .menu:focus-within .menu__panel,.js .menu.open .menu__panel{opacity:1;visibility:visible;transform:none}
.menu__panel a{display:block;padding:10px 12px;border-radius:12px;transition:background-color .15s}
.menu__panel a:hover{background:var(--brand-wash)}
.menu__panel a.on{background:var(--brand-wash)}
.menu__panel b{display:block;font-size:.92rem;font-weight:600;color:var(--ink)}
.menu__panel a.on b{color:var(--brand-lo)}
/* Sans, not mono. These are sentences ("Consent UX that respects people"),
   not machine values, and the mobile twin at .navview__list span renders the
   byte-identical 13 strings in Inter already — the same words wore two
   typefaces depending on viewport. family/weight/letter-spacing are dropped
   rather than reset so this inherits, exactly as the mobile rule does.
   .76rem, not the mobile .8rem: this panel is a fixed 340px and .8rem wraps
   "Product analytics, session tools, support widgets" — as, measurably, did
   the mono it replaces. */
.menu__panel span{display:block;margin-top:4px;font-size:.76rem;line-height:1.4;color:var(--ink-4)}
.nav__cta{display:flex;align-items:center;gap:4px;margin-left:auto}
.nav__cta .signin{font-size:.92rem;font-weight:500;color:var(--ink-2);padding:9px 14px;border-radius:999px}
.nav__cta .signin:hover{background:var(--brand-wash);color:var(--ink)}
.nav__cta .btn{padding:11px 20px;font-size:.9rem}

/* ─────────── hero ─────────── */
.hero{position:relative;padding:92px 0 104px}
.hero__wash{position:absolute;inset:0;pointer-events:none;overflow:hidden}
.hero__wash::before,.hero__wash::after{content:"";position:absolute;border-radius:50%;filter:blur(90px)}
.hero__wash::before{width:1100px;height:620px;left:50%;top:-320px;margin-left:-550px;background:radial-gradient(closest-side,rgb(7 122 13 / .12),transparent)}
.hero__wash::after{width:900px;height:520px;left:50%;top:-180px;margin-left:-180px;background:radial-gradient(closest-side,rgb(191 240 194 / .5),transparent)}
.motion .hero__wash::before{animation:aurora1 26s ease-in-out infinite alternate}
.motion .hero__wash::after{animation:aurora2 32s ease-in-out infinite alternate}
@keyframes aurora1{from{transform:translate3d(-60px,0,0) scale(1)}to{transform:translate3d(70px,26px,0) scale(1.12)}}
@keyframes aurora2{from{transform:translate3d(40px,10px,0) scale(1.05)}to{transform:translate3d(-80px,-18px,0) scale(.94)}}
.hero__inner{position:relative;text-align:center}
.hero__badge{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:.7rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-2);background:#fff;border:1px solid var(--line);border-radius:999px;
  padding:8px 16px;box-shadow:0 1px 2px rgb(16 23 17 / .04);
}
.hero__badge i{width:7px;height:7px;border-radius:50%;background:var(--brand);box-shadow:0 0 0 3px var(--brand-wash)}
.hero h1{max-width:20ch;margin:26px auto 0}
.hero .lede{max-width:60ch;margin:24px auto 0;color:var(--ink-2);font-size:clamp(1.04rem,.97rem + .35vw,1.18rem);line-height:1.62}
.hero__actions{display:flex;gap:12px;justify-content:center;margin-top:34px;flex-wrap:wrap}
.hero__proof{display:flex;gap:10px 26px;justify-content:center;flex-wrap:wrap;margin-top:26px;font-size:.9rem;color:var(--ink-2);font-weight:500}
.hero__proof span{display:inline-flex;align-items:center;gap:7px}
.hero__proof svg{color:var(--green-text)}
.hero--sub{padding:76px 0 44px}
.hero--sub .hero__inner{text-align:center}

/* ─────────── regulation ticker ─────────── */
.ticker{padding:4px 0 10px}
.ticker__wrap{border:1px solid var(--line);border-radius:999px;background:#fff;padding:18px 34px;position:relative}
.ticker__track{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:12px 30px}
.ticker__set{display:contents}
.ticker__set--dup{display:none}
.ticker__wrap span{font-family:var(--mono);font-size:.7rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);white-space:nowrap}
.ticker__wrap span.lbl{color:var(--green-text)}
/* The fade rides on pseudo-elements, not a mask: a mask would dissolve the
   pill's own hairline along with the words, and the pill is the DNA. */
.motion .ticker__wrap{overflow:hidden}
.motion .ticker__wrap::before,.motion .ticker__wrap::after{content:"";position:absolute;top:1px;bottom:1px;width:72px;z-index:2;pointer-events:none}
.motion .ticker__wrap::before{left:1px;background:linear-gradient(90deg,#fff,rgb(255 255 255 / 0))}
.motion .ticker__wrap::after{right:1px;background:linear-gradient(270deg,#fff,rgb(255 255 255 / 0))}
.motion .ticker__track{flex-wrap:nowrap;justify-content:flex-start;width:max-content;gap:0;animation:marq 34s linear infinite}
.motion .ticker__set{display:flex;gap:30px;padding-right:30px}
.motion .ticker__set--dup{display:flex}
@keyframes marq{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}

/* ─────────── steps ─────────── */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.step{border:1px solid var(--line);border-radius:20px;background:#fff;padding:28px 24px;box-shadow:var(--shadow-soft);transition:transform .2s var(--ease),box-shadow .2s var(--ease)}
.step small{font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--green-text)}
.step h3{margin-top:12px;font-size:1.1rem}
.step p{margin-top:10px;color:var(--ink-2);font-size:.93rem;line-height:1.6}
.stepbig{display:grid;grid-template-columns:auto 1fr;gap:24px;align-items:start;padding:30px 0;border-top:1px solid var(--line-2)}
.stepbig:first-child{border-top:0}
.stepbig__n{font-family:var(--mono);font-size:1.5rem;font-weight:700;color:var(--brand-soft);line-height:1;letter-spacing:-.02em}
.stepbig h3{font-size:1.32rem}
.stepbig p{margin-top:10px;color:var(--ink-2);font-size:1rem;line-height:1.65;max-width:64ch}

/* ─────────── coverage cards ─────────── */
.cover{border:1px solid var(--line);border-radius:20px;background:#fff;box-shadow:var(--shadow-soft);padding:26px 24px;display:flex;flex-direction:column;gap:12px;transition:transform .2s var(--ease),box-shadow .2s var(--ease)}
.cover small{font-family:var(--mono);font-size:.63rem;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--green-text)}
.cover p{color:var(--ink-2);font-size:.94rem;line-height:1.6;flex:1}
.cover .go{font-size:.86rem;font-weight:600;color:var(--green-text)}

/* ─────────── figures / metered ledger ─────────── */
.figs{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line);border-radius:18px;overflow:hidden;background:var(--line-2);gap:1px}
.fig{background:#fff;padding:22px 20px}
.fig b{display:block;font-size:2.4rem;font-weight:800;letter-spacing:-.04em;line-height:1;font-variant-numeric:tabular-nums;color:var(--ink)}
.fig small{display:block;font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4);margin-top:10px}
.fig span{display:block;font-size:.86rem;color:var(--ink-3);margin-top:6px;line-height:1.45}
.meter{border:1px solid var(--line);border-radius:18px;overflow:hidden;background:#fff}
.meter__row{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.6fr);gap:16px;padding:15px 22px;border-top:1px solid var(--line-2)}
.meter__row:first-child{border-top:0}
.meter__row dt{font-family:var(--mono);font-size:.68rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.meter__row dd{font-size:.94rem;color:var(--ink-2)}

/* ─────────── enforcement ledger ─────────── */
.fines{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.fine{border:1px solid var(--line);border-radius:20px;background:#fff;box-shadow:var(--shadow-soft);padding:26px 24px;transition:transform .2s var(--ease),box-shadow .2s var(--ease)}
.fine b{display:block;font-size:2.5rem;font-weight:800;letter-spacing:-.045em;line-height:1;font-variant-numeric:tabular-nums;color:var(--ink)}
.fine .who{display:block;font-weight:700;margin-top:12px;font-size:1.02rem}
.fine p{margin-top:8px;color:var(--ink-2);font-size:.9rem;line-height:1.58}
.fine time{display:block;margin-top:14px;font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.12em;color:var(--ink-4)}

/* ─────────── comparison ─────────── */
.vs{max-width:1100px;margin:0 auto;border:1px solid var(--line);border-radius:20px;overflow:hidden;background:#fff;box-shadow:var(--shadow-soft)}
.vs__row{display:grid;grid-template-columns:1.35fr 1fr 1fr 1.1fr;border-top:1px solid var(--line-2)}
.vs__row:first-child{border-top:0}
.vs__row--head{background:var(--sunken)}
.vs__row--head .vc{font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.vc{padding:16px 20px;font-size:.9rem;display:flex;align-items:center;gap:9px;min-width:0}
.vc--crit{font-weight:600;color:var(--ink)}
.vc small{display:none;font-family:var(--mono);font-size:.58rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.vc--ug{background:var(--brand-wash);font-weight:600}
.vs__row--head .vc--ug{color:var(--brand-lo)}
.ic{width:17px;height:17px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;flex:none;font-size:.68rem;font-weight:800}
.ic--no{background:#f4e9e2;color:#9a4a1e}
.ic--mid{background:var(--line-2);color:var(--ink-4)}
.ic--yes{background:var(--green-btn);color:#fff}
.vc span.t{color:var(--ink-2)}
.vc--ug span.t{color:var(--brand-lo)}

/* ─────────── pricing ─────────── */
.price__big{display:flex;align-items:baseline;justify-content:center;gap:10px;margin-top:40px;line-height:1}
.price__big b{font-size:clamp(5rem,3.2rem + 7.4vw,9rem);font-weight:800;letter-spacing:-.055em;font-variant-numeric:tabular-nums}
.price__big span{font-family:var(--mono);font-size:.78rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.ledger{max-width:900px;margin:48px auto 0;display:grid;grid-template-columns:repeat(5,1fr);border:1px solid var(--line);border-radius:18px;overflow:hidden;background:#fff}
.ledger__stop{padding:20px 12px;border-left:1px solid var(--line-2);text-align:center}
.ledger__stop:first-child{border-left:0}
.ledger__stop.on{background:var(--brand-wash)}
.ledger__stop small{display:block;font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-4)}
.ledger__stop .rng{display:block;font-size:.76rem;color:var(--ink-3);margin-top:4px}
.ledger__stop b{display:block;font-size:1.3rem;font-weight:800;letter-spacing:-.02em;margin-top:6px;font-variant-numeric:tabular-nums}
.ledger__stop.on b{color:var(--green-text)}
.price__note{margin:26px auto 0;max-width:56ch;color:var(--ink-2);font-size:.95rem;text-align:center}
.price__note em{font-weight:600;color:var(--ink);font-style:normal}
.price__cta{margin-top:34px;display:flex;flex-direction:column;align-items:center;gap:12px}
.price__cta small{font-size:.85rem;color:var(--ink-4)}
.tiers{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.tier{border:1px solid var(--line);border-radius:20px;background:#fff;box-shadow:var(--shadow-soft);padding:26px 24px;display:flex;flex-direction:column;gap:8px;transition:transform .2s var(--ease),box-shadow .2s var(--ease)}
.tier.on{border-color:var(--brand-soft);background:linear-gradient(#fff,var(--brand-wash))}
.tier h3{font-size:1.06rem}
.tier .rng{font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.tier .amt{font-size:2rem;font-weight:800;letter-spacing:-.04em;font-variant-numeric:tabular-nums;margin-top:6px;line-height:1}
.tier .amt i{font-size:.8rem;font-weight:600;color:var(--ink-4);letter-spacing:0;font-family:var(--mono)}
.tier .off{font-size:.82rem;color:var(--green-text);font-weight:600}
.tier p{color:var(--ink-2);font-size:.9rem;line-height:1.55;flex:1;margin-top:6px}
.tier .btn{margin-top:14px}
.scale{margin-top:20px;border:1px solid var(--line);border-radius:20px;background:var(--sunken);padding:24px 26px;display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
.scale p{color:var(--ink-2);font-size:.98rem;max-width:70ch}
.included{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line-2);border:1px solid var(--line);border-radius:18px;overflow:hidden}
.included li{background:#fff;padding:18px 22px;font-size:.94rem;color:var(--ink-2);display:flex;gap:10px;align-items:flex-start;list-style:none}
.included svg{color:var(--green-text);flex:none;margin-top:3px}

/* ─────────── FAQ ─────────── */
.faq{max-width:900px;margin:0 auto;border:1px solid var(--line);border-radius:20px;background:#fff;overflow:hidden;box-shadow:var(--shadow-soft)}
.faq details{border-top:1px solid var(--line-2)}
.faq details:first-of-type{border-top:0}
.faq summary{list-style:none;cursor:pointer;padding:22px 26px;display:flex;gap:16px;align-items:center;justify-content:space-between;font-weight:600;font-size:1.02rem;transition:background-color .15s}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{background:var(--brand-wash)}
.faq summary::after{content:"+";font-family:var(--mono);font-size:1.3rem;font-weight:600;color:var(--green-text);flex:none;line-height:1}
.faq details[open] summary::after{content:"\2212"}
.faq p{padding:0 26px 24px;color:var(--ink-2);font-size:.96rem;line-height:1.7;max-width:80ch}

/* ─────────── blog ─────────── */
.lead{
  display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,.8fr);gap:44px;align-items:center;
  border:1px solid var(--line);border-radius:26px;background:linear-gradient(120deg,#fff,var(--brand-wash));
  box-shadow:var(--shadow-soft);padding:46px;
  transition:transform .2s var(--ease),box-shadow .2s var(--ease),border-color .2s;
}
.lead__stamp{display:flex;flex-wrap:wrap;align-items:center;gap:12px;font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-4)}
.lead__stamp i{font-style:normal;background:var(--green-btn);color:#fff;border-radius:999px;padding:5px 13px;letter-spacing:.14em}
.lead__stamp b{font-weight:600;color:var(--brand-lo)}
.lead h3{margin-top:20px;font-size:clamp(1.55rem,1.1rem + 1.7vw,2.35rem);letter-spacing:-.036em;line-height:1.1}
.lead p{margin-top:16px;color:var(--ink-2);font-size:1.04rem;line-height:1.62;max-width:54ch}
.lead__meta{margin-top:22px;font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.lead .go{display:inline-block;margin-top:22px;font-weight:600;color:var(--green-text)}
.cats{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-bottom:36px}
.cats i{font-family:var(--mono);font-size:.66rem;font-weight:600;font-style:normal;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);border:1px solid var(--line);border-radius:999px;padding:8px 15px}
.cats i.on{background:var(--green-btn);border-color:var(--green-btn);color:#fff}
.teasers{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.teaser{border:1px solid var(--line);border-radius:20px;background:#fff;padding:26px 24px;display:flex;flex-direction:column;gap:12px;box-shadow:var(--shadow-soft);transition:transform .2s var(--ease),box-shadow .2s var(--ease),border-color .2s}
.teaser small.cat{align-self:flex-start;font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--brand-lo);background:var(--brand-wash);border-radius:999px;padding:4px 12px}
.teaser h3{font-size:1.06rem}
.teaser p{color:var(--ink-2);font-size:.9rem;line-height:1.58;flex:1}
.teaser .meta{font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.allposts{display:block;text-align:center;margin-top:36px;font-weight:600;color:var(--green-text)}
/* Paging. Real <button>s built by script rather than links, because in this
   concept the pages are one route — the built site would give each page its
   own crawlable URL, and the control would become anchors then. */
.pager{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px;margin-top:44px}
.pager button{
  min-width:42px;height:42px;padding:0 15px;border:1px solid var(--line);border-radius:999px;background:#fff;
  font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);
  transition:background-color .15s,border-color .15s,color .15s;
}
.pager button:hover:not(:disabled){background:var(--brand-wash);border-color:var(--brand-soft);color:var(--brand-lo)}
.pager button[aria-current="page"]{background:var(--green-btn);border-color:var(--green-btn);color:#fff}
.pager button:disabled{opacity:.42;cursor:not-allowed}
.pager__count{text-align:center;margin-top:16px;font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}

/* ─────────── the answer panel: an industry page's opening question ─────────── */
.answer{
  max-width:960px;margin:0 auto;border:1px solid var(--brand-soft);border-radius:24px;
  background:linear-gradient(135deg,#fff,var(--brand-wash));box-shadow:var(--shadow-soft);padding:40px 44px;
}
.answer h2{font-size:clamp(1.35rem,1.05rem + 1.15vw,1.95rem);letter-spacing:-.03em}
.answer p{margin-top:18px;color:var(--ink-2);font-size:1.02rem;line-height:1.7}
.answer p:first-of-type{font-size:1.1rem;color:var(--ink);font-weight:500}
.answer .kicker{margin-bottom:14px}

/* ─────────── contact ─────────── */
.contactGrid{display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);gap:48px;align-items:start}
.contactList{display:grid;gap:18px;list-style:none}
.contactList li{display:flex;gap:14px;align-items:flex-start;font-size:.98rem;color:var(--ink-2);line-height:1.55}
.contactList i{width:32px;height:32px;flex:none;border-radius:10px;background:var(--brand-wash);color:var(--brand-lo);display:grid;place-items:center;font-family:var(--mono);font-weight:700;font-size:.85rem}
.contactList a{color:var(--green-text);font-weight:600}
.form{border:1px solid var(--line);border-radius:20px;background:#fff;box-shadow:var(--shadow-soft);padding:30px}
.form__row{margin-bottom:18px}
.form label{display:block;font-size:.8rem;font-weight:600;color:var(--ink-2);margin-bottom:.35rem}
.field{width:100%;padding:.65rem .8rem;font-size:.94rem;font-family:inherit;color:var(--ink);background:#fff;border:1px solid var(--edge);border-radius:8px}
.field:focus{outline:2px solid var(--brand-hi);outline-offset:1px;border-color:transparent}
textarea.field{min-height:150px;resize:vertical}

/* ═══════════════ app mockup — drawn from the real app ═══════════════ */
.frame{
  background:#fff;border:1px solid var(--line);border-radius:20px;
  box-shadow:var(--shadow-float);overflow:hidden;text-align:left;
}
.frame--hero{margin-top:70px}
.motion .frame--hero{animation:float 9s ease-in-out infinite}
@keyframes float{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(0,-9px,0)}}
.frame__bar{display:flex;align-items:center;gap:14px;padding:11px 16px;border-bottom:1px solid var(--line-2);background:#fcfdfc}
.frame__dots{display:flex;gap:6px}
.frame__dots i{width:9px;height:9px;border-radius:50%;background:var(--line)}
.frame__url{flex:1;max-width:300px;margin:0 auto;text-align:center;font-family:var(--mono);font-size:.68rem;font-weight:500;color:var(--ink-4);background:#fff;border:1px solid var(--line-2);border-radius:999px;padding:4px 14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.frame__bar::after{content:"";width:33px;flex:none}

.a-top{display:flex;align-items:center;height:56px;border-bottom:1px solid var(--line);background:rgb(255 255 255 / .8);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}
.a-brand{display:flex;align-items:center;height:100%;flex:none;width:216px;padding:0 22px;border-right:1px solid var(--line)}
.a-brand img{width:132px}
.a-topmain{display:flex;align-items:center;gap:12px;flex:1;min-width:0;padding:0 22px}
.a-switch{display:inline-flex;align-items:center;gap:8px;min-width:0;max-width:22rem;border:1px solid var(--line);background:var(--sunken);border-radius:999px;padding:6px 14px;font-size:.8rem}
.a-favi{width:18px;height:18px;flex:none;border-radius:5px;background:var(--brand);color:#fff;display:grid;place-items:center;font-size:.6rem;font-weight:700}
.a-switch b{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.a-switch svg{color:var(--ink-4);flex:none}
.a-kbd{margin-left:6px;border:1px solid var(--line-2);background:#fff;border-radius:4px;padding:0 4px;font-family:var(--mono);font-size:10px;color:var(--ink-4);flex:none}
.a-topright{margin-left:auto;display:flex;align-items:center;gap:12px;flex:none}
.a-avatar{width:26px;height:26px;border-radius:50%;background:var(--brand-wash);color:var(--brand-lo);display:grid;place-items:center;font-size:.66rem;font-weight:700}
.a-topright svg{color:var(--ink-4)}

.a-body{display:flex;min-height:340px;background:var(--paper)}
.a-side{width:216px;flex:none;border-right:1px solid var(--line);padding:14px 12px;display:flex;flex-direction:column;background:#fff}
.a-side h4{font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4);padding:0 12px 6px}
.a-side h4+h4,.a-side ul+h4{padding-top:20px}
.a-side ul{list-style:none;display:grid;gap:2px}
.a-side li{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:8px;font-size:.82rem;font-weight:500;color:var(--ink-2);position:relative}
.a-side li svg{color:var(--ink-4);flex:none}
.a-side li.on{background:var(--brand-wash);color:var(--brand-lo);font-weight:600}
.a-side li.on svg{color:var(--brand)}
.a-side li.on::before{content:"";position:absolute;left:0;top:4px;bottom:4px;width:3px;border-radius:999px;background:var(--brand)}
.a-collapse{margin-top:auto;padding-top:16px;border-top:1px solid var(--line-2);display:flex;align-items:center;gap:10px;font-size:.78rem;color:var(--ink-4);padding-left:12px}
.a-main{flex:1;min-width:0;padding:20px;display:grid;gap:20px;align-content:start;background:var(--paper)}

.a-card{background:var(--card);border:1px solid var(--card-edge);border-radius:var(--radius-card);box-shadow:var(--shadow-card);overflow:hidden}
.microlabel{font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.stamp{display:inline-flex;align-items:center;gap:.3rem;padding:.15rem .5rem;border-radius:999px;font-family:var(--mono);font-size:.68rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase;white-space:nowrap;box-shadow:inset 0 0 0 1px rgb(0 0 0 / .09)}
.stamp .dot{width:.45em;height:.45em;border-radius:999px;background:currentColor;flex-shrink:0}
.stamp .dot-off{background:transparent;box-shadow:inset 0 0 0 1.5px currentColor;opacity:.7}
.stamp-ok{background:var(--brand-wash);color:var(--brand-lo)}
.stamp-context{background:var(--line-2);color:var(--ink-3)}
.stamp-warn{background:var(--warn-wash);color:var(--warn)}
.stamp-off{background:transparent;color:var(--ink-4)}

.a-band__top{padding:20px}
.a-band__v{display:flex;align-items:center;gap:10px}
.a-band__v i{width:10px;height:10px;border-radius:50%;background:var(--brand);flex:none}
.a-band__v h3{font-size:1.5rem;font-weight:700;letter-spacing:-.02em}
.a-help{width:16px;height:16px;border-radius:50%;border:1px solid var(--line);color:var(--ink-4);font-size:10px;font-weight:700;display:grid;place-items:center;flex:none}
.a-band__sub{margin-top:5px;font-size:.86rem;line-height:1.55;color:var(--ink-3);max-width:72ch}
.a-band__pub{border-top:1px solid var(--line-2);padding:12px 16px;display:grid;gap:8px}
.a-pub{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line-2);border-radius:12px;overflow:hidden}
.a-pub>div{background:var(--card);padding:10px 12px;min-width:0}
.a-pub p{margin-top:5px}

.a-work__head{display:flex;align-items:center;justify-content:space-between;gap:12px;border-bottom:1px solid var(--line-2);padding:12px 16px}
.a-work__head h3{font-size:.88rem;font-weight:700;letter-spacing:-.01em}
.a-work__head span{font-size:.75rem;color:var(--ink-4)}
/* The description had NO rule here, so it inherited the body size and came
   out larger than the heading above it — the one place in the mockup where a
   card's blurb outshouted its title. Matches .a-sec__head p, which is the same
   thing in the other card shape. */
.a-work__head p{font-size:.8rem;color:var(--ink-3);margin-top:2px;font-weight:400}
.a-work__done{padding:14px 16px;display:flex;align-items:center;gap:10px;justify-content:space-between;flex-wrap:wrap}
.a-work__done p{font-size:.86rem;color:var(--ink-2)}
.a-work__done i{width:20px;height:20px;border-radius:50%;background:var(--brand);color:#fff;display:inline-grid;place-items:center;flex:none;font-size:.62rem;font-weight:800;vertical-align:-5px;margin-right:6px}
.a-rows{list-style:none}
/* Sized, like every other text element in the mockup. Without a rule here
   a row inherited the 1rem body size and rendered LARGER than the .88rem card
   title above it — the rows shouted over their own headings. .82rem matches
   .a-side li, the other repeated row in this frame. */
.a-row{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;padding:10px 12px;border-top:1px solid var(--line-2);font-size:.82rem}
.a-row:first-child{border-top:0}
.a-row.cur{background:rgb(238 248 238 / .6);box-shadow:inset 2px 0 0 var(--brand);padding:12px 16px}
.a-row__l{display:flex;align-items:center;gap:12px;min-width:0;flex:1}
.a-num{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;font-size:.68rem;font-weight:700;flex:none}
.a-num.done{background:var(--brand);color:#fff}
.a-num.cur{color:var(--brand);box-shadow:inset 0 0 0 2px var(--brand)}
.a-num.idle{color:var(--ink-4);box-shadow:inset 0 0 0 1px var(--line)}
.a-row b{font-size:.84rem;font-weight:600}
.a-row .det{display:block;font-size:.76rem;color:var(--ink-3);margin-top:2px;font-weight:400;line-height:1.45}
.a-mini{display:inline-flex;align-items:center;border:1px solid var(--edge);border-radius:999px;padding:4px 12px;font-size:.72rem;font-weight:600;color:var(--ink-2);white-space:nowrap;flex:none}

.a-sec__head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:12px}
.a-sec__head h3{font-size:.95rem;font-weight:700}
.a-sec__head p{font-size:.8rem;color:var(--ink-3);margin-top:2px}
.a-statrow{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line-2);border-radius:12px;overflow:hidden}
.a-tile{background:var(--card);padding:13px 14px}
.a-tile b{display:block;font-size:1.75rem;line-height:2.25rem;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums;margin-top:3px}
.a-gpc{font-size:.74rem;color:var(--ink-4);margin-top:12px;font-variant-numeric:tabular-nums}
.a-chart{margin-top:12px;max-width:100%;overflow-x:auto;overscroll-behavior-x:contain}
.a-chart>div{min-width:560px}
.a-chart svg{display:block;width:100%;height:auto}
.a-legend{display:flex;gap:16px;margin-top:8px;font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.a-legend i{display:inline-block;width:9px;height:9px;border-radius:3px;margin-right:6px;vertical-align:baseline}

.a-pad{padding:16px}
.a-evi{display:flex;flex-wrap:wrap;align-items:flex-start;gap:12px 26px}
.a-evi__g p{margin-bottom:6px}
.a-cells{display:flex;flex-wrap:wrap;gap:3px;max-width:260px}
.d{width:12px;height:12px;border-radius:3px;background:var(--brand)}
.d--o{background:transparent;box-shadow:inset 0 0 0 2px var(--brand)}
.d--a{background:transparent;box-shadow:inset 0 0 0 2px var(--warn)}
.a-note{margin:0;padding:10px 16px 14px;font-size:.72rem;color:var(--ink-4);line-height:1.5}

.a-console{background:#fff;border-top:1px solid var(--line-2);font-family:var(--mono);font-size:.72rem}
.a-console__cmd{padding:12px 16px;border-bottom:1px solid var(--line-2);color:var(--ink-2)}
.a-console__cmd i{color:var(--green-text);margin-right:8px}
.a-console__cmd span{display:block;color:var(--ink-4);margin-top:6px;font-size:.68rem}
.a-sig{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:8px 16px;border-bottom:1px solid var(--line-2)}
.a-sig b{font-weight:500;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.a-tot{padding:12px 16px;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.a-tot b{font-family:var(--font);font-size:1.6rem;font-weight:800;letter-spacing:-.03em;color:var(--green-text);font-variant-numeric:tabular-nums}
.a-tot span{font-size:.72rem;color:var(--ink-3)}

/* a visitor-facing stage: the page's own surfaces, on the site's ground */
.a-stage{
  background:var(--sunken);padding:36px 28px;
  display:flex;flex-wrap:wrap;gap:26px;justify-content:center;align-items:flex-start;
  background-image:radial-gradient(rgb(16 23 17 / .045) 1px,transparent 1px);
  background-size:22px 22px;
}

/* ─── the visitor-facing surfaces, drawn from the real embed ───
   Mirrors packages/embed/src/ug.js so the mock and the shipped product are
   the same object: icon-chip header row, 13px body, equal-weight pill
   actions, role="switch" pills, dashed row rules, and the mono "Powered by"
   band. Accent and radius are the embed's own defaults (#077410 / 14px). */
.ugw{
  --acc:#077410;--edge2:rgb(0 0 0 / .12);
  width:100%;background:#fff;color:#101713;text-align:left;
  border:1px solid rgb(0 0 0 / .15);border-radius:14px;
  box-shadow:0 10px 40px rgb(0 0 0 / .18);overflow:hidden;
  display:flex;flex-direction:column;font-size:14px;line-height:1.5;
}
.ugw--banner{max-width:380px}
.ugw--prefs{max-width:440px}
.ugw--a11y{max-width:320px}
.ugw--dns{max-width:440px;display:block;padding:20px}
.ugw__head{display:flex;align-items:center;gap:9px;padding:13px 16px;border-bottom:1px solid var(--edge2)}
.ugw__chip{width:24px;height:24px;border-radius:7px;flex:none;display:grid;place-items:center;background:#e4f3e5;color:var(--acc)}
.ugw__head h2,.ugw__head h4{flex:1;min-width:0;margin:0;font-size:14px;font-weight:700;line-height:1.3;letter-spacing:0}
.ugw__x{flex:none;opacity:.55;display:grid;place-items:center}
.ugw__body{margin:0;padding:12px 16px 0;font-size:13px;opacity:.85}
.ugw__intro{margin:0;padding:12px 16px 2px;font-size:12.5px;opacity:.75;line-height:1.5}
.ugw__acts{display:flex;gap:8px;flex-wrap:wrap;padding:14px 16px 4px}
.ugw__b{padding:8px 16px;border-radius:999px;font-weight:600;font-size:13px;font-style:normal;text-align:center;white-space:nowrap}
/* Every consent choice is --pri: Accept and Reject on the banner, and Allow
   all, Reject all and Save choices in the preference centre, because the embed
   draws them all as one button. White and the 1px accent edge are what core's
   labelOn and choiceBorder return for #077410 on white; the edge matches the
   fill and is there so every choice is the same size. --gho is left to the
   accessibility panel's Reset all, which is not a consent choice. */
.ugw__b--pri{background:var(--acc);color:#fff;border:1px solid var(--acc)}
.ugw__b--gho{border:1px solid rgb(128 128 128 / .45)}
.ugw__acts .ugw__b{flex:1 1 120px}
.ugw__pref{flex:1 1 100%;padding:6px;font-size:13px;font-style:normal;text-align:center;text-decoration:underline}
.ugw__link{display:inline-block;margin:0 16px 12px;font-size:12px;opacity:.75}
.ugw__stmt{display:block;margin:0 16px 12px;font-size:12px;opacity:.75;text-align:center}
.ugw__foot{
  display:flex;align-items:center;justify-content:center;gap:6px;
  font-family:var(--mono);font-size:9.5px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  opacity:.6;padding:7px 10px;border-top:1px solid var(--edge2);background:rgb(0 0 0 / .03);
}
.ugw__foot img{width:64px;height:12px;object-fit:contain}
.ugw__cat{padding:11px 16px;border-bottom:1px dashed var(--edge2)}
.ugw__cat--last{border-bottom:0}
.ugw__catrow{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}
.ugw__catl{flex:1;min-width:0;display:flex;align-items:flex-start;gap:8px}
.ugw__chev{flex:none;margin-top:2px;display:inline-flex;opacity:.6}
.ugw__chev--open{transform:rotate(90deg)}
.ugw__catl b{display:block;font-size:13.5px;font-weight:700}
.ugw__catl i{display:block;font-size:11.5px;font-style:normal;opacity:.7;line-height:1.45}
.ugw__always{flex:none;font-size:10px;font-weight:700;font-style:normal;letter-spacing:.05em;text-transform:uppercase;padding:3px 9px;border-radius:999px;opacity:.75;border:1px solid var(--edge2);white-space:nowrap}
/* Every drawn switch, in the preference centre and the accessibility panel
   alike, as the embed's preference centre draws them. Off is hollow: a 1px
   ring and a 12px knob in choiceBorder(bg, bg, text), the first step from
   this white panel toward #101713 that reads at 3:1, which is #888b89 at
   3.44:1. On is the accent with the choices' 1px edge (the accent itself on
   white) and the accent's label ink for the knob (white on #077410). Fill
   against outline carries the state whatever the accent is; the pale #cfd8cc
   track this replaced was 1.46:1, an off state that barely showed. */
.ugw__sw{position:relative;flex:none;width:36px;height:20px;border-radius:999px;background:transparent;box-shadow:inset 0 0 0 1px #888b89}
.ugw__sw::after{content:"";position:absolute;top:4px;left:4px;width:12px;height:12px;border-radius:50%;background:#888b89}
.ugw__sw--on{background:var(--acc);box-shadow:inset 0 0 0 1px var(--acc)}
.ugw__sw--on::after{top:2px;left:18px;width:16px;height:16px;background:#fff;box-shadow:0 1px 2px rgb(0 0 0 / .3)}
.ugw__disc{margin-top:8px;display:grid;gap:8px}
.ugw__ck{display:grid;gap:4px;padding:9px 11px;border-radius:8px;background:rgb(128 128 128 / .07);font-size:12px}
.ugw__ck>div,.ugw__ck>span{display:flex;gap:10px;align-items:baseline}
.ugw__ck .k{flex:none;width:62px;font-size:10.5px;font-weight:600;opacity:.55}
.ugw__ck .v{min-width:0;overflow-wrap:anywhere;opacity:.85}
.ugw__ck .v.mn{font-family:var(--mono);font-weight:600;font-size:11.5px;opacity:1}
.ugw__end{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;padding:12px 16px 14px}
/* The preference centre's three choices sit in the embed's equal columns,
   repeat(auto-fit,minmax(120px,1fr)), not a flex row: wrapped on a phone, a
   flex row stretches whichever button lands alone to twice the others. */
.ugw--prefs .ugw__end{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr))}
.ugw__ctl{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;border-bottom:1px dashed var(--edge2)}
.ugw__ctl--last{border-bottom:0}
.ugw__ctl b{display:flex;align-items:center;gap:8px;min-width:0;font-size:13.5px;font-weight:600}
.ugw__ctl b svg{flex:none;opacity:.75}
.ugw__step{display:inline-flex;flex:none;border:1px solid rgb(0 0 0 / .18);border-radius:8px;overflow:hidden}
.ugw__step i{padding:5px 10px;font-size:12px;font-weight:700;font-style:normal;color:#374151;background:#fff;border-right:1px solid rgb(0 0 0 / .12)}
.ugw__step i:last-child{border-right:0}
.ugw__step i.on{background:var(--acc);color:#fff}
/* The floating launcher is a SOLID accent circle with a white glyph — the
   embed's `ug-a11y-btn` / `ug-tab`: 48px, radius 999px, background:accent,
   icon in the accent's label colour, 0 2px 12px shadow. It is deliberately
   NOT the header chip's treatment (light tint + dark-green glyph).
   `--acc` is declared on `.ugw`, and the launcher is a SIBLING of `.ugw`
   inside `.ugw-corner` — so the bare `var(--acc)` was invalid here and the
   background fell back to `initial`: a transparent circle with a white icon
   on it, which is what the washed-out button was. Fallback + a scoped
   declaration on the corner so neither path can lose the colour again. */
.ugw__launch{width:48px;height:48px;flex:none;border-radius:999px;background:var(--acc,#077410);color:#fff;display:grid;place-items:center;box-shadow:0 2px 12px rgb(0 0 0 / .25)}
.ugw__launch svg{display:block}
/* the real corner arrangement: panel above, launcher below-right */
.ugw-corner{--acc:#077410;display:flex;flex-direction:column;align-items:flex-end;gap:12px;max-width:320px;width:100%}
.a-stage--page{justify-content:space-between;align-items:stretch;gap:36px;flex-wrap:wrap}
.ph-page{flex:1 1 280px;min-width:0;display:flex;flex-direction:column;gap:13px;padding-top:6px}
.ph-page i{display:block;height:12px;border-radius:999px;background:rgb(16 23 17 / .08)}
.ph-page i.t{height:26px;width:58%;background:rgb(16 23 17 / .13);margin-bottom:6px}
.ph-page i.s{width:80%}
.ph-page i.q{width:44%}
.ugw__dnsh{display:block;margin:0 0 8px;font-size:16px;font-weight:700;line-height:1.3;letter-spacing:0}
.ugw__dnsb{display:block;margin:0 0 14px;font-size:14px;line-height:1.5}
.ugw__dnsa{display:flex;gap:8px;flex-wrap:wrap}
.ugw__dnsa i{padding:10px 12px;border-radius:8px;font-size:14px;font-weight:600;font-style:normal;text-align:center}
.ugw__dnsa i.pri{flex:1 1 160px;background:var(--acc);color:#fff}
.ugw__dnsa i.gho{flex:0 0 auto;border:1px solid rgb(0 0 0 / .25)}
.ugw__strip{
  width:100%;max-width:440px;background:#fff;border:1px solid rgb(0 0 0 / .12);border-radius:12px;
  box-shadow:var(--shadow-soft);padding:14px 16px;font-size:12px;color:var(--ink-3);
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;
}
.ugw__strip u{color:var(--ink);font-weight:600}
.ugw__strip em{font-style:normal;color:var(--green-text);font-weight:600}

/* ─── home: the four visitor-facing surfaces, one full-width row each ───
   Four cramped tiles became four rows, because each of these is a whole
   product surface and none of them fits in a third of a grid. Widget and
   words alternate sides down the page.

   The alternation is PRESENTATIONAL: every row is stage-then-words in the
   DOM, and `order` flips the even ones. The stage is aria-hidden, so a
   screen reader hears four identical, correctly-ordered blocks of copy no
   matter which way a row faces.

   Column ratio is tuned, not arbitrary. At the 1320px measure the content
   box is 1272px; minus the 48px gutter that is 1224px, and 1.55/2.55 of it
   is 744px of stage — exactly 680px of drawing once the 32px side padding
   is off. 680px is the preference centre's real modal width. */
.surfaces{display:flex;flex-direction:column;gap:88px}
.surface{display:flex;align-items:center;gap:48px}
.surface--flip .surface__stage{order:2}
.surface__stage{
  /* 1.22, down from 1.55 (owner: give the text room and balance the
     row). At the 1320 measure that is ~672px of stage against ~551px of
     copy — the copy column clears 60ch, which is where a paragraph stops
     fighting its own line breaks. Side padding drops with it so the
     drawings keep close to the widths they actually ship at. */
  flex:1.22 1 0;min-width:0;
  border:1px solid var(--line);border-radius:24px;background:var(--sunken);
  background-image:radial-gradient(rgb(16 23 17 / .045) 1px,transparent 1px);
  background-size:22px 22px;
  box-shadow:var(--shadow-soft);
  padding:46px 22px;min-height:300px;
  display:flex;align-items:center;justify-content:center;
  transition:transform .2s var(--ease),box-shadow .2s var(--ease),border-color .2s;
}
.motion .surface:hover .surface__stage{transform:translateY(-4px);box-shadow:var(--shadow-float);border-color:var(--line-2)}
.surface__copy{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:12px}
.surface__copy small{font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--green-text)}
.surface__copy h3{font-size:clamp(1.3rem,1.04rem + .72vw,1.62rem);letter-spacing:-.028em;line-height:1.21}
.surface__copy p{color:var(--ink-2);font-size:1rem;line-height:1.62}
.surface__copy .go{margin-top:4px;font-size:.9rem;font-weight:600;color:var(--green-text)}
.surface:hover .surface__copy .go{text-decoration:underline;text-underline-offset:3px}
/* The preference centre at the width it actually opens at:
   `width:min(680px,calc(100vw - 32px))` in packages/embed/src/ug.js. The
   440px drawing only ever existed so it could sit beside the banner. */
.surface__stage .ugw--prefs{max-width:680px;width:100%}
/* Do Not Sell owns a row, so both halves of the mechanism fit at once:
   the footer link with its GPC marker, reading as a real footer bar, and
   the panel that link opens sitting above it. */
.dnsGroup{display:flex;flex-direction:column;align-items:center;gap:26px;width:100%;max-width:560px}
.dnsGroup .ugw--dns{max-width:440px}
.dnsGroup .ugw__strip{max-width:none;width:100%;justify-content:space-between}

/* ═══════════════ card iconography ═══════════════
   The text-only grids were bold-headline-plus-paragraph, repeated. Each card
   in one now carries a single line icon in a pale tinted chip, and each GRID
   (never each card) carries one accent device so the eye has one anchor.
   The chip is the embed's own lighten(accent) pairing — pale ground, deep
   green glyph. Solid green stays reserved for launcher buttons and primary
   CTAs, and amber stays reserved for needs-attention inside app mockups. */
/* the glyph sprite itself renders nothing; <use> pulls from it */
.isprite{position:absolute;width:0;height:0;overflow:hidden}
.cico{
  width:38px;height:38px;flex:none;border-radius:11px;
  display:grid;place-items:center;margin-bottom:14px;
  background:var(--brand-wash);color:var(--green-deep);
}
.cico svg{display:block;width:20px;height:20px}
.cico--num{font-family:var(--mono);font-size:.78rem;font-weight:600;letter-spacing:.03em}
.cover .cico{margin-bottom:2px}
.step .cico{margin-bottom:12px}

/* the three accent devices, varied section to section so no page repeats one */
.card--wash,.cover--wash{background:var(--lead-wash);border-color:var(--lead-edge)}
/* The accent rule is a 3px bar pinned to an edge, and a bar cannot round
   itself into a corner it does not know the size of: at left:0/right:0 it
   spans the padding box and runs straight past the point where the card's
   corner curves away, which reads as a line sitting on top of the card
   rather than part of it. `overflow:hidden` on the card clips the bar to
   the card's own rounded shape, so one radius change can never desync the
   two again. (A card's own box-shadow is painted outside its border box and
   is not affected by its overflow, so the float treatment survives.) */
.card--rule,.cover--rule,.card--lrule,.cover--lrule,.cardrows--rule{position:relative;overflow:hidden}
.card--rule::before,.cover--rule::before,.cardrows--rule::before{
  content:"";position:absolute;left:0;right:0;top:0;height:3px;
  background:var(--brand);z-index:1;
}
.card--lrule::before,.cover--lrule::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--brand);z-index:1;
}

/* rhythm A: a lead card that spans its grid and turns icon-left */
.card--wide{
  grid-column:1 / -1;display:grid;
  grid-template-columns:auto minmax(0,1fr);gap:6px 24px;align-items:start;
}
.card--wide .cico{width:46px;height:46px;border-radius:14px;grid-row:1 / span 2;margin:0}
.card--wide .cico svg{width:24px;height:24px}
.card--wide h3{grid-column:2;font-size:1.34rem;letter-spacing:-.026em}
.card--wide p{grid-column:2}

/* rhythm B: a stacked card column becomes icon-led ledger rows on hairlines */
.cardrows{
  border:1px solid var(--line);border-radius:20px;background:#fff;
  box-shadow:var(--shadow-soft);overflow:hidden;
}
.cardrows .card{
  border:0;border-radius:0;box-shadow:none;background:transparent;
  border-top:1px solid var(--line-2);padding:20px 24px;
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:4px 16px;align-items:start;
}
.cardrows .card:first-child{border-top:0}
.cardrows .card .cico{width:34px;height:34px;border-radius:10px;grid-row:1 / span 2;margin:0}
.cardrows .card .cico svg{width:18px;height:18px}
.cardrows .card h3{grid-column:2;font-size:1.02rem;margin:0}
.cardrows .card p{grid-column:2}
.cardrows .card--wash{background:var(--lead-wash)}
.motion .cardrows .card.lift:hover{transform:none;box-shadow:none}

/* consent record receipt */
.a-receipt{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;background:var(--line-2);border-radius:12px;overflow:hidden}
.a-receipt>div{background:var(--card);padding:11px 14px;min-width:0}
.a-receipt p{font-size:.84rem;color:var(--ink);margin-top:4px;font-variant-numeric:tabular-nums;overflow-wrap:break-word}

/* ═══════════════ light-green CTA panel ═══════════════ */
.cta{padding:0 0 120px}
.cta__panel{
  position:relative;overflow:hidden;border-radius:32px;
  background:linear-gradient(135deg,#0a6b12 0%,#077410 52%,#0a8210 100%);
  padding:82px 64px;color:#fff;box-shadow:0 24px 70px -28px rgb(7 116 16 / .55);
}
.cta__panel::before{content:"";position:absolute;inset:0;background:radial-gradient(720px 420px at 84% 8%,rgb(255 255 255 / .16),transparent 62%);pointer-events:none}
/* The mark is brand green (#008f05) in the asset, so it has to be forced
   white to read on a green panel. grayscale()+brightness() only lifted it
   to a mid tone, which at .12 was invisible — the panel just looked half
   empty. brightness(0) invert(1) is absolute: any source colour becomes
   white, and the opacity alone then decides how present it is.
   That opacity was then set at .17, which measures 1.42:1 against the
   panel's mid gradient stop — technically painting, and reported twice as
   not visible, which is the same thing. .32 measures 2.10:1: unmistakably
   there, and still well under the white headline's 6.02:1, so it reads as
   a watermark rather than competing with the words.
   The bleed came in with it. At right:-40/bottom:-70 a quarter of the mark
   was outside the panel's overflow:hidden, and what survived was a pair of
   curved bands — an abstract swoosh, not a shield. */
/* Bleed right, never down. The asset ends at 178.12,375.02 in its viewBox —
   the shield point sits at bottom-centre ON the boundary, so any negative
   `bottom` under .cta__panel overflow:hidden cuts off the one feature that
   makes the silhouette read as a shield. bottom:-52px was taking 13% of the
   mark height. The right edge is a bulge, not a terminus, so it bleeds safely.
   Explicit height keeps the geometry deterministic if the fetch ever fails. */
.cta__shield{position:absolute;right:-28px;bottom:0;width:400px;height:400px;opacity:.32;pointer-events:none;filter:brightness(0) invert(1)}
.cta__inner{position:relative;max-width:600px}
.cta__logo{width:132px;margin-bottom:28px}
.cta .kicker{color:#c7f0c9}
.cta h2{margin-top:16px;color:#fff}
.cta p{margin-top:16px;color:#dcf1dc;max-width:52ch}
.cta__actions{display:flex;align-items:center;gap:18px;margin-top:32px;flex-wrap:wrap}
.cta__note{font-size:.85rem;color:#c7e6c8}

/* ═══════════════ footer ═══════════════ */
.footer{border-top:1px solid var(--line);padding:56px 0 40px}
/* A grid, not flex-wrap.
   As flex this row fitted only by luck, and the longer column labels took
   the luck away: brand 320 + gap 48 + five intrinsic columns 913 = 1281
   against a 1272px content box. Nine pixels over, so the whole column block
   wrapped to its own line — and there `justify-content:space-between` had a
   single item to distribute, which left it hard left with the right half of
   the footer empty.
   A grid hands the columns whatever space is actually left instead of
   asking whether they happen to fit, so no label length can wrap the
   layout again. */
.footer__top{display:grid;grid-template-columns:minmax(0,320px) minmax(0,1fr);gap:48px 56px;align-items:start}
.footer__brand{max-width:320px}
.footer__brand img{width:150px}
.footer__brand p{margin-top:16px;font-size:.86rem;color:var(--ink-4);line-height:1.6}
/* `auto` tracks plus space-between: each column takes the width its longest
   label actually needs, and the slack is shared between them — so nothing
   wraps mid-label and the last column lands flush with the container's
   right edge instead of trailing off into dead space. */
/* The 20px column-gap is a FLOOR, not the look: space-between pours all the
   slack into the gutters, so at 1440 these still sit 52px apart. Its only job
   is to postpone the squeeze — `auto` tracks shrink toward min-content once
   brand + gap + columns exceeds the content box, and every extra px of
   declared gap brings that point forward. At 20px the row stays wrap-free
   down to a 1136px content box, which is past where the layout stacks. */
.footer__cols{display:grid;grid-template-columns:repeat(5,auto);justify-content:space-between;gap:26px 20px}
.footer__cols b{display:block;font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-4);margin-bottom:14px}
.footer__cols a{display:block;font-size:.88rem;color:var(--ink-2);margin-top:8px}
.footer__cols a:hover{color:var(--green-text)}
.footer__bottom{margin-top:48px;padding-top:22px;border-top:1px solid var(--line-2);display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;font-size:.82rem;color:var(--ink-4)}
.footer__bottom a{color:var(--ink-2)}
.footer__bottom a:hover{color:var(--green-text)}
/* The entity block. Answer engines and knowledge panels want to know WHO is
   speaking before they will quote what was said, and that is the one thing a
   column of product links never states. Name, what it is, where it is, how to
   reach it — in the footer, on every page, in the same words as the JSON-LD
   at the bottom of the document. */
.footer__ent{display:grid;gap:7px;margin-top:20px}
.footer__ent div{display:flex;gap:12px;font-size:.82rem;color:var(--ink-3);line-height:1.5}
.footer__ent b{font-family:var(--mono);font-size:.58rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4);min-width:64px;flex:none;padding-top:3px}
.footer__ent a{color:var(--ink-2)}
.footer__ent a:hover{color:var(--green-text)}
/* Questions, phrased the way people ask them — each one the H1 of the page it
   points at. Ordinary nav labels ("SaaS", "GDPR") are nouns; these are the
   query. Cheap to carry, and the only footer row that reads as an answer. */
.footer__ask{margin-top:46px;padding-top:26px;border-top:1px solid var(--line-2)}
.footer__ask > b{display:block;font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-4)}
.footer__askgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px 40px;margin-top:14px}
.footer__askgrid a{display:block;padding:6px 0;font-size:.88rem;color:var(--ink-2);line-height:1.45}
.footer__askgrid a:hover{color:var(--green-text)}
.footer__mach{margin-top:14px;font-family:var(--mono);font-size:.66rem;letter-spacing:.06em;color:var(--ink-4)}
.footer__mach a{color:var(--ink-3)}
.footer__mach a:hover{color:var(--green-text)}
/* A cookie-consent vendor whose own footer has no way to change your mind
   would be the loudest possible advertisement against the product. */
.footer__prefs{color:var(--ink-2);font-weight:600;text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--brand-soft)}
.footer__prefs:hover{color:var(--green-text)}

/* ═══════════════ long-form: legal documents and articles ═══════════════ */

.doc{display:grid;grid-template-columns:224px minmax(0,1fr);gap:64px;align-items:start}
/* Sticky, because a legal page is not read — it is searched. The contents
   list is the only navigation a fourteen-section document has. */
.doc__toc{position:sticky;top:92px}
.doc__toc > b{display:block;font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-4);margin-bottom:12px;padding:0 12px}
.doc__toc a{display:block;padding:7px 12px;border-radius:8px;font-size:.85rem;line-height:1.4;color:var(--ink-3);transition:background-color .15s,color .15s}
.doc__toc a:hover{background:var(--brand-wash);color:var(--brand-lo)}
.docHead{border:1px solid var(--line);border-radius:20px;background:linear-gradient(120deg,#fff,var(--brand-wash));box-shadow:var(--shadow-soft);padding:26px 30px;margin-bottom:46px}
.docHead__facts{display:flex;flex-wrap:wrap;gap:16px 44px}
.docHead__facts div b{display:block;font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-4)}
.docHead__facts div span{display:block;margin-top:5px;font-size:.92rem;font-weight:600;color:var(--ink)}
.docHead > p{margin-top:20px;padding-top:18px;border-top:1px solid var(--lead-edge);font-size:.94rem;line-height:1.65;color:var(--ink-2);max-width:70ch}

.prose{max-width:72ch}
.prose h2{font-size:1.3rem;font-weight:700;letter-spacing:-.028em;line-height:1.24;margin-top:54px;padding-top:28px;border-top:1px solid var(--line-2);scroll-margin-top:96px}
.prose > h2:first-child{margin-top:0;padding-top:0;border-top:0}
.prose h3{margin-top:30px;font-size:1.02rem;font-weight:700;letter-spacing:-.015em}
.prose p{margin-top:14px;color:var(--ink-2);font-size:1rem;line-height:1.75}
.prose ul,.prose ol{margin-top:14px;padding-left:24px;display:grid;gap:9px;color:var(--ink-2);font-size:1rem;line-height:1.7}
.prose li::marker{color:var(--green-text)}
.prose a{color:var(--green-text);font-weight:500;text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--brand-soft)}
.prose strong{font-weight:650;color:var(--ink)}
/* .tldr is a SIBLING of .prose inside .artBody, not a descendant, and there
   is no bare code{} anywhere in this stylesheet — so the TL;DR box rendered
   its <code> spans as plain text while visually identical ones a few lines
   later, inside .prose, rendered as chips. */
.prose code,.tldr code,.pull code{font-family:var(--mono);font-size:.86em;background:var(--sunken);border-radius:5px;padding:2px 6px}
/* Section numbers are not decoration here: a DPA cites "section 6 of the
   Privacy Policy", so the number is part of the document's address. */
.prose--num{counter-reset:sec}
.prose--num > h2{counter-increment:sec}
.prose--num > h2::before{content:counter(sec) ". ";font-family:var(--mono);font-size:.82em;font-weight:600;color:var(--green-text)}
.prose__tbl{margin-top:18px;overflow-x:auto;overscroll-behavior-x:contain;border:1px solid var(--line);border-radius:14px}
.prose__tbl table{border-collapse:collapse;width:100%;min-width:520px;font-size:.88rem}
.prose__tbl th,.prose__tbl td{text-align:left;padding:11px 14px;border-bottom:1px solid var(--line-2);vertical-align:top;line-height:1.5}
.prose__tbl tr:last-child td{border-bottom:0}
.prose__tbl thead th{font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-4);background:#fcfdfc}
.prose__tbl td{color:var(--ink-2)}
.prose__tbl td:first-child{font-weight:600;color:var(--ink)}

/* The article view */
.artHead{max-width:840px;margin:0 auto;text-align:center}
/* .artHead sits INSIDE the hero, and .artHead h1 TIES .hero h1 at (0,1,1).
   Source order gave it font-size, but it declared no max-width — so
   .hero h1 max-width:20ch stayed unopposed and the article headline came out
   NARROWER than the 720px prose it heads. Same story for the lede at 60ch. */
.artHead h1{font-size:clamp(2.1rem,1.3rem + 3.1vw,3.4rem);max-width:none;margin:26px auto 0}
.artHead .lede{max-width:68ch}
.artMeta{display:flex;justify-content:center;flex-wrap:wrap;gap:8px 22px;margin-top:28px;font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.artBody{max-width:720px;margin:0 auto}
/* The short answer, first. It is what a person skimming wants and what an
   answer engine lifts — and putting it up top costs the article nothing,
   because anyone who wants the reasoning keeps reading. */
.tldr{border:1px solid var(--brand-soft);border-radius:20px;background:linear-gradient(135deg,#fff,var(--brand-wash));box-shadow:var(--shadow-soft);padding:28px 30px;margin-bottom:44px}
.tldr > b{display:block;font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-4)}
.tldr p{margin-top:12px;font-size:1.06rem;line-height:1.65;color:var(--ink);font-weight:500}
.pull{margin:36px 0;padding:4px 0 4px 26px;border-left:3px solid var(--brand-soft);font-size:1.16rem;line-height:1.55;letter-spacing:-.018em;font-weight:600;color:var(--ink)}
/* The only .pull in the document is nested inside a .prose, and `.prose p` is
   (0,1,1) against .pull (0,1,0) — one type selector, so the tie is decided on
   specificity before source order and being later in the file does not help.
   Without this the pull-quote rendered as an ordinary body paragraph that
   happened to have a green rule beside it. */
.prose p.pull{margin:36px 0;font-size:1.16rem;line-height:1.55;color:var(--ink)}
.artFoot{max-width:720px;margin:56px auto 0;padding-top:26px;border-top:1px solid var(--line)}
.author{display:flex;gap:16px;align-items:flex-start}
.author i{width:44px;height:44px;flex:none;border-radius:50%;background:var(--brand-wash);color:var(--brand-lo);display:grid;place-items:center;font-family:var(--mono);font-weight:700;font-size:.92rem;font-style:normal}
.author b{display:block;font-size:.95rem}
.author p{margin-top:4px;font-size:.88rem;color:var(--ink-3);line-height:1.6;max-width:60ch}

/* The site's own preference centre, opened from the footer. Built with real
   role="switch" buttons rather than cloning the decorative widget mockup:
   on an accessibility vendor's own site, a control panel you cannot operate
   with a keyboard is the worst possible thing to ship. */
/* `margin:auto` is load-bearing and is NOT the UA default here: a modal
   <dialog> is centred by the UA pairing `inset:0` with `margin:auto`, and
   this stylesheet opens with `*{margin:0}`, which wins and pins the panel to
   the top-left corner. Restoring the margin is the whole fix. */
.prefsModal{border:0;padding:0;margin:auto;width:min(520px,calc(100vw - 32px));max-height:calc(100dvh - 32px);overflow:hidden;border-radius:20px;background:#fff;color:var(--ink);box-shadow:var(--shadow-float)}
/* [open] is required: the UA rule dialog:not([open]){display:none} must still
   win for the closed dialog, and a bare display:flex here would beat it. */
.prefsModal[open]{display:flex;flex-direction:column}
.prefsModal__head,.prefsModal__foot{flex:none}
.prefsModal::backdrop{background:rgb(11 21 12 / .5)}
.prefsModal__head{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 24px;border-bottom:1px solid var(--line-2)}
.prefsModal__head h2{font-size:1.1rem;font-weight:700;letter-spacing:-.022em}
.prefsModal__x{width:32px;height:32px;flex:none;border-radius:9px;display:grid;place-items:center;color:var(--ink-4)}
.prefsModal__x:hover{background:var(--sunken);color:var(--ink)}
/* The body cannot know how tall the head and foot are, so a fixed 62vh was
   ADDITIVE on top of their 144px — past the UA cap on a modal dialog below
   about 482px of viewport height, i.e. every phone in landscape, which put
   the consent buttons under the fold. The dialog owns the budget now. */
.prefsModal__body{padding:18px 24px;flex:1 1 auto;min-height:0;overflow-y:auto}
.prefsModal__body > p{font-size:.92rem;line-height:1.65;color:var(--ink-2)}
.prefRow{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;padding:16px 0;border-top:1px solid var(--line-2);margin-top:6px}
.prefRow b{display:block;font-size:.95rem}
.prefRow span{display:block;margin-top:3px;font-size:.85rem;color:var(--ink-3);line-height:1.55}
.prefRow > i{font-family:var(--mono);font-size:.6rem;font-weight:600;font-style:normal;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-4);flex:none;padding-top:5px}
.sw{position:relative;flex:none;width:42px;height:24px;margin-top:2px;border-radius:999px;background:var(--line);transition:background-color .16s}
.sw::after{content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgb(16 23 17 / .32);transition:transform .16s}
.sw[aria-checked="true"]{background:var(--green-btn)}
.sw[aria-checked="true"]::after{transform:translateX(18px)}
.prefsModal__foot{display:flex;gap:10px;flex-wrap:wrap;justify-content:flex-end;padding:16px 24px;border-top:1px solid var(--line-2);background:#fcfdfc;border-radius:0 0 20px 20px}
.prefsModal__foot .btn{padding:10px 18px;font-size:.88rem}

/* 404 */
.nf{max-width:660px;margin:0 auto;text-align:center}
.nf__code{font-family:var(--mono);font-size:clamp(3.2rem,2rem + 5.4vw,5.6rem);font-weight:700;line-height:1;letter-spacing:-.05em;color:var(--brand-soft)}
.nf__links{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:34px}
.nf__links a{font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);border:1px solid var(--line);border-radius:999px;padding:9px 16px;transition:background-color .15s,color .15s,border-color .15s}
.nf__links a:hover{background:var(--brand-wash);border-color:var(--brand-soft);color:var(--brand-lo)}

/* ═══════════════ motion ═══════════════
   Reveals and hero entrances. Opt-in: `.motion` is set by script only when
   IntersectionObserver exists and the visitor has not asked for less. */
.motion .reveal{opacity:0;transform:translate3d(0,18px,0)}
.motion .reveal.in{opacity:1;transform:none;transition:opacity .62s var(--ease),transform .62s var(--ease);transition-delay:var(--d,0ms)}
.motion .hero__badge,.motion .hero h1,.motion .hero .lede,.motion .hero__actions,.motion .hero__proof,.motion .frame--hero{animation:rise .8s var(--ease) both}
.motion .hero h1{animation-delay:.08s}
.motion .hero .lede{animation-delay:.16s}
.motion .hero__actions{animation-delay:.24s}
.motion .hero__proof{animation-delay:.32s}
.motion .frame--hero{animation:rise .9s var(--ease) .4s both,float 9s ease-in-out 1.4s infinite}
@keyframes rise{from{opacity:0;transform:translate3d(0,26px,0)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .motion .reveal{opacity:1;transform:none}
  .motion .hero__badge,.motion .hero h1,.motion .hero .lede,
  .motion .hero__actions,.motion .hero__proof,.motion .frame--hero,
  .motion .hero__wash::before,.motion .hero__wash::after{animation:none}
  .motion .ticker__wrap{overflow:visible;-webkit-mask-image:none;mask-image:none}
  .motion .ticker__track{animation:none;flex-wrap:wrap;justify-content:center;width:auto;gap:12px 30px}
  .motion .ticker__set{display:contents}
  .motion .ticker__set--dup{display:none}
  *{transition-duration:.01ms !important}
}

/* ═══════════════ responsive ═══════════════ */
@media (max-width:1180px){
  .nav__logo img{width:132px}
  .navlink,.menu__btn{padding:9px 11px;font-size:.88rem}
  .a-brand{width:190px}
  .a-side{width:190px}
  /* The brand stops sharing a row with the links HERE, not at 1040. Below a
     1136px content box the five `auto` tracks start shrinking toward
     min-content and the long labels — "GDPR, UK GDPR + ePrivacy",
     "Accessibility statement" — break across two lines; measured, ten of the
     twenty-three were wrapping by 1041. Stacking first gives the columns the
     full width and they stop needing to. */
  .footer__top{grid-template-columns:minmax(0,1fr)}
  .footer__brand{max-width:640px}
  /* auto-fit rather than a fixed five, so the count steps 5 → 4 → 3 on its
     own as the width falls and no column is ever narrower than 150px. Five
     forced columns held to 145px at 901, which broke six of the labels; this
     drops to four at 899 and gives them 189px instead. It also means the
     ladder below needs one rule, not three. */
  .footer__cols{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));justify-content:stretch;gap:26px 32px}
}
@media (max-width:1040px){
  .nav__links,.nav__cta{display:none}
  .grid4,.steps,.figs,.fines,.tiers{grid-template-columns:repeat(2,1fr)}
  .split{grid-template-columns:1fr;gap:40px}
  .lead{grid-template-columns:1fr;gap:30px;padding:34px}
  /* Rows stack widget-above-words. The flip is switched off with them, so
     the stacking order matches the DOM order on every row. */
  .surfaces{gap:72px}
  .surface{flex-direction:column;align-items:stretch;gap:28px}
  .surface--flip .surface__stage{order:0}
  /* The column ratios are flex-BASIS, and basis follows the main axis: the
     moment the row turns vertical they would size the stage's HEIGHT to
     zero. Hand both children back to auto. */
  .surface__stage,.surface__copy{flex:0 0 auto}
  .surface__stage{min-height:0;padding:40px 28px}
  .surface__copy{max-width:68ch}
  .contactGrid{grid-template-columns:1fr;gap:36px}
  .included{grid-template-columns:repeat(2,1fr)}
  /* The contents list stops being a sidebar and becomes a lead-in. Sticky is
     removed with the column: a sticky element in normal flow would pin the
     list over the prose it introduces. */
  /* minmax(0,…) has to SURVIVE the collapse. `1fr` means minmax(auto,1fr),
     and that auto floor is the item min-content width — which propagates up
     from .prose__tbl table{min-width:520px}. .prose__tbl own overflow-x:auto
     does not zero it: the automatic-minimum-size-is-zero rule applies to grid
     ITEMS, and .prose__tbl is a plain block grandchild. So the track refused
     to go below the table, the table never became the scroll container it was
     written to be, and body{overflow-x:hidden} then amputated the last two
     columns of the cookie inventory with no scrollbar to recover them. */
  .doc{grid-template-columns:minmax(0,1fr);gap:36px}
  .doc__toc{position:static;padding-bottom:26px;border-bottom:1px solid var(--line-2)}
  .doc__toc a{display:inline-block;padding:6px 10px}
  /* .cta__panel keeps its 82px/64px padding down to 901px, so the copy column
     does not narrow but the panel does — and the mark starts closing on the
     words. Worst case in this band is vw 901: panel 853, paragraph ink ends
     at 576.7, so a 270px mark at right:-28 puts its left edge at 611 and
     clears the copy by 34px. */
  .cta__shield{width:270px;height:270px;bottom:0}
}
@media (max-width:900px){
  .section{--sec-y:72px}
  .cta{padding-bottom:72px}
  .grid3,.grid2,.teasers{grid-template-columns:1fr}
  .surfaces{gap:64px}
  .surface{gap:26px}
  .surface__stage{padding:36px 24px}
  .answer{padding:30px 26px}
  .a-side,.a-brand{display:none}
  .a-topmain{padding-left:16px}
  .a-pub,.a-statrow{grid-template-columns:repeat(2,1fr)}
  .cta__panel{padding:58px 32px;border-radius:26px}
  .vs{border-radius:16px}
  .vs__row{grid-template-columns:1fr}
  .vs__row--head{display:none}
  .vc{padding:10px 18px;justify-content:flex-start}
  .vc--crit{padding-top:16px;font-size:.95rem}
  .vc:last-child{padding-bottom:16px}
  .vc small{display:inline;order:2;margin-left:auto}
  .footer__askgrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:2px 32px}
  /* Below 900 the panel falls from 851px to 354px while .cta__inner stays a
     fixed 600px, so paragraph ink sits at 544.7px at EVERY width in the band.
     Clear ground to its right is 306px at vw 899 but 175px at 768, 107px at
     700 and 47px at 640 — no single size clears the band, and the copy runs
     full width all the way down, so there is no free corner to retreat into
     either. A watermark is decoration: drop it rather than run it under the
     words. Same call as `.a-side,.a-brand{display:none}` above. */
  .cta__shield{display:none}
}
@media (max-width:640px){
  .grid4,.steps,.figs,.fines,.tiers,.included{grid-template-columns:1fr}
  .ledger{grid-template-columns:1fr;max-width:440px}
  .ledger__stop{border-left:0;border-top:1px solid var(--line-2);display:flex;align-items:baseline;gap:12px;padding:14px 20px;text-align:left}
  .ledger__stop:first-child{border-top:0}
  .ledger__stop b{margin:0 0 0 auto}
  .ledger__stop .rng{margin:0}
  .ticker__wrap{border-radius:22px;padding:16px 20px}
  .a-pub,.a-statrow,.a-receipt{grid-template-columns:1fr}
  .meter__row{grid-template-columns:1fr;gap:4px}
  .stepbig{grid-template-columns:1fr;gap:8px}
  .footer__cols{grid-template-columns:repeat(2,minmax(0,1fr));gap:26px 28px}
  .footer__askgrid{grid-template-columns:1fr}
  .docHead{padding:22px 20px}
  .prose h2{margin-top:42px;padding-top:22px}
  .faq summary{padding:18px 20px;font-size:.96rem}
  .faq p{padding:0 20px 20px}
  .form{padding:22px}
  .surfaces{gap:52px}
  .surface__stage{padding:30px 18px;border-radius:20px}
}
@media (max-width:420px){
  body{font-size:16px}
  .hero{padding-top:60px}
  .nav{min-height:56px;padding-left:16px}
  .nav__logo img{width:124px}
  .wrap{padding:0 18px}
  .card,.step,.cover,.fine,.tier,.teaser{padding:22px 20px}
  .cardrows .card{padding:18px 18px}
  .card--wide{gap:6px 16px}
  .card--wide .cico{width:40px;height:40px}
  .cta__panel{padding:48px 24px}
  .a-main{padding:14px}
  .surface__stage{padding:26px 14px;border-radius:18px}
  .dnsGroup{gap:20px}
}


.menu__panel::before{content:"";position:absolute;left:0;right:0;top:-12px;height:12px}

/*
Append to the END of /Users/ryanlovett/projects/userguard/assets/site.css. It must be the last nav block in the file — it owns mobile bar geometry, and two earlier media queries would otherwise fight it. The deletions listed separately are required, not optional.
*/
/* ═══════════ mobile chrome: closed bar + full-screen nav view ═══════════
   Replaces .navMobile entirely. Existing tokens only. Two constants are
   load-bearing and must move together if either moves: the closed bar's
   horizontal padding, and the view bar's — the view bar's is the closed
   bar's PLUS the 16px .navZone gutter PLUS .nav's own 1px border. That is
   what makes MENU and CLOSE the same rectangle, measured to the pixel at
   375 and at 320. ───────────────────────────────────────────────────── */

/* ── the one control, in two seats ── */
.navBtn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  flex:0 0 auto;width:104px;height:44px;padding:0;border-radius:999px;
  font-family:var(--font);font-size:.95rem;font-weight:600;letter-spacing:-.012em;
  color:var(--brand-lo);background:var(--brand-wash);border:1px solid var(--brand-soft);
  -webkit-tap-highlight-color:transparent;
  transition:background-color .15s var(--ease),border-color .15s var(--ease);
}
.navBtn svg{flex:none}
.navBtn:active{background:var(--brand-soft)}
.navBtn:focus-visible{outline:2px solid var(--brand-hi);outline-offset:2px}
/* the stylesheet ships no global :focus-visible — only .field, .skipLink,
   .postRow and .kb-hash have one — so every new control needs its own */
.nav > .navBtn{display:none}

@media (max-width:1040px){
  /* FULL-BLEED AT MOBILE.
     The desktop bar is a floating pill: 16px of .navZone gutter, a 999px
     radius and a lifted shadow. Over the hero's gradient that pill draws a
     hard white edge along its bottom and sides — a card sitting on the
     gradient rather than chrome sitting above it. Flush to the top, edge to
     edge, with a hairline underneath, it reads as the app bar it is.

     The three constants below move together with .navview__bar's padding at
     the foot of this file: the view bar's inset was the closed bar's padding
     PLUS this gutter PLUS .nav's side border, and both of those are now zero.
     That arithmetic is what keeps MENU and CLOSE the same rectangle, so if
     one of these changes the other has to. */
  .navSpacer{display:none}
  .navZone{top:0;padding:0}
  .nav{
    max-width:none;border-radius:0;border-top:0;border-left:0;border-right:0;
    /* more opaque than the desktop pill: at full bleed the blur is all that
       separates the bar from whatever scrolls under it */
    background:rgb(255 255 255 / .92);
    box-shadow:0 1px 0 rgb(16 23 17 / .05);
  }
  .nav{gap:10px;padding:0 12px 0 20px;min-height:62px}
  /* the CTA leaves the bar: logo 132 + CTA 120 + menu 104 + gaps does not
     fit a 343px bar, and the hero and footer already carry Get started */
  .nav__links,.nav__cta{display:none}
  /* flex:none on BOTH link and image is the logo fix: the img was the only
     shrinkable item on an overflowing flex line, so it rendered 81x15 at
     375 and 26x5 at 320. Measured after: 132x21 at 375, 112x21 at 320,
     and .nav no longer overflows, so margin-left:auto resolves and the
     control sits hard right instead of the CTA floating mid-bar. */
  .nav__logo{display:flex;align-items:center;min-height:44px;flex:0 0 auto}
  .nav__logo img{width:132px;flex:none}
  .nav > .navBtn{display:inline-flex;margin-left:auto}
  html.js .nav > .nav__nojs{display:none}
  html:not(.js) .nav > [data-navopen]{display:none}
}
@media (max-width:360px){
  .nav{padding:0 10px 0 16px}
  .nav__logo img{width:112px}
  .navBtn{width:96px}
}

/* ── the view ──
   position:fixed + inset:0 gives a definite viewport box with no dvh calc
   to invalidate; the old max-height:min(78vh,calc(100dvh - 120px)) fell all
   the way back to 70vh wherever dvh was unsupported. The z-index only
   matters on the no-showModal fallback path, where the dialog is not
   promoted to the top layer. */
.navview{
  border:0;padding:0;margin:0;max-width:none;max-height:none;overflow:hidden;
  background:var(--paper);color:var(--ink);z-index:2147483002;
}
.navview[open]{position:fixed;inset:0;width:auto;height:auto;display:flex;flex-direction:column}
.navview::backdrop{background:rgb(11 21 12 / .5)}

/* band 1 — the view bar. Mirrors the closed pill to the pixel: same 16px
   top offset, same 62px centred row, hairline landing on y=78, which is the
   closed pill's own bottom edge. */
.navview__bar{
  flex:0 0 auto;display:flex;align-items:center;gap:10px;
  /* The same 62px the closed bar is, so the pill keeps its seat vertically as
     well as horizontally. It was 78px with a 16px top inset back when the
     closed bar floated 16px down the page on .navSpacer; with the bar flush to
     the top that offset moved the pill 30px on open. */
  height:calc(62px + env(safe-area-inset-top,0px));
  padding:env(safe-area-inset-top,0px) 12px 0 20px;
  border-bottom:1px solid var(--line);background:var(--paper);
}
.navview__bar .nav__logo{display:flex;align-items:center;min-height:44px;flex:0 0 auto}
.navview__bar .nav__logo img{width:132px;flex:none}
.navview__bar .navBtn{margin-left:auto}

/* band 2 — the directory, the only scrolling region */
.navview__body{
  flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;padding:10px 18px 24px;
}

/* the three flat, high-traffic destinations, first — they were all below
   the cut in the owner's screenshot */

/* --ink-3, not --ink-4: a heading must not be quieter than the links it
   groups — the same correction .docs__side already documents. */
.navview__head{
  display:flex;align-items:center;gap:12px;margin:24px 14px 2px;
  font-family:var(--mono);font-size:.68rem;font-weight:700;line-height:1;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);
}
.navview__head::after{content:"";flex:1 1 auto;height:1px;background:var(--line)}

/* two-line rows carrying the desktop dropdown's own blurbs. No nowrap, no
   ellipsis: truncated descriptions at 320px are worse than none, and
   clipping them fails SC 1.4.4 as text size grows. */
.navview__list{list-style:none;display:grid;gap:2px}
.navview__list a{display:block;min-height:56px;padding:11px 14px;border-radius:14px;transition:background-color .14s}
.navview__list b{display:block;font-size:1rem;font-weight:600;color:var(--ink);letter-spacing:-.012em;line-height:1.3}
.navview__list span{display:block;margin-top:2px;font-size:.8rem;line-height:1.4;color:var(--ink-4)}

/* Five chips now, not two, and they are short words of different lengths — a
   rigid 1fr 1fr grid would stretch "Blog" to half the sheet. */
.navview__grid{list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin-top:2px}
.navview__grid > li{flex:0 1 auto}
.navview__chip{
  display:flex;align-items:center;min-height:52px;padding:0 14px;border-radius:14px;
  border:1px solid var(--line);font-size:.95rem;font-weight:600;color:var(--ink-2);
}

.navview a:active{background:var(--brand-wash)}
.navview a:focus-visible{outline:2px solid var(--brand-hi);outline-offset:2px}
/* markCurrentNav() already adds .on and aria-current to the matching
   [data-nav] — the same active treatment .docs__side[aria-current] uses */
.navview__list a.on{background:var(--brand-wash);box-shadow:inset 2px 0 0 var(--brand)}
.navview__list a.on b{color:var(--brand-lo)}
.navview__chip.on{background:var(--brand-wash);border-color:var(--brand-soft);color:var(--brand-lo)}

/* band 3 — actions. Equal columns on purpose: the off-domain destination
   must not also be the largest and lowest object on the screen. 81px total,
   i.e. a tenth of the viewport — not the bottom third where a thumb flicks. */
.navview__actions{
  flex:0 0 auto;display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:center;
  padding:12px 18px calc(18px + env(safe-area-inset-bottom,0px));
  border-top:1px solid var(--line);background:var(--paper);
  box-shadow:0 -10px 22px -14px rgb(16 23 17 / .18);
}
.navview__actions .btn{min-height:50px;padding:0 16px;font-size:.95rem}

@media (max-width:360px){
  /* 16 + 0 gutter + 0 border, matching the full-bleed closed bar at this width */
  .navview__bar{padding-left:16px;padding-right:10px}
  .navview__bar .nav__logo img{width:112px}
  .navview__body{padding-left:14px;padding-right:14px}
  .navview__actions{padding-left:14px;padding-right:14px}
}

/* ── scroll lock: the only form iOS Safari respects ──
   showModal() does NOT lock page scroll. overflow:hidden on <html> alone is
   not honoured on iOS. */
html.navview-open{overflow:hidden}
body.navview-open{position:fixed;left:0;right:0;width:100%;overflow:hidden}

/* ── motion: one surface, one move ── */
@keyframes navviewIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes navviewOut{from{opacity:1;transform:none}to{opacity:0;transform:translateY(8px)}}
@keyframes navviewWash{from{opacity:0}to{opacity:1}}
@keyframes navviewWashOut{from{opacity:1}to{opacity:0}}
/* `backwards`, NOT `both`. A filling animation's transform overrides the
   inline transform the pull-down gesture writes, which silently kills the
   gesture. Measured. */
.navview[open]{animation:navviewIn .22s var(--ease) backwards}
.navview[open]::backdrop{animation:navviewWash .2s var(--ease) backwards}
.navview[open].is-closing{animation:navviewOut .16s var(--ease) both}
.navview[open].is-closing::backdrop{animation:navviewWashOut .16s var(--ease) both}
.navview.is-drag{animation:none;transition:none}
.navview.is-spring{animation:none;transition:transform .2s var(--ease)}

/* The stylesheet's existing reduced-motion block ends in
   *{transition-duration:.01ms !important} and does NOT touch animation, so
   these overrides are required, not decorative. */
@media (prefers-reduced-motion:reduce){
  .navview[open],.navview[open]::backdrop,
  .navview[open].is-closing,.navview[open].is-closing::backdrop{animation:none}
  .navview.is-spring{transition:none}
}
/* ═══════════════════════════════════════════════════════════════════════
   HELP CENTRE (/kb) — THE REFERENCE MANUAL
   Appended to assets/site.css, replacing the deleted .docs* block. One
   shell for kb/index.html and the 17 guides, scoped to .kb-page on <html>
   and .kb on <main>, so no marketing page is touched. Existing custom
   properties only: no new token, no new palette, no new font.

   Ornament budget for the whole shell: two 1px hairlines.
   Colour ladder, and it is never inverted: --ink-4 is mono metadata only,
   --ink-3 is navigation, --ink-2 is body, --ink is headings and emphasis,
   --brand-lo/--green-text is the current item and links. Green is reserved
   for links, section numerals and the current-item marker — nothing else.
   The breakpoint blocks are NOT here; they are in `responsive` and are
   appended immediately after this block, in that order.
   ═══════════════════════════════════════════════════════════════════════ */

/* A contents click across 1800px should land, not fly. Class, not :has() —
   site.css uses :has() zero times in 1453 lines and this needs no new
   baseline dependency. html.kb-page (0,1,1) beats html (0,0,1). */
html.kb-page{scroll-behavior:auto}

.kb{
  --kb-rail:232px;      /* rail text column                                  */
  --kb-toc:196px;       /* on-this-page text column                          */
  --kb-pad:28px;        /* column edge → hairline                            */
  --kb-inset:36px;      /* hairline → article text                           */
  /* Sticky offset, matching the shipped .docs__side. Arithmetic, so the next
     person can audit it: .navZone is position:sticky;top:16px (site.css:148)
     and .nav has min-height:62px (site.css:150) → the pill's bottom edge is
     at 78px, and it carries a 0 12px 32px shadow. 16 + 62 + 14 air = 92. */
  --kb-top:92px;
  /* Deliberately NOT derived from --kb-top: raising the sticky offset must
     not drag every heading anchor with it. */
  --kb-anchor:104px;
  /* 39rem = 624px ≈ 73 characters of Inter at 16px, measured. Anchored in
     rem, never in ch: the old `max-width:72ch` resolved to 746.56px inside a
     736px column, so the cap never engaged and lines ran to 87 characters. */
  --kb-measure:39rem;
  padding:34px 0 88px;
}
.kb__wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px;width:100%}

/* At 1320: 1272 live = 260 rail + 788 main + 224 toc. .kb__main's 36px
   padding leaves 716px of text width, capped at 624 by --kb-measure. */
.kb__grid{
  display:grid;align-items:stretch;
  grid-template-columns:calc(var(--kb-rail) + var(--kb-pad)) minmax(0,1fr) calc(var(--kb-toc) + var(--kb-pad));
}
/* DOM order is rail → on-this-page → article, placed by grid. That is the
   tab order a keyboard user wants, and it is what lets the TOC fall above
   the article at narrow widths with no JS and no second copy in the DOM. */
.kb__railCol{grid-column:1;grid-row:1;border-right:1px solid var(--line-2);padding-right:var(--kb-pad)}
.kb__tocCol {grid-column:3;grid-row:1;border-left:1px solid var(--line-2);padding-left:var(--kb-pad)}
.kb__main   {grid-column:2;grid-row:1;min-width:0;padding:0 var(--kb-inset)}

/* The hairlines run the full height of the page because the grid COLUMN
   carries the border and the sticky block lives inside it. */
.kb__rail,.kb__toc{
  position:sticky;top:var(--kb-top);
  max-height:calc(100dvh - var(--kb-top) - 24px);
  overflow-y:auto;scrollbar-width:thin;padding-bottom:22px;
}
/* No overscroll-behavior:contain. A 1067px list inside a 780px window hits
   its end constantly and the page must keep scrolling when it does. */

/* ─────────── search: the rail is the index ─────────── */
.kb-find{position:relative;display:flex;align-items:center;margin-bottom:18px}
.kb-find svg{position:absolute;left:10px;width:14px;height:14px;color:var(--ink-4);pointer-events:none}
.kb-find input{
  -webkit-appearance:none;appearance:none;width:100%;height:34px;padding:0 40px 0 30px;
  font-family:var(--font);font-size:.8125rem;font-weight:500;color:var(--ink);
  background:#fff;border:1px solid var(--line);border-radius:9px;
  transition:border-color .15s,box-shadow .15s;
}
.kb-find input::placeholder{color:var(--ink-4)}
.kb-find input::-webkit-search-decoration,
.kb-find input::-webkit-search-cancel-button{-webkit-appearance:none;display:none}
.kb-find input:focus{outline:none;border-color:var(--brand-soft);box-shadow:0 0 0 3px var(--brand-wash)}
.kb-find kbd{
  position:absolute;right:8px;pointer-events:none;background:#fff;
  font-family:var(--mono);font-size:.6875rem;font-weight:600;color:var(--ink-4);
  border:1px solid var(--line);border-radius:5px;padding:1px 6px;
  transition:opacity .12s;
}
.kb-find input:focus ~ kbd,.kb-find input:not(:placeholder-shown) ~ kbd{opacity:0}

/* ─────────── the rail ─────────── */
.kb-nav b{
  display:block;margin:22px 0 6px;padding:0 9px;
  font-family:var(--mono);font-size:.6875rem;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2);
}
.kb-nav a{
  display:block;padding:5px 9px;border-radius:7px;
  font-size:.8125rem;line-height:1.38;color:var(--ink-3);
  transition:background-color .12s,color .12s;
}
.kb-nav a:hover{background:var(--brand-wash);color:var(--brand-lo)}
.kb-nav a[aria-current="page"]{
  background:var(--brand-wash);color:var(--brand-lo);font-weight:600;
  box-shadow:inset 2px 0 0 var(--brand);
}
.kb-nav__home{
  margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid var(--line-2);
  border-radius:7px 7px 0 0;font-weight:600;color:var(--ink-2)
}
.kb-nav b:first-of-type{margin-top:0}
/* a{display:block} would otherwise beat the hidden attribute. */
.kb-nav a[hidden],.kb-nav b[hidden],.kb-idx__row[hidden],.kb-idx__grp[hidden]{display:none}
.kb-nav__empty{margin-top:12px;padding:0 9px;font-size:.8125rem;line-height:1.55;color:var(--ink-4)}
.kb-nav__empty a{color:var(--green-text);font-weight:600;text-decoration:underline;text-underline-offset:3px}

/* Hidden at desktop; a real button at ≤1020px. It is never rendered as a
   control that refuses to act. */
.kb-drawer{
  display:none;align-items:center;height:34px;padding:0 13px;cursor:pointer;
  font-family:var(--mono);font-size:.625rem;font-weight:600;
  letter-spacing:.11em;text-transform:uppercase;color:var(--ink-2);
  background:#fff;border:1px solid var(--line);border-radius:9px;
}
.kb-drawer[aria-expanded="true"]{background:var(--brand-wash);border-color:var(--brand-soft);color:var(--brand-lo)}

/* ─────────── page head ─────────── */
.kb-head{padding-bottom:22px;border-bottom:1px solid var(--line);margin-bottom:32px}
/* One mono row carries the trail on the left and "is this still true?" on
   the right. It replaces two separate rows of chrome above the h1. */
.kb-crumb{
  display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:6px 20px;
  font-family:var(--mono);font-size:.75rem;font-weight:500;color:var(--ink-4);
}
.kb-crumb__trail{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 6px}
.kb-crumb a{color:var(--ink-3);transition:color .12s}
.kb-crumb a:hover{color:var(--brand-lo);text-decoration:underline;text-underline-offset:3px}
.kb-crumb i{font-style:normal;color:var(--line)}
.kb-crumb [aria-current]{color:var(--ink-4)}
.kb-crumb__meta{display:flex;align-items:baseline;gap:0 7px;font-size:.6875rem;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-4)}
/* SPECIFICITY, stated so the next person does not lose it the way
   .artHead h1 lost its max-width: .kb-head h1 is (0,1,1) and beats the
   global h1{font-size:clamp(2.5rem,1.3rem + 4.6vw,4.5rem)} +
   h1,h2{font-weight:800;letter-spacing:-.042em;line-height:1.04} at
   (0,0,1) in either source order. Every property they set is reset here. */
.kb-head h1{
  margin-top:14px;max-width:none;
  font-size:1.9rem;font-weight:700;letter-spacing:-.03em;line-height:1.18;
  color:var(--ink);text-wrap:balance;
}
.kb-lede{margin-top:12px;max-width:var(--kb-measure);font-size:1.0625rem;line-height:1.58;color:var(--ink-2)}

/* ─────────── the document ─────────── */
.kb-prose{counter-reset:sec}
.kb-prose > *{max-width:var(--kb-measure)}
.kb-prose > .kb-code,.kb-prose > .prose__tbl{max-width:none}

.kb-prose h2{
  position:relative;counter-increment:sec;margin-top:40px;
  font-size:1.1875rem;font-weight:700;letter-spacing:-.02em;line-height:1.32;
  color:var(--ink);text-wrap:balance;scroll-margin-top:var(--kb-anchor);
}
.kb-prose > h2:first-child{margin-top:0}
/* The old 54px margin + 28px pad + a near-invisible --line-2 hairline was an
   82px chasm that read as a page break. Sections are joined by proximity and
   addressed by number instead: the right rail carries the same numbers, so
   rail and body can be matched without reading either. */
.kb-prose h2::before{
  content:counter(sec);position:absolute;left:calc(var(--kb-inset) * -1 + 2px);top:.34em;
  font-family:var(--mono);font-size:.6875rem;font-weight:600;color:var(--ink-4);
}
.kb-hash{margin-left:8px;font-family:var(--mono);font-weight:600;color:var(--ink-4);opacity:0;text-decoration:none;transition:opacity .15s}
.kb-prose h2:hover .kb-hash,.kb-hash:focus-visible{opacity:1}
.kb-hash:hover{color:var(--brand-lo)}

.kb-prose h3{margin-top:26px;font-size:1rem;font-weight:700;letter-spacing:-.012em;line-height:1.45;color:var(--ink)}
.kb-prose p{margin-top:14px;font-size:1rem;line-height:1.7;color:var(--ink-2)}
.kb-prose ul,.kb-prose ol{margin-top:14px;padding-left:22px;display:grid;gap:8px;font-size:1rem;line-height:1.65;color:var(--ink-2)}
/* Green is for links, section numerals and the current item. A bullet is
   none of those. */
.kb-prose li::marker{color:var(--edge)}
.kb-prose ol li::marker{font-family:var(--mono);font-size:.84em;color:var(--edge)}
.kb-prose strong{font-weight:650;color:var(--ink)}
.kb-prose a{color:var(--green-text);font-weight:500;text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--brand-soft)}
.kb-prose a:hover{text-decoration-color:var(--green-text)}

/* Two different things wore the same chip: "text you type or read literally"
   and "a control you click". Monospace now means only the first. The chip
   ground is green-cast like every other surface in the palette, instead of
   sharing --line-2 with the hairlines. */
.kb-prose code{
  font-family:var(--mono);font-size:.86em;color:var(--ink);
  background:var(--lead-wash);border:1px solid var(--lead-edge);
  border-radius:5px;padding:1px 5px;
}
/* A control you click: body face, 650, no chip, no border, no geometry. */
.kb-ui{font-family:var(--font);font-size:1em;font-weight:650;color:var(--ink);white-space:nowrap}

/* Block code. Dormant: the migration authors none of these. It exists so the
   install guide's own sentence, "copy the tag exactly as shown", can one day
   be honoured by a human editing the file. */
.kb-code{margin-top:18px;border:1px solid var(--line);border-radius:10px;background:#fff;overflow:hidden}
.kb-code__bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:6px 8px 6px 12px;border-bottom:1px solid var(--line-2);background:var(--brand-wash)}
.kb-code__bar b{font-family:var(--mono);font-size:.625rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.kb-copy{
  font-family:var(--mono);font-size:.625rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-3);background:#fff;border:1px solid var(--line);border-radius:6px;
  padding:4px 9px;cursor:pointer;transition:color .15s,border-color .15s,background-color .15s;
}
.kb-copy:hover{color:var(--brand-lo);border-color:var(--brand-soft);background:var(--brand-wash)}
.kb-copy[data-done]{color:var(--brand-lo);border-color:var(--brand-soft)}
.kb-code pre{margin:0;padding:13px 14px;overflow-x:auto;overscroll-behavior-x:contain}
.kb-code code{font-family:var(--mono);font-size:.8125rem;line-height:1.62;color:var(--ink);background:none;border:0;padding:0;white-space:pre}

/* Callouts. Flat: a 2px left rule and a mono label, no fill on the note, and
   the warning uses the real amber tokens rather than a grey hairline. */
.kb-note{margin-top:20px;padding:1px 0 1px 16px;border-left:2px solid var(--brand-soft)}
.kb-note > b{display:block;font-family:var(--mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.kb-note p{margin-top:6px}
.kb-note--warn{border-left-color:var(--warn);background:var(--warn-wash);padding:12px 16px;border-radius:0 8px 8px 0}
.kb-note--warn > b{color:var(--warn)}

/* Tables reuse the shipped .prose__tbl skin (site.css:877, currently zero
   uses in the KB) rather than authoring a second table style. Also dormant:
   there are zero <table> elements in kb/*.html today.
   .kb-prose .prose__tbl is (0,2,0) and beats .prose__tbl at (0,1,0). */
.kb-prose .prose__tbl{max-width:none;border-radius:10px}
.kb-prose .prose__tbl table{min-width:440px;font-size:.875rem}
.kb-prose .prose__tbl th,.kb-prose .prose__tbl td{padding:9px 13px}
.kb-prose .prose__tbl thead th{background:var(--brand-wash)}

/* ─────────── on this page ─────────── */
/* Primary in-page navigation is --ink-3, never the palest text on the page. */
.kb-toc > b{display:block;margin-bottom:10px;font-family:var(--mono);font-size:.6875rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2)}
.kb-toc__list{counter-reset:tsec}
.kb-toc__list a{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  padding:5px 0 5px 13px;border-left:2px solid var(--line-2);counter-increment:tsec;
  font-size:.8125rem;line-height:1.42;color:var(--ink-3);
  transition:color .15s,border-color .15s;
}
.kb-toc__list a::before{content:counter(tsec) ".";margin-right:6px;font-family:var(--mono);font-size:.8em;color:var(--ink-4)}
/* The index's list jumps to group headings, which carry no body counter, so
   it carries no numbers either. */
.kb-toc--plain .kb-toc__list a::before{content:none}
.kb-toc__list a:hover{color:var(--ink);border-left-color:var(--brand-soft)}
.kb-toc__list a.is-on{color:var(--ink);font-weight:600;border-left-color:var(--brand)}
.kb-toc__list a.is-on::before{color:var(--brand-lo)}
.kb-toc__top{display:inline-block;margin-top:14px;font-family:var(--mono);font-size:.625rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.kb-toc__top:hover{color:var(--brand-lo)}

/* ─────────── foot ─────────── */
.kb-foot{margin-top:52px;padding-top:22px;border-top:1px solid var(--line)}
.kb-pager{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.kb-pager a{display:block;padding:12px 15px;border:1px solid var(--line);border-radius:10px;background:#fff;transition:border-color .15s,background-color .15s}
.kb-pager a:hover{border-color:var(--brand-soft);background:var(--brand-wash)}
.kb-pager b{display:block;font-family:var(--mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.kb-pager span{display:block;margin-top:5px;font-size:.9375rem;font-weight:600;line-height:1.35;color:var(--ink)}
.kb-pager__next{grid-column:2;text-align:right}
.kb-related{margin-top:28px}
.kb-related > b{display:block;font-family:var(--mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.kb-related ul{margin-top:9px;padding:0;list-style:none;display:grid;gap:6px}
.kb-related a{font-size:.875rem;line-height:1.5;color:var(--ink-3)}
.kb-related a:hover{color:var(--brand-lo)}
/* The commitment is the content, not the container: a hairline and a line of
   text, not the last panel left standing at the foot of 18 pages. */
.kb-ask{margin-top:28px;padding-top:18px;border-top:1px solid var(--line-2);font-size:.9375rem;line-height:1.6;color:var(--ink-3)}
.kb-ask b{font-weight:650;color:var(--ink)}
.kb-ask a{color:var(--green-text);font-weight:600;text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--brand-soft)}

/* ─────────── index page only ─────────── */
/* .kb-sec > h2 is (0,1,1) and beats the global h2{clamp(1.8rem…2.7rem);
   font-weight:800;letter-spacing:-.036em} at (0,0,1). */
.kb-sec{margin-top:36px}
.kb-sec > h2{
  padding-bottom:9px;border-bottom:1px solid var(--line-2);
  font-family:var(--mono);font-size:.6875rem;font-weight:600;
  letter-spacing:.13em;line-height:1.2;text-transform:uppercase;color:var(--ink-4);
  scroll-margin-top:var(--kb-anchor);
}
.kb-path{margin:0;padding:0;list-style:none;counter-reset:step}
.kb-path li{
  counter-increment:step;display:grid;align-items:baseline;
  grid-template-columns:20px minmax(0,236px) minmax(0,1fr);gap:0 16px;
  padding:11px 0;border-bottom:1px solid var(--line-2);
}
.kb-path li::before{content:counter(step);font-family:var(--mono);font-size:.6875rem;font-weight:600;color:var(--ink-4)}
.kb-path a{font-size:.9375rem;font-weight:600;line-height:1.4;color:var(--ink)}
.kb-path a:hover{color:var(--brand-lo)}
.kb-path span{font-size:.875rem;line-height:1.55;color:var(--ink-3)}

.kb-idx__grp{margin-top:26px;scroll-margin-top:var(--kb-anchor)}
.kb-idx__grp > h3{margin-bottom:3px;font-family:var(--mono);font-size:.625rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.kb-idx dl{margin:0}
.kb-idx__row{display:grid;grid-template-columns:minmax(0,268px) minmax(0,1fr);gap:0 26px;padding:10px 0;border-bottom:1px solid var(--line-2)}
.kb-idx dt a{font-size:1rem;font-weight:600;line-height:1.4;color:var(--ink)}
.kb-idx dt a:hover{color:var(--brand-lo)}
.kb-idx dd{margin:0;font-size:.9375rem;line-height:1.55;color:var(--ink-3)}

/* ── The breakpoint blocks follow, verbatim from `responsive`. ── */
/*
HOW THE THREE COLUMNS BEHAVE, AT EVERY WIDTH
════════════════════════════════════════════════════════════════════════
SIDEBAR (.kb__railCol > .kb__rail)
  ≥1181px  A 260px column with a 1px --line-2 right hairline that runs the
           full height of the page (the border is on the grid column, which
           stretches; the sticky block lives inside it). Sticky at 92px,
           max-height 100dvh − 116px, own thin scrollbar, NO
           overscroll-behavior — the page keeps scrolling when the list
           ends. Search field, then Overview, then the 9 group headings and
           17 links, unchanged from today's taxonomy. On load, site.js
           centres the aria-current link inside the rail. Identical on all
           18 pages; only aria-current moves. It is never removed at any
           width, on any page.
  ≤1180px  Unchanged: still the left column, still sticky, still bordered.
           It spans both grid rows so its hairline still runs full height.
  ≤1020px  Becomes a full-width sticky bar at top:92px with a 1px bottom
           rule: the 34px search field on the left, an "All guides" button
           on the right, and the 17-link nav folded behind it in a 56vh
           scroller. The collapse is gated on html.js, so with JS off the
           full list is simply visible below the bar and the button is not
           rendered as the only way in.

CONTENT COLUMN (.kb__main > article)
  ≥1181px  788px of grid track, 36px padding each side, 716px usable, prose
           capped at 624px. The 36px inset is what holds the section
           numbers in the left gutter.
  ≤1180px  Same column, padding only on the left (36px), so the numbers
           still have a gutter — but they fall inline anyway at this width.
  ≤1020px  Full width, no side padding, starting 26px under the rail bar.
  ≤640px   h1 drops to 1.55rem, lede to 1rem, the pager stacks to one
           column, index rows stack title over summary.

TOC (.kb__tocCol > .kb-toc) — one element in the DOM, repositioned, never
duplicated and never deleted.
  ≥1181px  224px third column with a 1px --line-2 left hairline, sticky at
           92px, entries at --ink-3 with a mono counter matching the body
           section number and a live scrollspy marker on the 2px left
           border. "↑ Top" closes it.
  ≤1180px  The third grid track is dropped. The same <nav> is placed at
           column 2 / row 1 — a bordered block directly above the article,
           list in two columns, always visible. It is demoted, not hidden,
           and it is never a disclosure that refuses to disclose.
  ≤1020px  Same block, now row 2 of a single column, under the rail bar.
  ≤640px   List collapses to one column.
  print    Both rails and the pager are removed; the grid becomes a block.

════════════════════════════════════════════════════════════════════════
THE MEDIA QUERIES — append verbatim, in this order, immediately after the
main block in `css`.
════════════════════════════════════════════════════════════════════════
*/
/* ─────────── ≤1180px: two columns. The section index is demoted to an
   inline block above the article — one element, repositioned by grid, not
   a second copy in the DOM and not display:none. ─────────── */
@media (max-width:1180px){
  .kb__grid{grid-template-columns:calc(var(--kb-rail) + var(--kb-pad)) minmax(0,1fr)}
  .kb__railCol{grid-column:1;grid-row:1 / span 2}
  .kb__tocCol{
    grid-column:2;grid-row:1;
    border-left:0;padding:12px 16px;margin:0 0 26px;
    border:1px solid var(--line);border-radius:10px;
  }
  .kb__toc{position:static;max-height:none;overflow:visible;padding-bottom:0}
  .kb-toc__list{columns:2;column-gap:24px}
  .kb-toc__list a{break-inside:avoid;-webkit-line-clamp:2}
  .kb-toc__top{display:none}
  .kb__main{grid-column:2;grid-row:2;padding:0 0 0 var(--kb-inset)}
  /* The number leaves the gutter and joins the heading. */
  .kb-prose h2::before{position:static;display:inline;margin-right:9px}
}

/* ─────────── ≤1020px: one column. The rail becomes a bar. ─────────── */
@media (max-width:1020px){
  .kb{padding-top:0}
  .kb__grid{grid-template-columns:minmax(0,1fr)}

  .kb__railCol{
    grid-column:1;grid-row:1;
    position:sticky;top:var(--kb-top);z-index:20;
    padding:10px 0;border-right:0;border-bottom:1px solid var(--line-2);
    background:var(--paper);
  }
  .kb__rail{
    position:static;max-height:none;overflow:visible;padding-bottom:0;
    display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  }
  .kb-find{flex:1 1 180px;margin-bottom:0}
  .kb-drawer{display:inline-flex;flex:0 0 auto}
  .kb-nav,.kb-nav__empty{flex:1 1 100%}
  .kb-nav__home{margin-bottom:10px;padding-bottom:10px}
  /* Gated on html.js — site.js stamps it (line 26). With JS off the full
     17-link list stays visible: the failure mode is everything-visible,
     never nothing-visible. */
  html.js .kb-nav{display:none}
  html.js .kb__rail.is-open .kb-nav{display:block;max-height:56vh;overflow-y:auto;margin-top:2px}

  .kb__tocCol{grid-column:1;grid-row:2;margin:22px 0 24px}
  .kb__main{grid-column:1;grid-row:3;padding:0}
}

/* ─────────── ≤640px ─────────── */
@media (max-width:640px){
  .kb__wrap{padding:0 18px}
  .kb-head h1{font-size:1.55rem}
  .kb-lede{font-size:1rem}
  .kb-crumb{gap:6px 12px}
  .kb-toc__list{columns:1}
  .kb-pager{grid-template-columns:1fr}
  .kb-pager__next{grid-column:1;text-align:left}
  .kb-idx__row{grid-template-columns:minmax(0,1fr);gap:4px}
  .kb-path li{grid-template-columns:20px minmax(0,1fr);gap:2px 14px}
  .kb-path span{grid-column:2}
}

/* ─────────── print ─────────── */
@media print{
  .kb__railCol,.kb__tocCol,.kb-pager,.kb-copy,.kb-hash{display:none}
  .kb__grid{display:block}
  .kb__main{padding:0}
  .kb-prose > *{max-width:none}
  .kb-prose h2::before{position:static;display:inline;margin-right:9px}
}

/* ─────────── reduced motion. Nothing on /kb animates by design; this is
   the contract, stated. ─────────── */
@media (prefers-reduced-motion:reduce){
  .kb *,.kb *::before,.kb *::after{transition:none !important;animation:none !important}
}

.faq details:not([open]) summary:hover{background:var(--brand-wash)}
.faq details[open] summary:hover{background:transparent}
.faq details[open] summary{padding-bottom:12px}
.faq p{padding:0 26px 26px}
/* The pager is server-rendered anchors now, not scripted buttons — a page you
   can link, share and crawl. Same skin; the disabled ends are spans, since
   there is nowhere for them to go. */
.pager a,.pager span{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:42px;height:42px;padding:0 15px;border:1px solid var(--line);border-radius:999px;
  background:#fff;font-family:var(--mono);font-size:.66rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);
  transition:background-color .15s,border-color .15s,color .15s;
}
.pager a:hover{background:var(--brand-wash);border-color:var(--brand-soft);color:var(--brand-lo)}
.pager a[aria-current="page"]{background:var(--green-btn);border-color:var(--green-btn);color:#fff}
.pager .is-off{opacity:.42}
/* category chips are links too now */
.cats a.filterPill[aria-current="page"]{background:var(--green-btn);border-color:var(--green-btn);color:#fff}
.cats a.filterPill[aria-current="page"]:hover{color:#fff}
/* ticker breathing room. 10px under a full-width pill put the next section's
   kicker almost against it, so the two read as one block instead of the ticker
   closing the hero. The section below opens with padding-top:0 by design, so
   the space has to come from here. */
.ticker{padding:4px 0 56px}
@media (max-width:900px){.ticker{padding-bottom:40px}}
/* Blog filter chips. The markup is <button class="filterPill"><i>Label</i></button>
   inside .cats, and BOTH .cats i and .filterPill style themselves as a pill —
   so every chip rendered as two concentric pills. The button keeps the pill;
   the <i> goes back to being text. And the active state was --ink, near-black,
   from the old design: green is what "on" means everywhere else here. */
.cats .filterPill i{border:0;background:none;padding:0;border-radius:0;font-style:normal;color:inherit;letter-spacing:inherit}
.cats .filterPill[aria-pressed="true"]{background:var(--green-btn);border-color:var(--green-btn);color:#fff}
.cats .filterPill[aria-pressed="true"]:hover{color:#fff}
/* Contact form: short fields pair up, and the message box asks for a message
   rather than an essay — at 150px it was taller than the three fields above it
   put together, which is most of where the whitespace came from. */
.form__pair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 18px}
.form__pair .form__row{margin-bottom:18px}
.form textarea.field{min-height:118px}
.contactGrid{align-items:start}
@media (max-width:640px){.form__pair{grid-template-columns:1fr}}
[data-blog-list] .is-paged-out{display:none}


/* ═══════════════ a11y utilities ═══════════════ */
.skipLink{
  position:absolute;left:16px;top:-72px;z-index:200;
  background:#fff;color:var(--ink);border:1px solid var(--line);border-radius:999px;
  padding:12px 22px;font-size:.9rem;font-weight:600;box-shadow:var(--shadow-float);
  transition:top .18s var(--ease);
}
.skipLink:focus{top:16px;outline:2px solid var(--brand-hi);outline-offset:2px}
.visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}


/* ═══════════════ carried forward: components the concept never had ═══════════════
   The article furniture (metaBit, goDeeper, lucide icons), the blog index and
   its filter, the contact form, the banner playground, the cookie-policy embed,
   and the cards index.php and blog-rows.php emit from PHP. None of these exist
   in the concept, and all of them are on live pages. Legacy-only tokens are
   remapped to Daylight equivalents (line-soft->line-2, shadow-1/2/pop->
   soft/card/float, tint->brand-wash, stamp-amber->warn) and the dark-section
   variants are dropped with the dark sections they belonged to. */
.hp{position: absolute !important; left: -9999px !important; width: 1px; height: 1px; opacity: 0;}
.stamp--ok{color: var(--green-text); background: var(--brand-wash);}
.stamp--mute{color: var(--warn); background: var(--warn-wash);}
.stamp--tilt{transform: rotate(-2deg);}
.band .stamp--mute{color: #d9a04e; background: rgba(217, 160, 78, .1);}
/* ─── playground (cookie banner page) ─── */
.playground{display: grid; grid-template-columns: 1fr 1.15fr; gap: clamp(28px, 4vw, 52px); padding: clamp(26px, 4vw, 44px); align-items: center;}
@media (max-width: 980px){
  .playground{grid-template-columns: 1fr;}
}
.playground__copy{display: grid; gap: 16px; justify-items: start;}
.playground__copy p{color: var(--ink-2);}
.segmented{display: inline-flex; background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: 4px; gap: 2px;}
.segmented__btn{border: 0; background: none; padding: 8px 18px; border-radius: 999px; cursor: pointer;
  font-weight: 650; font-size: .92rem; color: var(--ink-2); transition: background .15s, color .15s;}
.segmented__btn[aria-pressed="true"]{background: var(--card); color: var(--ink); box-shadow: 0 1px 2px rgba(18, 30, 18, .10);}
.browserFrame{border: 1px solid var(--line); border-radius: 16px; overflow: hidden; background: var(--card); box-shadow: var(--shadow-card);}
.browserFrame__bar{display: flex; align-items: center; gap: 6px; padding: 10px 14px; border-bottom: 1px solid var(--line-2); background: var(--paper);}
.browserFrame__bar i{width: 10px; height: 10px; border-radius: 50%; background: var(--line);}
.browserFrame__bar span{margin-left: 10px; font-family: var(--mono); font-size: .74rem; color: var(--ink-3);
  background: var(--card); border: 1px solid var(--line-2); padding: 3px 14px; border-radius: 999px;}
.browserFrame__page{padding: 22px; display: grid; gap: 10px; min-height: 280px; position: relative; align-content: start;}
.ph{height: 9px; border-radius: 5px; background: var(--line-2);}
.ph--title{height: 16px; width: 55%; background: var(--line);}
.ph--short{width: 70%;}
.miniBanner{position: absolute; left: 18px; right: 18px; bottom: 16px;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px;
  box-shadow: var(--shadow-float); display: grid; gap: 6px; transition: all .25s ease;}
.miniBanner[data-style="card"]{max-width: 300px; right: 18px; left: auto;}
.miniBanner b{font-size: .88rem;}
.miniBanner p{font-size: .76rem; color: var(--ink-3); line-height: 1.45;}
.miniBanner__btns{display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px;}
.miniBanner__btns i{flex: 1 1 0; text-align: center; font-style: normal; font-size: .72rem; font-weight: 700; padding: 6px 10px; border-radius: 7px;
  border: 1px solid var(--line); color: var(--ink-2);}
/* Both buttons carry .pri, at one flex basis: the banner draws Accept and
   Reject as the same button, so the thumbnail does too. */
.miniBanner__btns i.pri{background: var(--green-btn); border-color: var(--green-btn); color: #fff;}
.bigForm{background: var(--card); border: 1px solid var(--line); border-radius: 16px;
  padding: clamp(24px, 3vw, 36px); display: grid; gap: 16px; box-shadow: var(--shadow-card);}
.bigForm h2{font-family: var(--font); font-weight: 750; font-size: 1.28rem; letter-spacing: -0.015em;}
/* ─── journal ─── */
.postIndex{display: grid; gap: 0; border-top: 1px solid var(--line);}
@media (max-width: 640px){
}
.metaBit{display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: .76rem; color: var(--ink-3); letter-spacing: .04em;}
.metaBit .ic{width: 14px; height: 14px;}
.blogFilters{display: flex; gap: 8px; flex-wrap: wrap;}
.filterPill{border: 1px solid var(--line); background: var(--card); border-radius: 999px;
  padding: 7px 17px; font-weight: 650; font-size: .9rem; color: var(--ink-2); cursor: pointer;
  transition: all .15s;}
.filterPill:hover{border-color: var(--green-text); color: var(--green-deep);}
.filterPill[aria-pressed="true"]{background: var(--ink); border-color: var(--ink); color: #fff;}
/* journal rows: hover affordance */
/* in-article money links */
.goDeeper{display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  border-top: 1px dashed var(--line); padding-top: 20px;
  font-size: .95rem; color: var(--ink-2);}
.goDeeper .ic{width: 15px; height: 15px; color: var(--green-text); align-self: center;}
.goDeeper b{color: var(--ink);}
/* journal empty state */
.emptyState{background: var(--warn-wash); border: 1px solid #eeddc0; color: var(--warn);
  border-radius: 12px; padding: 14px 18px; font-size: .93rem; margin-top: 22px;}
/* ------------------------------------------------ contact form + help center */
/* The bigForm grew a select and a textarea; give them the .field input look. */
/* No border here. .field (:397) already draws it at var(--edge) #869686,
   3.12:1 on white — and this rule's (0,1,1) specificity was beating that
   (0,1,0) with var(--line) #dfe8dc, so every input on the contact form drew
   its boundary at 1.26:1. WCAG 1.4.11 wants 3:1 for the only thing telling
   an empty field from the page, and this is the site that sells that. */
.bigForm input, .bigForm select, .bigForm textarea{padding: 12px 16px; border-radius: 11px;
  background: var(--paper); font: inherit; color: inherit; width: 100%;
  transition: border-color .15s, box-shadow .15s;}
.bigForm textarea{resize: vertical; min-height: 130px;}
.bigForm input:focus, .bigForm select:focus, .bigForm textarea:focus{outline: none; border-color: var(--green-btn); box-shadow: 0 0 0 3px rgba(7, 116, 16, .16);}
/* Mini banner and demo banner, brought level with the shipped widget: a cookie
   glyph beside the title, Preferences demoted to a link under the two real
   buttons, and the Powered-by band the widget always draws. */
.miniBanner__title{display: flex; align-items: center; gap: 6px;}
.miniBanner__title svg{flex: none; color: var(--green-text);}
.miniBanner__prefs{font-style: normal; font-size: .7rem; font-weight: 600; color: var(--ink-3);
  text-decoration: underline; text-underline-offset: 2px; justify-self: center;}
.miniBanner__foot{margin-top: 2px; padding-top: 7px; border-top: 1px solid var(--line-2);
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: .5rem; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-4);}
.miniBanner__foot img{width: 42px; height: 8px; object-fit: contain; opacity: .8;}
/* The launched demo banner (site.js, banner playground). It is the .ugw
   drawing made live, so it adds only what an interactive copy needs and a
   drawing does not: the embed's placement (a 380px box in the corner the
   playground's card sits in, or a full-width bar, and the preference centre
   centred at 680px over a 45% scrim), a middle that scrolls so a short phone
   never loses the buttons, and the embed's system font, 1.25 button line
   height, 20px above the choices and focus ring. It sits above the real embed
   this page also runs (its floating buttons at z-index 2147483000, its banner
   at 2147483001), because a launcher in the same corner would cover the
   demo's buttons. */
.ugDemo{position: fixed; z-index: 2147483002; right: 16px; bottom: 16px;
  width: min(380px, calc(100vw - 32px)); max-height: calc(100vh - 32px);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif; outline: none;}
.ugDemo--bar{left: 0; right: 0; bottom: 0; width: 100%; border-radius: 0; border-width: 1px 0 0;}
.ugDemo--prefs{left: 50%; top: 50%; right: auto; bottom: auto; transform: translate(-50%, -50%);
  width: min(680px, calc(100vw - 32px)); max-width: none; max-height: calc(100vh - 48px);}
.ugDemo__scrim{position: fixed; inset: 0; z-index: 2147483001; background: rgb(0 0 0 / .45);}
.ugDemo__scroll{overflow-y: auto; overscroll-behavior: contain; min-height: 0;}
.ugDemo .ugw__head, .ugDemo .ugw__foot{flex: none;}
.ugDemo .ugw__acts{padding-top: 20px;}
.ugDemo .ugw__b{line-height: 1.25;}
.ugDemo .ugw__x{padding: 6px; margin: -6px;}
.ugDemo .ugw__sw, .ugDemo .ugw__sw::after{transition: background .15s, left .15s, top .15s, width .15s, height .15s;}
.ugDemo :focus-visible{outline: 2px solid #fff; outline-offset: 0; box-shadow: 0 0 0 4px #101713;}
.ugDemo .ugw__pref:focus-visible, .ugDemo .ugw__x:focus-visible, .ugDemo .ugw__link:focus-visible{border-radius: 6px;}
/* A switch draws its edge as an inset box-shadow, which the ring above
   replaces, so a focused off switch lost the hollow ring that shows it is
   off. The edge stays inside and the band goes outside it. */
.ugDemo .ugw__sw:focus-visible{box-shadow: inset 0 0 0 1px #888b89, 0 0 0 4px #101713;}
.ugDemo .ugw__sw--on:focus-visible{box-shadow: inset 0 0 0 1px var(--acc), 0 0 0 4px #101713;}
/* The toast site.js raises (after a demo choice, and on the waitlist and
   bad-email redirects) lost its rules with the old demo's in 64f25f5 and has
   rendered unstyled, after the footer, ever since. Restored on today's
   tokens (--shadow-pop is --shadow-float now, and --night-green, which no
   longer exists, is --brand-soft), and lifted over ug.js's floating buttons
   for the same reason as the demo. Its width is max-content: a box pinned at
   left:50% otherwise shrinks to the half of the viewport beside it, which on
   a phone wrapped the message two words to a line. */
.toast{position: fixed; z-index: 2147483002; left: 50%; bottom: 26px; translate: -50% 0;
  display: flex; gap: 12px; align-items: center; width: max-content; max-width: min(92vw, 480px);
  background: var(--ink); color: #fff; border-radius: 14px; padding: 15px 22px;
  box-shadow: var(--shadow-float); font-weight: 600; font-size: .95rem;
  animation: toastIn .35s cubic-bezier(.2, .9, .3, 1.15);}
.toast .ic{color: var(--brand-soft); flex: none;}
@keyframes toastIn{from{translate: -50% 24px; opacity: 0;}}
@media (prefers-reduced-motion: reduce){ .toast{animation: none;} }
/* ═══════════════════════════════════════════════════════════════════════
   DESIGN POLISH PASS
   Cards are hairline now (the shadow tokens went flat above), so the hover
   affordance has to stop being a lift-and-shadow. It becomes a border and a
   faint wash instead — the surface reacts without leaving the page.
   ═══════════════════════════════════════════════════════════════════════ */
.card, .stepCard, .moduleCard, .lawCard, .duoCard, .duoWide, .teaserCard,
.kbCard, .faqItem, .planCustom, .gateCol, .tourBeat, .vsTable, .noteCard,
.featuredPost, .articleBody, .browserFrame, .bigForm, .authCard{transition: border-color .18s ease, background-color .18s ease;}
.moduleCard:hover, .duoCard:hover, .duoWide:hover, .teaserCard:hover,
.planCustom:hover, .tourBeat:hover, .card:hover{translate: none; transform: none; box-shadow: none;
  border-color: #b9d8b4; background: #fbfdfa;}
/* The live cookie-policy embed. doc.js injects the generated document — one
   flat section of h3s, paragraphs, and bare tables — so it borrows the
   legalShell rhythm here, and its own "Cookie policy" h2 hides because the
   page's h1 already says it. The static fallback inside the container keeps
   its normal legalShell styling. */
.ugDocEmbed{width: 100%; display: grid; gap: 10px;}
.ugDocEmbed .cookie-policy{display: grid; gap: 10px;}
.ugDocEmbed .cookie-policy > h2:first-of-type{display: none;}
.ugDocEmbed .cookie-policy h3{font-size: 1.35rem; margin-top: 18px;}
@media (max-width: 700px){
  .ugDocEmbed .cookie-policy table{display: block; overflow-x: auto; min-width: 0;}
}
.playground__stage{min-width:0;display:flex;flex-direction:column;justify-content:center}


/* ═══════════════ carried forward: the pricing calculator ═══════════════ */
.calcBand{display: grid; grid-template-columns: 1fr 1.1fr; gap: clamp(28px, 4vw, 56px); align-items: center;}
@media (max-width: 900px){
  .calcBand{grid-template-columns: 1fr;}
}
.calcBand__copy{display: grid; gap: 14px; justify-items: start;}
.calc{display: grid; gap: 14px; background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; padding: 28px; box-shadow: var(--shadow-soft);}
.calc label{font-weight: 750; font-size: 1.12rem; letter-spacing: -0.01em;}
.calc input[type="range"]{width: 100%; accent-color: var(--green-btn); height: 34px; cursor: pointer;}
.calc__out{display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;}
.calc__out b{font-weight: 800; font-size: 2.5rem; letter-spacing: -0.03em; font-variant-numeric: tabular-nums;}
.calc__out b small{font-family: var(--mono); font-size: .8rem; color: var(--ink-3); font-weight: 600; letter-spacing: .06em;}
.calc__total{color: var(--ink-2); font-weight: 600; font-variant-numeric: tabular-nums;}
.calc input[type="range"]{-webkit-appearance: none; appearance: none; background: transparent;}
.calc input[type="range"]::-webkit-slider-runnable-track{height: 8px; border-radius: 999px;
  background: linear-gradient(90deg, var(--green-btn) 0 var(--fill, 6%), #7f927a var(--fill, 6%));}
.calc input[type="range"]::-webkit-slider-thumb{-webkit-appearance: none; appearance: none; width: 24px; height: 24px; border-radius: 50%;
  background: var(--green-btn);
  border: 3px solid #fff; box-shadow: 0 1px 3px rgba(18, 30, 18, .28);
  margin-top: -8px; cursor: grab;}
.calc input[type="range"]::-webkit-slider-thumb:active{cursor: grabbing; scale: 1.08;}
.calc input[type="range"]::-moz-range-track{height: 8px; border-radius: 999px; background: #7f927a;}
.calc input[type="range"]::-moz-range-progress{height: 8px; border-radius: 999px; background: var(--green-btn);}
.calc input[type="range"]::-moz-range-thumb{width: 18px; height: 18px; border-radius: 50%;
  background: var(--green-btn);
  border: 3px solid #fff; box-shadow: 0 1px 3px rgba(18, 30, 18, .28);}
.calc__scale{font-family: var(--mono); font-size: .72rem; letter-spacing: .05em; color: var(--ink-3);
  border-top: 1px dashed var(--line); padding-top: 12px; margin-top: 2px;}
.calc__scale b{color: var(--green-text); font-weight: 700;}
.calcTicks{position: relative; height: 15px; margin: -6px 0 22px;
  font-family: var(--mono); font-size: .68rem; color: var(--ink-4);}
.calcTicks span{position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap;}
.calcTicks span:first-child{transform: none;}
.calcTicks span:last-child{transform: translateX(-35%);}
.calcStops{display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; margin-top: 16px;}
.calcStop{border-radius: 10px; padding: 9px 4px; text-align: center;
  background: var(--paper); border: 1px solid var(--line);
  transition: background .2s, border-color .2s, translate .2s;}
.calcStop__range{display: block; font-family: var(--mono); font-size: .63rem;
  letter-spacing: .06em; color: var(--ink-4);}
.calcStop__price{display: block; font-weight: 700; font-size: 1rem; margin-top: 3px; letter-spacing: -.01em;}
.calcStop.is-on{background: var(--brand-wash); border-color: #9ccb97; translate: 0 -2px;}
.calcStop.is-on .calcStop__range{color: var(--green-text);}
.calc__scale em{font-style: normal; font-weight: 700; color: var(--ink-2);}
@media (max-width: 560px){
  .calcStops{gap: 4px;}
  .calcStop{padding: 7px 2px;}
  .calcStop__price{font-size: .85rem;}
}
/* The calculator's own call to action. It sits with the explainer rather than
   below the fold, because the moment someone has just seen their number is the
   moment the button is worth anything. */
.calc__cta{margin-top: 18px; padding-top: 18px; border-top: 1px dashed var(--line);
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;}
.calc__cta .btn{flex: none;}
.calc__ctaNote{font-size: .82rem; color: var(--ink-3);}
.includedPanel{padding:clamp(28px, 4vw, 44px)}
.includedPanel .sectionHead{margin-bottom:22px}
.calc__scale{font-family:var(--font);font-size:.86rem;letter-spacing:0;line-height:1.6}
.calcBand{align-items:start}
.calcBand__copy{padding-top:6px}
/* The pricing calculator band was a card wrapping a card. The outer .card held the copy on the left and the .calc card on the right, and the calculator runs ~710px tall against ~195px of copy, so the outer card drew a border around a column that was two-thirds empty. The gap is unavoidable — the calculator is genuinely that tall — but it only reads as a hole because a box was drawn around it. Without the outer skin the same space is page whitespace. Scoped to pricing: the homepage's .includedPanel is a different component with no nested card and keeps its own. */
.calcSection{padding:0}
.calcSection .calcBand{align-items:start}
@media (min-width:901px){.calcSection .calcBand{grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr)}}


/* ==========================================================================
   Mobile pass — Aug 29 2026
   Everything below is phone-only. The site had no horizontal overflow at any
   width; what it had was desktop spacing and desktop composition surviving
   down to 375px. Findings came from a 12-agent audit at 375/320px.
   ========================================================================== */
@media (max-width:640px){
  /* ---- vertical rhythm -------------------------------------------------
     88px top + 88px bottom put 187px of nothing between every section — 23%
     of an 812px screen, repeated six times on the homepage. 48px lands the
     ink-to-ink gap near 108px, which still reads as a section break. */
  .section{--sec-y:56px}
  /* A `--top0` join is single-sided, so once the modifier actually works it
     collapses to one section's padding — 26px of ink gap, which welds two
     unrelated topics together. Give continuations a little back so they still
     read as separate, while a plain join (two-sided, 112px) stays visibly
     larger. Continuation ~54px, topic change ~94px: the hierarchy the desktop
     layout has, at a phone's scale. */
  .section--top0{padding-top:16px}
  .cta{padding-bottom:48px}
  .footer{padding-top:36px}
  .sectionHead{margin-bottom:32px}

  /* The hero is the worst offender: 2.9 screens, of which 65% is a decorative
     desktop-app mock the phone renders at a size that persuades nobody. Cap it
     and fade the cut so it reads as a peek rather than a truncation — the copy
     and both CTAs are above it and unaffected. */
  .hero{padding:36px 0 48px}
  .frame--hero{max-height:560px;overflow:hidden;
    -webkit-mask-image:linear-gradient(#000 68%,transparent 100%);
    mask-image:linear-gradient(#000 68%,transparent 100%)}

  /* ---- typography ------------------------------------------------------
     Centred display type is fine for two lines; centred BODY copy over seven
     lines at 34 characters is not — every line starts in a different place.
     Headings keep their centring, paragraphs get a left edge to read down. */
  .sectionHead .sub,.hedge{text-align:left}
  /* Display leading tuned for desktop is too tight once a heading wraps to
     three or four lines on a phone. */
  h1{line-height:1.14}
  h2{line-height:1.22}
  /* The flanking rules are an inline-flex ::before/::after, so they stay on
     line 1 when the label wraps — leaving two dashes bracketing half a phrase
     and the rest orphaned below. Same call the sheet already makes for
     .cta__shield and .a-side: drop the flourish rather than let it break. */
  .kicker::before,.kicker--c::after{display:none}

  /* ---- pricing calculator ---------------------------------------------
     A bordered card inside a bordered card: two concentric borders 28px apart
     ate 112px of a 375px screen before any content, and the five price chips
     then overflowed their own card at 320px. The panel is a wrapper here, not
     a component — drop its skin and give the calculator the width. */
  .includedPanel{padding:0;border:0;background:none;box-shadow:none}
  .calc{padding:20px}
  .calc input[type="range"]{height:44px}
  .calc input[type="range"]::-webkit-slider-thumb{width:28px;height:28px;margin-top:-10px}
  .calc input[type="range"]::-moz-range-thumb{width:28px;height:28px}

  /* ---- app mockups -----------------------------------------------------
     Label-over-pill stacking is a desktop grid cell's shape. In a full-width
     row it leaves the right half empty and doubles the row height. */
  .a-pub > *{display:flex;align-items:center;justify-content:space-between;gap:10px}
  .a-row{flex-direction:column;align-items:flex-start;gap:8px}
  /* The chart is a viewBox SVG that scales perfectly well; the 560px floor
     was forcing a scroll region around something that did not need one. */
  .a-chart{overflow-x:visible}
  .a-chart > div{min-width:0}

  /* ---- long-document furniture ----------------------------------------
     The collapsed table of contents became a run-in of inline-block links
     with no separator, so 14 section titles read as one ragged paragraph —
     the only navigation for a document 7,000px long. */
  .doc__toc a{display:block;padding:9px 12px;border-bottom:1px solid var(--line-2)}
  .doc__toc a:last-child{border-bottom:0}
  /* A 520px floor on a 339px screen. The content is two columns of short
     text; let it wrap instead of scrolling sideways. */
  .prose__tbl table{min-width:0}
  .prose__tbl thead th{font-size:.7rem}
  /* Injected at runtime by doc.js, so it never matches .prose__tbl. */
  .ugDocEmbed table{min-width:0;width:100%}

  /* ---- footer ----------------------------------------------------------
     Five groups in two columns orphan the fifth beside an empty cell, which
     reads as a block that failed to render. Give it the full row. */
  .footer__cols > :last-child{grid-column:1/-1}
  /* Nav links, not prose links: a 23px box is under any thumb target. But
     paying for that with pure height put 248px onto a footer that is already
     the tallest block on every page — so the padding absorbs the existing
     8px gap instead of stacking on top of it (35px box, 35px pitch, up from
     a 31px pitch), and the rest of the footer gives the height back. */
  .footer__cols a{padding:6px 0;margin-top:0}
  .footer__top{gap:32px}
  .footer__cols{gap:20px 24px}
  .footer__ask{margin-top:32px;padding-top:20px}
  .footer__askgrid{margin-top:10px}
  .footer__bottom{margin-top:28px;padding-top:18px}
  /* The smallest type on the site, at 9.9px. .kicker's 11.5px is the floor. */
  .footer__cols b,.footer__ask > b,.footer__mach{font-size:.72rem}
  .vc small{font-size:.7rem;letter-spacing:.08em}
}

/* .a-statrow's three tiles fit two-up at 375px and only need to stack on the
   narrowest phones — the ≤640 rule was collapsing them a breakpoint early and
   leaving 65% of each row empty. */
@media (max-width:640px) and (min-width:360px){
  .a-statrow{grid-template-columns:repeat(2,minmax(0,1fr))}
}

@media (max-width:420px){
  .section{--sec-y:48px}
  .section--top0{padding-top:12px}
  /* Five 38px chips cannot hold a price; three rows of wider ones can. */
  .calcStops{grid-template-columns:repeat(3,1fr)}
  .calcStop{padding:9px 6px}
}

/* ---- knowledge base ----------------------------------------------------
   The rail and the search bar are the KB's only two controls and both were
   still mouse-sized. 16px on the input is what stops iOS zooming the page on
   focus — and iOS never zooms back, so a visitor who taps search is stranded
   at 1.2x for the rest of the visit. */
@media (max-width:1020px){
  /* 92px was the desktop rail's offset; on a phone the header bar is 62px, so
     the sticky rail floated with a strip of page scrolling through the gap.
     --kb-anchor has to move with it or in-page links land under the bar: the
     bar bottom sits at 117px once the rail is flush, so an anchored heading
     needs more than that to clear it. */
  .kb{--kb-top:62px;--kb-anchor:136px}
  .kb-find input{height:44px;font-size:1rem}
  .kb-drawer{height:44px;font-size:.6875rem}
  /* A "/" shortcut badge on a device with no "/" key, eating field width. */
  .kb-find kbd{display:none}
  /* The article was pushed below its own table of contents on every phone. */
  .kb__main{grid-row:2}
  .kb__tocCol{grid-row:3}
}

/* These three instances want two columns instead of the default three, and
   said so with an inline `style` attribute — which no stylesheet can override,
   so they stayed two-up on a 375px phone and shredded sentence-length labels
   into one-word lines. Same intent, expressed where the breakpoints can reach
   it: desktop-only, so the ≤640 single-column rules win on a phone. */
@media (min-width:641px){
  .included--2,.a-pub--2{grid-template-columns:repeat(2,1fr)}
}

/* ═══════════ drawn app surfaces: the /product hero's Cookies page ═══════════
   The frame used to draw a CLI the product does not have, an Export CSV
   control that page does not carry, and a grouped dot-grid for a panel that
   was removed from the app. These are the parts that replaced them, built
   from the same tokens as the rest of the drawn chrome. */

/* The site tab strip every real site page carries. */
.a-tabs{display:flex;gap:2px;flex-wrap:wrap;padding:0 4px 12px}
.a-tabs span{font-size:.78rem;font-weight:600;color:var(--ink-3);padding:6px 10px;border-radius:8px;white-space:nowrap}
.a-tabs span.on{background:var(--brand-wash);color:var(--brand-lo)}

/* The Scan card's four rows, in place of the terminal. */
.a-facts{padding:10px 16px;display:grid;gap:7px}
.a-facts div{display:flex;align-items:center;justify-content:space-between;gap:12px}
.a-facts dt{font-size:.78rem;color:var(--ink-3)}
.a-facts dd{font-size:.78rem;font-weight:600;color:var(--ink)}
.a-link{color:var(--brand-lo);font-weight:600}
.a-evidence{border-top:1px solid var(--line-2)}

/* The inventory: category rail beside the table of rows that carry the proof. */
.a-inv{display:grid;gap:14px;padding:12px 16px 16px}
@media (min-width:900px){ .a-inv{grid-template-columns:150px minmax(0,1fr);align-items:start} }
.a-rail{display:flex;flex-wrap:wrap;gap:2px}
@media (min-width:900px){ .a-rail{flex-direction:column;flex-wrap:nowrap} }
.a-rail span{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:5px 9px;border-radius:8px;font-size:.78rem;color:var(--ink-2);white-space:nowrap}
.a-rail span.on{background:var(--brand-wash);color:var(--brand-lo);font-weight:600}
.a-rail b{font-weight:500;font-size:.72rem;color:var(--ink-4)}
.a-rail span.on b{color:inherit;opacity:.7}
.a-tbl{width:100%;border-collapse:collapse;font-size:.76rem}
.a-tbl th,.a-tbl td{text-align:left;padding:8px 10px 8px 0;vertical-align:middle}
.a-tbl thead th{font-size:.68rem;font-weight:700;color:var(--ink-4);border-bottom:1px solid var(--line);padding-bottom:6px}
.a-tbl tbody tr{border-bottom:1px solid var(--line-2)}
.a-tbl tbody th{font-family:var(--mono);font-size:.72rem;font-weight:600;color:var(--ink)}
.a-tbl td{color:var(--ink-3)}

/* Stamps INSIDE a drawn app surface, only.
   The app moved its own stamps off mono uppercase on Aug 31 — the engraving
   was the single thing making it read as dated next to the CMPs it is sold
   against. The marketing skin keeps its ledger stamps; a drawing of the app
   should look like the app, so the override is scoped to .a-body and changes
   nothing outside the frames. */
.a-top .stamp,.a-body .stamp{font-family:var(--font);font-size:.7rem;letter-spacing:0;text-transform:none}
