/* ONE STYLESHEET FOR edge.armore.ai — extracted from the homepage 2026-10-14.
   🔴 THIS IS THE SOURCE OF TRUTH FOR THE WHOLE SITE. Before this, four pages carried
   four inline <style> blocks (22.7KB / 9.6KB / 3.9KB / 3.8KB) that had already drifted:
   three different navs, two different --maxw values, and two unrelated card styles.
   Editing one page's look no longer changes only that page — which is the point.
   Add a component here, never in a page. */


  :root{
    /* Canonical brand tokens — mirror the app's tokens.css (SSOT): bg #0a0a0f,
       indigo #6366f1, sky #0ea5e9. --indigoL #818cf8 == app --accent-hover.
       --mk1/--mk2 are DIFFERENT and deliberately so: they are the two gradient
       stops SAMPLED off the shipped app icon (see the mark's provenance note),
       so the logo on this page is the logo in the product rather than a
       near-miss repaint of it. */
    --bg:#0a0a0f; --bg2:#111118; --panel:rgba(255,255,255,.035); --panel2:rgba(255,255,255,.06);
    --line:rgba(255,255,255,.09); --line2:rgba(255,255,255,.16);
    /* 🔴 --muted2 WAS #6b7385, MEASURED 4.154:1 ON --bg — a WCAG AA FAILURE for
       body text, and it is used for real copy (.platforms, .portal-note,
       .wl-note, footer, .plat li span:last-child, .cmp .n), not decoration.
       #757c8e measures 4.731:1 on #0a0a0f, so it clears 4.5:1 with margin while
       staying a step dimmer than --muted (#9aa3b6, 7.796:1).
       ⚠️ DO NOT "align" this with sovereign.armore.ai's #787f93 (4.943:1). That
       token is deliberately different and already passes; the two sites are not
       required to share this value and Sovereign's must not be lowered to meet
       Edge's. Recompute with the WCAG 2.x relative-luminance formula against
       --bg before changing it — the eye cannot judge 4.5:1. */
    --fg:#EDEEF2; --muted:#9aa3b6; --muted2:#757c8e;
    --indigo:#6366f1; --indigoL:#818cf8; --cyan:#0ea5e9; --amber:#E0A23C; --red:#ef5f6b;
    --mk1:#5B64F4; --mk2:#28DCF3;
    --grad:linear-gradient(115deg,#818cf8,#0ea5e9);
    --sans:ui-sans-serif,-apple-system,"SF Pro Display","Segoe UI",Roboto,Inter,sans-serif;
    --mono:ui-monospace,"SF Mono","JetBrains Mono",Menlo,monospace;
    --maxw:1120px;
    --ease:cubic-bezier(.22,.61,.36,1);
  }
  *{box-sizing:border-box;margin:0;padding:0}
  html{scroll-behavior:smooth}
  body{background:var(--bg);color:var(--fg);font-family:var(--sans);line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
  body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
    background:radial-gradient(55% 40% at 15% -5%,rgba(99,102,241,.14),transparent 60%),radial-gradient(50% 45% at 100% 108%,rgba(14,165,233,.10),transparent 60%)}
  a{color:inherit;text-decoration:none}
  .wrap{max-width:var(--maxw);margin:0 auto;padding:0 clamp(20px,5vw,40px)}
  .grad{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
  .mono{font-family:var(--mono)}

  .btn{display:inline-block;background:var(--indigo);color:#fff;font-weight:600;font-size:15px;padding:13px 24px;border-radius:12px;border:1px solid transparent;cursor:pointer;
       transition:transform .18s var(--ease),box-shadow .18s var(--ease),background .18s var(--ease)}
  .btn:hover{transform:translateY(-2px);box-shadow:0 10px 34px rgba(99,102,241,.38)}
  .btn:active{transform:translateY(0)}
  .btn.ghost{background:transparent;border-color:var(--line2);color:var(--fg)}
  .btn.ghost:hover{border-color:rgba(129,140,248,.55);background:rgba(99,102,241,.08);box-shadow:0 10px 30px rgba(0,0,0,.35)}
  :focus-visible{outline:2px solid var(--indigoL);outline-offset:3px;border-radius:10px}

  .chip{display:inline-flex;align-items:center;gap:7px;font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--cyan);border:1px solid rgba(14,165,233,.35);background:rgba(14,165,233,.08);padding:5px 11px;border-radius:999px}
  .dot{width:6px;height:6px;border-radius:50%;background:var(--cyan);box-shadow:0 0 10px var(--cyan);animation:pulse 2.6s ease-in-out infinite}
  @keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.78)}}

  /* ── header ─────────────────────────────────────────────────────────────── */
  header{position:sticky;top:0;z-index:50;backdrop-filter:blur(14px);background:rgba(10,10,15,.72);border-bottom:1px solid var(--line);transition:border-color .3s var(--ease),background .3s var(--ease)}
  header.stuck{background:rgba(10,10,15,.9);border-bottom-color:var(--line2)}
  .nav{display:flex;align-items:center;justify-content:space-between;height:66px;gap:14px}
  /* ── NAV BUTTONS ARE SMALLER THAN PAGE BUTTONS ─────────────────────────────
     Operator directive 2026-10-14: the header CTAs read as oversized. They shared
     `.btn` with the hero and in-page CTAs — 15px type on 13/24 padding — which is
     right for a button someone has scrolled to and decides on, and too heavy for a
     66px-tall header bar where the same pair repeats on every scroll position.

     ⚠️ SCOPED TO `.nav`, NOT A CHANGE TO `.btn`. Shrinking `.btn` globally would
     also shrink the hero "Download free" and the one at the foot of the download
     section, which are the page's primary conversion targets and are deliberately
     large. The nav pair is navigation; the page pair is the ask.

     Kept: 44px minimum touch height via padding + line-height, so this stays above
     the pointer-target floor on touch devices rather than becoming a hairline. */
  .nav .btn{font-size:13.5px;padding:8px 15px;border-radius:9px}
  .nav .btn:hover{transform:translateY(-1px);box-shadow:0 6px 20px rgba(99,102,241,.3)}
  .logo{display:flex;align-items:center;gap:11px;font-weight:700;letter-spacing:-.015em;font-size:17px;flex-shrink:0}
  .logo .mk{width:30px;height:30px;flex-shrink:0}
  .nav-cta{display:flex;gap:10px;align-items:center}

  /* ── hero ───────────────────────────────────────────────────────────────── */
  .hero{padding:clamp(52px,8vw,104px) 0 clamp(40px,6vw,72px)}
  .hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,60px);align-items:center}
  h1{font-size:clamp(34px,6vw,62px);line-height:1.03;letter-spacing:-.035em;font-weight:800;margin:18px 0 16px}
  .sub{color:var(--muted);font-size:clamp(16px,2.4vw,20px);max-width:36ch}
  .cta-row{display:flex;gap:12px;flex-wrap:wrap;margin-top:28px;align-items:center}
  .platforms{font-family:var(--mono);font-size:12px;color:var(--muted2);margin-top:16px}
  .hero-art{position:relative;min-width:0}

  h2{font-size:clamp(24px,4vw,38px);line-height:1.1;letter-spacing:-.025em;font-weight:800;margin-bottom:10px}
  .lead{color:var(--muted);font-size:17px;max-width:62ch}
  section{padding:clamp(48px,7vw,88px) 0;border-top:1px solid var(--line)}
  .eyebrow{font-family:var(--mono);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--indigoL);margin-bottom:14px}

  .problem{font-size:clamp(20px,3vw,31px);font-weight:700;letter-spacing:-.015em;line-height:1.32;max-width:26ch}
  .problem b{color:#fff}

  /* ── cards ──────────────────────────────────────────────────────────────── */
  .tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:34px}
  .tile{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:26px;position:relative;
        transition:transform .3s var(--ease),border-color .3s var(--ease),background .3s var(--ease)}
  .tile:hover{transform:translateY(-4px);border-color:var(--line2);background:var(--panel2)}
  .tile .ic{width:42px;height:42px;border-radius:12px;display:grid;place-items:center;background:rgba(99,102,241,.12);border:1px solid rgba(99,102,241,.3);margin-bottom:15px;
            transition:transform .3s var(--ease)}
  .tile:hover .ic{transform:scale(1.07) rotate(-3deg)}
  .tile h3{font-size:18px;letter-spacing:-.015em;margin-bottom:7px}
  .tile p{color:var(--muted);font-size:14.5px}

  .relbar{background:rgba(99,102,241,.10);border-bottom:1px solid rgba(99,102,241,.28)}
  .relbar .wrap{display:flex;gap:10px 18px;align-items:baseline;flex-wrap:wrap;padding-top:11px;padding-bottom:11px}
  .relbar .tag{font-family:var(--mono);font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--indigoL);font-weight:600;white-space:nowrap}
  .relbar .txt{font-size:13.5px;color:var(--muted)}

  /* `.steps` is the shared 4-up card grid. `.g2`/`.g3` force 2-up/3-up on wide
     screens. Both are CLASSES, not inline styles: an inline
     grid-template-columns outranks every @media rule below, which is how a
     2-up grid used to survive all the way down to 375px. */
  .steps{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:30px}
  .steps.g2{grid-template-columns:repeat(2,1fr)}
  .steps.g3{grid-template-columns:repeat(3,1fr)}
  .step{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px;min-width:0;
        transition:transform .3s var(--ease),border-color .3s var(--ease),background .3s var(--ease)}
  .step:hover{transform:translateY(-3px);border-color:var(--line2);background:var(--panel2)}
  .step .n{font-family:var(--mono);font-size:13px;color:var(--cyan);font-weight:700}
  .step h4{margin:8px 0 5px;font-size:15.5px;letter-spacing:-.01em}
  .step p{color:var(--muted);font-size:13.5px}

  .cmp{width:100%;border-collapse:collapse;margin-top:26px;font-size:14.5px;display:block;overflow-x:auto}
  .cmp table{width:100%;border-collapse:collapse;min-width:560px}
  .cmp th,.cmp td{border:1px solid var(--line);padding:13px 15px;text-align:left;vertical-align:top}
  .cmp th{font-family:var(--mono);font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);font-weight:500}
  .cmp td.win{background:rgba(99,102,241,.09);color:#fff;font-weight:600}
  .cmp .y{color:var(--cyan)} .cmp .n{color:var(--muted2)}

  .aha{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,48px);align-items:center}
  .receipt{background:#0a0c11;border:1px solid var(--line2);border-radius:16px;padding:24px;font-family:var(--mono);font-size:13px;min-width:0}
  .receipt .row{display:flex;justify-content:space-between;gap:12px;padding:8px 0;border-bottom:1px dashed rgba(255,255,255,.08);color:var(--muted);flex-wrap:wrap}
  .receipt .row:last-of-type{border:none}
  .receipt .row b{color:var(--fg);font-weight:600;transition:color .3s var(--ease)}
  .verify{margin-top:16px;display:flex;gap:10px;align-items:center;flex-wrap:wrap}
  .badge{font-family:var(--mono);font-size:12px;padding:5px 10px;border-radius:8px;transition:color .3s var(--ease),background .3s var(--ease),border-color .3s var(--ease)}
  .badge.ok{color:var(--cyan);background:rgba(14,165,233,.1);border:1px solid rgba(14,165,233,.4)}
  .badge.fail{color:var(--red);background:rgba(239,95,107,.1);border:1px solid rgba(239,95,107,.4)}
  .shake{animation:shake .4s var(--ease)}
  @keyframes shake{0%,100%{transform:translateX(0)}22%{transform:translateX(-5px)}46%{transform:translateX(4px)}72%{transform:translateX(-2px)}}

  .cta-band{border-top:1px solid var(--line);text-align:center}
  .cta-inner{max-width:620px;margin:0 auto}
  form.wl{display:flex;gap:10px;margin-top:26px;flex-wrap:wrap;justify-content:center}
  form.wl input{flex:1;min-width:220px;background:var(--panel2);border:1px solid var(--line2);border-radius:12px;padding:14px 16px;color:var(--fg);font-size:15px;font-family:var(--sans);
                transition:border-color .2s var(--ease),box-shadow .2s var(--ease)}
  form.wl input:focus{outline:none;border-color:var(--indigo);box-shadow:0 0 0 3px rgba(99,102,241,.2)}
  .wl-note{font-family:var(--mono);font-size:12px;color:var(--muted2);margin-top:16px}
  .wl-ok{display:none;margin-top:22px;color:var(--cyan);font-size:16px;font-weight:600}

  footer{border-top:1px solid var(--line);padding:40px 0;color:var(--muted2);font-family:var(--mono);font-size:12px;line-height:1.8}
  .foot-row{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
  .foot-logo{display:flex;align-items:center;gap:9px;margin-bottom:10px;color:var(--muted)}
  .foot-logo .mk{width:20px;height:20px}

  .dl{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:30px}
  .plat{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:24px;min-width:0;
        transition:transform .3s var(--ease),border-color .3s var(--ease)}
  .plat:hover{transform:translateY(-4px);border-color:var(--line2)}
  /* ── THE THREE PLATFORM TILES ARE LINKS NOW ────────────────────────────────
     Operator directive 2026-10-14: they looked clickable and were not. Each one
     is an <a> to /download#p-mac | #p-win | #p-linux — the per-platform anchors
     that already existed on that page, so a visitor lands on THEIR platform's
     section rather than the top of a long page.

     🔴 THEY ALREADY HAD A HOVER TRANSFORM, WHICH IS WHY THIS WAS WORSE THAN A
     MISSING LINK. `.plat:hover` lifts the card 4px — a card that rises under the
     cursor and then does nothing when clicked reads as broken, not as static.
     The affordance was already promising the behaviour; only the behaviour was
     missing.

     `display:block` because an <a> is inline by default and would collapse the
     tile's layout. `color:inherit` + `text-decoration:none` so the heading, the
     mono filenames and the amber signing warnings keep their own colours instead
     of all turning link-blue.

     ⚠️ The 4th tile ("In your browser") is deliberately still a <div>: it
     describes a feature of the installer above rather than offering a download,
     so there is nowhere for it to go. */
  a.plat{display:block;color:inherit;text-decoration:none}
  a.plat:hover,a.plat:focus-visible{text-decoration:none}
  a.plat:focus-visible{outline:2px solid var(--indigoL);outline-offset:3px}
  .plat h3{font-size:17px;letter-spacing:-.015em;margin-bottom:4px}
  .plat .arch{font-family:var(--mono);font-size:11.5px;color:var(--cyan);letter-spacing:.04em}
  .plat ul{list-style:none;margin:14px 0 0;padding:0}
  .plat li{font-family:var(--mono);font-size:12px;color:var(--muted);padding:7px 0;border-bottom:1px dashed rgba(255,255,255,.07);
           display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;overflow-wrap:anywhere}
  .plat li:last-child{border:none}
  .plat li span:last-child{color:var(--muted2);white-space:nowrap}
  .plat .sig{margin-top:14px;font-size:12.5px;line-height:1.5}
  .plat .sig.ok{color:var(--cyan)} .plat .sig.warn{color:var(--amber)}

  .chg{list-style:none;margin:26px 0 0;padding:0;display:grid;gap:10px}
  .chg li{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:15px 17px;font-size:14.5px;color:var(--muted);
          transition:border-color .3s var(--ease),transform .3s var(--ease)}
  .chg li:hover{border-color:var(--line2);transform:translateX(3px)}
  .chg li b{color:var(--fg);font-weight:600}
  .chg li .k{font-family:var(--mono);font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:var(--indigoL);display:block;margin-bottom:4px}

  /* Portal / downloads / source CTAs — FAIL-CLOSED. All are hidden in CSS; only
     the config scripts can reveal them. If JS never runs, or `enabled` is false,
     no LINK is ever rendered and no visitor is sent to a destination that may
     not serve. The matching `*-note` elements are plain copy, not destinations,
     so they render regardless. */
  [data-portal-link],[data-portal-note],[data-dl-link],[data-dl-note],[data-src-link],[data-src-note]{display:none}
  .portal-note{font-family:var(--mono);font-size:12px;color:var(--muted2);margin-top:12px}
  .flag-note{background:var(--panel);border:1px solid var(--line2);border-left:3px solid var(--amber);
             border-radius:10px;padding:15px 17px;margin-top:26px;font-size:14px;color:var(--muted)}
  .flag-note b{color:var(--fg);font-weight:600}

  /* ── MEASURED: the number and its scope, welded into ONE TEXT FLOW ──────────
     🔴 THE RULE IS UNCHANGED AND IT IS THE WHOLE POINT: the ~99.5% figure and
     the task class it applies to are ONE finding. "~99.5%" unqualified is not
     a bolder claim, it is a FALSE one — the same run scored 54% vs 42% on
     yes/no judgement, so an unscoped number asserts something the data does
     not support and hands a skeptic a ready-made gotcha.

     ⚠️ WHAT CHANGED 2026-10-14, and why it is a tightening and not a loosening:
     this used to be a two-CELL grid (number | bound), collapsing to one column
     under 860px. The operator asked for it much shorter, so the bound cell is
     gone and the scope now lives in the SAME ELEMENT as the number — inside
     `.big`'s own `<span>`. That is a STRICTER weld than the grid was: two cells
     can be cropped apart by a screenshot or pulled apart by a deck author;
     one text flow cannot. `.bound`, `.k` and the 860px override were removed
     with it rather than left as dead rules.

     🔴 CONSTRAINTS FOR ANYONE EDITING THIS:
       • never render the number without its scope clause in the same box;
       • never move the scope into a footnote, an asterisk, a tooltip, or a
         later section — all four have been tried on this page;
       • if the scope will not fit, DELETE THE NUMBER. A bare 99.5% is worse
         than no figure at all.
     The amber left rule marks the whole box as a bounded claim, so the scope
     reads as part of the finding rather than as fine print. */
  .msr{margin-top:30px;border:1px solid var(--line2);border-left:3px solid var(--amber);
       border-radius:16px;background:var(--panel);overflow:hidden}
  .msr > div{padding:clamp(20px,3vw,26px);min-width:0}
  .msr .big{font-size:clamp(30px,5vw,44px);font-weight:800;letter-spacing:-.035em;line-height:1.02;color:#fff}
  .msr .big span{display:block;font-size:15px;font-weight:600;letter-spacing:0;line-height:1.55;
                 color:var(--muted);margin-top:10px;max-width:62ch}
  .msr .big span b{color:var(--fg);font-weight:600}

  /* ── MOTION ─────────────────────────────────────────────────────────────────
     Three animations, each earning its place by showing something the copy
     otherwise only asserts:
       1. `.rv`      scroll reveal — gives the page its reading order back; a
                     long single-column argument lands better one beat at a time.
       2. `.mk path` the mark draws itself once, like a seal being struck.
       3. the hero SVG — the ONE that does real work: it shows a query crossing
                     to the other machine and an answer returning while the file
                     never moves, and a packet being stopped at the egress gate.
                     That is the product thesis; a static picture cannot say it.
     Everything is transform/opacity/stroke-dashoffset, so it stays off the
     main thread. All of it is switched off wholesale under
     prefers-reduced-motion at the bottom of this block. */
  .js .rv{opacity:0;transform:translateY(20px);transition:opacity .75s var(--ease),transform .75s var(--ease)}
  .js .rv.in{opacity:1;transform:none}
  .js .rv-d1{transition-delay:.07s} .js .rv-d2{transition-delay:.14s}
  .js .rv-d3{transition-delay:.21s} .js .rv-d4{transition-delay:.28s}
  .js .rv-d5{transition-delay:.35s} .js .rv-d6{transition-delay:.42s}

  /* `pathLength="100"` on the paths normalises BOTH the long outline (~716
     user units) and the short stem (~42) to the same 100-unit scale, so one
     dasharray draws each proportionally over the same 1.5s. With a raw
     dasharray the stem would have been fully drawn in the first 6% and the
     outline would have sat invisible for half the animation. */
  .mk .mk-p{stroke-dasharray:100;stroke-dashoffset:0}
  .js .mk .mk-p{animation:draw 1.5s var(--ease) both}
  @keyframes draw{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}

  /* hero: the encrypted query crossing to the other machine, and back */
  .tok{animation:tok 4.6s var(--ease) infinite}
  .tok2{animation:tok2 4.6s var(--ease) infinite}
  @keyframes tok{
    0%{transform:translateX(0);opacity:0}
    6%{opacity:1} 40%{transform:translateX(210px);opacity:1}
    47%{transform:translateX(210px);opacity:0} 100%{transform:translateX(210px);opacity:0}}
  @keyframes tok2{
    0%,50%{transform:translateX(0);opacity:0}
    56%{opacity:1} 90%{transform:translateX(-210px);opacity:1}
    97%,100%{transform:translateX(-210px);opacity:0}}
  .flow{stroke-dasharray:7 9;animation:flow 1.6s linear infinite}
  @keyframes flow{to{stroke-dashoffset:-32}}
  .screen{animation:screen 3.4s ease-in-out infinite}
  @keyframes screen{0%,100%{opacity:.9}50%{opacity:.45}}
  /* a packet rises toward the gate and is turned back: default-deny, drawn */
  .deny{animation:deny 3.8s var(--ease) infinite}
  @keyframes deny{
    0%{transform:translateY(16px);opacity:0}
    18%{opacity:1} 44%{transform:translateY(-6px);opacity:1}
    62%{transform:translateY(10px);opacity:.25} 100%{transform:translateY(16px);opacity:0}}
  .gate-glow{animation:gateglow 3.8s var(--ease) infinite}
  @keyframes gateglow{0%,38%,100%{opacity:.18}52%{opacity:.6}}

  @media(max-width:860px){
    /* The art follows the copy here, in DOM order — it used to be pulled above
       it with `order:-1`, which on a 375px phone pushed the headline entirely
       below the fold: the first screen was a diagram with no claim attached to
       it. The headline is the pitch, so it leads and the diagram illustrates
       what you have just read. */
    .hero-grid{grid-template-columns:1fr} .hero-art{max-width:430px;margin:8px auto 0}
    .tiles{grid-template-columns:1fr}
    .steps,.steps.g2,.steps.g3{grid-template-columns:1fr 1fr}
    .dl{grid-template-columns:1fr}
    .aha{grid-template-columns:1fr} .sub{max-width:none} .problem{max-width:none}
  }
  /* Phone. Every multi-column grid collapses to ONE column here — at 375px a
     2-up card is ~150px wide and the mono strings inside the download cards
     would push the body into horizontal scroll. */
  @media(max-width:580px){
    .steps,.steps.g2,.steps.g3{grid-template-columns:1fr}
    .nav{height:auto;padding:10px 0;flex-wrap:wrap;gap:10px}
    .nav-cta{width:100%;gap:8px}
    .nav-cta .btn{flex:1 1 auto;text-align:center;padding:10px 12px;font-size:13.5px}
    .btn{font-size:14px;padding:11px 18px}
    .cta-row{gap:10px} .cta-row .btn{flex:1 1 auto;text-align:center}
    .foot-row{flex-direction:column} .foot-row div:last-child{text-align:left!important}
    .receipt{padding:18px;font-size:12px}
    .tile,.plat{padding:20px}
  }

  /* 🔴 NON-NEGOTIABLE. One block, scoped to no component, so a future
     animation cannot be added without it being covered. `!important` because
     the reveal rule sets opacity:0 — reduced motion must not mean invisible. */
  @media(prefers-reduced-motion:reduce){
    html{scroll-behavior:auto}
    *,*::before,*::after{
      animation-duration:.001ms!important;animation-iteration-count:1!important;
      transition-duration:.001ms!important;scroll-behavior:auto!important}
    .js .rv{opacity:1!important;transform:none!important}
    .mk .mk-p{stroke-dashoffset:0!important}
    .tok,.tok2,.deny{opacity:1!important;transform:none!important}
    .flow{stroke-dasharray:none!important}
  }


/* ══════════════════════════════════════════════════════════════════════════════
   DOCS COMPONENTS — authored against the tokens above, not a second design system.
   These eight classes exist only on /docs/* and /download; everything else on those
   pages now uses the homepage's own classes so the two surfaces cannot drift.
   Operator directive 2026-10-14: "I want all the pages to look how the home page
   looks right now."
   ══════════════════════════════════════════════════════════════════════════════ */

.lede{color:var(--muted);font-size:17px;max-width:68ch;margin-top:13px}
.crumb{color:var(--muted2);font-size:13px;padding:26px 0 0}
.stepn{font-size:11.5px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
       color:var(--muted2)}
/* `.step` already exists on the homepage as a numbered process row. Docs use it as a
   SECTION, so only the spacing is extended here — the look is inherited. */
.docstep{border-top:1px solid var(--line);margin-top:34px;padding-top:26px}
.flag{display:flex;gap:11px;border:1px solid var(--line);border-left:3px solid var(--amber);
      border-radius:12px;padding:14px 16px;background:var(--panel);margin:16px 0;
      font-size:14.5px;color:var(--muted);line-height:1.6}
.flag.good{border-left-color:#3ECF8E}
.flag b{color:var(--fg);font-weight:620}
.flag .ic{flex:0 0 auto;color:var(--amber);font-weight:800}
/* 🔴 A <pre> INSIDE A .flag OVERFLOWED THE BOX AND THE PAGE, AND THE pre's OWN
   overflow-x:auto NEVER GOT A CHANCE. .flag is display:flex, so its text <div>
   is a flex item — and a flex item's default min-width is AUTO, meaning it
   refuses to shrink below its content's intrinsic minimum. A <pre> holding an
   unbreakable 100-char URL (the signing-certificate identity on /docs/verify)
   has an intrinsic minimum of the whole URL, so the ITEM grew instead of the
   pre scrolling. The parent wins that argument every time.
   ⇒ min-width:0 is what lets overflow-x:auto do its job. Affects all three
   pages that put a pre in a flag (verify, add-a-device, cli), not just the one
   it was reported on.
   ⚠️ Do not "fix" this by wrapping the URL — a signing identity you are asked
   to compare by eye must not be re-flowed across lines by a stylesheet. */
/* 🔴 THE INVARIANT, NOT THE INSTANCE. The /docs/verify overflow was a <pre>
   inside .flag, but the CAUSE is generic: a flex or grid child defaults to
   min-width:auto and refuses to shrink below its content's intrinsic minimum,
   so ONE unbreakable token (a URL, a hash, a base64 blob) grows the item, the
   box, and the page. It is invisible until some content happens to be long,
   which is why it shipped. Every container here is flex or grid somewhere, so
   every one of them gets the floor. */
/* Every flex/grid container in this stylesheet, enumerated by scripts/check-layout.mjs
   rather than by hand — a hand-written list is the one that goes stale the next time
   someone adds a container. Run that script after touching layout; it fails with the
   names to add.
   ⚠️ min-width:0 only ever RELAXES a constraint. For items declared flex:0 0 auto
   (.ic, .logo, .vtag …) flex-shrink is already 0, so the floor cannot shrink them —
   it is inert there and load-bearing everywhere else. */
:where(.aha, .brand, .can, .card, .cards, .cta-row, .chg, .chip, .dep, .dl, .dlrow,
       .flag, .foot-logo, .foot-row, .g3, .half-hd, .hero, .hero-grid, .ic, .logo,
       .nav, .nav-cta, .nav-l, .navlinks, .ostab, .ostabs, .pager, .plat, .plist,
       .reftab, .row, .sfbar, .step, .steps, .tiles, .verify, .vtag, .wl, .wrap,
       figure) > *{min-width:0}
/* And a hard ceiling on the things that actually carry long content. Belt and
   braces: the rule above lets them shrink, these stop them spilling if some
   future container is missed. */
:where(pre, table, img, iframe, video, canvas, figure){max-width:100%}
pre{overflow-x:auto}
.flag.good .ic{color:#3ECF8E}
.next{border-top:1px solid var(--line);margin-top:38px;padding:24px 0 54px}
.navlinks{display:flex;gap:20px;align-items:center}
.navlinks a{color:var(--muted);font-size:14px;font-weight:500;text-decoration:none}
.navlinks a:hover,.navlinks a:focus-visible{color:var(--fg);text-decoration:none}
.nav-l{display:flex;gap:18px;align-items:center}
.nav-l a{color:var(--muted);font-size:14px;text-decoration:none}
.nav-l a:hover,.nav-l a:focus-visible{color:var(--fg);text-decoration:none}

/* Docs pages read long-form, so they narrow the column. Everything else — type scale,
   colour, cards, nav — comes from the homepage rules above. */
/* 🔴 :not(.nav) IS LOAD-BEARING. This read `body.doc .wrap{max-width:880px}` and the
   HEADER's inner element is `<div class="wrap nav">` — so the narrow reading column was
   also squeezing the header, and /docs rendered its nav 240px narrower than /download
   with byte-identical markup. Operator 2026-10-14: "different spacing on the header and
   the body". The narrow measure is for PROSE; the header is chrome and must align across
   every page or the site reads as several sites. */
body.doc .wrap:not(.nav){max-width:880px}
body.doc pre{font-family:var(--mono);font-size:12.9px;line-height:1.62;background:#07070b;
     border:1px solid var(--line);border-radius:12px;padding:14px 16px;overflow-x:auto;
     margin:13px 0;color:#cfd4e2}
body.doc pre .c{color:var(--muted2)}
body.doc pre .ok{color:#3ECF8E}
body.doc table{width:100%;border-collapse:collapse;margin:14px 0;font-size:14.5px}
body.doc th,body.doc td{text-align:left;padding:9px 11px;border-bottom:1px solid var(--line);
     color:var(--muted)}
body.doc th{color:var(--muted2);font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;
     font-weight:700}
body.doc td:first-child{color:var(--fg);font-family:var(--mono);font-size:12.8px}
body.doc figure{margin:18px 0}
body.doc figure img{width:100%;border:1px solid var(--line);border-radius:12px;display:block}
body.doc figcaption{color:var(--muted2);font-size:13.5px;margin-top:9px}
body.doc h1{font-size:clamp(28px,4.2vw,40px);line-height:1.1;letter-spacing:-.028em;
     font-weight:680;margin:10px 0 0}
body.doc h2{font-size:23px;letter-spacing:-.018em;font-weight:660;margin:7px 0 10px}
body.doc h3{font-size:16px;font-weight:640;margin:22px 0 7px}
body.doc p{color:var(--muted);margin:10px 0;font-size:15.5px;line-height:1.68}
body.doc li{color:var(--muted);margin:5px 0;font-size:15.5px}
body.doc code{font-family:var(--mono);font-size:13px;background:var(--panel2);
     border:1px solid var(--line);border-radius:6px;padding:1.5px 5px;color:var(--fg)}

/* ── DOCS HUB — the card grid and the reference chips ─────────────────────────
   Added when every page moved to this stylesheet. `.card` deliberately reuses the
   homepage's panel/line/radius tokens rather than inventing a second card. */
.sec{padding:30px 0 54px}
.h2sub{color:var(--muted2);font-size:14.5px;margin-bottom:18px}
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(286px,1fr));gap:14px}
.card{display:block;border:1px solid var(--line);border-radius:16px;padding:20px 20px 18px;
      background:var(--panel);transition:transform .3s var(--ease),border-color .3s var(--ease)}
a.card:hover,a.card:focus-visible{transform:translateY(-4px);border-color:var(--line2);
      text-decoration:none}
.card .n{font-size:11px;font-weight:700;letter-spacing:.1em;color:var(--muted2)}
.card h3{font-size:17px;font-weight:640;letter-spacing:-.015em;margin:7px 0 6px;color:var(--fg)}
.card p{color:var(--muted);font-size:14.5px;margin:0}
.reftab{display:flex;flex-wrap:wrap;gap:7px;margin-top:4px}
.reftab span{font-size:12.5px;font-family:var(--mono);color:var(--muted);
      border:1px solid var(--line);border-radius:7px;padding:4px 9px}
.reftab span.area{color:var(--muted2);border-color:transparent;padding-left:0;
      letter-spacing:.09em;text-transform:uppercase;font-size:10.5px;font-weight:700;
      align-self:center}


/* ══════════════════════════════════════════════════════════════════════════
   /download COMPONENTS — recovered 2026-10-14.
   🔴 THESE WERE DELETED BY MISTAKE. When every page moved onto this shared
   stylesheet, /download's inline <style> was removed along with the others —
   but only the DOCS classes were ported here. The download page's own 30-odd
   components (the OS tab strip, the download rows, the two-column halves, the
   numbered step list) had nothing to land on, so the page rendered as unstyled
   boxes with black icons on white.
   ⚠️ THE LIST OF MISSING CLASSES WAS PRINTED DURING THE MIGRATION AND NOT ACTED
   ON. A diff that is computed and then ignored is worse than one never run —
   it creates a record showing the problem was visible. Recovered verbatim from
   git (78ba55dbb), filtered to rules whose selectors this sheet did not already
   define, so nothing above is overridden.
   ══════════════════════════════════════════════════════════════════════════ */

.brand{display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:-.02em;
         color:var(--fg);text-decoration:none;font-size:15px}
.vtag{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:12px;
        color:var(--muted);border:1px solid var(--line2);border-radius:999px;padding:5px 12px}
.vtag b{color:var(--fg);font-weight:600}
.pulse{width:6px;height:6px;border-radius:50%;background:#34d399}
/* ══ THE TWO HALVES ══ */
  .halves{display:grid;grid-template-columns:1fr 1fr;gap:clamp(18px,2.4vw,30px);
          align-items:start;padding-bottom:clamp(40px,6vw,72px)}
.halves>*{min-width:0}
.half{background:var(--panel);border:1px solid var(--line);border-radius:18px;
        padding:clamp(18px,2.2vw,26px)}
.half.right{background:linear-gradient(180deg,rgba(99,102,241,.05),rgba(255,255,255,.02));
              border-color:rgba(129,140,248,.2)}
.half-hd{display:flex;align-items:flex-start;gap:12px;margin-bottom:6px}
.half-hd .big{font-family:var(--mono);font-size:12px;color:var(--indigoL);
       border:1px solid rgba(129,140,248,.38);border-radius:8px;padding:3px 9px;flex:0 0 auto;margin-top:4px}
.dep{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:#e8c48d;
       background:rgba(224,162,60,.08);border:1px solid rgba(224,162,60,.26);
       border-radius:999px;padding:4px 11px;margin:10px 0 2px;font-weight:600}
.halfsub{color:var(--muted);font-size:14.5px;margin:6px 0 0}
.ostabs{display:flex;gap:8px;flex-wrap:wrap;margin:18px 0 16px}
.ostab{display:inline-flex;align-items:center;gap:8px;background:rgba(255,255,255,.03);
         border:1px solid var(--line);color:var(--muted);border-radius:11px;
         padding:9px 14px;font-size:14px;font-weight:600;cursor:pointer;
         transition:all .2s var(--ease);font-family:inherit}
.ostab:hover{color:var(--fg);border-color:var(--line2)}
.ostab[aria-selected="true"]{color:#fff;border-color:rgba(129,140,248,.6);
         background:rgba(99,102,241,.14)}
.ostab svg{width:16px;height:16px;flex:0 0 auto}
.ostab .auto{font-family:var(--mono);font-size:9.5px;letter-spacing:.09em;color:var(--indigoL);
         border:1px solid rgba(129,140,248,.4);border-radius:5px;padding:1px 4px;display:none}
.ostab[data-detected="1"] .auto{display:inline}
.ospane{display:none}
.ospane.on{display:block;animation:fade .3s var(--ease)}
.dlrow{display:flex;align-items:center;justify-content:space-between;gap:14px;
         background:rgba(255,255,255,.025);border:1px solid var(--line);border-radius:13px;
         padding:14px 16px;margin:0 0 10px;flex-wrap:wrap}
.dlrow.primary{border-color:rgba(129,140,248,.34);background:rgba(99,102,241,.07)}
.dlrow .meta{min-width:0;flex:1 1 190px}
.dlrow .mt{font-family:var(--mono);font-size:10.5px;color:var(--muted2);letter-spacing:.08em;
             text-transform:uppercase;margin:0 0 3px}
.dlrow .fn{font-family:var(--mono);font-size:11.5px;color:var(--muted);word-break:break-all;margin:4px 0 0}
.dlrow .szi{font-weight:500;font-size:13px;color:var(--muted);font-family:var(--mono)}
.plist{list-style:none;counter-reset:p;margin:18px 0 0;padding:0}
.plist>li{counter-increment:p;position:relative;padding:0 0 18px 40px;margin:0}
.plist>li::before{content:counter(p);position:absolute;left:0;top:0;width:27px;height:27px;
       border-radius:50%;border:1px solid rgba(129,140,248,.42);background:rgba(99,102,241,.1);
       color:var(--indigoL);font-family:var(--mono);font-size:12.5px;display:grid;place-items:center}
.plist>li:not(:last-child)::after{content:'';position:absolute;left:13px;top:31px;bottom:4px;
       width:1px;background:linear-gradient(180deg,rgba(129,140,248,.3),rgba(129,140,248,.05))}
.plist h3{margin:3px 0 5px}
.plist p{margin:0;color:var(--muted);font-size:14px}
pre .hl{color:#a7e8cd}
.can{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:12px 0 0}
.can>div{border:1px solid var(--line);border-radius:11px;padding:12px 13px;background:rgba(255,255,255,.022)}
.can .hd{font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;margin:0 0 7px}
.can .yes .hd{color:#34d399}
.can .no .hd{color:var(--red)}
.can ul{margin:0;padding-left:16px;color:var(--muted);font-size:13.2px}
.can li{margin:0 0 3px}
.halves{grid-template-columns:1fr}
.can{grid-template-columns:1fr}

/* Compound selectors from /download — `.dlrow .meta`, `.btn.ghost`, `.half.right`
   and friends. Missed by the first pass because its filter tested whether ANY class
   in a selector was already defined, which skips every rule that scopes a new class
   under an existing parent. */
.btn.ghost:hover{border-color:rgba(129,140,248,.55);background:rgba(99,102,241,.08)}
.btn.sm{font-size:13.5px;padding:8px 14px}
.flag.info{background:rgba(255,255,255,.028);border-color:var(--line);color:var(--muted)}
.flag.info .ic{color:var(--muted2)}

/* ─────────────────────────────────────────────────────────────────────────────
   SURFACE TOGGLE — "In the app" vs "From the command line", per docs page.
   Reuses .ostabs/.ostab from the download picker rather than inventing a second
   tab idiom; only the panes are new, because .ospane is keyed by id and these
   are keyed by surface and repeat once per step.

   🔴 FAIL-OPEN, DELIBERATELY. .sfpane is VISIBLE by default and JS hides the
   inactive one. The inverse — hidden by default, revealed by JS — renders a
   BLANK PAGE for anyone whose JS did not run, on a docs site whose whole
   argument is that you can follow along. A reader with no JS sees both surfaces,
   which is redundant but complete; never the reverse.
──────────────────────────────────────────────────────────────────────────── */
.sfbar{position:sticky;top:0;z-index:5;padding:10px 0 8px;margin:0 0 4px;
  background:linear-gradient(180deg,var(--bg) 70%,transparent);backdrop-filter:blur(6px)}
.sfpane{display:block}
.sfnote{color:var(--muted2);font-size:13px;margin:-2px 0 14px}
html.sf-js .sfpane{display:none}
html.sf-js .sfpane.on{display:block}
/* Prev / next pager */
.pager{display:flex;gap:12px;justify-content:space-between;align-items:stretch;margin:34px 0 0}
.pager a{flex:1 1 0;display:block;text-decoration:none;border:1px solid var(--line);
  border-radius:12px;padding:13px 15px;transition:border-color .18s var(--ease),background .18s var(--ease)}
.pager a:hover{border-color:var(--line2);background:rgba(255,255,255,.02)}
.pager .dir{display:block;color:var(--muted2);font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;margin-bottom:5px}
.pager .ttl{display:block;color:var(--fg);font-size:15px;font-weight:600}
.pager .nx{text-align:right}
.pager .spacer{flex:1 1 0}
@media (max-width:620px){.pager{flex-direction:column}.pager .nx{text-align:left}}
