/* ═══════════════════════════════════════════════════════════════════════════
   wabi-header.css — the header that is live on wabi.ai, ported.
   Source: sotabot/website-v1 (the dev.wabi.ai working tree), verbatim values:
     nav              src/features/marketing/components/header.tsx
     logo             src/features/marketing/components/wabi-logo.tsx
     glass button     src/components/ui/marketing-glass-button.tsx
     the popup        src/features/marketing/components/get-app-dialog.tsx
     store rows + QR  src/features/marketing/components/app-download-options.tsx
   These are wabi.ai's numbers. If the site changes, RE-PORT — do not nudge them.
   The one addition is the Manifesto link, which the live nav does not carry.

   StyleX cannot express parent-hover descendant selectors, so the React version
   tracks pointer state in state and passes it down as props. In CSS the same
   thing is :hover / :active on the button, and :has() for the wrap that has to
   react to its own child being pressed.
   ═══════════════════════════════════════════════════════════════════════════ */

@property --angle-1 { syntax: '<angle>'; inherits: false; initial-value: -75deg; }
@property --angle-2 { syntax: '<angle>'; inherits: false; initial-value: -45deg; }

@font-face { font-family:'Kalice'; src:url('../fonts/Kalice-Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }

.wh { --ease-q:cubic-bezier(0.25, 1, 0.5, 1);       /* easings.outQuart */
      --ease-x:cubic-bezier(0.22, 1, 0.36, 1); }    /* easings.outExpoish */

/* ── nav ─────────────────────────────────────────────────────────────────
   Fixed at ALL widths: the live header is `relative` on mobile unless the page
   passes fixedOnMobile, and /import passes it — a phone that scrolls past the
   header loses the App Store link for the whole page. */
.wh {
  position:fixed; top:0; left:0; right:0; z-index:200;
  display:flex; align-items:center; justify-content:space-between;
  padding:24px; overflow:visible;
  pointer-events:none;                 /* the empty middle must not eat clicks */
}
@media (min-width:1025px) { .wh { padding:32px; } }
.wh-logo, .wh-right { pointer-events:auto; }

.wh-logo {
  display:flex; align-items:center; text-decoration:none; position:relative;
  top:0; min-width:140px; min-height:50px;
}
@media (min-width:1025px) { .wh-logo { top:-4px; min-width:200px; min-height:60px; } }

.wh-right { display:flex; align-items:center; gap:clamp(18px, 2.2vw, 36px); }

/* the one addition — set to match the nav's own scale, not invented */
.wh-link {
  font-family:var(--face);
  font-size:clamp(14px, 1.35vw, 20px);
  font-weight:400; letter-spacing:-0.02em;
  color:#191919; text-decoration:none; opacity:.62; white-space:nowrap;
  transition:opacity 200ms ease;
  display:inline-flex; align-items:center;
}
.wh-link:hover { opacity:1; }

/* ── the logo, and its settle ───────────────────────────────────────────── */
.wh-logo svg {
  height:30px; width:auto; display:block;
  /* ⚠ SCALED, NOT RESIZED. `height` on an `auto`-width SVG is a LAYOUT change, and
     the mark is the first flex child of the nav — growing it on hover pushes the
     nav's own geometry about under the pointer. A transform grows the drawing and
     leaves the box exactly where it was, which is also what keeps the whole width
     hoverable: the box is what `:hover` is tested against. */
  transform-origin:left center;
  transition:height .6s var(--ease-q), transform .42s var(--ease-q);
}
.wh-logo.is-settled svg { height:24px; }
@media (min-width:1025px) {
  .wh-logo svg { height:33.6px; }
  .wh-logo.is-settled svg { height:26.88px; }
}
/* ⚠ IT GROWS. A DIVERGENCE from the live site's own hover, which SHRINKS the lockup
   (24px → 18px) and holds the wordmark at .6 — that reads as the logo backing away
   from the pointer. Here the mark leans in and the word steps aside for it. */
.wh-logo:hover svg { transform:scale(1.13); }
.wh-logo .logo-circles { opacity:.3; transition:opacity .4s ease; }
.wh-logo.is-settled .logo-circles, .wh-logo:hover .logo-circles { opacity:.6; }
.wh-logo .logo-text { opacity:0; transition:opacity .15s ease; }
.wh-logo.is-settled .logo-text, .wh-logo:hover .logo-text {
  opacity:.6; transition-duration:.4s; transition-delay:.45s;
}
.wh-logo .logo-letter { transition:transform .2s ease, opacity .2s ease, fill 180ms ease; }
.wh-logo .logo-w { transform:translateX(-35px); }
.wh-logo .logo-a { transform:translateX(-65px); }
.wh-logo .logo-b { transform:translateX(-90px); }
.wh-logo .logo-i { transform:translateX(-110px); }
.wh-logo.is-settled .logo-letter, .wh-logo:hover .logo-letter {
  transform:translateX(0);
  transition:transform .5s var(--ease-q) .3s, opacity .4s ease .3s, fill 180ms ease;
}
.wh-logo.is-settled .logo-a, .wh-logo:hover .logo-a { transition-delay:.32s; }
.wh-logo.is-settled .logo-b, .wh-logo:hover .logo-b { transition-delay:.34s; }
.wh-logo.is-settled .logo-i, .wh-logo:hover .logo-i { transition-delay:.36s; }

/* ── the hover: the mark grows and the word leaves, letter by letter ───────
   ⚠ THE WORD FADES, IT DOES NOT COLLAPSE. Opacity takes a letter out of the picture
   and leaves its BOX, so the anchor is the same width hovered as not — the whole
   lockup stays the hover area, and letting go cannot make the pointer fall out of
   the thing it is hovering (which is a flicker loop: word gone, box shrinks, hover
   lost, word back).
   ⚠ AND THESE RULES COME AFTER the settled pair above, which is also `(0,3,0)` and
   also matches while hovering. Same specificity, so the later one wins — putting
   this block earlier in the file silently does nothing. */
.wh-logo:hover .logo-letter {
  opacity:0;
  /* w first, then a, b, i — 55ms apart, which at .26s each keeps the four reading
     as one motion rather than four separate fades */
  transition:opacity .26s ease, transform .5s var(--ease-q) .3s, fill 180ms ease;
}
.wh-logo:hover .logo-w { transition-delay:0ms, .3s, 0s; }
.wh-logo:hover .logo-a { transition-delay:55ms, .3s, 0s; }
.wh-logo:hover .logo-b { transition-delay:110ms, .3s, 0s; }
.wh-logo:hover .logo-i { transition-delay:165ms, .3s, 0s; }
/* the whole group must NOT fade as one on top of that, or the stagger is buried
   under a single 400ms wash of the four letters together */
.wh-logo:hover .logo-text { opacity:.6; transition-delay:0s; }
@media (prefers-reduced-motion:reduce) {
  .wh-logo:hover svg { transform:none; }
  .wh-logo:hover .logo-letter { transition-duration:.01s; }
}

/* ══ the marketing glass button ═════════════════════════════════════════════
   Real spans in place of pseudo-elements, because the ring and the shadow ring
   both need mask compositing. */
.mgb {
  position:relative; z-index:2; border-radius:999vw;
  background-color:transparent; pointer-events:none;
  transition:all 400ms var(--ease-q);
}
.mgb:has(.mgb-btn:active) { transform:rotate3d(1, 0, 0, 25deg); }
.mgb--header { width:112px; }
@media (min-width:1025px) { .mgb--header { width:148px; } }

.mgb-btn {
  appearance:none; margin:0; padding:0; border-style:none;
  outline:2px solid transparent; outline-offset:3px;
  box-sizing:content-box;
  font:inherit; color:inherit; text-align:inherit; text-decoration:none;
  cursor:pointer; position:relative;
  -webkit-tap-highlight-color:rgba(0,0,0,0);
  pointer-events:auto; z-index:3;
  background-color:transparent;
  background-image:linear-gradient(-75deg, rgba(255,255,255,.05), rgba(255,255,255,.2), rgba(255,255,255,.05));
  border-radius:999vw;
  box-shadow:inset 0 0.125em 0.125em rgba(0,0,0,.035), inset 0 -0.125em 0.125em rgba(255,255,255,.5),
             0 0.25em 0.125em -0.125em rgba(0,0,0,.1), 0 0 0.1em 0.25em inset rgba(255,255,255,.2),
             0 0 0 0 rgba(255,255,255,1);
  -webkit-backdrop-filter:blur(clamp(1px, 0.125em, 4px));
  backdrop-filter:blur(clamp(1px, 0.125em, 4px));
  transition:all 400ms var(--ease-q);
  display:flex; align-items:center; justify-content:center;
  height:46px;
}
.mgb-btn:focus-visible { outline-color:rgba(25,25,25,.58); }
.mgb-btn:hover {
  transform:scale(.975);
  box-shadow:inset 0 0.125em 0.125em rgba(0,0,0,.035), inset 0 -0.125em 0.125em rgba(255,255,255,.5),
             0 0.075em 0.025em -0.1em rgba(0,0,0,.25), 0 0 0.05em 0.1em inset rgba(255,255,255,.5),
             0 0 0 0 rgba(255,255,255,1);
}
/* variant styles come AFTER hover so the header's own shadow keeps precedence */
.mgb--header .mgb-btn {
  width:112px; height:40px;
  background-image:linear-gradient(-75deg, rgba(255,255,255,.10), rgba(255,255,255,.30), rgba(255,255,255,.10));
  background-color:rgba(255,255,255,.55);
  border:1px solid rgba(255,255,255,.9);
  box-shadow:inset 0 1px 4px rgba(255,255,255,.665), inset 0 -4px 4px rgba(255,255,255,.85),
             inset 0 0 14px rgba(229,229,229,.55), 0 11px 28px rgba(0,0,0,.07), 0 23px 31px rgba(0,0,0,.05);
  -webkit-backdrop-filter:blur(clamp(4px, 0.5em, 14px));
  backdrop-filter:blur(clamp(4px, 0.5em, 14px));
}
@media (min-width:1025px) { .mgb--header .mgb-btn { width:148px; height:56px; } }

/* hero and heroLarge: the header button at page scale, sized by its label */
.mgb--hero, .mgb--heroLarge { width:fit-content; }
.mgb--hero .mgb-btn, .mgb--heroLarge .mgb-btn {
  width:auto;
  background-image:linear-gradient(-75deg, rgba(255,255,255,.10), rgba(255,255,255,.30), rgba(255,255,255,.10));
  background-color:rgba(255,255,255,.55);
  border:1px solid rgba(255,255,255,.9);
  box-shadow:inset 0 1px 4px rgba(255,255,255,.665), inset 0 -4px 4px rgba(255,255,255,.85),
             inset 0 0 14px rgba(229,229,229,.55), 0 11px 28px rgba(0,0,0,.07), 0 23px 31px rgba(0,0,0,.05);
  -webkit-backdrop-filter:blur(clamp(4px, 0.5em, 14px));
  backdrop-filter:blur(clamp(4px, 0.5em, 14px));
}
.mgb--hero .mgb-btn { height:62px; }
.mgb--heroLarge .mgb-btn { height:60px; }
@media (min-width:1025px) {
  .mgb--hero .mgb-btn { height:77px; }
  .mgb--heroLarge .mgb-btn { height:74px; }
}

.mgb-label {
  position:relative; width:100%; height:100%;
  display:flex; align-items:center; justify-content:center;
  user-select:none;
  color:rgba(50,50,50,1);
  text-shadow:0em 0.05em 0.05em rgba(0,0,0,.05);
  transition:all 400ms var(--ease-q);
  padding-inline:1.75em;
  font-size:16px; font-weight:500; letter-spacing:-0.18px; white-space:nowrap;
}
.mgb--header .mgb-label {
  font-family:var(--face); font-size:13px; font-weight:400; letter-spacing:-0.14px;
  color:#363636; padding-inline:0.65em;
  display:inline-flex; align-items:center; gap:5px;
}
@media (min-width:1025px) {
  .mgb--header .mgb-label { font-size:19px; letter-spacing:-0.19px; padding-inline:0.7em; gap:7px; }
}
.mgb--hero .mgb-label, .mgb--heroLarge .mgb-label {
  font-family:var(--face); font-weight:400; color:#363636;
  padding-inline:1.5em; display:inline-flex; align-items:center; gap:8px;
}
.mgb--hero .mgb-label { font-size:19px; letter-spacing:-0.24px; }
.mgb--heroLarge .mgb-label { font-size:18px; letter-spacing:-0.24px; }
@media (min-width:1025px) {
  .mgb--hero .mgb-label { font-size:24px; padding-inline:1.6em; }
  .mgb--heroLarge .mgb-label { font-size:23px; padding-inline:1.6em; }
}

.mgb-shine {
  display:block; position:absolute; z-index:3;
  width:calc(100% - clamp(1px, 0.0625em, 4px));
  height:calc(100% - clamp(1px, 0.0625em, 4px));
  top:calc(0% + clamp(1px, 0.0625em, 4px) / 2);
  left:calc(0% + clamp(1px, 0.0625em, 4px) / 2);
  border-radius:999vw; overflow:clip;
  background-image:linear-gradient(var(--angle-2), rgba(255,255,255,0) 0%, rgba(255,255,255,.5) 40% 50%, rgba(255,255,255,0) 55%);
  mix-blend-mode:screen; pointer-events:none;
  background-size:200% 200%; background-position:0% 50%; background-repeat:no-repeat;
  transition:background-position 500ms var(--ease-q), --angle-2 500ms var(--ease-q);
}
.mgb-btn:hover .mgb-shine { background-position:25% 50%; }

.mgb-ring {
  position:absolute; z-index:1; border-radius:999vw;
  width:calc(100% + clamp(1px, 0.0625em, 4px));
  height:calc(100% + clamp(1px, 0.0625em, 4px));
  top:calc(0% - clamp(1px, 0.0625em, 4px) / 2);
  left:calc(0% - clamp(1px, 0.0625em, 4px) / 2);
  padding:clamp(1px, 0.0625em, 4px); box-sizing:border-box;
  background-image:conic-gradient(from var(--angle-1) at 50% 50%, rgba(0,0,0,.5), rgba(0,0,0,0) 5% 40%, rgba(0,0,0,.5) 50%, rgba(0,0,0,0) 60% 95%, rgba(0,0,0,.5)),
                   linear-gradient(180deg, rgba(255,255,255,.5), rgba(255,255,255,.5));
  -webkit-mask-image:linear-gradient(#000 0 0), linear-gradient(#000 0 0);
  -webkit-mask-clip:content-box, border-box;
  -webkit-mask-origin:content-box, border-box;
  -webkit-mask-composite:xor;
  mask-image:linear-gradient(#000 0 0), linear-gradient(#000 0 0);
  mask-clip:content-box, border-box;
  mask-origin:content-box, border-box;
  mask-composite:exclude;
  transition:all 400ms var(--ease-q), --angle-1 500ms ease;
  box-shadow:inset 0 0 0 calc(clamp(1px, 0.0625em, 4px) / 2) rgba(255,255,255,.35);
}
.mgb-btn:hover .mgb-ring { --angle-1:-125deg; }

.mgb-shadow {
  position:absolute;
  width:calc(100% + 0.5em); height:calc(100% + 0.5em);
  top:calc(0% - 0.25em); left:calc(0% - 0.25em);
  filter:blur(clamp(0.5px, 0.0313em, 3px));
  overflow:visible; pointer-events:none; z-index:1;
}
@media (min-width:1025px) {
  .mgb-shadow {
    width:calc(100% + 1em); height:calc(100% + 1em);
    top:calc(0% - 0.5em); left:calc(0% - 0.5em);
    filter:blur(clamp(1px, 0.0625em, 6px));
  }
}
.mgb:has(.mgb-btn:hover) .mgb-shadow { filter:blur(clamp(0.25px, 0.0156em, 1.5px)); }
.mgb-shadow span {
  position:absolute; z-index:0; border-radius:999vw;
  background-image:linear-gradient(180deg, rgba(0,0,0,.015), rgba(0,0,0,.0075));
  width:calc(100% - 0.5em - 0.0625em); height:calc(100% - 0.5em - 0.0625em);
  top:calc(0.5em - 0.125em); left:calc(0.5em - 0.21875em);
  padding:0.125em; box-sizing:border-box;
  -webkit-mask-image:linear-gradient(#000 0 0), linear-gradient(#000 0 0);
  -webkit-mask-clip:content-box, border-box;
  -webkit-mask-origin:content-box, border-box;
  -webkit-mask-composite:xor;
  mask-image:linear-gradient(#000 0 0), linear-gradient(#000 0 0);
  mask-clip:content-box, border-box;
  mask-origin:content-box, border-box;
  mask-composite:exclude;
  transition:all 400ms var(--ease-q); opacity:1;
}
@media (min-width:1025px) {
  .mgb-shadow span {
    background-image:linear-gradient(180deg, rgba(0,0,0,.03), rgba(0,0,0,.015));
    width:calc(100% - 1em - 0.125em); height:calc(100% - 1em - 0.125em);
    top:calc(1em - 0.25em); left:calc(1em - 0.4375em);
  }
}

/* ══ the iOS / Android popup ════════════════════════════════════════════════
   `Get the app` on a coarse-pointer phone is a direct link; everywhere else it
   opens this. */
.wh-get-direct { display:none; }
.wh-get-dialog { display:block; }
@media (max-width:1024px) and (hover:none) and (pointer:coarse) {
  .wh-get-direct { display:block; }
  .wh-get-dialog { display:none; }
}

.gad-backdrop {
  position:fixed; inset:0; min-height:100dvh; z-index:10000;
  background-color:rgba(24,24,24,.32);
  -webkit-backdrop-filter:blur(18px) saturate(85%);
  backdrop-filter:blur(18px) saturate(85%);
  opacity:1; transition:opacity 180ms var(--ease-q, cubic-bezier(0.25,1,0.5,1));
}
.gad-viewport {
  position:fixed; inset:0; z-index:10001;
  display:flex; align-items:center; justify-content:center;
  overflow-y:auto; overscroll-behavior:contain; padding:16px;
}
@media (min-width:1025px) { .gad-viewport { padding:28px; } }
.gad[hidden] { display:none; }
.gad-backdrop[data-state="closed"], .gad-popup[data-state="closed"] { opacity:0; }
.gad-popup[data-state="closed"] { transform:scale(.97); }
.gad-backdrop[data-state="closing"] { transition-duration:140ms; }
.gad-popup[data-state="closing"] { transition-duration:160ms; }

.gad-popup {
  box-sizing:border-box; position:relative;
  width:min(430px, 100%); margin-block:auto;
  display:flex; flex-direction:column; align-items:center;
  padding:34px 20px 26px;
  border-radius:34px;
  border:1px solid rgba(255,255,255,.76);
  background-color:rgba(246,246,246,.88);
  background-image:radial-gradient(circle at 82% 18%, rgba(255,236,222,.48), transparent 34%),
                   radial-gradient(circle at 18% 74%, rgba(217,231,255,.42), transparent 38%);
  -webkit-backdrop-filter:blur(30px) saturate(145%);
  backdrop-filter:blur(30px) saturate(145%);
  box-shadow:0 34px 100px rgba(0,0,0,.22), inset 0 1px 1px rgba(255,255,255,.9);
  color:#171717; font-family:var(--face);
  outline:none; opacity:1; transform:scale(1); transform-origin:center;
  transition:transform 220ms cubic-bezier(0.22,1,0.36,1), opacity 220ms cubic-bezier(0.22,1,0.36,1);
}
@media (min-width:1025px) {
  .gad-popup { width:min(680px, 100%); padding:52px 52px 42px; border-radius:48px; }
}
@media (prefers-reduced-motion:reduce) {
  .gad-popup { transition-duration:1ms; }
  .gad-popup[data-state="closed"] { transform:scale(1); }
}

.gad-close {
  appearance:none; position:absolute; top:14px; right:14px;
  width:42px; height:42px;
  display:inline-flex; align-items:center; justify-content:center; padding:0;
  border:1px solid rgba(255,255,255,.88); border-radius:50%;
  outline:2px solid transparent; outline-offset:3px;
  background-color:rgba(255,255,255,.82); color:#252525;
  box-shadow:0 6px 18px rgba(0,0,0,.09); cursor:pointer;
  transition:transform 150ms var(--ease-q, cubic-bezier(0.25,1,0.5,1)), background-color 150ms, box-shadow 150ms;
}
@media (min-width:1025px) { .gad-close { top:20px; right:20px; width:48px; height:48px; } }
.gad-close:active { transform:scale(.96); }
.gad-close:focus-visible { outline-color:rgba(25,25,25,.58); }

.gad-mark { display:block; width:36px; height:auto; margin-bottom:18px; color:#171717; }
@media (min-width:1025px) { .gad-mark { width:42px; margin-bottom:24px; } }

.gad-title {
  margin:0; max-width:540px;
  font-family:'Kalice', ui-serif, Georgia, serif;
  font-size:43px; font-weight:400; line-height:.94; letter-spacing:-0.055em;
  text-align:center; text-wrap:balance;
}
@media (min-width:1025px) { .gad-title { font-size:62px; } }
.gad-title span { display:block; }

/* ── the store rows, the divider, the QR ─────────────────────────────────── */
.ado { width:100%; display:flex; flex-direction:column; align-items:center; margin-top:28px; }
@media (min-width:1025px) { .ado { margin-top:38px; } }
.ado-links { width:100%; display:flex; flex-direction:column; gap:14px; }
@media (max-width:1024px) {
  .ado-links .ado-link { flex:0 0 auto; width:100%; max-width:340px; margin-inline:auto; }
}
/* ⚠ ONE WAY IN ON A PHONE. See the note in js/app.js: the single row is the
   `.ado-open` one, relabelled and pointed at wabi.ai/get, and the two store rows,
   both OR rules and the QR come off. `flex:0 0 auto` on it too — in this column
   its 246px basis was a HEIGHT, so it rendered as a giant white lozenge. */
/* ⚠ ONE WAY IN ON A PHONE, and it is the nav's own button at a bigger size — see
   the note in js/app.js. Everything the desktop block carries comes off: both store
   rows, both OR rules, the QR, and the "Open Wabi" row the single button replaces. */
.ado-big { display:none; }
@media (max-width:1024px) {
  .ado .ado-links, .ado .ado-div, .ado .ado-qr, .ado .ado-open { display:none; }
  .ado-big { display:block; width:100%; max-width:320px; margin-inline:auto; }
  /* full width, because it is the page's one primary at this size — the wrap being
     block is not enough, the button inside it is inline-block and sizes to its text */
  .ado-big, .ado-big .mgb-btn { width:100%; }
  .ado-big .mgb-btn { height:60px; justify-content:center; }
  .ado-big .mgb-label { font-size:17px; letter-spacing:-.01em; }
}
@media (min-width:1025px) {
  /* ⚠ NOT `flex:1` each. Stretched across the closing section's 620px the two
     store rows came out ~300px wide apiece, which is a pair of banners rather
     than a pair of buttons. They take their own width and the row centres. */
  .ado-links { flex-direction:row; justify-content:center; }
}
/* ⚠ THE HEADER'S OWN GLASS, not a white pill. These were `background-color:
   rgba(255,255,255,.9)` with a flat drop shadow — opaque, and nothing like the
   material the rest of the page is made of. The declarations below are `.glass-btn`'s
   from css/wabi.css (itself a verbatim port of the live site's): the diagonal
   translucent gradient, the five-layer shadow that puts a dark line inside the top
   and a lit one inside the bottom, and the em-scaled backdrop blur. Re-port from
   there rather than nudging these.
   ⚠ NO `border` — the port has none. A 1px white border over a translucent gradient
   is a hard ring the glass does not have, and it was the main thing making these
   read as buttons drawn on the page rather than lenses lying on it. */
.ado-link {
  /* ⚠ THE BASIS IS A WIDTH ONLY WHILE THE ROW IS A ROW. `.ado-links` is a COLUMN
     below 1025px, where `flex-basis` sizes the MAIN axis — i.e. the height — so
     each store button came out 246px TALL on a phone: two enormous white lozenges
     with a line of type lost in the middle of each. In the column it takes its
     height from its content and its width from the column. */
  flex:0 1 246px; min-height:66px;
  display:flex; align-items:center; justify-content:center; gap:11px;
  padding-inline:18px;
  border:0; border-radius:999vw;
  outline:2px solid transparent; outline-offset:3px;
  color:#181818; text-decoration:none;
  background:linear-gradient(-75deg,
    rgba(255,255,255,.05), rgba(255,255,255,.2), rgba(255,255,255,.05));
  box-shadow:
    inset 0 .125em .125em rgba(0,0,0,.035),
    inset 0 -.125em .125em rgba(255,255,255,.5),
    0 .25em .125em -.125em rgba(0,0,0,.1),
    0 0 .1em .25em inset rgba(255,255,255,.2),
    0 0 0 0 rgba(255,255,255,1);
  backdrop-filter:blur(clamp(1px, .125em, 4px));
  -webkit-backdrop-filter:blur(clamp(1px, .125em, 4px));
  transition:all 400ms var(--ease-wabi, cubic-bezier(.4,0,.2,1));
}
/* ⚠ THE OUTLINE IS THE PORT'S CONIC EDGE, not a border. `.glass-btn::after` in
   css/wabi.css draws the rim as a 1px ring filled with a CONIC gradient — dark at
   four points around the circumference, clear between them — over a flat white
   half, masked to the ring by mask-composite, with one more white hairline inside
   it. That turning bright/dark edge is what makes the header pill read as a lens
   with a thickness; a plain `1px solid` cannot, which is why it was cut earlier.
   Verbatim from there, hover angle included. Re-port, don't nudge. */
.ado-link { --angle-1:-75deg; }
.ado-link::after {
  content:''; position:absolute; z-index:1; inset:0; border-radius:999vw;
  width:calc(100% + clamp(1px,.0625em,4px)); height:calc(100% + clamp(1px,.0625em,4px));
  top:calc(0% - clamp(1px,.0625em,4px) / 2); left:calc(0% - clamp(1px,.0625em,4px) / 2);
  padding:clamp(1px,.0625em,4px); box-sizing:border-box;
  background:
    conic-gradient(from var(--angle-1) at 50% 50%,
      rgba(0,0,0,.5), rgba(0,0,0,0) 5% 40%, rgba(0,0,0,.5) 50%, rgba(0,0,0,0) 60% 95%, rgba(0,0,0,.5)),
    linear-gradient(180deg, rgba(255,255,255,.5), rgba(255,255,255,.5));
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  transition:all 400ms var(--ease-wabi, cubic-bezier(.4,0,.2,1)), --angle-1 500ms ease;
  box-shadow:inset 0 0 0 calc(clamp(1px,.0625em,4px) / 2) rgba(255,255,255,.35);
  pointer-events:none;
}
.ado-link:hover::after { --angle-1:-125deg; }
/* ⚠ the rim is an ::after INSIDE the link, so the link has to be a positioned
   ancestor and its own contents have to sit above the ring. */
.ado-link { position:relative; }
.ado-link > * { position:relative; z-index:2; }

/* the port's own hover: it shrinks slightly and the rim brightens */
.ado-link:hover {
  transform:scale(.975);
  box-shadow:
    inset 0 .125em .125em rgba(0,0,0,.035),
    inset 0 -.125em .125em rgba(255,255,255,.5),
    0 .075em .025em -.1em rgba(0,0,0,.25),
    0 0 .05em .1em inset rgba(255,255,255,.5),
    0 0 0 0 rgba(255,255,255,1);
}
@media (min-width:1025px) { .ado-link { min-height:72px; gap:13px; } }
.ado-link:active { transform:scale(.975); }
.ado-link:focus-visible { outline-color:rgba(25,25,25,.58); }
.ado-icon { width:27px; height:27px; flex-shrink:0; }
@media (min-width:1025px) { .ado-icon { width:31px; height:31px; } }
.ado-copy { display:flex; flex-direction:column; align-items:flex-start; line-height:1; }
 /* the live site sets these 11/12px — raised, because this block is the page's
    own call to action now and the page carries no tiny text */
.ado-eyebrow { font-size:14px; line-height:1.25; color:#6d6d6d; }
@media (min-width:1025px) { .ado-eyebrow { font-size:15px; } }
/* ⚠ 30% tighter than the port: 3px -> 2.1px between "Download on the" and "App
   Store". The two lines are one label, and at 3px on a 13px sub they read as two. */
/* ⚠ 30% OFF WHAT YOU CAN SEE, which is not 30% off this number. The margin is 2.1px
   but the gap between the two lines of ink is ~4.5: the eyebrow's 15px type sits in an
   18.75px line box (≈1.9px of leading under its baseline) and the name's 20px in 21
   (≈0.5 above). Taking 30% off the margin alone is 0.63px — invisible. The optical gap
   goes 4.5 → 3.15, and the 1.35 comes out of the margin. */
.ado-name { margin-top:0.75px; font-size:19px; line-height:1.05; font-weight:500; letter-spacing:-0.025em; }
@media (min-width:1025px) { .ado-name { font-size:20px; } }

.ado-open { display:flex; align-self:stretch; }
.ado-open .ado-icon { height:auto; }
@media (min-width:1025px) { .ado-open { display:none; } }

.ado-div {
  width:100%; display:flex; align-items:center; gap:14px; margin-block:22px;
  color:#686868; font-size:14px; font-weight:500; letter-spacing:.06em;
}
@media (min-width:1025px) { .ado-div { margin-block:28px; } }
.ado-div i { height:1px; flex:1; background-color:rgba(31,31,31,.14); }
.ado-div--mobile { display:flex; }
.ado-div--desktop { display:none; }
@media (min-width:1025px) {
  .ado-div--mobile { display:none; }
  .ado-div--desktop { display:flex; }
}

/* ⚠ The panel is gone — the QR carries its own liquid-glass card now (see
   js/qrtilt.js, ported from the live site's QRTiltCard), and a white panel behind
   a glass tile is two cards for one thing. This is only the slot it sits in. */
/* ⚠ The slot fits the CARD, and the card is the live site's own size — a small
   square chip, clamp(96px, 9vw, 132px), with no words on it. The slot used to be
   262px with the card stretched to fill it and a caption underneath, which is a
   poster with a label rather than the thing wabi.ai actually shows. The padding is
   still here because the card grows to 1.65 on hover and lifts out of the flow. */
.ado-qr {
  display:none;
  width:fit-content;
  padding:8px;
}
@media (min-width:1025px) { .ado-qr { display:block; } }


/* ══ NOT PORTED — added for this page ═══════════════════════════════════════
   ⚠ Everything above this line is a verbatim port of the live site's header and
   should be re-ported rather than edited. What follows is ours.

   ON A PHONE THE NAV NEEDS A GROUND. It is `position:fixed` over a page that
   scrolls under it, so the wordmark and the Get-the-app pill end up sitting on
   whatever photograph or dark section happens to be passing — legible one moment
   and not the next. A hard white bar would cut the page in half, so this is a
   PROGRESSIVE BLUR: four bands of increasing blur, each masked to a shorter slice
   from the top, under one white gradient that fades to nothing at the bottom
   edge. The result has no edge of its own — the strength ramps out.
   ⚠ FOUR ELEMENTS, NOT ONE. A single `backdrop-filter` layer behind a gradient
   mask ramps its OPACITY, not its blur, so the blur has a visible cut-off wherever
   the mask ends. Stacking layers is the only way the blur itself can ramp, which
   is why the veil carries real children rather than being a pseudo-element.
   ⚠ z-index:0 on the veil and the nav's own children lifted above it, because a
   positioned child with an explicit z-index paints over every `auto` sibling
   however early it appears in the DOM. */
.wh-veil { display:none; }
@media (max-width: 700px) {
  .wh-veil {
    display:block; position:absolute; z-index:0;
    left:0; right:0; top:0;
    /* past the nav's own foot, so the fade ends in clear air rather than on the
       line where the items stop */
    height:calc(100% + 22px);
    pointer-events:none;
    background:linear-gradient(to bottom,
      rgba(255,255,255,.94) 0%, rgba(255,255,255,.86) 42%,
      rgba(255,255,255,.55) 72%, rgba(255,255,255,0) 100%);
  }
  .wh-veil i {
    position:absolute; inset:0; display:block;
    -webkit-mask-image:linear-gradient(to bottom, #000 var(--a), transparent var(--b));
            mask-image:linear-gradient(to bottom, #000 var(--a), transparent var(--b));
  }
  .wh-veil i:nth-child(1) { --a:52%; --b:100%; backdrop-filter:blur(2px);  -webkit-backdrop-filter:blur(2px); }
  .wh-veil i:nth-child(2) { --a:38%; --b:78%;  backdrop-filter:blur(5px);  -webkit-backdrop-filter:blur(5px); }
  .wh-veil i:nth-child(3) { --a:22%; --b:56%;  backdrop-filter:blur(9px);  -webkit-backdrop-filter:blur(9px); }
  .wh-veil i:nth-child(4) { --a:0%;  --b:34%;  backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px); }
  #nav.wh > .wh-logo, #nav.wh > .wh-right { position:relative; z-index:1; }
}

/* ── the nav over the dark chapter ─────────────────────────────────────────
   ⚠ ALSO OURS, not ported. The nav is fixed and the Discover chapter is near-black,
   so scrolling it under the header put a #191919 wordmark and a #191919 link on a
   #191919 ground: the header disappeared for the length of the section. The items
   swap to their dark treatment while that chapter is behind them and swap back
   after it — a 180ms fade on colour only, so nothing moves.
   ⚠ The glass pill needs its own dark answer: the light material over near-black is
   a grey slab (the same trap as [[light-glass-needs-dark-variant]]), so on dark it
   takes a light-on-dark fill and a lighter rim rather than keeping its own. */
/* ⚠ THE PATHS, NOT THE SVG. Every path in the wordmark carries its own
   `fill="#191919"` attribute, and a `fill` on the <svg> element loses to a fill on
   the child — so the mark stayed near-black and simply DISAPPEARED over the dark
   chapter while the link beside it turned light correctly. */
/* ⚠ NOT THE LETTERS. This rule carries an ID, so at (1,2,2) it outranks every
   `.wh-logo …` rule in this file and REPLACES their whole `transition` shorthand —
   the four wordmark letters were computing `transition-property: fill`, which
   silently killed both their hover fade AND the settle slide-in they have had since
   the port (they were snapping into place, not sliding). The letters carry
   `fill 180ms` in their own transition lists instead, so the dark swap still fades
   them; everything else in the mark is a plain path and keeps this. */
#nav.wh .wh-logo svg path:not(.logo-letter) { transition:fill 180ms ease; }
#nav.wh .wh-link { transition:color 180ms ease, opacity 180ms ease; }
html[data-navink="dark"] #nav.wh .wh-logo svg path { fill:#f0f0f0; }
html[data-navink="dark"] #nav.wh .wh-link { color:#f0f0f0; opacity:.72; }
html[data-navink="dark"] #nav.wh .wh-link:hover { opacity:1; }
html[data-navink="dark"] #nav.wh .glass-btn {
  transition:background 180ms ease, box-shadow 180ms ease, color 180ms ease;
  background:
    linear-gradient(-75deg, rgba(255,255,255,.10), rgba(255,255,255,.22), rgba(255,255,255,.10)),
    rgba(255,255,255,.14);
  box-shadow:
    inset 0 1px 4px rgba(255,255,255,.22),
    inset 0 -4px 4px rgba(255,255,255,.14),
    inset 0 0 14px rgba(0,0,0,.28),
    0 11px 28px rgba(0,0,0,.30),
    0 23px 31px rgba(0,0,0,.22);
}
html[data-navink="dark"] #nav.wh .glass-btn span { color:#f4f4f4; text-shadow:none; }
/* the veil is a WHITE gradient — over the dark chapter it would be a bright bar,
   so it fades out with the swap */
html[data-navink="dark"] .wh-veil { opacity:0; transition:opacity 180ms ease; }
.wh-veil { transition:opacity 180ms ease; }

/* ── NOT PORTED: the nav mark on a phone ────────────────────────────────────
   10% down on the 30px it ships at. The desktop size is set at 1025px and up and
   is untouched. */
@media (max-width: 700px) {
  #nav.wh .wh-logo svg { height:27px; }
}
