/* ============================================================================
 * mobile.css — the mobile page's ONE stylesheet, generated by build-mobile.js.
 * styles.css (design tokens + shared components) is BUNDLED IN first, then the
 * mobile layers — one file, one request, no staged first paint.
 * Order matters: tokens → base → §1 hero → §2 fix/work → §3 → overrides.
 * Do not edit by hand — edit styles.css / the mobile-*.html parts and re-run.
 * ========================================================================== */

/* ═══════════ design tokens + shared components (styles.css, bundled) ═══════════ */
    /* --- Surt (commercial typeface — TRIAL .otf files) --------------------
       Surt-Normal = body width, Surt-Expanded = headings width.
       These are the trial OTFs; swap the src to licensed .woff2 before launch
       (lighter + properly licensed for web). Filenames must match ./fonts/. */
    @font-face {
      font-family: 'Surt';
      src: url('../fonts/Surt-Normal-Regular-TRIAL.otf') format('opentype');
      font-weight: 400; font-style: normal; font-display: swap;
    }
    @font-face {
      font-family: 'Surt';
      src: url('../fonts/Surt-Normal-Medium-TRIAL.otf') format('opentype');
      font-weight: 500; font-style: normal; font-display: swap;
    }
    @font-face {
      font-family: 'Surt';
      src: url('../fonts/Surt-Normal-Semibold-TRIAL.otf') format('opentype');
      font-weight: 600; font-style: normal; font-display: swap;
    }
    @font-face {
      font-family: 'Surt Expanded';
      src: url('../fonts/Surt-Expanded-Regular-TRIAL.otf') format('opentype');
      font-weight: 400; font-style: normal; font-display: swap;
    }
    @font-face {
      font-family: 'Surt Expanded';
      src: url('../fonts/Surt-Expanded-Medium-TRIAL.otf') format('opentype');
      font-weight: 500; font-style: normal; font-display: swap;
    }
    @font-face {
      font-family: 'Surt Expanded';
      src: url('../fonts/Surt-Expanded-Semibold-TRIAL.otf') format('opentype');
      font-weight: 600; font-style: normal; font-display: swap;
    }

    /* --- Theme tokens (RGB channels so Tailwind can apply /opacity) --------
       Dark is the default. .light on <html> flips the whole page. */
    :root {
      --c-base:  0 0 0;       /* pure black page + hero margins in dark mode */
      --c-panel: 0 0 0;       /* hero box / raised surfaces = pure black too */
      --c-card:  20 20 23;    /* cards keep a hair of elevation so they read on black */
      --c-line:  30 30 33;
      --c-soft:  107 107 115;
      --c-faint: 58 58 64;
      --c-fg:    255 255 255;
      /* brand accents (Figma 156:654) — theme-independent */
      --brand-coral: #ff4201; --brand-blue: #015eff; --brand-pink: #e12b6a; --brand-purple: #642be1; --brand-lavender: #d6c2ff;
      --brand-pink-grad: linear-gradient(168deg, #e12b6a 5%, #f7859a 91%);
      --brand-purple-grad: linear-gradient(168deg, #642be1 5%, #a485f7 91%);
    }
    html.light {
      --c-base:  255 255 255;   /* white page */
      --c-panel: 255 255 255;   /* pure-white hero margins in light mode */
      --c-card:  242 242 242;   /* #f2f2f2 light gray card (mobbin) */
      --c-line:  230 230 228;   /* hairlines */
      --c-soft:  110 110 116;   /* muted text */
      --c-faint: 168 168 172;   /* placeholders */
      --c-fg:    30 39 46;      /* near-black text */
    }
    html { background: rgb(var(--c-base)); }
    /* smooth the flip */
    body, header, .preview, input, textarea, a, button { transition: background-color .25s ease, border-color .25s ease, color .25s ease; }

    /* page-loader state: hero acts as a loader — no scroll, no nav until the crash */
    html.loading { overflow: hidden; }
    html.loading body { overflow: hidden; }
    /* nav fades in on a delay so it arrives WITH the rising h1 (which only clears its
       clip mask partway through its reveal), not before it — appearing too early reads as distracting */
    header { transition: opacity .7s cubic-bezier(.22,.61,.36,1) .45s; }
    html.loading header { opacity: 0; pointer-events: none; }

    /* active segment in the theme switch */
    .theme-btn.is-active { background: rgb(var(--c-fg) / .12); color: rgb(var(--c-fg)); }
    /* theme switch: borderless over the hero, gains a hairline once scrolled past it */
    #theme-switch { border: 1px solid transparent; transition: border-color .35s ease; }
    #theme-switch.bordered { border-color: rgb(var(--c-line)); }

    /* top-nav progressive blur → css/nav.css (shared component) */

    /* headings stay solid in BOTH themes — no muted/gray heading text */
    .h-mute { color: rgb(var(--c-fg)); }

    /* hide scrollbar on the horizontal testimonial track */
    .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
    .no-scrollbar::-webkit-scrollbar { display: none; }

    /* --- Record wheel (testimonials) ------------------------------------- */
    .wheel-mask {
      -webkit-mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
              mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 78%, transparent);
    }
    .wheel-3d { perspective: 1200px; }
    #wheel { transform-style: preserve-3d; }
    .wheel-item {
      position: absolute; left: 0; top: 50%;
      white-space: nowrap; cursor: pointer;
      transform-origin: center center;
      backface-visibility: hidden; -webkit-backface-visibility: hidden;
      font-size: 1.25rem; line-height: 1; color: rgb(var(--c-soft));
      transition: transform .55s cubic-bezier(.22,.61,.36,1), opacity .55s ease, filter .55s ease, color .3s ease;
    }
    .wheel-item.is-active { color: rgb(var(--c-fg)); font-weight: 500; }
    .wheel-item.is-active::before { content: "\2192"; margin-right: .6em; color: rgb(var(--c-fg)); }

    /* now-playing card: whole deck dips + content slides as the next plays */
    .t-card { transition: transform .35s cubic-bezier(.22,.61,.36,1); }
    .t-card.swapping { transform: translateY(10px) scale(.985); }
    .t-card #t-quote, .t-card #t-who { transition: opacity .35s ease, transform .35s ease; }
    .t-card.swapping #t-quote, .t-card.swapping #t-who { opacity: 0; transform: translateY(12px); }

    /* Placeholders from the copy doc stay legible but quiet — no dashed boxes. */
    .ph { color: rgb(var(--c-faint)); font-style: normal; }

    /* --- Hero "build then collapse" skeleton UI -------------------------- */
    #sk-layer { position: absolute; inset: 0; z-index: 1; transition: opacity .5s ease; pointer-events: none; }   /* pass-through: empty areas let hover reach the chip/card bands below (drag lives on .gen, which is pointer-events:auto); matches the JS intent (drag delegated on #hero-box + .gen) */
    #hero-clouds { display: none; }   /* desktop-only sky clouds (shown in the ≥821 block) */
    #sk-layer .sk { position: absolute; top: 0; left: 0; will-change: transform; }
    #sk-layer .sk-in {
      width: 100%; height: 100%; opacity: 0; transform: scale(.92);
      transition: opacity .45s ease, transform .5s cubic-bezier(.2,.75,.25,1);
    }
    #sk-layer .sk.in .sk-in { opacity: 1; transform: none; }
    /* skeleton GRAY LADDER — depth in flat design: gray canvas → white card →
       light inset → mid line → near-ink text. Shared by loader, rain & generated UI. */
    :root {
      /* dark-theme skeleton tokens — components ADAPT: dark cards + light text in dark mode.
         (#hero-box.splash overrides these to light during the loader; :root applies after collapse) */
      --sk-card: #18181d; --sk-inset: rgba(255,255,255,.07); --sk-line: rgba(255,255,255,.13);
      --sk-line2: rgba(255,255,255,.3); --sk-text: rgba(244,244,246,.88); --sk-sub: rgba(244,244,246,.42);
      --sk-ink: #f2f4f6; --sk-panel: rgba(255,255,255,.04); --sk-hair: rgba(255,255,255,.07);
      --sk-disc: rgba(255,255,255,.06); --sk-cloud: rgba(255,255,255,.1); --sk-cloud-frost: rgba(255,255,255,.05);
      --sk-ring-track: rgba(255,255,255,.1); --sk-ring-arc: #ffa485;
      --sk-shadow: 0 14px 30px -16px rgba(0,0,0,.65);
      --sk-appbg: #0c0c0e;   /* the phone's app canvas (recessed screen) */
    }
    html.light {
      --sk-card: #ffffff; --sk-inset: #f1f1f2; --sk-line: #e8e8e9;
      --sk-line2: #cbcbcd; --sk-text: rgba(20,20,23,.85); --sk-sub: rgba(20,20,23,.38);
      --sk-ink: #1e272e; --sk-panel: rgba(239,239,241,.45); --sk-hair: rgba(0,0,0,.05);
      --sk-disc: #f8f8f9; --sk-cloud: #dbdbdc; --sk-cloud-frost: rgba(241,241,242,.35);
      --sk-ring-track: #f0edeb; --sk-ring-arc: #ffa485;   /* soft-coral progress arc (Figma 156:657) */
      --sk-shadow: 0 14px 30px -16px rgba(34,34,40,.16);
      --sk-appbg: #eeeeef;
    }
    .sk-card { background: var(--sk-card); border-radius: 22px; }
    .sk-fill { background: var(--sk-inset); border-radius: 12px; }
    .sk-line { background: var(--sk-line); border-radius: 99px; }
    .sk-strong { background: var(--sk-line2); }
    .sk-round { border-radius: 999px; }
    .sk-col { display: flex; flex-direction: column; }
    .sk-t { font: 500 12.5px/1.2 'Surt', system-ui, sans-serif; letter-spacing: -.01em; color: var(--sk-text); white-space: nowrap; }
    .sk-s { font: 500 8.5px/1.2 'Surt', system-ui, sans-serif; letter-spacing: .09em; text-transform: uppercase; color: var(--sk-sub); white-space: nowrap; }
    .sk-num { font: 600 12px/1 'Surt', system-ui, sans-serif; color: var(--sk-text); }
    .sk-ttl { font-family: 'Surt', system-ui, sans-serif; font-weight: 600; line-height: 1; letter-spacing: .005em; color: var(--sk-ink); white-space: nowrap; }
    /* AI bar (Figma 164:843): full white pill + soft iridescent glow + glossy inset edge */
    .aibar { position: relative; box-sizing: border-box; border-radius: 200px; background: var(--sk-card); overflow: hidden;
             border: 1.25px solid #fff; box-shadow: 0 11.529px 36px -15.372px rgba(30,39,46,.21); }
    .aibar-glow span { position: absolute; bottom: -11px; height: 12px; width: 152px; border-radius: 24.89px; filter: blur(27.5px); opacity: .5; pointer-events: none; }
    .aibar-glow .gc { left: 0; background: var(--brand-coral); }
    .aibar-glow .gp { right: 88px; background: var(--brand-pink); }
    .aibar-glow .gb { right: 0; background: var(--brand-blue); }
    .aibar-text { position: relative; font: 500 12.489px/12.105px 'Surt', system-ui, sans-serif; letter-spacing: .0624px; color: var(--sk-ink); opacity: .55; white-space: nowrap; }
    .aibar-mic { position: absolute; right: 9.89px; top: calc(50% + 1.27px); transform: translateY(-50%); width: 26.9px; height: 26.9px; border-radius: 999px; background: rgba(28,44,63,.06); display: flex; align-items: center; justify-content: center; }
    .aibar-gloss { position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
                   box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.5), inset 0 -6px 14px 1px rgba(30,39,46,.12), inset 0 4px 9px 0 rgba(30,39,46,.15); }
    .sk-dash { border: 1.5px dashed var(--sk-line2); border-radius: 12px; box-sizing: border-box; }
    .skic { display: block; background: var(--sk-ink); -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; }
    .ic-d { display: block; } .ic-l { display: none; }
    html.light .ic-d { display: none; } html.light .ic-l { display: block; }

    /* ===== Hero generator: click-to-make UI, credits, crosshair shove ===== */
    #hero-box.gen-live { cursor: crosshair; }

    /* generator meta row — editorial baseline strip (layout via utility classes);
       only the reveal + state styling lives here. JS toggles .live / .empty / .shake */
    #gen-hud { opacity: 0; transform: translateY(6px); transition: opacity .5s ease, transform .5s ease; }
    #gen-hud.live { opacity: 1; transform: none; }
    #gen-credits svg { color: rgb(var(--c-fg) / .5); }
    #gen-credits.empty { color: rgb(var(--c-fg) / .4); cursor: pointer; }
    #gen-credits.shake { animation: gc-shake .42s ease; }
    @keyframes gc-shake { 0%,100%{transform:translateX(0)} 20%{transform:translateX(-4px)} 40%{transform:translateX(4px)} 60%{transform:translateX(-3px)} 80%{transform:translateX(3px)} }

    /* floating spawn label: "Generating…" → component name (or "Out of credits") */
    .gen-label { position: absolute; z-index: 7; transform: translate(-50%, -50%) scale(.92); opacity: 0; pointer-events: none;
                 display: inline-flex; align-items: center; gap: 8px; padding: 7px 13px; border-radius: 11px; white-space: nowrap;
                 font: 500 12.5px 'Surt','Inter Tight',system-ui,sans-serif; background: rgb(var(--c-fg)); color: rgb(var(--c-base));
                 box-shadow: 0 8px 24px -6px rgb(0 0 0 / .45); transition: opacity .5s ease, transform .9s cubic-bezier(.2,.7,.2,1); }
    .gen-label.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    .gen-label.rise { opacity: 0; transform: translate(-50%, -150%) scale(1); }
    .gen-label.bad { background: rgb(var(--c-card)); color: rgb(var(--c-fg)); box-shadow: 0 8px 24px -6px rgb(0 0 0 / .45); }
    .gen-label svg { width: 13px; height: 13px; }
    .gen-label .gl-matrix circle { fill: currentColor; }

    /* generated, interactive components (driven by physics like .sk) */
    #sk-layer .gen { position: absolute; top: 0; left: 0; will-change: transform; pointer-events: auto; }
    #sk-layer .gen .g-in { width: 100%; height: 100%; opacity: 0; transform: scale(.78); transition: opacity .4s ease, transform .45s cubic-bezier(.2,.85,.25,1); }
    #sk-layer .gen.in .g-in { opacity: 1; transform: none; }
    /* MINI DESIGN SYSTEM — theme-aware via --sk-* tokens: white card+ink in light,
       dark card+light text in dark. Accent = --sk-ink (the high-contrast neutral per theme). */
    .g-card { width: 100%; height: 100%; box-sizing: border-box; display: flex; align-items: center; gap: 10px; padding: 0 14px;
              background: var(--sk-card); border-radius: 18px; color: var(--sk-ink); user-select: none;
              box-shadow: var(--sk-shadow);
              font-family: 'Surt','Inter Tight',system-ui,sans-serif; }
    .g-tag { font-size: 12.5px; font-weight: 400; line-height: 18.75px; color: var(--sk-ink); }
    /* profile card — Figma 222:1114: r12, pl12/pr24/py12, gap12; avatar 36 = pink gradient + photo */
    .g-row { border-radius: 12px; padding: 12px 24px 12px 12px; gap: 12px; }
    .g-col { display: flex; flex-direction: column; gap: 0; }
    .g-av { width: 36px; height: 36px; border-radius: 999px; overflow: hidden; flex: none; }
    .g-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
    .g-l1 { font-size: 13px; font-weight: 500; line-height: 19.5px; color: var(--sk-ink); white-space: nowrap; }
    .g-l2 { font-size: 11px; font-weight: 400; line-height: 16.5px; color: var(--sk-sub); white-space: nowrap; }
    /* toggle — Figma 222:1082: 155×44 card, r10, pl16/pr10/py10, label left + track right */
    .g-toggle { justify-content: space-between; border-radius: 10px; padding: 10px 10px 10px 16px; box-shadow: 0 14px 15px rgba(34,34,40,.16); }
    .g-sw { position: relative; width: 42px; height: 24px; border-radius: 999px; background: var(--sk-inset); flex: none; transition: background .2s ease; }
    .g-knob { position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 999px; background: var(--sk-card); box-shadow: 0 1px 3px rgba(0,0,0,.35); transition: left .22s cubic-bezier(.3,1.5,.5,1); }
    .g-toggle.on .g-sw { background: var(--sk-ink); } .g-toggle.on .g-knob { left: 21px; }
    /* button */
    /* primary button — Figma 222:1093: 132×46 pill r34.864, blue gradient, white Surt Medium 13 */
    .g-btn { width: 100%; height: 100%; border: 0; border-radius: 34.864px; background: linear-gradient(180deg, #266BE1 6.337%, #5395F7 100%); color: #fff; font: 500 13px 'Surt',system-ui; letter-spacing: -.0762px; cursor: pointer; transition: filter .15s ease, transform .1s ease; }
    .g-btn:active { transform: scale(.96); } .g-btn.done { filter: brightness(.9); }
    /* checkbox — Figma 222:1103: BARE on the stage (no white card); white box r6 + inner mark */
    .g-check { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; gap: 9px; cursor: pointer; font-family: 'Surt','Inter Tight',system-ui,sans-serif; }
    .g-box { position: relative; width: 20px; height: 20px; border-radius: 6px; background: #fff; flex: none; transition: background .15s ease; }
    .g-box::before { content:''; position:absolute; left:6px; top:6px; width:8px; height:8px; border-radius:2px; background:rgba(0,0,0,.1); transition: opacity .12s ease; }
    .g-check.on .g-box { background: var(--sk-ink); } .g-check.on .g-box::before { opacity: 0; }
    .g-check.on .g-box::after { content:''; position:absolute; left:6px; top:3px; width:6px; height:10px; border:solid #fff; border-width:0 2px 2px 0; transform: rotate(45deg); }
    /* badge — Figma 222:1155: 77×34 card r18, pl10/pr20, gap7; dot #5D98FF 15 + 4px translucent-blue ring */
    .g-badge { justify-content: center; gap: 7px; font-size: 12.5px; font-weight: 500; color: var(--sk-ink); border-radius: 18px; padding: 0 20px 0 10px; box-shadow: 0 14px 15px rgba(34,34,40,.16); }
    .g-dot2 { width: 8px; height: 8px; border-radius: 999px; background: #5D98FF; box-shadow: 0 0 0 4px rgba(166,198,254,.16); }
    /* slider — Figma 222:1165: 154×25 card r6, p10; track #f1f1f2 5px, ink fill 45%, ink handle 14 */
    .g-slider { border-radius: 6px; padding: 10px; box-shadow: 0 14px 15px rgba(34,34,40,.16); }
    .g-track { position: relative; width: 100%; height: 5px; border-radius: 999px; background: var(--sk-inset); }
    .g-fill { position: absolute; left: 0; top: 0; height: 100%; width: 45%; border-radius: 999px; background: var(--sk-ink); transition: width .3s ease; }
    .g-handle { position: absolute; top: 50%; left: 45%; width: 14px; height: 14px; border-radius: 999px; background: var(--sk-ink); transform: translate(-50%, -50%); box-shadow: 0 .875px 3.5px rgba(0,0,0,.3); transition: left .3s ease; }
    .g-slider.hi .g-fill { width: 82%; } .g-slider.hi .g-handle { left: 82%; }
    /* avatar (standalone) — Figma 258:1606: bare disc on the stage (no white card / no border) */
    .g-avatar { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
    .g-avatar img { width: 56px; height: 56px; display: block; }
    /* color swatch — Figma 222:1184: r11, px12/py10, gap8; each = 24 ring (1px border, 3px pad) + 18 dot */
    .g-swatch { gap: 8px; justify-content: center; border-radius: 11px; padding: 10px 12px; box-shadow: 0 14px 15px rgba(34,34,40,.16); }
    .g-swatch i { box-sizing: border-box; width: 24px; height: 24px; border-radius: 999px; padding: 3px; border: 1px solid rgba(30,39,46,.15); background-clip: content-box; }
    .g-swatch i:nth-child(1){ border-color: #1e272e; background-image: linear-gradient(180deg,#266BE1 6.337%,#5395F7 100%); }
    .g-swatch i:nth-child(2){ background-color: rgba(194,53,227,.25); }
    .g-swatch i:nth-child(3){ background-color: rgba(229,60,116,.25); }
    .g-swatch i:nth-child(4){ background-color: rgba(250,167,25,.25); }
    /* gradient icon tile — Figma 257:1283 etc: 54 circle + multi-colour icon (Figma render baked into PNG) */
    .g-tile { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
    .g-tile img { width: 54px; height: 54px; display: block; }
    /* list item — Figma 258:1684: white card r11, pl10/pr12/py10, gap8; leading 18 icon + 2 lines */
    .g-list { border-radius: 11px; padding: 10px 12px 10px 10px; gap: 8px; justify-content: flex-start; box-shadow: 0 14px 15px rgba(34,34,40,.16); }
    .g-li-ic { width: 18px; height: 18px; flex: none; display: block; }
    .g-li-tx { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
    .g-li-l1 { width: 89.4px; height: 6px; border-radius: 99px; background: #C6C9D1; }
    .g-li-l2 { width: 55.6px; height: 5px; border-radius: 99px; background: #E4E6EB; }
    /* the faint phone outline behind the components; fades out on collapse */
    /* #sk-stage = the gray container box that surrounds the phone on the right.
       At 100% it expands left, then goes fullscreen (geometry transition added then). */
    #sk-stage {
      position: absolute; z-index: 0; pointer-events: none; overflow: hidden;
      top: 12px; right: 12px; bottom: 12px; width: calc(50% - 12px);   /* half-width loader box; expands to the margined card */
      background: linear-gradient(to bottom, #cad9dc, #f3f2ec); border-radius: 32px;   /* softer/lighter loader bg (blue less harsh while half); shader takes over after collapse */
      transition: top .9s cubic-bezier(.16,1,.3,1), right .9s cubic-bezier(.16,1,.3,1),
                  bottom .9s cubic-bezier(.16,1,.3,1), width .9s cubic-bezier(.16,1,.3,1),
                  border-radius .9s cubic-bezier(.16,1,.3,1), opacity .5s ease;
    }
    /* WebGL is OFF during the loader — only the flat gradient shows; the shader fades in once the UI has collapsed */
    #hero-shader { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 1.2s ease; }
    #sk-stage.webgl-on #hero-shader { opacity: 1; }
    #sk-stage.expand { width: calc(100% - 24px); }                       /* grow to the full-width margined card */
    /* #sk-frame = the phone body (white device that floats on the gray hero);
       #sk-screen = the recessed app canvas, inset by a bezel gap. Both fade on collapse. */
    #sk-frame {
      position: absolute; border-radius: 36px; transition: opacity .5s ease; z-index: 0; pointer-events: none;
      background: #f5f8f9;                                           /* no white border, no drop shadow — flat F5F8F9 device body */
    }
    #sk-screen {
      position: absolute; border-radius: 26px; transition: opacity .5s ease; z-index: 0; pointer-events: none;
      background: #f5f8f9; overflow: hidden;                          /* same F5F8F9 app canvas, no border */
    }
    #sk-statusbar { position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; }
    /* loading splash (Figma 134:386): a WHITE surface with a light container,
       scoped to the hero only — rest of the page stays dark. Kept through reveal()
       so the hero ends light (the gray box becomes the fullscreen backdrop). */
    #hero-box.splash {
      background: #fff; transition: background .6s ease;
      --c-base: 255 255 255; --c-panel: 242 242 242; --c-card: 242 242 242;
      --c-line: 230 230 228; --c-soft: 110 110 116; --c-faint: 168 168 172; --c-fg: 30 39 46;
      --sk-card: #ffffff; --sk-inset: #f1f1f2; --sk-line: #e8e8e9; --sk-line2: #cbcbcd;
      --sk-text: rgba(20,20,23,.85); --sk-sub: rgba(20,20,23,.38); --sk-ink: #1e272e;
      --sk-panel: rgba(239,239,241,.45); --sk-hair: rgba(0,0,0,.05); --sk-disc: #f8f8f9;
      --sk-cloud: #dbdbdc; --sk-cloud-frost: rgba(241,241,242,.35);
      --sk-ring-track: #f0edeb; --sk-ring-arc: #ffa485;   /* soft-coral progress arc (Figma 156:657) */
      --sk-shadow: 0 14px 30px -16px rgba(34,34,40,.16); --sk-appbg: #eeeeef;
    }
    html.loading #gen-hud { opacity: 0; }   /* HUD hidden during the splash; returns when the sandbox unlocks */
    /* headline tracks the theme: ink on the light splash during load, white on the
       night-sky backdrop after collapse (splash class is dropped at collapse) */
    #hero-content { color: rgb(var(--c-fg)); }

    /* loader (Figma 134:386): big % numeral on the left, matrix dot beneath —
       the glass canvas sits on the right (ox = W*0.72). No colour yet. */
    #hero-progress {
      position: absolute; left: 17%; top: 50%; transform: translateY(-50%);
      z-index: 3; pointer-events: none;
      display: flex; flex-direction: column; align-items: flex-start; gap: 20px;
      color: rgb(var(--c-fg)); transition: opacity .45s ease, transform .45s ease;
    }
    #hero-progress.gone { opacity: 0; transform: translateY(-50%) scale(.96); }
    /* the big percentage — Surt Expanded, "%" sits at the BASE of the numerals (Figma 116/76) */
    #hp-pct {
      display: inline-flex; align-items: flex-end;
      font-family: 'Surt Expanded', 'Surt', system-ui, sans-serif; font-weight: 400;
      line-height: .85; letter-spacing: -.04em; font-variant-numeric: tabular-nums;
    }
    /* fixed 2-digit slot, right-aligned: the % stays pinned and the digits don't
       shift; when it hits 100 the leading "1" overflows leftward instead of pushing %. */
    /* gentle white gradient over the top/bottom so rolling digits fade in/out instead of a hard clip */
    #hp-num { font-size: clamp(64px, 9vw, 116px); display: inline-flex; width: 2ch; justify-content: flex-end;
      /* ── DIGIT SPACING KNOBS (tweak these two values) ───────────────────
         --digit-gap   : space between EVERY digit. More negative = tighter.
                         Tune this so "23 / 45 / 99" look right (no overlap).
         --lead-1-pull : EXTRA pull applied ONLY to the leading "1" in "100",
                         because the narrow "1" glyph sits centered in a wide
                         cell and otherwise floats too far from the "00".
                         More negative = "1" sits closer to the "00".          */
      --digit-gap: -.05em;
      --lead-1-pull: -.13em; }
    /* per-digit odometer: each digit is a 0–9 strip that rolls vertically to its
       target; the digit that changed softly blurs during the roll, then eases sharp. */
    /* gentle white gradient over top/bottom so rolling digits fade in/out instead of a hard clip.
       Lives on the reel (not #hp-num) so the leading "1" of "100" — which overflows the 2ch
       slot to the left — isn't clipped by the mask box. */
    /* window = exactly ONE digit tall, so neighbouring digits in the 0–9 strip stay
       clipped. The fade only grazes the natural blank leading at top/bottom (keep the
       solid band wide so it doesn't eat into the glyph). */
    /* exactly one digit tall (neighbours clipped). A gentle 4px white gradient softens the
       top/bottom edges as a digit ROLLS, but the static centred digit's glyph is inset well
       clear of those 4px bands, so it's never cut. */
    .reel { display: inline-block; flex: none; overflow: hidden; height: 1em;
      -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 4px, #000 calc(100% - 4px), transparent 100%);
      mask-image: linear-gradient(to bottom, transparent 0, #000 4px, #000 calc(100% - 4px), transparent 100%); }
    .reel-strip {
      display: flex; flex-direction: column; color: rgb(var(--c-fg));
      /* colour snaps back to ink quickly (gentle but soon); blur lingers much longer — distinct timings */
      /* tiny overshoot → the digit settles with a very small bounce as it lands */
      transition: transform .6s cubic-bezier(.36,1.28,.5,1), color .14s ease, filter .55s ease;
    }
    .reel-d { display: block; height: 1em; line-height: 1; text-align: center; }
    .reel + .reel { margin-left: var(--digit-gap); }   /* even gap between all digits */
    /* quantity query: matches the FIRST reel only when there are exactly 3 reels
       ("100"). Pulls the "00" toward the narrow leading "1" so it isn't airy —
       without touching any 2-digit number (23, 45, 99…). */
    .reel:first-child:nth-last-child(3) { margin-right: var(--lead-1-pull); }
    /* changing digit flashes orange (quick) + blurs as it rolls, then EASES back to ink (color .4s on .reel-strip) — no sudden snap */
    /* the changing digit flashes the Rubik cube's CURRENT phase colour (set by rubik-loader.js), then eases back to ink */
    .reel.flash .reel-strip { color: var(--flash-color, #ff6a33); filter: blur(3.4px); transition: transform .6s cubic-bezier(.36,1.28,.5,1), color .08s ease, filter .12s ease; }
    /* --pct-rise: nudge the "%" UP so its base lines up with the numerals' base.
       More = higher. */
    .hp-sign { font-size: clamp(42px, 6vw, 76px); transform: translateY(calc(-1 * var(--pct-rise, 11px))); }
    /* the cycling chip: matrix dot + state label (Figma 135:436) */
    .hp-chip { display: inline-flex; align-items: center; gap: 10px; align-self: center; }   /* optically centred under the numerals */
    #hp-text {
      font-family: 'Surt Expanded', 'Surt', system-ui, sans-serif; font-weight: 400;
      font-size: clamp(15px, 1.5vw, 21px); letter-spacing: -.01em; white-space: nowrap;
      transition: opacity .26s ease, filter .26s ease;
    }
    #hero-progress.swap #hp-text { opacity: 0; filter: blur(5px); }
    /* the label behaves EXACTLY like the number reels. Each glyph sits in its own clipped
       window; on a word change only the differing glyphs roll up/down a letter or two
       (shortest path — never the whole alphabet), flashing the cube's colour + blurring as
       they roll, then easing back to ink. Matched glyphs don't move. */
    .hp-label { display: inline-flex; align-items: center; }
    #hp-text .hp-ch { display: inline-block; overflow: hidden; height: 1.3em; line-height: 1.3;
      vertical-align: bottom; white-space: pre; }
    #hp-text .hp-ch-i { display: block; color: rgb(var(--c-fg));
      transition: transform .5s cubic-bezier(.36,1.28,.5,1), color .14s ease, filter .55s ease; }
    #hp-text .hp-ch-d { display: block; height: 1.3em; line-height: 1.3; text-align: center; }
    #hp-text .hp-ch.flash .hp-ch-i { color: var(--flash-color, #ff6a33); filter: blur(3px);
      transition: transform .5s cubic-bezier(.36,1.28,.5,1), color .08s ease, filter .12s ease; }
    /* circular dot-matrix "thinking" icon — 3x3 cluster breathes as ONE synced pulse
       (the inline per-dot delays are overridden to 0 so they don't fire one-by-one).
       inherits currentColor so it works on any chip. */
    .dm { flex: none; color: inherit; }
    .dm circle { fill: currentColor; opacity: .16; }
    .dm circle.on { animation: dm-pulse 1.5s ease-in-out infinite; animation-delay: 0s !important; transform-box: fill-box; transform-origin: center; }
    @keyframes dm-pulse { 0%, 100% { opacity: .22; transform: scale(.78); } 50% { opacity: 1; transform: scale(1); } }
    .hp-matrix { width: 22px; height: 22px; }
    /* Rubik's-cube loader chip — JS (rubik-loader.js) turns slices, solves (pulse) + near-miss (shake) */
    #rubik { overflow: visible; transform-origin: center; }   /* slices slide out past the grid */
    #rubik.shaking { animation: rubik-shake .5s ease-in-out; }   /* "argh — one's still off" */
    @keyframes rubik-shake { 0%,100% { transform: translateX(0) rotate(0deg); } 18% { transform: translateX(-1.6px) rotate(-5deg); } 40% { transform: translateX(1.6px) rotate(5deg); } 62% { transform: translateX(-1.1px) rotate(-3deg); } 82% { transform: translateX(.9px) rotate(2deg); } }
    #rubik circle { fill: var(--sk-line2); }   /* fallback before JS paints */

    /* --- Section 2: floating icon cards with parallax ------------------- */
    .float-card { position: absolute; will-change: transform; }   /* JS sets parallax transform */
    .fc {
      display: none; align-items: center; justify-content: center;
      border-radius: 22px; background: rgb(var(--c-card));
      box-shadow: 0 4px 5px rgba(30,39,46,.04), 8px 16px 13.5px rgba(30,39,46,.16);   /* Figma icon-tile shadow */
      opacity: 0; transform: scale(.85); transition: opacity .45s ease, transform .45s cubic-bezier(.2,.8,.25,1);
    }
    /* Figma icon tiles (185:2): gradient container + masked icon tinted white/ink */
    .fc-ic { width: 54%; height: 54%; object-fit: contain; display: block; }
    @media (min-width: 1024px) { .fc { display: flex; } }
    .fc-bob { animation: fc-bob 6s ease-in-out infinite; }    /* gentle idle float (inner) */
    @keyframes fc-bob { 0%,100% { transform: translateY(-5px) rotate(-1.5deg); } 50% { transform: translateY(5px) rotate(1.5deg); } }
    .fc.on { opacity: 1; transform: none; }
    .fc svg { width: 38%; height: 38%; color: rgb(var(--c-soft)); }   /* only the (invisible) data-work pencil card now */
    .fc-sm { width: 62px; height: 62px; border-radius: 16px; }
    .fc-md { width: 88px; height: 88px; }
    .fc-lg { width: 112px; height: 112px; border-radius: 28px; }
    /* §2→§3 entry: pencil overlay on the first real §3 card (fades as it becomes a product card) */
    .card0-pencil { position: absolute; inset: 0; z-index: 20; display: flex; align-items: center; justify-content: center; color: rgb(var(--c-soft)); pointer-events: none; }
    .card0-pencil svg { width: 34%; height: 34%; }

    /* per-letter reveal (each char pops up, staggered) */
    .word { display: inline-block; white-space: nowrap; }
    .ch { display: inline-block; opacity: 0; transform: translateY(.4em); transition: opacity .3s ease, transform .4s cubic-bezier(.2,.8,.25,1); }
    .ch.on { opacity: 1; transform: none; }
    .ch.out { opacity: 0; transform: translateY(-.55em); }   /* exit: fades UP, letter by letter (mirrors the entrance) */

    /* --- Process: sticky scrollytelling steps --------------------------- */
    .proc-step { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0; transform: translateY(30px); transition: opacity .55s ease, transform .65s cubic-bezier(.2,.8,.25,1); pointer-events: none; }
    .proc-step.on { opacity: 1; transform: none; }
    /* double-diamond progress indicator */
    #dd-bg { stroke: rgb(var(--c-fg) / .16); }
    #dd-trail { stroke: rgb(var(--c-fg)); transition: stroke-dashoffset .15s linear; }
    #dd-dot { fill: rgb(var(--c-fg)); }
    /* ambient floating icons in the pinned process stage */
    .pfloat { position: absolute; z-index: 0; }
    .pfloat .fc { animation: pfloat-bob 7s ease-in-out infinite; }
    @keyframes pfloat-bob { 0%,100% { transform: translateY(-9px) rotate(-2deg); } 50% { transform: translateY(9px) rotate(2deg); } }

    /* work cards: the SAME squares slide/marquee, then each grows into a full
       card. JS drives card scale (size) + preview scaleY (square→full) + content. */
    #proof .grid { will-change: transform; }
    .reel-card { opacity: 0; transform: scale(.5); transform-origin: center; will-change: transform, opacity; cursor: pointer; }   /* feedback #11: invite the click */
    a.reel-link { display: block; color: inherit; text-decoration: none; }   /* card 1 is an <a> to the case study — reset link defaults, keep the card's block layout */
    article.reel-card { cursor: default; }   /* no case study yet → don't promise a click the card can't honour */
    .reel-card .preview { transform: scaleY(.69); transform-origin: top center; will-change: transform; }  /* .69 = 1/1.45 → looks square */
    .reel-card .preview > span,
    .reel-card .preview > button,
    .reel-late { opacity: 0; will-change: opacity; }

    /* worked-with logo marquee (seamless loop; track holds 2 copies) */
    .logo-marquee { overflow: hidden;
      -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
              mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent); }
    .logo-track { display: flex; align-items: center; gap: clamp(48px, 7vw, 110px); width: max-content; animation: logo-scroll 40s linear infinite; }
    .logo-marquee:hover .logo-track { animation-play-state: paused; }
    @keyframes logo-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
    .logo { font-family: 'Surt', 'Inter Tight', system-ui, sans-serif; font-weight: 500; font-size: clamp(20px, 2.4vw, 34px); letter-spacing: -.02em; color: rgb(var(--c-soft)); white-space: nowrap; transition: color .3s ease; }
    .logo:hover { color: rgb(var(--c-fg)); }

    /* Reveal-footer: the page is an opaque slab with a rounded bottom that scrolls
       UP to uncover a darker footer fixed behind it. JS reserves the scroll room. */
    .page-wrap { position: relative; z-index: 1; background: rgb(var(--c-base)); }
    .footer-dark { background: rgb(6 6 8); }
    html.light .footer-dark { background: rgb(236 236 238); }
    /* desktop only: the slab gets a rounded bottom and scrolls UP to uncover the
       fixed footer-form. JS reserves margin-bottom = footer height. On mobile the
       form is too tall to pin, so the footer just sits in normal flow. */
    @media (min-width: 768px) {
      .page-wrap { border-bottom-left-radius: 40px; border-bottom-right-radius: 40px; margin-bottom: 30rem; }
      .footer-dark { position: fixed; left: 0; right: 0; bottom: 0; z-index: 0; }
    }

    /* selectable pill chips ("What do you need?") — hidden checkbox drives the fill */
    .chip { display: inline-flex; align-items: center; cursor: pointer; padding: .5rem .95rem; border-radius: 9999px; font-size: .875rem; line-height: 1; background: rgb(var(--c-panel)); color: rgb(var(--c-soft)); transition: background .18s ease, color .18s ease; user-select: none; }
    .chip:hover { color: rgb(var(--c-fg)); }
    .chip:has(input:checked) { background: rgb(var(--c-fg)); color: rgb(var(--c-base)); }
    .chip:focus-within { box-shadow: 0 0 0 2px rgb(var(--c-fg) / .25); }

    /* multi-step lead form (lives in the footer) */
    .lf-prog { height: 3px; border-radius: 999px; background: rgb(var(--c-fg) / .12); overflow: hidden; }
    .lf-fill { display: block; height: 100%; width: 33.333%; border-radius: 999px; background: rgb(var(--c-fg)); transition: width .45s cubic-bezier(.4,0,.2,1); }
    .lf-steps { min-height: 16rem; }   /* fixed floor keeps the footer height (and reveal) stable across steps */
    .lf-step { animation: lf-in .35s ease both; }
    @keyframes lf-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
    .lf-hide { visibility: hidden; pointer-events: none; }

    /* Reserved slot for the future three.js canvas, behind hero content. */
    .fx-layer { position: absolute; inset: 0; z-index: 0; pointer-events: none; }

    /* Animation-ready: [data-reveal] starts hidden; GSAP/ScrollTrigger or the
       IntersectionObserver fallback below reveals it. Quiet, short, no bounce. */
    [data-reveal] { opacity: 0; transform: translateY(14px); }
    [data-reveal].is-in {
      opacity: 1; transform: none;
      transition: opacity .8s cubic-bezier(.22,.61,.36,1), transform .8s cubic-bezier(.22,.61,.36,1);
    }

    /* line-mask reveal: each line rises up from behind a clip edge */
    .cl { display: block; overflow: hidden; padding-bottom: .22em; margin-bottom: -.22em; }
    .cl-i { display: block; transform: translateY(120%); transition: transform .9s cubic-bezier(.16,.84,.3,1); }
    [data-hold].is-in .cl-i { transform: none; }
    #work-head.show .cl-i { transform: none; }
    .cl:nth-child(2) .cl-i { transition-delay: .09s; }
    .cl:nth-child(3) .cl-i { transition-delay: .18s; }

    ::selection { background: rgb(var(--c-fg)); color: rgb(var(--c-base)); }
    body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }


/* ─────────────────────────── base + unified nav ─────────────────────────── */

    html { background: #0c0c0e; }
    html.light { background: #d9d9dc; }

    /* .m-wrap = §3 variant: overflow:clip (sticky-safe) + rounded slab bottom that
       lifts to uncover the dark footer #contact (css/footer.css); no 1px ring (it seamed at the reveal). */
    .m-wrap {
      position: relative; z-index: 1; margin: 0 auto; min-height: 100vh;   /* R9: NO max-width — the mobile layout keeps extending edge-to-edge up to the 821 breakpoint (was capped 440 → white gutters at 500px) */
      background: rgb(var(--c-base));
      box-shadow: 0 30px 80px -30px rgba(0,0,0,.6);
      overflow: clip;
      border-bottom-left-radius: 32px; border-bottom-right-radius: 32px;
    }

    .m-wrap [data-reveal] { opacity: 1 !important; transform: none !important; }
    .m-wrap .cl-i        { transform: none !important; }
    .m-wrap .reel-card   { opacity: 1 !important; transform: none !important; will-change: auto; }   /* clear the base will-change: a promoted card layer leaks its .preview rounded clip on real GPUs */
    .m-wrap .reel-card .preview { transform: none !important; will-change: auto; }   /* CRITICAL: no compositing hint on the rounded-clip frame → corners hold on hover */
    .m-wrap .reel-card .preview > span,
    .m-wrap .reel-card .preview > button,
    .m-wrap .reel-late   { opacity: 1 !important; will-change: auto; }   /* clear the base will-change:opacity too — no reason to hold layers after reveal */
    .m-wrap .preview img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }

    .m-ic { width: 40px; height: 40px; border-radius: 12px; overflow: hidden; flex: 0 0 auto; background: rgb(var(--c-card)); display:flex; align-items:center; justify-content:center; }
    .m-ic img { width: 100%; height: 100%; object-fit: cover; }

    /* ── UNIFIED TOP NAV → moved to css/nav.css (shared with the case/blog pages); js/mobile/nav.js drives it ── */

/* ─────────────── §1 · HERO (preloader build→drop physics) ────────────────── */
    /* ---- HERO: build→drop physics (ported from hero-sandbox; mobile-tuned) ---- */
    /* item 3+9 · BLUEISH at the start of the animation (Figma 413:914 loader-bg gradient) — then the
       warm `::before` (below) fades in on .expand, i.e. it "changes to the one we have" on reveal. */
    #sk-stage { background: linear-gradient(180.75deg, rgb(202,222,227) 28%, rgb(139,183,209) 98%); }
    #sk-stage::before {
      content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
      /* item 6 · INVERTED — lighter (warm-white) at the TOP for legibility, steel-blue at the bottom */
      background: linear-gradient(180.67deg, rgb(237,236,230) 8%, rgb(190,208,213) 52%, rgb(139,183,209) 99%);
      opacity:0; transition: opacity .4s ease;
    }
    #sk-stage.expand::before { opacity:1; }
    /* feedback #2 · smooth ENTRANCE — the gradient card, phone chassis and loader % fade in
       together on arrival. From-only keyframe + no forwards fill: once it finishes, nothing
       keeps applying, so the later fade-outs (reveal sets inline opacity) are untouched. */
    @keyframes hero-enter { from { opacity: 0; } }
    #sk-stage, #sk-frame, #sk-screen, #hero-progress { animation: hero-enter .9s ease .05s backwards; }
    #gen-hud { display:none !important; }
    #hero-box.gen-live { cursor:auto; }
    #sk-layer .sk, #sk-layer .gen, #sk-layer .sk *, #sk-layer .gen *, #sk-layer .sk .aibar-gloss { transition: box-shadow .4s ease, filter .4s ease; }
    /* feedback #4 · keep the GENTLE POP-IN of the build components: the blanket rule above
       overrides styles.css's .sk-in transition (same specificity, later layer) → widgets were
       snapping in. Re-assert opacity/transform alongside the shadow/filter pair. */
    #sk-layer .sk .sk-in { transition: opacity .45s ease, transform .5s cubic-bezier(.2,.75,.25,1), box-shadow .4s ease, filter .4s ease; }
    #hero-box.dropped #sk-layer .sk, #hero-box.dropped #sk-layer .gen,
    #hero-box.dropped #sk-layer .sk *, #hero-box.dropped #sk-layer .gen * { box-shadow:none !important; }
    #hero-box.dropped #sk-layer .sk .sk-avatar { filter:none !important; }
    .g-avatar, .g-tile { border-radius:999px; overflow:hidden; }
    .g-avatar img, .g-tile img { width:100%; height:100%; object-fit:cover; }
    .g-tile img { transform: scale(1.04); }
    .g-avatar img { transform: scale(1.25); }
    #hero-box.cloud-nudge #hero-content { pointer-events:auto; }
    #hero-box.cloud-nudge #hero-content h1 span { pointer-events:none; }

    /* --- feedback.md mobile-hero tuning ------------------------------------ */
    /* MOBILE-ONLY geometry: on desktop the base rules above already hold the ORIGINAL
       hero-sandbox composition (half-width stage card on the right, loader numeral on the
       left at 17%/50%) — these !important nudges must never leak past the breakpoint. */
    @media (max-width: 820px) {
    /* 6 · radius −8px (32 → 24). The gradient is a CARD that covers the PHONE ONLY —
       it starts BELOW the heading (top:300, heading sits on the plain bg above) and runs to
       the card bottom. It does NOT span full height and never touches the heading copy. */
    #sk-stage { border-radius: 24px !important; right: 8px !important; width: calc(100% - 16px) !important;
                /* anchored at the BOTTOM, sized by HEIGHT (no top pin, so height drives the expand).
                   When fully loaded it grows to FULL height (8px margins all round): height
                   calc(100% - 16px) with bottom:8 ⇒ top lands at 8. */
                top: auto !important; bottom: 8px !important; height: calc(100% - 16px) !important;
                transition: height .9s cubic-bezier(.16,1,.3,1), border-radius .6s ease, opacity .5s ease !important; }
    /* loading: the card COVERS THE PHONE so the app BUILDS visibly inside it during load.
       item 2 · height is now a PROPORTION (Figma 413:914 = 400/675 ≈ 59%) so it scales nicely,
       clamped so it never gets too short/tall on extreme viewports. */
    html.loading #sk-stage { height: clamp(370px, 59%, 560px) !important; }
    /* THE TRICK (item 1): the app is built during loading, then DISAPPEARS at 100% (#hero-box.ready)
       — the phone fades out and the components fall from the CTA instead. Dispensed .gen are NOT faded. */
    #hero-box.ready #sk-frame, #hero-box.ready #sk-screen, #hero-box.ready #sk-layer .sk { opacity: 0 !important; transition: opacity .5s ease; }
    }
    /* dispensed components: NO drop shadows, and draggable by touch/mouse (item 3 + 6) */
    #sk-layer .gen, #sk-layer .gen * { box-shadow: none !important; }
    /* pan-y (was none): a VERTICAL swipe on a component scrolls the page — only sideways-ish
       drags grab it. Fixes "can't scroll past the hero because I keep grabbing the pile". */
    #sk-layer .gen { pointer-events: auto; touch-action: pan-y; }

    /* item 4 · the CTA text swaps to "Generating…" (in place) while a component is made,
       then back to "Book a call" — the button itself never moves */
    /* item 3 · CTA letters roll up + flash like the loader label; item 4 · the chip is a
       colour-cycling "rubik" cube (not plain dots) */
    .cta-label { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
    .cta-txt { display: inline-flex; }
    .cta-txt .hp-ch { display: inline-block; overflow: hidden; height: 1.25em; line-height: 1.25; vertical-align: bottom; white-space: pre; }
    .cta-txt .hp-ch-i { display: block; transition: transform .42s cubic-bezier(.36,1.24,.5,1), color .1s ease; }
    .cta-txt .hp-ch-d { display: block; height: 1.25em; line-height: 1.25; }
    .cta-txt .hp-ch.flash .hp-ch-i { color: #7fb2ff; }
    .cta-cube { width: 15px; height: 15px; flex: none; animation: cta-cube-in .32s ease both; }
    @keyframes cta-cube-in { from { opacity: 0; transform: scale(.5); } to { opacity: 1; transform: scale(1); } }
    /* base + resting fill = the button colour (#1e272e) so idle dots blend in — no pure-black dots.
       fill-mode:both keeps that resting colour during each dot's animation-delay too. */
    .cta-cube circle { fill: #1e272e; transform-box: fill-box; transform-origin: center; animation: cta-cube 1.9s ease-in-out infinite both; }
    .cta-cube circle:nth-child(2){animation-delay:.1s} .cta-cube circle:nth-child(3){animation-delay:.2s}
    .cta-cube circle:nth-child(4){animation-delay:.3s} .cta-cube circle:nth-child(5){animation-delay:.4s} .cta-cube circle:nth-child(6){animation-delay:.5s}
    .cta-cube circle:nth-child(7){animation-delay:.6s} .cta-cube circle:nth-child(8){animation-delay:.7s} .cta-cube circle:nth-child(9){animation-delay:.8s}
    @keyframes cta-cube {
      0%,100% { fill: #1e272e; transform: scale(.66); }   /* off = button colour */
      15% { fill: #a78bf2; transform: scale(1); }          /* soft purple  (brighter, less saturated) */
      40% { fill: #f18aa6; }                               /* soft pink */
      63% { fill: #f8bd72; }                               /* soft amber */
      85% { fill: #7db0f7; }                               /* soft blue */
    }
    /* MOBILE-ONLY loader placement/sizing (desktop keeps the base left-side numeral) */
    @media (max-width: 820px) {
    /* 1 · loading % sits at the TOP, in the white space above the card (its own element, not
       inside #sk-stage) — it fades out and the headline takes its place when loaded */
    #hero-progress { left: 50% !important; top: 80px !important; transform: translateX(-50%) !important; align-items: center !important; gap: 20px !important; padding-left: 16px !important; }
    #hero-progress.gone { transform: translateX(-50%) scale(.96) !important; }
    /* item 1 · loader sized 1:1 to Figma 413:910 (mobile): number 76 · cube 25.85 · "Finalised" 18.26,
       cube↔text gap 10.77 + pr-20 optical balance (mirrors the left-hand cube) */
    #hp-num { font-size: 76px !important; }
    .hp-matrix { width: 25.85px !important; height: 25.85px !important; }
    .hp-chip { gap: 10.77px !important; padding-right: 20px !important; }
    #hp-text { font-size: 18.26px !important; letter-spacing: -0.18px !important; }
    }
    /* OUT-OF-CREDITS chip — Figma 413:2146 1:1: dark #1e272e pill, blue cloud-slash icon,
       "Out of credits" 12px Surt Medium white, radius 10, pad 7/14/7/8, gap 6 */
    .gen-label.oc { gap: 6px !important; padding: 7px 14px 7px 8px !important; border-radius: 10px !important;
      background: #1e272e !important; color: #fff !important; box-shadow: 0 10px 26px -8px rgb(0 0 0 / .4) !important;
      font-family: 'Surt','Inter Tight',system-ui,sans-serif; font-weight: 500; font-size: 12px !important; }
    .gen-label.oc .oc-ico { width: 16px !important; height: 16px !important; display: block; flex: none; }
    .gen-label.oc .gl-tx { line-height: 18.75px; }
    /* 3 + 4 · hero copy hidden until the build is READY (loading done), then rises in — so the
       CTA is visible to be clicked; it sits ABOVE the rubble so it stays readable after the drop */
    #hero-content { z-index: 40; }
    #hero-box #hero-content .cl-i { transform: translateY(120%) !important; transition: transform .8s cubic-bezier(.16,.84,.3,1); }
    #hero-box.ready #hero-content .cl-i { transform: none !important; }
    #hero-box #hero-content [data-reveal] { opacity: 0 !important; transform: translateY(14px) !important; transition: opacity .7s ease .14s, transform .7s ease .14s; }
    #hero-box.ready #hero-content [data-reveal] { opacity: 1 !important; transform: none !important; }
    /* ── CTA ROLODEX ─────────────────────────────────────────────────────────
       The pill (#cta-btn, overflow:hidden) is a WINDOW. Inside, #cta-reel is a
       "large rectangle" carrying BOTH faces, laid out on an invisible circle whose
       centre is ~300px BELOW the window. Rotating the reel by 24° swaps which face
       sits level & centred in the window: "Book a call" swings out to the right,
       "Generating" swings up from the lower-left (and back). One rigid rotation = the swing.
       Each face is counter-rotated so it lands LEVEL when it reaches the window. */
    #cta-btn { position: relative; overflow: hidden; height: 50px; width: 174px; --k2-ic: 38px; --k2-icon: 18px; }   /* the K2 call button (nav.css); phones: the reel window, sized for "Book a call" */
    .cta-reel { position: absolute; inset: 0; transform-origin: 50% 325px;
                transition: transform .62s cubic-bezier(.34,1.3,.5,1); }
    #cta-btn.busy .cta-reel { transform: rotate(30deg); }        /* rotate → "Generating" into view */
    .cta-face { position: absolute; inset: 0; display: flex; align-items: center;
                justify-content: center; gap: 7px; backface-visibility: hidden; }
    #cta-btn .ctar-win { flex: 1 1 auto; min-width: 0; }   /* phones: the label window fills the fixed-width pill right of the circle */
    #cta-btn .cta-face { justify-content: flex-start; gap: 0; }   /* K2: the faces hold only the padded label; the circle stays put */
    #cta-btn .k2-ic { transition: background-color .3s ease; }
    #cta-btn .k2-ic > * { grid-area: 1 / 1; transition: opacity .3s ease, scale .35s cubic-bezier(.3,1.5,.5,1), visibility 0s .35s; }
    #cta-btn .k2-ic .cta-cube { opacity: 0; scale: .6; visibility: hidden; animation: none; }   /* hidden at rest, for sure: its pop-in animation used to pin it visible */
    #cta-btn.busy .k2-ic { background: #1e272e; }   /* "Generating": the circle turns ink (owner, Oct 26); the cube's off-dots are this colour */
    #cta-btn.busy .k2-ic img { opacity: 0; scale: .6; }
    #cta-btn.busy .k2-ic .cta-cube { opacity: 1; scale: 1; visibility: visible; transition-delay: 0s; }
    /* parked off-window, lower-left; +6px right padding optically balances the left-hand cube */
    .cta-face.is-busy { transform: translate(-150px, 40px) rotate(-30deg); padding-right: 6px; }

/* §1 baked nudges (mobile ≤640px) — #nav-mobile nudge dropped (unified nav owns its padding) */
    @media (max-width: 640px) {
      #hero-h1 {
        margin-left: 4.992179999999999px;
        margin-top: 0.230469px;
        font-size: 31px;
        padding-bottom: 0px;
        letter-spacing: -1.0px;
        line-height: 35.9px;
      }
      #hero-content {
        margin-left: 1.32812px;
        margin-top: -0.4960935px;
        padding-top: 100px;
        padding-right: 20px;
        row-gap: 14px;
        column-gap: 20px;
      }
      #hero-box {
        margin-left: 0.27343775000000003px;
        margin-top: -0.50781225px;
        padding-left: 0px;
        padding-right: 0px;
      }
      #menu-open > svg {
        padding-right: 0px;
      }
      #hero-sub {
        margin-left: 7px;
        margin-top: -0.02343725000000002px;
        padding-bottom: 10px;
        letter-spacing: -0.2px;
        font-size: 17px;
        padding-left: 0px;
      }
    }

/* ─────────────────────── §2 · WHAT WE FIX + WORK ─────────────────────────── */
    /* ===== "we run" statement — overlapping cluster of the four brand icons
            (left tile on top, each tucked -17.379px). Tile 56px, r15.448. (Figma 385:1076) ===== */
    .run-row     { display: flex; align-items: center; justify-content: center; isolation: isolate; }
    .run-ic      { position: relative; flex: none; display: flex; align-items: center; justify-content: center; overflow: hidden;
                   width: 56px; height: 56px; border-radius: 15.448px;
                   box-shadow: 0 13.517px 21.241px -13.517px rgba(18,22,45,.5), inset 0 0.966px 0 0 rgba(255,255,255,.18);
                   /* cavalry-dot reveal: a 9px grid of dots (radius --cav) grows to merge → the icon
                      materialises. default 8px = fully merged (visible) so a no-JS fallback still shows. */
                   --cav: 8px;
                   -webkit-mask-image: radial-gradient(circle, #000 var(--cav), transparent calc(var(--cav) + 0.5px));
                   -webkit-mask-size: 9px 9px;
                           mask-image: radial-gradient(circle, #000 var(--cav), transparent calc(var(--cav) + 0.5px));
                           mask-size: 9px 9px; }
    .run-ic img  { width: 51.72%; height: 51.72%; object-fit: contain; display: block; }
    .run-ic.lite { box-shadow: 0 13.517px 21.241px -13.517px rgba(18,22,45,.22); }   /* white tile: softer shadow, no inset line */
    .run-ic:not(:last-child) { margin-right: -17.379px; }
    .run-ic:nth-child(1) { z-index: 4; }   /* left tile on top; the rest tuck under, left→right */
    .run-ic:nth-child(2) { z-index: 3; }
    .run-ic:nth-child(3) { z-index: 2; }
    .run-ic:nth-child(4) { z-index: 1; }
    /* loop "jump" — staggered bounce wave; starts only after the cavalry reveal (.revealed) */
    .run-row.revealed .run-ic { animation: run-jump 1.7s cubic-bezier(.45,.05,.55,.95) infinite; }
    .run-row.revealed .run-ic:nth-child(1) { animation-delay: 0s; }
    .run-row.revealed .run-ic:nth-child(2) { animation-delay: .11s; }
    .run-row.revealed .run-ic:nth-child(3) { animation-delay: .22s; }
    .run-row.revealed .run-ic:nth-child(4) { animation-delay: .33s; }
    @keyframes run-jump { 0% { transform: translateY(0); } 17% { transform: translateY(-15px); } 36%, 100% { transform: translateY(0); } }

    /* ===== pencil app-icon (section23 card-0, Figma 385:1217): blue rounded square
            116px r28 (user-set), the 3D pencil lying at 28° poking from the top-right,
            soft contact shadow on the surface ===== */
    /* clip-path: top + sides extended (cap/diagonal poke free), bottom clipped at the
       blue-card bottom (7.85px up from .run-pencil's 151) so the pencil never peeks below it */
    .run-pencil  { position: relative; width: 123px; height: 151px; flex: none;
                   clip-path: inset(-80px -80px 7.85px -80px); }
    .run-pbase   { position: absolute; left: 50%; top: 27.15px; transform: translateX(-50%);
                   width: 116px; height: 116px; border-radius: 28px; overflow: hidden;
                   background: linear-gradient(180deg, #266BE1 6.337%, #5395F7 100%); }
    .run-pshadow { position: absolute; left: 30.32px; top: 98.85px; width: 90px; height: 10px;
                   background: radial-gradient(50% 50% at 50% 50%, rgba(12,28,70,.30), rgba(12,28,70,0) 72%);
                   opacity: 1; transition: opacity .4s ease; }
    .run-penwrap { position: absolute; left: -50.07px; top: -43.07px; width: 223.371px; height: 223.371px;
                   display: flex; align-items: center; justify-content: center; pointer-events: none; }
    /* initial = lying 28° (PERFECT — left untouched). On scroll-in it reuses the §23
       pencil move: rotates upright + slides down (no app-cover overlay). Final = retouchable. */
    .run-pen     { transform-origin: 50% 50%; transition: transform .9s cubic-bezier(.34,1.06,.4,1);
                   --pen-y: 0px; --pen-rot: 28deg; --pen-s: 1;   /* initial: 28°, no offset, scale 1 */
                   transform: translateY(var(--pen-y)) rotate(var(--pen-rot)) scale(var(--pen-s)); }
    .run-pencil.animate .run-pen { --pen-rot: 0deg; --pen-y: 76px; --pen-s: 1.3; }   /* final resting place: upright, down 76px, scale 1.3 */
    .run-pencil.animate .run-pshadow { opacity: 0; }   /* shadow drops to zero as the pencil moves */
    .run-pen img { width: 165.164px; height: 165.164px; display: block; }

    /* ===== card cavalry-dot reveal (§23 logic, from white): the screenshot reveals through a
            grid of circles growing small→big, swept top→bottom, over the white card. Auto on
            in-view (JS). Footer + chips fade/rise in, synced. ===== */
    .cav-svg { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; display: block; }
    /* the source <img> (shown pre-JS / if the cavalry SVG is skipped) fills the card with cover —
       no stretch/distortion regardless of the card's aspect ratio */
    .reel-card .preview img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
    /* .pv-zoom = the zoom LAYER inside the .preview frame (frame owns radius + overflow at every breakpoint;
       the layer animates left/top/width/height on desktop hover — plain layout, no transform/compositing). */
    .reel-card .pv-zoom { position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: 0; }
    /* armed ONLY once JS runs → chips + footer CONTENT (icon, text) start hidden, then cascade
       in fade+rise, synced with the dot reveal (JS-off fallback = visible). We animate the
       reel-late CHILDREN (not the container) so we don't fight the m-wrap opacity:1 force. */
    #proof.cav-armed .reel-card [data-badge],
    #proof.cav-armed .reel-card .reel-late > * { opacity: 0; transform: translateY(10px);
      transition: opacity .45s ease, transform .45s cubic-bezier(.2,.7,.3,1); }
    /* .revealed-card is added ~60% through the dots → a quick cascade that overlaps the tail */
    #proof.cav-armed .reel-card.revealed-card [data-badge]               { opacity: 1; transform: none; transition-delay: 0s; }
    #proof.cav-armed .reel-card.revealed-card .reel-late > :nth-child(1) { opacity: 1; transform: none; transition-delay: .07s; }  /* icon */
    #proof.cav-armed .reel-card.revealed-card .reel-late > :nth-child(2) { opacity: 1; transform: none; transition-delay: .14s; }  /* title + copy */

    /* ===== heading reveal (§2-3 feel): words rise in + flash a brand colour, staggered.
            JS splits into .rv-w/.rv-wi and triggers on in-view. ===== */
    .rv-w  { display: inline-block; }
    .rv-armed .rv-wi { display: inline-block; opacity: 0; transform: translateY(0.5em);
      transition: opacity .42s ease, transform .46s cubic-bezier(.2,.85,.3,1), color .18s ease; }   /* feedback #6: snappier → reads together with the icon fly-in */
    .rv-armed .rv-wi.shown { opacity: 1; transform: none; }
    .rv-armed .rv-wi.flash { color: var(--rv-flash, #642BE1); }

    @media (max-width: 640px) {
      #fix > h2.font-expanded.font-normal {
        line-height: 39.8px;
        letter-spacing: -1.0px;
        margin-left: 0px;
        margin-top: -0.2421875px;
      }
      #work-head > h2.font-expanded.font-medium {
        margin-left: 0px;
        margin-top: -0.25390625px;
        font-size: 35px;
        line-height: 40.3px;
        letter-spacing: -1.0px;
      }
      #proof > div.flex.flex-col:nth-of-type(1) {
        margin-left: -0.25390625px;
        margin-top: 0px;
        row-gap: 20px;
      }
      #proof > div.flex.flex-col:nth-of-type(2) {
        margin-left: 0px;
        margin-top: 0.25px;
      }
      #proof > div.flex.flex-col:nth-of-type(1) > div.run-pencil:nth-of-type(1) > div.run-pbase:nth-of-type(1) > div.run-pshadow {
        left: 16px;
        top: 99.75px;
        margin-bottom: 0px;
      }
      #fix {
        margin-left: 0.24609375px;
        margin-top: 0px;
      }
      #proof {
        margin-left: 0.25px;
        margin-top: 0px;
        padding-top: 36px;
      }
    }

/* ────────────────── §3 · PROJECT JOURNEY ─────────────────── */
    /* (the dark footer #contact lives in css/footer.css) */

    /* HOW WE WORK — vertical list rows (Figma 461:108): 68px animated-icon tile + title/body, divider under each */
    #mp-list { padding: 40px 20px 48px; }   /* Figma inset 20 sides; top 92→40 — tighter seam to the last work card (feedback) */
    .mp-heading { margin: 0 0 40px; font-family: 'Surt Expanded','Surt',system-ui,sans-serif; font-weight: 500;
      font-size: 32px; line-height: 1.15; letter-spacing: -.48px; color: #1e272e; }   /* Figma 461:1429 "Project journey" */
    .mp-rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 32px; }   /* Figma article gap 32 */
    .mp-item { display: flex; gap: 20px; align-items: flex-start; padding-bottom: 32px; border-bottom: 1px solid rgba(0,0,0,.08); }
    .mp-item:last-child { border-bottom: 0; padding-bottom: 0; }
    .mp-icon { flex: 0 0 auto; width: 56px; height: 56px; }   /* user: 68→64→56 */
    .mp-icon svg { width: 100%; height: 100%; display: block; border-radius: 14px; overflow: visible; }
    /* per-row reveal on scroll-in: row rises + fades; icon cavalry-dots in (top→bottom); title reels letter-by-letter */
    .mp-item.mp-hide { opacity: 0; transform: translateY(14px); }
    .mp-item.mp-in   { opacity: 1; transform: none; transition: opacity .5s ease, transform .6s cubic-bezier(.2,.7,.3,1); }
    .mp-text { flex: 1 1 0; min-width: 0; padding-top: 4px; display: flex; flex-direction: column; gap: 6px; }
    .mp-item-title { margin: 0; font-family: 'Surt Expanded','Surt',system-ui,sans-serif; font-weight: 500;
      font-size: 22px; line-height: 1.1; letter-spacing: -.22px; color: #1e272e; }
    /* title word-reel (each word rolls up from a clipped cell, flashing the step colour); opacity:1!important beats the styles.css .ch{opacity:0}
       clip is taller than the line (1.42em) so descenders (g/j/p/y) aren't cut; negative margin-bottom cancels the extra height from layout */
    .mp-reel .ch { position: relative; display: inline-block; overflow: hidden; height: 1.42em; line-height: 1.2; margin-bottom: -.22em; vertical-align: bottom; white-space: pre; opacity: 1 !important; transform: none !important; }
    .mp-reel .ch-i { display: block; transition: transform .46s cubic-bezier(.36,1.24,.5,1), color .16s ease; }
    .mp-reel .ch-d { display: block; }
    .mp-reel .ch.flash .ch-i { color: var(--flash, #642BE1); }
    .mp-item-body { margin: 0; font-family: 'Surt','Inter',system-ui,sans-serif; font-weight: 400;
      font-size: 15px; line-height: 1.4; color: #6e6e74; }   /* user: 140% */

/* ───────────────── viewport + performance overrides (last) ───────────────── */

    /* ── Mobile browser-chrome viewport fix (Samsung S21 / Chrome / Samsung Internet) ──────────
       A phone browser's UI (address bar + bottom toolbar/back buttons) overlaps CSS 100vh, so
       full-height regions ran BEHIND it and their bottoms — including the loader/hero's rounded
       corners — were clipped. Size them to the SMALL viewport height (always fully visible).
       NOT dvh: dvh re-resolves as the chrome collapses on scroll, which made the hero gradient
       visibly grow ~50px mid-scroll. svh is stable AND clears the toolbar.
       vh is kept as the fallback for old browsers; this block is last so it wins. */
    #hero { height: 100vh; height: 100svh; }        /* the loader/hero — the reported clip */
    .m-wrap { min-height: 100vh; min-height: 100svh; }

    /* ── FONT GATE: hold the loader invisible until Surt is ready (html.fonts-in, set by the
       head script ≤1.2s). Removing the override lets the hero-enter entrance animation start
       FRESH at that moment — so the % fades in already in the right font, no fallback jump. ── */
    html:not(.fonts-in) #sk-stage, html:not(.fonts-in) #sk-frame,
    html:not(.fonts-in) #sk-screen, html:not(.fonts-in) #hero-progress { opacity: 0 !important; animation: none !important; }

    /* ── PERF: abandon blur in the loader + phone widgets (filter/backdrop blur is brutal on mobile GPUs) ── */
    #hp-text .hp-ch.flash .hp-ch-i,
    #hero-progress.swap #hp-text { filter: none !important; }                 /* loader label: keep the colour flash, drop the per-glyph blur */
    #sk-layer * { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }   /* phone widgets: no frosted-glass blur */
    .aibar > div[style*="pointer-events:none"] { display: none !important; }  /* the AI-bar's 4 heavy filter:blur glow blobs → gone */

/* ════════════════════════════════════════════════════════════════════════════
   DESKTOP — one breakpoint (≥821px). Everything above is the mobile base;
   the rules below only RESTYLE the same divs for wide screens. No second DOM,
   no builders, no scroll-pinned timelines.

   Scaling model: on desktop 1rem tracks the viewport — calc(100vw / 90) is
   16px at the 1440 design width — clamped so ultrawide doesn't balloon.
   Everything below is authored in rem (sizes) + % (anchors), so typography,
   icons and spacing scale in LOCKSTEP and nothing can drift out on resize.
   ════════════════════════════════════════════════════════════════════════════ */

/* mobile base bits for desktop-only elements */
#orbit { display: none; }       /* desktop process orbit; #mp-list serves mobile */
.only-d { display: none; }      /* desktop copy variant (§2/§3 headings) */
br.br-d { display: none; }      /* desktop-only line break (br{display:none} suppresses the break — spec'd) */
#fix .run-pencil { display: none; }   /* §2 pencil tile is a desktop-only float (mobile keeps it in §3) */

/* NUDGE MODE — while nudge.js is ON (html.nudge-on) let the hero copy be selected/moved.
   #hero-content is normally pointer-events:none so the physics/generator plays through it;
   in nudge mode we re-enable it (and disable the h1's inner reel spans) so clicks land on
   #hero-h1 / #hero-sub as whole blocks — for optical alignment of the hero text. */
html.nudge-on #hero-content { pointer-events: auto; }
html.nudge-on #hero-content #hero-h1,
html.nudge-on #hero-content #hero-sub,
html.nudge-on #hero-content #hero-cta { pointer-events: auto; }
html.nudge-on #hero-content #hero-h1 span { pointer-events: none; }
/* nudge the hero chip/card BANDS (whole-cluster move) and each chip/card individually. Clicks land on the
   .hchip / .hcard box (not its inner text/img). Empty band space selects the container. */
html.nudge-on #hero-chips, html.nudge-on #hero-chips-c, html.nudge-on #hero-chips-r,
html.nudge-on .hchip, html.nudge-on .hcard { pointer-events: auto; }
html.nudge-on .hchip span, html.nudge-on .hcard img { pointer-events: none; }

/* ── BENTO (Figma 505:8687) · mobile base = single-column stack; desktop grid lives in the ≥821 block ── */
#bento .bento { display: flex; flex-direction: column; gap: 20px; }   /* Figma 580:21369: 20px tile gaps */
#bento .brow  { display: flex; flex-direction: column; gap: 20px; }
#bento .btile { box-sizing: border-box; position: relative; overflow: hidden; background: #f2f2f2; border-radius: 28px; padding: 28px 32px; min-height: 180px; }
#bento .btile-title { margin: 0; }
/* bento glass pills (cards 1, 3, 5): 19px / 23px, padding 10 18 (owner, Oct 26: 21px + 12 20 read a few px too big) */
/* card 5 · Services — an endless drifting field of service tiles (js/work-canvas.js mounts .wc-field into the tile;
   tuned in _sandbox/work-canvas.html). Tile = the owner's w12 tile: white 2px rim (tone, not a border) · #f2f2f2 panel ·
   white folder tab merged into the top-left corner. The title stays on top, over a soft fade. */
#bento .btile--svc { min-height: 340px; }
#bento .btile--svc .wc-pill { position: absolute; left: 24px; top: 24px; z-index: 2; pointer-events: none; padding: 10px 18px; border-radius: 48px;   /* same glass pill as cards 1 + 3; */
  background: rgba(255,255,255,.45); -webkit-backdrop-filter: blur(8px) saturate(1.5); backdrop-filter: blur(8px) saturate(1.5); box-shadow: inset 0 0 0 1px rgba(255,255,255,.85);   /* CSS glass: the WebGPU engine can't repaint the moving tiles */
  font: 400 19px/23px 'Surt Expanded','Surt',system-ui,sans-serif; letter-spacing: -.2px; color: #1e272e; white-space: nowrap; }
.wc { overflow: clip; clip-path: inset(0 round 28px); isolation: isolate; touch-action: pan-y; cursor: grab; user-select: none; -webkit-user-select: none; outline: none; }   /* clip-path: moving tiles never leak the corners; pan-y: vertical swipes scroll the page */
.wc:focus-visible { box-shadow: inset 0 0 0 2px #1e272e; }
.wc.is-drag { cursor: grabbing; }
.wc-field { position: absolute; inset: 0; }   /* the lens filter sits here (JS grows it past the tile) */
.wc-defs, .wc-plane { position: absolute; }
.wc-plane { left: 50%; top: 50%; width: 0; height: 0; }   /* flat on purpose: preserve-3d rastered the tiles softer */
.wc-tile { position: absolute; left: 0; top: 0; will-change: transform; display: block; background: #fff; border-radius: 12px;   /* moved every frame: compositor only */
           box-shadow: 0 1.1px .9px rgba(30,39,46,.017), 0 2.7px 2.1px rgba(30,39,46,.023), 0 5px 4px rgba(30,39,46,.029),
                       0 8.9px 7.1px rgba(30,39,46,.035), 0 16.7px 13.4px rgba(30,39,46,.042), 0 40px 32px rgba(30,39,46,.059); }   /* recipe C (--shadow-m) ×0.6 */
.wc-panel { position: absolute; inset: 2px; border-radius: 10px; background: #f2f2f2; }
.wc-vis { position: absolute; pointer-events: none; }
.wc-vis > img { display: block; width: 100%; height: 100%; max-width: none; }
.wc-vis--cover { inset: 2px; border-radius: 10px; overflow: hidden; }   /* fit 'cover'/'frame': the artwork fills the panel, the tab sits over it */
.wc-vis--cover > img { object-fit: cover; }
.wc--sm .wc-vis--cover { border-radius: 8px; }
/* fit 'frame': the tab sits OUTSIDE, on the tile's top-left edge (it would cover the artwork inside); its white runs straight
   into the tile's white rim, with one concave join on its right where it meets the top edge */
.wc-tile--frame { border-top-left-radius: 0; }
.wc-tile--frame .wc-tab { top: auto; bottom: 100%; border-radius: 12px 12px 0 0; }
.wc-tile--frame .wc-tab::before { display: none; }
.wc-tile--frame .wc-tab::after { top: auto; bottom: 0; background: radial-gradient(circle at 100% 0, transparent 7.5px, #fff 8px); }
.wc--sm .wc-tile--frame .wc-tab { border-radius: 10px 10px 0 0; }
.wc-tab { position: absolute; z-index: 1; left: 0; top: 0; height: 33px; display: flex; align-items: center; gap: 6px; padding: 0 10px 0 5.5px; background: #fff; border-radius: 12px 0 8px 0;
          white-space: nowrap; font: 400 12px/1 'Surt Expanded','Surt',system-ui,sans-serif; color: #1e272e; }   /* 12px Expanded = "Native apps" at the reference's 72px */
.wc-tab--text { padding-left: 12px; }
.wc-tab::before, .wc-tab::after { content: ''; position: absolute; width: 8px; height: 8px; background: radial-gradient(circle at 100% 100%, transparent 7.5px, #fff 8px); }   /* concave joins into the panel */
.wc-tab::after { left: 100%; top: 2px; }
.wc-tab::before { left: 2px; top: 100%; }
.wc-ic { width: 22px; height: 22px; border-radius: 5.5px; flex: none; }
.wc--sm .wc-tile { border-radius: 10px; }
.wc--sm .wc-panel { border-radius: 8px; }
.wc--sm .wc-tab { height: 29px; padding: 0 8px 0 5px; gap: 5px; border-radius: 10px 0 7px 0; }
.wc--sm .wc-ic { width: 19px; height: 19px; border-radius: 4.8px; }

/* card 2 · craft: the live session (css/craft.css). The tile only sets its size here. */
#bento .btile--craft { min-height: 360px; padding: 0; }
@media (max-width: 820px) { #bento .btile--craft { min-height: 288px; } }   /* 360 × .8: the session stage zooms .8 (craft.css) */

/* card 3 · Process — mobile 1:1 (Figma 580:21418): pin + heading centered, the 2 white side orbs shown */
/* card 3 · Process (Figma 1932:858785) — live orbit (js/bento-orbit.js): the squircle deck cycles the 5 steps, glass orbit
   icons ride a wide shallow arc, the step title rolls inside a glass pill over two blurred glows. One layout at every width. */
#bento .btile--proc { display: block; padding: 0; min-height: 360px; }
#bento .proc-stage { position: absolute; left: 50%; top: 76.1px; transform: translateX(-50%); width: 360px; height: 140px; }   /* orbs + squircle ~12% smaller by SIZE (owner, Oct 26): a scale on this stage broke the 3D deck */   /* centre = Figma front icon (mid, y 146.1) */
#bento .proc-core  { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); width: 104px; height: 104px; z-index: 60; perspective: 620px; }   /* was 117.73 */
#bento .proc-core .sq { position: absolute; inset: 0; border-radius: 26px; transform-origin: 50% 50%; will-change: transform, opacity; backface-visibility: hidden; }
#bento .proc-core .sq.front {   /* recipe C, sized to a 118px icon (ambient y ≈ 25% of its height), medium alpha */
  box-shadow: 0 .8px .7px rgba(30,39,46,.028), 0 2px 1.6px rgba(30,39,46,.039), 0 3.7px 3px rgba(30,39,46,.049),
              0 6.6px 5.3px rgba(30,39,46,.059), 0 12.3px 9.9px rgba(30,39,46,.07), 0 29.5px 23.6px rgba(30,39,46,.098); }
#bento .proc-core.anim .sq { transition: transform .58s cubic-bezier(.22,.8,.24,1), opacity .45s ease, box-shadow .45s ease; }
#bento .proc-core.anim .sq .o-gray { transition: opacity .5s ease; }
#bento .proc-core .sq svg { width: 104px; height: 104px; display: block; overflow: visible; }
#bento .proc-stage .orb { position: absolute; left: 50%; top: 50%; width: 58px; height: 58px;   /* was 66 */
                          display: flex; align-items: center; justify-content: center;
                          border-radius: 50%; background: rgba(255,255,255,.1); isolation: isolate; will-change: transform, opacity;   /* Figma: fill white 10% + Glass */
                          --orb-sh: 0 1px 2px rgba(30,39,46,.025), 0 3px 6px rgba(30,39,46,.03), 0 8px 14px rgba(30,39,46,.035), 0 18px 30px rgba(30,39,46,.04);   /* softer, wider (Oct 26) */
                          box-shadow: var(--orb-sh); }   /* lift off the light tile (owner, Oct 26: "a bit more visible vs the bg"): the smooth recipe for a 66px orb, tamed */
#bento .proc-stage .orb.glass--css { box-shadow: inset 0 0 0 1px rgba(255,255,255,.6), var(--orb-sh); }   /* CSS-glass fallback keeps its rim */
#bento .proc-stage .orb img { width: 50%; height: 50%; display: block; filter: drop-shadow(0 1px 1.5px rgba(30,39,46,.1)); }   /* the glyph reads a touch firmer */
#bento .proc-glow   { position: absolute; top: 241px; height: 103px; max-width: none; pointer-events: none; }   /* Figma Ellipse 14/15, blur 20.5 baked in the SVG */
#bento .proc-glow--a { left: calc(50% - 143.5px); width: 182px; }   /* Figma x 42 on the 371 card, kept relative to the centre */
#bento .proc-glow--b { left: calc(50% - 69.5px); width: 206px; }
#bento .proc-pill  { position: absolute; left: 50%; top: 252px; translate: -50% 0; z-index: 70; display: flex; padding: 10px 18px; border-radius: 48px;
                     background: rgba(255,255,255,.45); isolation: isolate; }                                              /* Figma: fill white 45% + Glass */
#bento .proc-head  { margin: 0; font: 400 19px/23px 'Surt Expanded','Surt',system-ui,sans-serif; letter-spacing: -.2px; color: #1e272e; white-space: nowrap; }
#bento .proc-head .ch   { opacity: 1 !important; transform: none !important; transition: none !important; position: relative; display: inline-block; overflow: hidden; height: 23px; line-height: 23px; vertical-align: bottom; white-space: pre; }
#bento .proc-head .ch-i { display: block; transition: transform .4s cubic-bezier(.36,1.24,.5,1), color .14s ease; }
#bento .proc-head .ch-d { display: block; height: 23px; line-height: 23px; }
#bento .proc-head .ch.flash .ch-i { color: var(--flash-color, #642BE1); transition: transform .4s cubic-bezier(.36,1.24,.5,1), color .07s ease; }
/* liquid glass (js/liquid-glass.js): the WebGPU canvas sits under the element's content; no WebGPU → frosted CSS */
.glass-gl    { position: absolute; inset: 0; width: 100%; height: 100%; z-index: -1; border-radius: inherit; pointer-events: none; }
.glass--css  { background: rgba(255,255,255,.35) !important; -webkit-backdrop-filter: blur(8px) saturate(1.5); backdrop-filter: blur(8px) saturate(1.5); box-shadow: inset 0 0 0 1px rgba(255,255,255,.85); }

/* ───────── SERVICES (#services, below the bento) · Figma 1741:29070. 3 offer cards: dark art head (Figma "KH / Head ground"
   export, text live on top) + white list + call / LinkedIn row. Card colour = --a/--b rgb triplets on the article. ───────── */
.pk-head { display: flex; flex-direction: column; align-items: center; text-align: center; }
.sv-h2  { margin: 0; font: 500 48px/50.4px 'Surt Expanded', 'Surt', sans-serif; letter-spacing: -1.5px; color: #1e272e; zoom: .75; }   /* ≤820: text + px tiles as one unit at 75% (36px) */
.sv-tl  { position: relative; display: inline-block; vertical-align: top; width: 153.142px; height: 50.4px; }   /* Figma 1756:19733 / 19760 */
.sv-tl--less { width: 79.05px; }
.sv-tile { position: absolute; width: 52px; height: 52px; border-radius: 13.709px; display: flex; align-items: center; justify-content: center; rotate: var(--r);
           background: linear-gradient(168.44deg, rgb(var(--a, 38,107,225)) 6.7538%, rgb(var(--b, 83,149,247)) 93.246%);
           box-shadow: 0 var(--y, 7.987px) var(--bl, 12.552px) calc(-1 * var(--y, 7.987px)) rgba(18,22,45,.5), inset 0 var(--in, .571px) 0 rgba(255,255,255,.18); }
.sv-tile--w { background: linear-gradient(180deg, #f0f0f3, #fff); box-shadow: 0 7.987px 12.552px -7.987px rgba(18,22,45,.22); }
/* the heading's tiles float (owner, Oct 22: "so it doesn't look static"): translate only, so each keeps its --r rotate;
   out of phase; plain keyframes (compositor); paused offscreen via .av-off (#services is observed in index.html) */
.sv-tile { animation: sv-float 3.8s ease-in-out -.4s infinite; }   /* owner, Oct 22: the 5–6 s float was too slow */
.sv-tl--more .sv-tile:nth-child(2) { animation-duration: 4.3s; animation-delay: -1.6s; }
.sv-tl--more .sv-tile:nth-child(3) { animation-duration: 3.5s; animation-delay: -2.7s; }
.sv-tl--less .sv-tile { animation-duration: 4s; animation-delay: -1s; }
@keyframes sv-float { 50% { translate: 0 -6px; } }
.sv-tile img, .sv-ic img, .pk-badge img, .sv-bi img { display: block; max-width: none; }
.sv-sub { margin: 24px auto 0; max-width: 600px; font: 400 16px/24px 'Surt', sans-serif; color: #425063; }
.sv-ic  { display: inline-flex; align-items: center; justify-content: center; vertical-align: top; width: 20px; height: 20px; margin: 2px 3.9px 0 .6px; border-radius: 5.27px; background: linear-gradient(135deg, #3a4650, #1e272e); }
.sv-ic--f { margin-left: 2.575px; margin-right: 2.17px; }   /* gaps measured off Figma 1742:36224's clipped text runs (they are not symmetric there) */
.pk-row  { display: flex; flex-direction: column; align-items: center; gap: 20px; margin-top: 40px; }
.pk-card { box-sizing: border-box; width: 100%; max-width: 429.33px; display: flex; flex-direction: column; padding: 0 6px 8px; border-radius: 28px; background: #f2f2f2; }   /* Figma card 1 (Oct 22): head full-bleed, 6 sides, 8 bottom */
.pk-cover { position: relative; isolation: isolate; overflow: hidden; box-sizing: border-box; min-height: 300px; display: flex; flex-direction: column; margin: 0 -6px; padding: 22px 22px 34px;
            border-radius: 28px 28px 14px 14px; background: linear-gradient(145.39deg, #0f1012, #09090a); color: #fff; }
.pk-art  { position: absolute; z-index: -1; top: 0; right: 0; width: 429.33px; height: 300px; max-width: none; }   /* right-anchored: a narrower card crops the plain dark left side, never the UI art */
.pk-name { display: flex; align-items: center; gap: 12px; margin: 0; font: 500 18px/25.3px 'Surt Expanded', 'Surt', sans-serif; letter-spacing: .25px; }
.pk-badge { flex: none; width: 40px; height: 40px; border-radius: 10.545px; display: flex; align-items: center; justify-content: center;
            background: linear-gradient(168.46deg, rgb(var(--a)) 6.7474%, rgb(var(--b)) 93.253%); box-shadow: inset 0 .439px 0 rgba(255,255,255,.18); filter: drop-shadow(0 6.144px 4.827px rgba(18,22,45,.5)); }
.pk-tag  { align-self: flex-start; margin: auto 0 0; padding: 5px 10px; border-radius: 8px; background: rgba(255,255,255,.1); font: 500 13px/15.6px 'Surt Expanded', 'Surt', sans-serif; }
.sv-price { display: flex; align-items: baseline; column-gap: 6px; margin: 5.15px 0 0; }   /* keeps Figma's visible space before /day */
.sv-price .amt  { font: 500 36px/36px 'Surt Expanded', 'Surt', sans-serif; letter-spacing: -1.1px; }
.sv-price .unit { font: 500 17px/17px 'Surt Expanded', 'Surt', sans-serif; letter-spacing: -.2px; }
.pk-line { max-width: 366px; margin: 14px 0 0; font: 400 16px/24px 'Surt', sans-serif; color: rgba(255,255,255,.88); }
.sv-list { flex: 1; margin: 6px 0 0; padding: 18px 18px 17px 12px; list-style: none; display: flex; flex-direction: column; gap: 10px; font: 400 15px/21px 'Surt', sans-serif; color: #425063; }
.sv-list li { display: flex; gap: 10px; align-items: flex-start; }
.sv-list li + li { padding-top: 10px; border-top: 1px solid #e8eaed; }   /* Figma "LT-C hairline": 10 · 1px · 10 */
.sv-list li > span { padding-top: 3.5px; }   /* first line centred on the 28px marker */
.pk-mk  { flex: none; width: 28px; height: 28px; border-radius: 8px; display: flex; align-items: center; justify-content: center; background: #fff; box-shadow: 0 9.319px 7.322px rgba(18,22,45,.04); }   /* Figma 1742:30927 */
.pk-mk::before { content: ''; width: 16px; height: 16px; background: var(--ic); -webkit-mask: var(--i) center / 16px 16px no-repeat; mask: var(--i) center / 16px 16px no-repeat; }   /* duotone icon (Figma 1948:912226) in the card colour */
.pk-cta { display: flex; gap: 6px; padding-top: 6px; }
.sv-btn { position: relative; box-sizing: border-box; flex: 1; min-width: 0; height: 52px; display: flex; align-items: center; justify-content: center; padding: 0 57px; overflow: hidden; border-radius: 26px;
          background: #fff; color: #1e272e; font: 500 15px/19.5px 'Surt Expanded', 'Surt', sans-serif; text-decoration: none; white-space: nowrap;
          transition: transform .3s cubic-bezier(.22,.8,.24,1), box-shadow .3s ease; }
.sv-btn:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -8px rgba(30,39,46,.32); }
.sv-btn--in { flex: none; width: 52px; padding: 0 5px; }
.sv-bi  { position: absolute; left: 5px; top: 50%; translate: 0 -50%; box-sizing: border-box; width: 42px; height: 42px; border-radius: 21px; border: .87px solid rgba(255,255,255,.26);
          display: flex; align-items: center; justify-content: center; background: linear-gradient(168.23deg, rgb(var(--a)) 6.8966%, rgb(var(--b)) 93.103%);
          box-shadow: inset 0 -1.73px 5.2px rgba(255,255,255,.16), inset 0 1px 0 rgba(255,255,255,.3); filter: drop-shadow(0 5.88px 5.04px rgba(var(--a), .34)); }
.sv-btn--in .sv-bi { position: static; translate: none; }
.sv-bi img { translate: .709px .398px; }   /* Figma's 17px icon box sits off the svg's centre (the svg carries its shadow margin) */
.sv-btn--in .sv-bi img { translate: 0 .657px; }

/* card 3 · Process — LIVE orbit on MOBILE + TABLET too (≤820). Mirrors the desktop @media orbit block so the
   SAME engine (bento-orbit.js) drives a cycling squircle deck + orbs + reel heading. Keep in sync with the
   ≥821 rules; desktop is left untouched. The static pin/badges (above) are hidden here. */
@media (max-width: 820px) {
}

/* card 4 · Personal — centered stack (avatar → intro → button → microcopy) */
/* card 4 · chat (Figma 1932:859600). Base = flowing column (phones); the ≥821 block pins every piece to its Figma x/y. */
#bento .btile--me { padding: 24px 20px; }
#bento .mc     { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
#bento .mc > * { margin: 0; transition: opacity .4s ease, translate .5s cubic-bezier(.2,.8,.2,1), scale .5s cubic-bezier(.2,.8,.2,1); }
#bento .mc-arm > :not(.on) { opacity: 0; translate: 0 10px; scale: .96; }        /* armed by JS; without JS everything shows */
#bento .mc-who  { position: relative; width: 129px; height: 60px; margin-left: -6px; }
#bento .mc-tag  { position: absolute; inset: 0; width: 129px; height: 60px; max-width: none; }   /* the grey ring + name tab, one Figma "Union" */
#bento .mc-av   { position: absolute; left: 6px; top: 6px; width: 48px; height: 48px; border-radius: 24px; overflow: hidden; background: #1d1d26; }
#bento .mc-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
#bento .mc-av::after { content: ""; position: absolute; inset: 0; background: linear-gradient(144.38deg, rgba(255,255,255,.2) 17.6%, rgba(0,0,0,.2) 79.13%); }
#bento .mc-name { position: absolute; left: 70px; top: 7.95px; font: 500 17px/22.1px 'Surt Expanded','Surt',sans-serif; color: #1e272e; }
#bento .mc-b    { padding: 10.18px 13.88px 10.82px; background: rgba(255,255,255,.6); font: 500 20px/26px 'Surt Expanded','Surt',sans-serif; letter-spacing: -.2px; color: #1e272e; transform-origin: 0 100%; }
#bento .mc-b1   { border-radius: 20px 20px 2px 6px; }
#bento .mc-b2   { border-radius: 6px 24px 24px 20px; }
#bento .mc-typing { display: none; gap: 5px; padding: 18px 16px; border-radius: 20px 20px 20px 6px; background: rgba(255,255,255,.6); }
#bento .mc-typing.on { display: flex; animation: mc-pop .35s cubic-bezier(.2,.8,.2,1); }   /* display:none when idle = no gap in the phone column */
@keyframes mc-pop { from { opacity: 0; translate: 0 10px; scale: .96; } }
#bento .mc-typing i { width: 7px; height: 7px; border-radius: 50%; background: #1e272e; opacity: .3; }
#bento .mc-typing.on i { animation: mc-dot 1s ease-in-out infinite; }               /* only animates while it is shown */
#bento .mc-typing i:nth-child(2) { animation-delay: .15s; }
#bento .mc-typing i:nth-child(3) { animation-delay: .3s; }
@keyframes mc-dot { 30% { opacity: .8; translate: 0 -3px; } }
#bento .mc-r    { position: relative; align-self: flex-end; box-sizing: border-box; height: 42px; padding: 7.51px 17px 0 43.11px; border: 1px solid rgba(255,255,255,.32);
                  background: linear-gradient(to right, #266be1 5.965%, #1d5ccb 87.193%); filter: drop-shadow(0 12px 10px rgba(0,0,0,.11)); transform-origin: 100% 100%;
                  font: 500 18px/23.4px 'Surt Expanded','Surt',sans-serif; letter-spacing: -.18px; color: #fff; text-decoration: none; white-space: nowrap; }
#bento .mc-r1   { margin-top: 12px; border-radius: 24px 20px 6px 24px; }
#bento .mc-r2   { height: 43px; border-radius: 24px 6px 24px 24px; opacity: .5; }   /* same CSS icon circle + padding as the call reply (the old Figma export sat 1px off, Oct 26) */
#bento .mc-r.on:hover, #bento .mc-r:focus-visible { translate: 0 -2px; opacity: 1; }
#bento .mc-ic   { position: absolute; left: 4px; top: calc(50% - 16px);   /* centred, equal inset top/left (Oct 26) */ box-sizing: border-box; width: 32px; height: 32px; border-radius: 16px; border: 1px solid rgba(255,255,255,.38);
                  background: linear-gradient(rgba(255,255,255,.17), rgba(255,255,255,.11)); box-shadow: 0 2px 2px rgba(0,0,0,.12), 0 2px 4px rgba(0,0,0,.05), 0 2.644px 5.28px rgba(0,0,0,.23);
                  display: flex; align-items: center; justify-content: center; }
#bento .mc-ic img { width: 12.952px; height: 12.952px; display: block; }
#bento .mc-ic img.mc-in { width: 13px; height: 11.14px; }
@media (max-width: 640px) { #bento .mc { zoom: .85; } }   /* phones: the whole chat at 85% so the LinkedIn reply (321px) fits a 295px column */

/* card 1 · Experience — mobile 1:1 (Figma 580:21373): centered stat at top 64, the 4 logos ABSOLUTE at the
   bottom edge, bleeding off (same px as the desktop tile, % of the 327 design width). */
#bento .btile--exp { display: block; min-height: 360px; padding: 0; text-align: center; }
#bento .exp-stat    { position: absolute; top: 58.15px; left: 50%; transform: translateX(-50%); width: 246px; display: flex; flex-direction: column; align-items: center; gap: 24px; z-index: 2; }
#bento .exp-locksvg { display: block; width: 132px; height: auto; }   /* "5+ Years" lockup (SVG, exact) */
#bento .exp-sub     { position: relative; isolation: isolate; margin: 0; padding: 10px 18px; border-radius: 48px; background: rgba(255,255,255,.45);   /* Figma 1932:858776: fill 45% + Glass */
                       font: 400 19px/23px 'Surt Expanded','Surt',system-ui,sans-serif; letter-spacing: -.2px; color: #1e272e; white-space: nowrap; }
#bento .exp-blurs   { position: absolute; left: calc(50% - 154.5px); top: 179px; width: 314px; height: 110px; max-width: none; pointer-events: none; }   /* Figma "color blurs" under the pill */
/* logos = UNROTATED Figma originals (svg / 2× fills); rotation EXACT per Figma (556:13938 design context),
   composed into the float keyframes. Positioned by each icon's Figma CENTRE (% of the 327 mobile tile). */
#bento .exp-logos { position: static; }
#bento .exp-logo  { position: absolute; display: block; transform: rotate(var(--rot, 0deg));
                    animation: exp-logo-float 7s ease-in-out infinite; }
#bento .exp-logo--kuro  { --rot: 12.33deg;  width: 80px; height: 80px; left: calc(13.94% - 40px); top: 281.5px; animation-duration: 6.2s; animation-delay: -1.2s; }
#bento .exp-logo--natix { --rot: -10.45deg;  width: 80px; height: 80px; left: calc(37.31% - 40px); top: 305.2px; animation-duration: 8.5s; animation-delay: -3s; }
#bento .exp-logo--fin   { --rot: 3deg;      width: 72px; height: 72px; left: calc(77.45% - 36px); top: 294.2px; border-radius: 21.6px; animation-duration: 7.3s; animation-delay: -2s; }
#bento .exp-logo--tyson { --rot: -24.69deg; width: 64px; height: 64px; left: calc(96.65% - 32px); top: 323.6px;
                          background: #54dfac; border-radius: 19.2px; display: flex; align-items: center; justify-content: center;
                          animation-duration: 9.4s; animation-delay: -4.3s; }
#bento .exp-logo--tyson img { width: 29px; height: 29px; display: block; }
/* livelier idle float — bigger bob + a little horizontal drift + a rotation wobble around each logo's --rot.
   Uses `transform`; the hover parallax (bento-orbit.js) uses the individual `translate` property so the two compose. */
@keyframes exp-logo-float {
  0%   { transform: translate(0, -9px)  rotate(calc(var(--rot, 0deg) - 3deg)); }
  25%  { transform: translate(5px, 1px) rotate(var(--rot, 0deg)); }
  50%  { transform: translate(0, 9px)   rotate(calc(var(--rot, 0deg) + 3deg)); }
  75%  { transform: translate(-5px, 1px) rotate(var(--rot, 0deg)); }
  100% { transform: translate(0, -9px)  rotate(calc(var(--rot, 0deg) - 3deg)); }
}

#hero-chips, #hero-chips-c, #hero-chips-r { display: none; }   /* desktop-only keyword chips/cards (Figma 568:17868); shown in the ≥821px block */

/* ═══════════ TABLET (Figma 580:19321, feedback #17): mobile bones, bigger sizes ═══════════
   hero = mobile build w/ larger type · products 2×2 · proof header = the desktop variant, left ·
   bento: exp+craft side-by-side, the rest full width. */
@media (min-width: 641px) and (max-width: 820px) {
  #hero-h1 { font-size: 54px; }
  #hero-sub { font-size: 18px; }
  #fix > h2 { font-size: 44px; }
  /* products 2×2, near-full width w/ page margins */
  #proof .proof-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 56px 20px; }   /* Figma tablet: 56 row / 20 column */
  /* proof header: desktop copy variant, LEFT, no pencil centrepiece */
  #proof .proof-head .run-pencil { display: none; }
  #proof .proof-head { align-items: flex-start; }
  #proof #work-head h2 { text-align: left; font-size: 44px; }
  #proof #work-head .only-m { display: none; }
  #proof #work-head .only-d { display: inline; }
  /* bento: 5+Years + Pixel-perfect share a row; problem/founder/services full width */
  #bento .brow--1 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
  #bento .brow--1 > .btile--proc { grid-column: 1 / -1; }
}

@media (min-width: 821px) {
  html { font-size: clamp(10px, calc(100vw / 90), 21px); }
  /* page gutter = the nav's desktop side padding (nav.js), so section content lines up with the logo.
     Fixed px (not rem) so it stays aligned with the nav at every width. */
  :root { --gutter: 56px; }

  /* ── page slab: release the 440px phone column ── */
  .m-wrap { max-width: none; }

  /* ── nav (desktop pill + Book-a-call) → css/nav.css (shared component); js/mobile/nav.js drives the scroll morph ── */

  /* ── §1 hero (Figma 499:1178): content bottom-left, FLIPPED gradient, bigger type ── */
  #hero-box { align-items: flex-end; }
  /* gradient flipped for desktop — the VISIBLE fill is the #sk-stage::before overlay (opacity 1
     on .expand); base rule is behind it. Figma 499:1180 = blue (top) → cream (bottom). */
  #sk-stage::before { background: linear-gradient(180deg, rgb(139, 183, 209) 1.5%, rgb(190, 208, 213) 48%, rgb(237, 236, 230) 91.5%); }

  /* ── keyword chips 1:1 Figma 568:17868. Each chip's opacity + bg-alpha VARY and are set inline per-node.
        Sized in em off a CAPPED base — font-size:min(1rem,16px) inside a 1440-max centred band — so the chips
        freeze at their 1440 look and never balloon on >1440 screens (positions are % of the band). Fades after load. ── */
  #hero-chips { display: block; position: absolute; top: 0; bottom: 0; left: 0;
                width: 100%; max-width: 1440px; pointer-events: none; font-size: min(1rem, 16px);
                opacity: 0; transition: opacity .8s ease .12s; }   /* LEFT-anchored (not centred) so cards/chips hug the left on >1440 screens */
  #hero-box.dropped #hero-chips { opacity: 1; }
  /* right cluster lives in a RIGHT-anchored twin band → on >1440 it hugs the right edge and spreads out
     (left band stays left-anchored). Both freeze at 1440 sizes; positions given as right:% per element. */
  #hero-chips-r { display: block; position: absolute; top: 0; bottom: 0; right: 0;
                  width: 100%; max-width: 1440px; pointer-events: none; font-size: min(1rem, 16px);
                  opacity: 0; transition: opacity .8s ease .12s; }
  #hero-box.dropped #hero-chips-r { opacity: 1; }
  /* center cluster lives in a CENTER-anchored band → on >1440 it stays centred (pulls away from the left
     cluster) instead of hugging the left. Same freeze/sizes; positions given as left:% within the band. */
  #hero-chips-c { display: block; position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%);
                  width: 100%; max-width: 1440px; pointer-events: none; font-size: min(1rem, 16px);
                  opacity: 0; transition: opacity .8s ease .12s; }
  #hero-box.dropped #hero-chips-c { opacity: 1; }
  .hchip { position: absolute; display: flex; align-items: center; justify-content: center; border-radius: 999px; padding: 0 1.125em; isolation: isolate;   /* hugs its label (owner, Oct 2026); isolation keeps the glass canvas under the text */
           background: rgba(255,255,255,.73); animation: hchip-float 5.5s ease-in-out infinite; }   /* opacity + bg-alpha overridden per-chip inline */
  /* feedback #2: varied float — some chips drift slower + further than others (a parallax depth read); no mouse parallax on the hero */
  .hchip:nth-child(4n+1) { animation-duration: 5s;   animation-delay: -1.3s; --amp: .5rem;  }
  .hchip:nth-child(4n+2) { animation-duration: 7.5s; animation-delay: -3.4s; --amp: .32rem; }
  .hchip:nth-child(4n+3) { animation-duration: 6.2s; animation-delay: -2.2s; --amp: .62rem; }
  .hchip:nth-child(4n)   { animation-duration: 9s;   animation-delay: -5.1s; --amp: .4rem;  }
  .hchip span { font: 500 1em 'Surt','Inter Tight',system-ui,sans-serif; color: #1e272e;
                text-transform: capitalize; line-height: 1; white-space: nowrap; letter-spacing: -.01em; opacity: .70; }
  .hchip--sm { padding: 0 1em; }
  .hchip--sm span { font-size: .818em; }   /* 13.091px small pills */
  /* card-box project thumbnails 1:1 Figma (569:18477/18499/18524): white 2px-border rounded cards holding real
     project shots + a slight tilt. Live in #hero-chips → share the em base + 1440 freeze. */
  /* project cards: gentle FLOAT (outer) + HOVER-EXPAND (Figma 580:21596) — the inner grows ~2×, straightens,
     and reveals "Explore case study →". Wrapper so the float (outer transform) + tilt/scale (inner) compose. */
  .hcard { position: absolute; pointer-events: auto; cursor: pointer; animation: hcard-float 6.6s ease-in-out infinite; }   /* feedback #11: invite the click */
  a.hcard { text-decoration: none; color: inherit; }          /* card WITH a case study = the whole card is the link */
  div.hcard { cursor: default; }                               /* no case study yet → nothing to click */
  .hcard::before { content: ''; position: absolute; inset: -4.5em; }   /* hit-box covers the 2×-grown card so hover doesn't drop (feedback #5) */
  .hcard-mag { position: relative; display: block; width: 100%; height: 100%; }   /* magnetic layer — GSAP translates this toward the cursor */
  /* Figma 580:21596: on hover the card GROWS to ~2× (260px) by animating WIDTH/HEIGHT — NOT transform:scale — so the
     "Explore case study →" text stays crisp at its own size; only the image scales (object-fit) as the box grows; rotates to 0. */
  .hcard-in { position: absolute; left: 0; top: 0; width: 100%; height: 100%; box-sizing: border-box; background: #fff; padding: 1.67%; border-radius: .75em; overflow: hidden;
              box-shadow: 0 .75em 1.75em -.6em rgba(30,39,46,.28); transform: rotate(var(--rot,0deg)); transform-origin: center; }
  .hcard-media { position: relative; width: 100%; height: 100%; overflow: hidden; border-radius: .6em; }
  .hcard-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
  /* CTA = white pill (Figma 638:10040) centred on the card. em-sized so it scales with the floating card;
     alpha bumped a touch since the rotated/overflow-hidden parent kills backdrop-filter here. */
  .hcard-cap { position: absolute; left: 50%; bottom: 8.5%; transform: translateX(-50%);
               display: inline-flex; align-items: center; white-space: nowrap;
               padding: .818em 1em; border-radius: 1.636em; background: rgba(255,255,255,.82);
               font: 400 .82em/1 'Surt Expanded','Surt','Inter Tight',system-ui,sans-serif; letter-spacing: -.02em; color: #1e272e;
               opacity: 0; transition: opacity .26s ease .06s; pointer-events: none; isolation: isolate; }   /* liquid glass (index.html); (backdrop-filter removed: the rotated/clipped parent killed it anyway — never rendered, only cost) */
  .hcard-cap--soon { color: #6e6e74; }   /* no case study yet: same pill, muted label — reads as a status, not a CTA */
  .hcard.is-open .hcard-cap { opacity: 1; }   /* pill appears ON the visual, crisp — its own size, never scaled */
  .hcard.is-open { z-index: 40; }
  html.nudge-on .hcard::before { display: none; }   /* don't let the hit-box steal nudge grabs */
  @keyframes hcard-float { 0%,100% { transform: translate(-.15rem, -.6rem) rotate(-.5deg); } 50% { transform: translate(.15rem, .6rem) rotate(.5deg); } }
  @keyframes hchip-float { 0%,100% { transform: translateY(calc(-1 * var(--amp, .42rem))); } 50% { transform: translateY(var(--amp, .42rem)); } }

  /* ── desktop sky clouds (Figma 545:4543): main = generation source, project cloud carries an icon ── */
  #hero-clouds { display: block; position: absolute; inset: 0; pointer-events: none; visibility: hidden; }   /* NO z-index/opacity → not an isolated stacking context, so the imgs multiply against the sky */
  /* clouds concept RETIRED (replaced by the dot-canvas above). #hero-clouds stays visibility:hidden so nothing
     shows, but .hc-main keeps its layout box — the component spawn origin reads its rect (display:none would zero it). */
  #hero-clouds .hc-left { position: absolute; left: 1.6%; top: 24%; width: 27.6%; height: auto; display: block; mix-blend-mode: multiply; filter: brightness(1.28); }
  /* z-index:2 lifts the main cloud ABOVE the components (#sk-layer z:1) so they generate from BEHIND it.
     #hero-clouds itself has no z-index, so .hc-main compares directly against #sk-layer in #hero-box's context
     — and .hc-left keeps no stacking context, so its multiply still blends against the sky. */
  #hero-clouds .hc-main { position: absolute; left: 47.4%; top: 6.9%; width: 42.2%; z-index: 2; }
  #hero-clouds .hc-main img { display: block; }
  #hero-clouds .hc-sky { width: 100%; height: auto; }                                                   /* light cloud: in flow, sets .hc-main height */
  #hero-clouds .hc-storm { position: absolute; inset: 0; width: 100%; height: auto; opacity: 0; transition: opacity .55s ease; }  /* darker twin (Figma 565:15802) — crossfades in while generating */
  #hero-box.gen-active #hero-clouds .hc-storm { opacity: 1; }
  /* generating chip 1:1 Figma 565:15732 (the mobile look): #1e272e pill · brand colour dot-matrix + "Generating" (Surt Medium 15) */
  #hero-clouds .hc-gen { position: absolute; left: 47%; top: 49%; transform: translate(-50%,-50%) scale(.94);
                         display: inline-flex; align-items: center; gap: 7px; padding: 15px 18px 15px 15px; border-radius: 999px;
                         background: #1e272e; color: #fff; font: 500 15px/18.75px 'Surt','Inter Tight',system-ui,sans-serif; letter-spacing: -.1px;
                         white-space: nowrap; opacity: 0; transition: opacity .32s ease, transform .32s ease; box-shadow: 0 12px 34px -10px rgba(30,39,46,.5); }
  #hero-box.gen-active #hero-clouds .hc-gen { opacity: 1; transform: translate(-50%,-50%) scale(1); }
  #hero-clouds .hc-dm { width: 15px; height: 15px; flex: none; display: block; }
  #hero-clouds .hc-gen-tx { display: block; }
  /* hero copy — baked from the nudge (Copy-CSS). CAPPED so nothing balloons past 1440: min(rem,px) scales
     below 1440 and FREEZES at the px value above. The negative-margin "gap" hacks are folded into a real
     gap + one positive margin (h1↔sub 18px, sub↔CTA 26px); sub-pixel nudge artifacts dropped. 1:1 visual. */
  #hero-content { padding: 0 60px min(6.75rem, 108px); gap: min(1.125rem, 18px); }   /* px 60 · pb 108 · gap 18 (= h1↔sub) */
  #hero-h1  { font-weight: 400; font-size: min(3.75rem, 60px); line-height: 1.1933; letter-spacing: -0.0367em; margin-left: 6px; }   /* 60px · lh 71.6 · ls -2.2px @60 */
  #hero-sub { font-size: min(1.3125rem, 21px); line-height: 1.4; letter-spacing: -0.025em; color: rgb(var(--c-fg) / .8); max-width: 25.06rem; margin-left: 10.2344px; margin-bottom: 16px; }   /* 21px · +16px → sub↔CTA 34px (nudge) */
  #cta-btn { width: auto; height: 60px; font-size: 17px; --k2-ic: 48px; --k2-icon: 20px; }   /* Figma K2 60: 60 tall, 48 circle, 17px; the rolodex sizer sets the width */
  /* the desktop hero uses the sandbox flow — it finishes in .dropped/.gen-live, NOT mobile's
     .ready. site.css (built from mobile) only revealed the copy on .ready, so on desktop the
     headline + sub stayed hidden (.cl-i translateY 120%). Reveal on the desktop end-state. */
  #hero-box.dropped #hero-content .cl-i { transform: none !important; }
  #hero-box.dropped #hero-content [data-reveal] { opacity: 1 !important; transform: none !important; }
  #gen-hud { padding-left: var(--gutter); padding-right: var(--gutter); }

  /* breakpoint copy variants + line breaks (user pattern: br gets a class per breakpoint) */
  .only-m { display: none; }
  .only-d { display: inline; }
  br.br-d { display: inline; }
  br.br-m { display: none; }

  /* ── §2 what-we-fix: relative parent box (Figma 185:2). The SAME .run-ic tiles float
        absolutely inside it; anchors/sizes live in VARIABLES here so other breakpoints
        can re-tune them in one place. % anchors + rem sizes scale with the heading. ── */
  #fix {
    position: relative; max-width: 67.5rem; margin: 0 auto 3.5rem; padding: 19.5rem 1.5rem 7.5rem;   /* section 1080×685.8 (Figma 503:2486): heading text starts at y312, icon %s below map to that box. margin-bottom 56px separates §2/§3 without growing the icon box */
    /* icon tiles — final positions from Figma 503:2485 (section 1080×685.8) */
    --ic1-l: 1.3%;   --ic1-t: 42%;   --ic1-b: auto; --ic1-s: 5.5rem;  --ic1-r: 1.45rem;  /* pen-sparkle — left, mid   */
    --ic2-l: 32.8%;  --ic2-t: 28.2%; --ic2-b: auto; --ic2-s: 5.5rem;  --ic2-r: 1.45rem;  /* binary — top, centre-left */
    --ic3-l: 8.6%;   --ic3-t: 80.5%; --ic3-b: auto; --ic3-s: 6rem;    --ic3-r: 1.5rem;   /* storage — lower left      */
    --ic4-rgt: 1.4%; --ic4-t: 43.1%;               --ic4-s: 6.25rem;  --ic4-r: 1.55rem;  /* box-sparkle — right, mid  */
    --pen-l: 79.5%;  --pen-b: 3.8%;                                                       /* blue pencil tile — lower right */
  }
  #fix > h2 { font-size: 3rem; line-height: 1.235; letter-spacing: -0.032em; }   /* 48px, lh 59.3, ls -1.536 (user spec) */
  /* personal copy: statement muted to 20%, only "my own … products" (+ the two brand marks) full */
  /* default: the whole statement is solid. Hovering "my own products" mutes the
     SURROUNDING copy to 20% (via :has) and reveals the marks — so the phrase pops. */
  #fix > h2.fx-h2 { color: #1e272e; transition: color .5s ease .14s; }                                  /* hover-OUT: mute lingers */
  #fix > h2.fx-h2:has(.fx-hover.fx-open) { color: rgb(30 39 46 / .2); transition: color .32s ease; }      /* hover-IN: quicker */
  #fix > h2.fx-h2 .fx-hover, #fix > h2.fx-h2 .fx-on { color: #1e272e; transition: color .3s ease; }
  #fix > h2.fx-h2:has(.fx-hover.fx-open) .fx-hover, #fix > h2.fx-h2:has(.fx-hover.fx-open) .fx-on { color: rgb(30 39 46 / .2); }   /* feedback #7: dim the OTHER interactive phrase too */
  #fix > h2.fx-h2 .fx-hover.fx-open, #fix > h2.fx-h2 .fx-hover.fx-open .fx-on { color: #1e272e; }   /* keep ONLY the hovered phrase dark */
  /* bigger hover target — invisible padding around the phrase so it's easy to hit (vertical padding
     extends the inline hit area without shifting other lines; the horizontal pad is margin-cancelled) */
  #fix .fx-hover { padding: 0.6em 0.35em; margin: 0 -0.35em; cursor: default; }   /* not a text I-beam over the interactive phrase */
  /* HOVER REEL: the AREA opens first, then the marks RISE from the ground (staggered). The clip cell stays
     at mark height (no layout shift); the gradient fade is a 220%-tall mask whose position is animated —
     parked OFF the mark at rest (solid), and slid across only while a mark enters/leaves. So the gradient
     shows briefly during the transit and disappears once settled, reappearing on the way out. Hover-OUT
     reverses slower + delayed (marks drop, then the area closes). */
  #fix .fx-inl { display: inline-flex; align-items: center; gap: 0.545rem; vertical-align: -0.08em;   /* feedback R4: marks ride HIGH — bottoms just kiss the baseline (Figma image-8) */
                 width: 0; overflow: hidden; margin: 0 0.42rem;                                          /* 0.42rem×2 ≈ a space when collapsed */
                 -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 46%, #000 100%);
                         mask-image: linear-gradient(to top, transparent 0%, #000 46%, #000 100%);
                 -webkit-mask-size: 100% 220%; mask-size: 100% 220%;
                 -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
                 -webkit-mask-position: 50% 100%; mask-position: 50% 100%;                               /* collapsed / hover-out: fade sits over the marks (ground) */
                 transition: width .58s cubic-bezier(.4,0,.2,1) .46s, margin .58s cubic-bezier(.4,0,.2,1) .46s,
                             -webkit-mask-position .34s ease, mask-position .34s ease; }                 /* hover-OUT: area closes last + slower; fade reappears quickly */
  #fix .fx-hover.fx-open .fx-inl { width: 6.045rem; margin: 0 calc(0.42rem + 4px);                        /* 2×2.75rem icons + .545 gap; +4px white space each side when open */
                 -webkit-mask-position: 50% 0%; mask-position: 50% 0%;                                   /* settled: fade slides off → solid marks */
                 transition: width .4s cubic-bezier(.2,.85,.25,1), margin .4s cubic-bezier(.2,.85,.25,1),
                             -webkit-mask-position .4s ease .34s, mask-position .4s ease .34s; }         /* hover-IN: area opens first; gradient disappears quickly once risen */
  #fix .fx-inl img { width: 2.75rem; height: 2.75rem; border-radius: 0.8rem; display: block; flex: 0 0 auto;   /* R4: 120% of capH, measured vs Figma image-8 */
                     transform: translateY(150%); opacity: 0;
                     transition: transform .44s cubic-bezier(.4,0,.2,1), opacity .3s ease; }             /* hover-OUT: drop back into the ground */
  #fix .fx-inl img:nth-child(1) { transition-delay: .1s; }    /* exit staggers BACKWARDS: mark 2 leaves first, mark 1 after */
  #fix .fx-inl img:nth-child(2) { transition-delay: 0s; }
  #fix .fx-hover.fx-open .fx-inl img { transform: translateY(0); opacity: 1;
                     transition: transform .6s cubic-bezier(.32,1.16,.4,1), opacity .42s ease; }         /* hover-IN: rise up (slight overshoot) */
  #fix .fx-hover.fx-open .fx-inl img:nth-child(1) { transition-delay: .24s; }                             /* staggered, after the area has opened */
  #fix .fx-hover.fx-open .fx-inl img:nth-child(2) { transition-delay: .37s; }
  /* feedback #7: hover "I am experienced" → the founder's avatar reveals to its left (rest of heading dims via the same :has() rule) */
  /* avatar reveal (feedback R5): the slot opens via WIDTH; the img is a FIXED 1.2em circle absolutely anchored in the
     slot and scales in from its own CENTER (transform-origin center) — no bottom-origin growth, no left-to-right drift. */
  #fix .fx-av { display: inline-block; position: relative; vertical-align: -0.08em; width: 0; height: 1.2em; overflow: visible;
                transition: width .42s cubic-bezier(.2,.9,.3,1); }
  #fix .fx-hover--av.fx-open .fx-av { width: 1.42em; }   /* 1.2em avatar + .22em breathing room */
  #fix .fx-av img { position: absolute; left: 0; top: 50%; width: 1.2em; height: 1.2em; border-radius: 50%; object-fit: cover; display: block;
                    opacity: 0; transform: translateY(-50%) scale(0); transform-origin: center;
                    transition: opacity .28s ease, transform .42s cubic-bezier(.2,.9,.3,1); }
  #fix .fx-hover--av.fx-open .fx-av img { opacity: 1; transform: translateY(-50%) scale(1); }
  #fix .run-row { position: absolute; inset: 0; display: block; pointer-events: none; }   /* pointer-events:none: this absolute icon layer paints ABOVE the in-flow heading, so it must let hover pass through to the "my own products" phrase · the overlap row becomes the full-box icon layer
                                                                        (keeps a real box so proof.js's reveal observer fires) */
  #fix .run-ic { position: absolute; margin: 0; z-index: 1; }
  #fix .run-ic, #fix .run-row.revealed .run-ic { animation: fix-bob 4.8s ease-in-out infinite; }   /* replaces the mobile run-jump — faster + bigger float */
  #fix .run-ic:nth-child(1), #fix .run-row.revealed .run-ic:nth-child(1) { width: var(--ic1-s); height: var(--ic1-s); border-radius: var(--ic1-r); left: var(--ic1-l); top: var(--ic1-t); animation-delay: 0s;   }
  #fix .run-ic:nth-child(2), #fix .run-row.revealed .run-ic:nth-child(2) { width: var(--ic2-s); height: var(--ic2-s); border-radius: var(--ic2-r); left: var(--ic2-l); top: var(--ic2-t); animation-delay: .9s;  }
  #fix .run-ic:nth-child(3), #fix .run-row.revealed .run-ic:nth-child(3) { width: var(--ic3-s); height: var(--ic3-s); border-radius: var(--ic3-r); left: var(--ic3-l); top: var(--ic3-t); bottom: var(--ic3-b); animation-delay: 1.8s; }
  #fix .run-ic:nth-child(4), #fix .run-row.revealed .run-ic:nth-child(4) { width: var(--ic4-s); height: var(--ic4-s); border-radius: var(--ic4-r); right: var(--ic4-rgt); top: var(--ic4-t); animation-delay: 2.7s; }
  /* the blue pencil tile floats below the statement (same component + scroll interaction as §3 mobile) */
  #fix .run-pencil { display: block; position: absolute; left: var(--pen-l); bottom: var(--pen-b); z-index: 1;
    transform: translate(calc(var(--fx,0px) + var(--px,0px)), calc(var(--fy,0px) + var(--py,0px))) scale(var(--fs,1));
    animation: pen-bob 5.6s ease-in-out infinite 1.2s; }   /* fly-in + parallax + gentle float (inner .run-pen keeps its rotation) */

  /* ── §3 proof (Figma 499:2257): full bleed with 56px page gutters, heading LEFT, no pencil,
        4-up grid, badges BOTTOM-left ── */
  #proof { max-width: none; margin: 0; padding: 6.25rem var(--gutter) 7.5rem; }   /* pt 100, pb 120 (Figma) */
  #proof .proof-head { display: block; margin-bottom: 3rem; }     /* 48px heading→cards (Figma) */
  #proof .proof-head .run-pencil { display: none; }               /* pencil lives in §2 on desktop */
  #proof #work-head h2 { font-size: 3rem; font-weight: 500; line-height: 1; letter-spacing: -0.031em; text-align: left; }   /* 48px Surt Expanded Medium, ls -1.5 */
  #proof .proof-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; padding-top: 0; }  /* feedback #12: user set the card grid gap to 18px */
  /* R3: the ONE frame owner on desktop. THE FIX (user-found): keep border-radius (28px, matches the Tailwind
     rounded-[28px] + mobile) DIFFERENT from the clip-path radius. When the rounded overflow border-box clip
     coincides with the clip-path radius, THAT border-box clip is the one that leaks its corners on hover repaint;
     making them differ leaves only the non-leaking clip-path doing the visible rounding. (will-change already
     cleared in the base rule so the frame isn't composited either.) */
  #proof .reel-card .preview { aspect-ratio: 320 / 464; border-radius: 28px; overflow: hidden; clip-path: inset(0 round 22px); }   /* Figma 505:7139 */
  #proof [data-badge] { bottom: 16px; left: 16px; top: auto; }    /* badges BOTTOM-left on desktop (Figma 499:2268) */
  #proof .reel-late { padding-top: 24px; padding-left: 0; gap: 12px; align-items: center; }   /* caption: 24 top, 12 icon→text */
  /* feedback #12: baked the user's optical alignment for the card text area (title tightened to copy, icon nudged up 1px) */
  #proof .reel-card .reel-late h3 { margin-bottom: -4px; }
  #proof .reel-card .reel-late .m-ic img { margin-top: -1px; }
  /* feedback #8 + R3 (final): the .preview frame owns radius + overflow; the .pv-zoom layer zooms via
     WIDTH/HEIGHT/LEFT/TOP — a layout animation is never lifted to its own compositor layer, so the rounded
     clip applies in the ordinary paint path on every browser/GPU. No transform anywhere in the card. */
  #proof .reel-card .pv-zoom { transition: width .55s cubic-bezier(.2,.7,.2,1), height .55s cubic-bezier(.2,.7,.2,1),
                                           left .55s cubic-bezier(.2,.7,.2,1), top .55s cubic-bezier(.2,.7,.2,1); }
  #proof .reel-card:hover .pv-zoom { width: 106%; height: 106%; left: -3%; top: -3%; }
  #proof .reel-card [data-badge] { opacity: 0; transition: opacity .16s ease; }   /* hidden at rest → appear quickly on hover */
  #proof .reel-card:hover [data-badge] { opacity: 1; }
  /* Figma 505:7841 chips EXACT: #1e272e · h28 · Surt Expanded 11.667px uppercase, tracking .35px · gap 1.167 · bottom 12 / left 16.
     Year chip = full pill; category chip = SQUARED (rounded 4.667px). */
  #proof .pv-badges { position: absolute; bottom: 12px; left: 16px; display: flex; gap: 1.167px; align-items: center; z-index: 2; }
  #proof .pv-chip { display: inline-flex; align-items: center; height: 28px; box-sizing: border-box; background: #1e272e; color: #fff; white-space: nowrap;   /* glass tried Oct 26, reverted: the owner will revisit */
                    font: 400 11.667px/1 'Surt Expanded','Surt',system-ui,sans-serif; letter-spacing: 0.35px; text-transform: uppercase; }
  #proof .pv-chip--year { padding: 0 10.5px; border-radius: 999px; }
  #proof .pv-chip--cat  { padding: 0 8.167px; border-radius: 4.667px; }

  /* ── SERVICES (Figma 1741:29070): px-locked 1328 like the bento (JS zooms it below 1440); 3 cards × 429.33, gap 20 ── */
  #services { max-width: none; margin: 0; padding: 100px var(--gutter) 168px; }   /* bottom 120 → 168: air above the footer (owner, Oct 22) */
  .pk { width: 1328px; max-width: 1328px; margin-inline: auto; }
  .sv-h2  { zoom: 1.2; }   /* owner, Oct 22: the block read small next to §2 → text + px tiles as one unit at 120% (57.6px) */
  .sv-sub { font-size: 18px; line-height: 27px; }
  .sv-ic  { margin-top: 3.25px; }
  .pk-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: stretch; gap: 20px; margin-top: 112px; }   /* subhead → cards: 80 → 112 (owner, Oct 22) */
  .pk-card { max-width: none; }

  /* ── BENTO (Figma 505:8687): 2 rows · 20px gaps. Row flex-grows == Figma tile px, basis 0 →
        reproduces the 367/550/371 & 582/726 widths 1:1 and scales fluidly. ── */
  /* BENTO is px-LOCKED (not rem) so it holds its 1440 design on larger displays instead of
     scaling up with the html font-size clamp. Widths use grid fr (fill up to the 1328 cap). */
  #bento { max-width: none; margin: 0; padding: 100px var(--gutter) 72px; }   /* 100 top · 56 sides · 72 bottom (was 120: the bento → Proof gap read too big, owner Oct 22) */
  #bento .bento { gap: 20px; width: 1328px; max-width: 1328px; margin-inline: auto; transform-origin: top center; }   /* FIXED 1328 (Figma) — JS zooms it to fit below 1440 so the px-locked internals scale as a unit (no clip). */
  #bento .brow  { gap: 20px; }
  /* CSS grid: fr tracks split proportionally AFTER the gaps and ignore item padding, so the
     Figma tile widths land exactly (a flex item can't shrink its border-box below its padding). */
  #bento .brow--1 { display: grid; grid-template-columns: minmax(0,367fr) minmax(0,550fr) minmax(0,371fr); }
  #bento .brow--2 { display: grid; grid-template-columns: minmax(0,582fr) minmax(0,726fr); }
  #bento .brow > .btile { min-width: 0; min-height: 360px; }
  #bento .btile { border-radius: 28px; padding: 28px 32px; }
  #bento .btile-title { font-size: 28px; }
  /* card 5 · Services — the field fills the tile (base rules); the title sits over it */
  #bento .btile--svc { padding: 0; }

  /* card 1 · Experience — centered stat (top 58.15, glass pill) + 4 logos absolute, rotated, bleeding off the bottom */
  #bento .btile--exp { display: block; padding: 0; }
  #bento .exp-stat  { position: absolute; top: 58.15px; left: 50%; transform: translateX(-50%); width: 246px; gap: 24px; }
  #bento .exp-locksvg { width: 132px; }   /* Figma lockup 132px wide → "5+" renders at exactly 108px */
  #bento .exp-logos { position: static; }                 /* unpositioned → logos absolute vs the tile */
  /* desktop tile (367): only the CENTRES move vs mobile — sizes/rotations/float inherit from the base */
  #bento .exp-logo--kuro  { left: calc(6.54%  - 40px); top: 277.69px; }   /* Figma 1932:858743 centres on the 367 tile */
  #bento .exp-logo--natix { left: calc(32.32% - 40px); top: 289.79px; }
  #bento .exp-logo--fin   { left: calc(71.11% - 36px); top: 291.83px; }
  #bento .exp-logo--tyson { left: calc(90.09% - 32px); top: 292.98px; }



  /* card 4 · Personal — stack vertically centered (Figma nudges it 11.5px above centre) */
  #bento .btile--me { padding: 0; }
  #bento .mc       { position: absolute; inset: 20px 0 0 6px; display: block; zoom: .9; }   /* ~10% smaller, more breathing room (owner, Oct 26); the inset re-centres the smaller group in the tile */
  #bento .mc > *   { position: absolute; }
  #bento .mc-who   { left: 26px; top: 43px; margin: 0; }
  #bento .mc-typing { left: 92px; top: 88px; }
  #bento .mc-b     { left: 92px; white-space: nowrap; }
  #bento .mc-b1    { top: 88px; }
  #bento .mc-b2    { top: 141px; }
  #bento .mc-r     { right: 40px; margin: 0; }
  #bento .mc-r1    { top: 206px; }
  #bento .mc-r2    { top: 255px; }

  /* ── §4: the mobile step list hands over to the process orbit ── */
  #mp-list { display: none; }
  #orbit { display: block; position: relative; background: #fff; }   /* white — flows seamlessly out of the white §3 (no divider) */
  #orbit .orbit-pin { position: sticky; top: 0; height: 100vh; overflow: hidden;
                      display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; }
  /* the orbital cluster — orbs ride an INVISIBLE shallow arc; no path drawn */
  #orbit .stage { position: relative; width: 760px; height: 208px; flex: none; }
  #orbit .orb { position: absolute; left: 50%; top: 48%; width: 60px; height: 60px;
                display: flex; align-items: center; justify-content: center; border-radius: 50%;
                background: #fff; box-shadow: 0 8px 22px rgba(30,39,46,.10), 0 2px 6px rgba(30,39,46,.06);
                will-change: transform, opacity; }   /* soft-shadow chips so the satellites read on the white bg */
  #orbit .orb img { width: 50%; height: 50%; display: block; }
  /* active centre — a small perspective stack of squircle cards; the next waits behind, slides in on step change */
  #orbit .core { position: absolute; left: 50%; top: 48%; transform: translate(-50%, -50%); width: 112px; height: 112px;
                 z-index: 60; perspective: 760px; }
  #orbit .core .sq { position: absolute; inset: 0; transform-origin: 50% 50%; will-change: transform, opacity; backface-visibility: hidden; }
  #orbit .core.anim .sq { transition: transform .58s cubic-bezier(.22,.8,.24,1), opacity .45s ease; }
  #orbit .core.anim .sq .o-gray { transition: opacity .5s ease; }
  #orbit .core .sq svg { width: 112px; height: 112px; display: block; overflow: visible; }
  #orbit .copy { text-align: center; width: 100%; padding: 0 24px; }
  #orbit .copy h2 { margin: 0; font-family: 'Surt Expanded', 'Surt', system-ui, sans-serif; font-weight: 400;
                    font-size: clamp(28px, 4.6vw, 60px); line-height: 1.04; letter-spacing: -.04em; color: #1e272e; white-space: nowrap; }
  /* heading = per-glyph letter reels; neutralise the base .ch reveal system (motion is the inner .ch-i) */
  #orbit .copy h2 .ch { opacity: 1 !important; transform: none !important; transition: none !important;
                        position: relative; display: inline-block; overflow: hidden; height: 1.34em; line-height: 1.34; vertical-align: bottom; white-space: pre; }
  #orbit .copy h2 .ch-i { display: block; color: #1e272e; transition: transform .4s cubic-bezier(.36,1.24,.5,1), color .14s ease; }
  #orbit .copy h2 .ch-d { display: block; height: 1.34em; line-height: 1.34; }
  #orbit .copy h2 .ch.flash .ch-i { color: var(--flash-color, #642BE1);
                                    transition: transform .4s cubic-bezier(.36,1.24,.5,1), color .07s ease; }
  #orbit .copy h2 .ch::before, #orbit .copy h2 .ch::after { content: ''; position: absolute; left: 0; right: 0; height: .3em; z-index: 2;
                                                            pointer-events: none; opacity: 0; transition: opacity .05s linear; }
  #orbit .copy h2 .ch::before { top: 0;    background: linear-gradient(to bottom, #fff, rgba(255,255,255,0)); }
  #orbit .copy h2 .ch::after  { bottom: 0; background: linear-gradient(to top, #fff, rgba(255,255,255,0)); }
  #orbit .copy h2 .ch.rolling::before, #orbit .copy h2 .ch.rolling::after { opacity: 1; }
  #orbit .copy p { margin: 14px auto 0; font-size: 20px; line-height: 1.4; color: #6e6e74; max-width: 470px; }
  #orbit .copy .layer { transition: opacity .4s ease, transform .5s cubic-bezier(.2,.85,.25,1); }
  #orbit .copy.swap .layer { opacity: 0; transform: translateY(8px); }

}

/* narrow desktop: the 760px orbit cluster gets tight — shrink it a touch */
@media (min-width: 821px) and (max-width: 980px) { #orbit .stage { transform: scale(.7); } .sv-h2 { zoom: 1; } }   /* the 1.2× services heading wraps below ~930 */

/* fix-bob composes the idle float with the fly-in (--fx/--fy/--fs) and per-icon parallax (--px/--py),
   all set live by proof.js — CSS animations re-read custom props each frame, so everything combines.
   AGGRESSIVE, organic float: big ±1rem swing, out-of-phase x drift + a rotation wobble. */
@keyframes fix-bob {
  0%   { transform: translate(calc(var(--fx,0px) + var(--px,0px) - .28rem), calc(var(--fy,0px) + var(--py,0px) - 1rem))  scale(var(--fs,1)) rotate(-1.8deg); }
  33%  { transform: translate(calc(var(--fx,0px) + var(--px,0px) + .32rem), calc(var(--fy,0px) + var(--py,0px) + .35rem)) scale(var(--fs,1)) rotate(1.3deg); }
  66%  { transform: translate(calc(var(--fx,0px) + var(--px,0px) - .12rem), calc(var(--fy,0px) + var(--py,0px) + .95rem)) scale(var(--fs,1)) rotate(-.7deg); }
  100% { transform: translate(calc(var(--fx,0px) + var(--px,0px) - .28rem), calc(var(--fy,0px) + var(--py,0px) - 1rem))  scale(var(--fs,1)) rotate(-1.8deg); }
}
/* pencil: gentler float (no wobble — the inner .run-pen keeps its scroll rotation) */
@keyframes pen-bob {
  0%, 100% { transform: translate(calc(var(--fx,0px) + var(--px,0px)), calc(var(--fy,0px) + var(--py,0px) - .7rem)) scale(var(--fs,1)); }
  50%      { transform: translate(calc(var(--fx,0px) + var(--px,0px)), calc(var(--fy,0px) + var(--py,0px) + .7rem)) scale(var(--fs,1)); }
}

/* ═══════════ SMALL-DESKTOP BRIDGE (feedback #18): 821–1120px — the 4-col products and the
   3+2 bento get cramped → products go 2×2 and the bento stacks like the tablet (exp+craft 2-col,
   the rest full width, fluid instead of the px-locked 1328 + JS zoom). ═══════════ */
@media (min-width: 821px) and (max-width: 1120px) {
  #proof .proof-cards { grid-template-columns: 1fr 1fr; gap: 24px; }
  #bento .bento { width: auto; max-width: none; }   /* release the px-lock (the JS zoom disengages ≤1120 too) */
  #bento .brow--1 { grid-template-columns: 1fr 1fr; }
  #bento .brow--1 > .btile--proc { grid-column: 1 / -1; }
  #bento .brow--2 { grid-template-columns: 1fr; }
  .pk { width: auto; }   /* services: one column of Figma-width cards (3 x 429 do not fit) */
  .pk-row { display: flex; align-items: center; }
  .pk-card { max-width: 429.33px; }
}

/* ── perf: ambient idle animations PAUSE while their section is offscreen (index.html toggles .av-off
      via IntersectionObserver). paused preserves phase → resumes exactly where it left off, no visual change. ── */
.av-off .hchip, .av-off .hcard, .av-off .fc-bob, .av-off .pfloat .fc,
.av-off .run-ic, .av-off .run-pencil, .av-off .exp-logo,
.av-off .logo-track, .av-off .dm circle.on, .av-off .cta-cube circle, .av-off .sv-tile
{ animation-play-state: paused !important; }   /* !important: `#fix .run-ic`, `#fix .run-pencil`, `#bento .exp-logo` set `animation` with an id, which outranked this and kept them running offscreen */

/* ── revisit skip (html.hero-skip, set pre-paint in the head): the loader UI must never paint —
      no % counter flash, no phone chassis — regardless of how late the physics script boots. ── */
html.hero-skip #hero-progress { display: none !important; }
html.hero-skip #sk-frame, html.hero-skip #sk-screen { visibility: hidden !important; }

/* ── primary-CTA ROLODEX (.ctar, built by index.html from data-swap; desktop only).
      Same geometry as the hero pill: the button is a WINDOW, .ctar-reel carries both faces on an
      invisible circle centred ~325px below, and one rigid 30deg rotation swings the labels through. ── */
@media (min-width: 821px) {
  .ctar            { position: relative; overflow: hidden; }
  .ctar-sizer      { display: inline-flex; align-items: center; gap: 8px; visibility: hidden; }   /* in-flow, invisible → holds the button's width for the LONGER label */
  /* origin measured from the button's own CENTRE → radius is exactly 300px whatever the button's height,
     so the parked offset below (R·sin30, R·(1-cos30)) lands the alt face dead-centre on every CTA. */
  .ctar-reel       { position: absolute; inset: 0; transform-origin: 50% calc(50% + 300px); transition: transform .62s cubic-bezier(.34,1.3,.5,1); }
  .ctar:hover .ctar-reel { transform: rotate(30deg); }
  .ctar-face       { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 8px; backface-visibility: hidden; }
  .ctar-face--alt  { transform: translate(-150px, 40.19px) rotate(-30deg); }   /* parked off-window, lower-left; counter-rotated so it lands level */
}

/* iOS-style continuous corners where supported (Chrome 139+). superellipse(1.6) at 40px = Figma's 28px with 60% corner smoothing
   (edge profile matched within 3px); everything else keeps the plain 28px. Nested radii scale by the same 40/28. */
@supports (corner-shape: superellipse(1.6)) {
  #bento .btile, .pk-card { corner-shape: superellipse(1.6); border-radius: 40px; }
  .pk-cover { corner-shape: superellipse(1.6); border-radius: 40px 40px 20px 20px; }
}

/* ── scroll-in, take 3 (owner, Oct 22): the card FRAMES stay put ("it's too obvious that the card is moving, it looks
   so bad"); what moves is inside each offer card, once, when it first comes into view (index.html adds .rv-in):
   the price rolls up like an odometer, then the list's icon tiles pop in (the brand's playful pop). The bento tiles
   carry their own in-view animations already. No fade anywhere; one motion for everyone. ── */
.sv-price .od { position: relative; display: inline-block; overflow: hidden; height: 1em; vertical-align: top; }
.sv-price .od > i { font-style: normal; visibility: hidden; }   /* the final digit: sets the column's width, so spacing never shifts */
.sv-price .od-s { position: absolute; left: 50%; top: 0; translate: -50% 0; display: flex; flex-direction: column; align-items: center;
  transition: transform 1.1s cubic-bezier(.2,.8,.2,1); transition-delay: calc(var(--n, 0) * 70ms); }
.sv-price .od-s > b { display: block; height: 1em; font-weight: inherit; }
.pk-card.rv-in .sv-price .od-s { transform: translateY(calc(var(--d) * -1em)); }
html.rv-js .pk-card .pk-mk { animation: rv-pop .5s cubic-bezier(.3,1.5,.5,1) both paused; }
.pk-card .sv-list li:nth-child(2) .pk-mk { animation-delay: .07s; }
.pk-card .sv-list li:nth-child(3) .pk-mk { animation-delay: .14s; }
.pk-card .sv-list li:nth-child(4) .pk-mk { animation-delay: .21s; }
html.rv-js .pk-card.rv-in .pk-mk { animation-play-state: running; }
@keyframes rv-pop { from { scale: .6; rotate: -6deg; } to { scale: none; rotate: none; } }
