/* ============================================================
   AMAL DAMODAR, Apple gradient/glass portfolio (v3)
   MagicUI iPhone frame · cinematic card hero · fluid motion
   ============================================================ */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}

/* ---- THEME ----
   Two families of colour carry the whole page, and both are declared as bare RGB
   channels so a theme can invert them without touching the 100-odd places that
   use them:

     --ink-rgb   the type colour. Every dimmed label is that same colour at a
                 lower alpha, which is why they all stay in key when it flips.
     --hi-rgb    the "light on the surface" colour: glass fills, hairline borders,
                 rim highlights. White on a dark page, near-black on a light one,
                 because on paper the thing that defines an edge is shadow.

   Anything written as rgba(var(--hi-rgb),a) or rgba(var(--ink-rgb),a) would have been
   frozen to the dark theme, so those literals are gone. Use the tokens. */
:root{
  color-scheme:dark;
  --ink-rgb:245,241,232;
  --hi-rgb:255,255,255;
  --bg:var(--bg);
  --bg-2:#131117;
  --mesh-top:var(--mesh-top);
  --ink:#f5f1e8;
  --ink-dim:rgba(var(--ink-rgb),.62);
  --ink-faint:rgba(var(--ink-rgb),.34);
  --line:rgba(var(--ink-rgb),.10);
  /* dark wells that media sits in, and the warm near-black of the testimonial
     and CTA slabs. Both need a paper-side counterpart. */
  --well:var(--well);
  --well-2:var(--well-2);
  --warm-1:var(--warm-1); --warm-2:var(--warm-2);
  --warm-3:var(--warm-3); --warm-4:var(--warm-4);
  --warm-solid:var(--warm-solid);
  --g1:#a3761f; --g2:#d4a53c; --g3:#f2d98a;
  --grad:linear-gradient(118deg,var(--g2) 0%,var(--g3) 46%,#fff8e3 72%,var(--g3) 100%);
  --glass:rgba(var(--hi-rgb),.055);
  --blur-thick:blur(38px) saturate(175%);
  --mesh-a:rgba(163,118,31,.58);
  --mesh-b:rgba(212,165,60,.36);
  --mesh-c:rgba(74,66,86,.44);
  --mesh-op:.55;
  --grain-op:.045;
  --grain-blend:overlay;
  --on-gold:#141006;
  --gold-rim:rgba(255,248,227,.5);
  --copy-warm:rgba(163,118,31,.14);
  --haze:rgba(12,11,14,.9);
  --haze-2:rgba(12,11,14,.42);
  --panel-rgb:18,17,21;
  --logo-bg:#0d0704;
  --shadow-soft:rgba(0,0,0,.5);
  --shadow-deep:rgba(0,0,0,.62);
  --glow-warm:rgba(212,165,60,.2);
  --glow-mid:rgba(60,52,40,.5);
  --glow-deep:rgba(18,17,20,.9);
  --scrim-1:rgba(10,10,11,.5);
  --scrim-2:rgba(10,10,11,.82);
  --scrim-3:rgba(10,10,11,.92);
  /* a lit top edge and a shadowed bottom edge together: this pair, not the
     border, is what makes a surface read as a slab rather than a rectangle */
  --rim:inset 0 1px 0 rgba(var(--hi-rgb),.28),inset 0 -1px 0 rgba(0,0,0,.34);
  --rim-lit:inset 0 1px 0 rgba(255,248,227,.46),inset 0 -1px 0 rgba(0,0,0,.36);
  --glass-brite:rgba(242,217,138,.16);
  /* The platform's own face. On a Mac or an iPhone this resolves to SF Pro,
     which is the face Apple sets its own headlines in; everywhere else it falls
     to the local system face, which is the point of a system stack. No webfont
     request, no flash of fallback text, and it is already optically sized and
     tracked for UI, which no downloaded display face is. */
  --display:-apple-system,BlinkMacSystemFont,'SF Pro Display','Segoe UI',system-ui,sans-serif;
  --sans:-apple-system,BlinkMacSystemFont,'SF Pro Text','Segoe UI',system-ui,sans-serif;
  --ease:cubic-bezier(.16,1,.3,1);
  /* container: caps content width, symmetric side padding site-wide */
  --container:1360px;
  --pad-x:clamp(1.25rem,5vw,4rem);
  --edge:max(var(--pad-x),calc((100% - var(--container)) / 2));
}
/* ---- LIGHT ----
   Not the dark theme with the values flipped. Paper is warm, not white: a true
   #fff page under a gold accent reads clinical, and the gold itself has to come
   down the ramp because #d4a53c on white is roughly 2:1 and fails outright as
   text. The highlight channel goes near-black, since on a light surface it is
   shadow, not light, that defines an edge. */
[data-theme="light"]{
  color-scheme:light;
  --ink-rgb:24,21,17;
  --hi-rgb:24,21,17;
  --bg:#f6f3ec;
  --bg-2:#ece6da;
  --mesh-top:#fffdf7;
  --ink:#181511;
  --ink-dim:rgba(var(--ink-rgb),.68);
  --ink-faint:rgba(var(--ink-rgb),.5);
  --line:rgba(var(--ink-rgb),.14);
  --well:#e4ddd0;
  --well-2:#e9e2d6;
  --warm-1:#fff4dd; --warm-2:#f7e7c9;
  --warm-3:#fdf1d9; --warm-4:#f3e2c2;
  --warm-solid:#f7ecd8;
  /* the ramp darkens so gold-on-paper still carries; the light end stays for
     fills and edges where it is decoration rather than type */
  --g1:#6b4a0e; --g2:#8a6414; --g3:#c99a2e;
  --grad:linear-gradient(118deg,#8a6414 0%,#a97c1c 46%,#c99a2e 72%,#8a6414 100%);
  --glass:rgba(255,255,255,.55);
  --rim:inset 0 1px 0 rgba(255,255,255,.9),inset 0 -1px 0 rgba(var(--ink-rgb),.1);
  --rim-lit:inset 0 1px 0 rgba(255,255,255,.95),inset 0 -1px 0 rgba(var(--ink-rgb),.12);
  --glass-brite:rgba(138,100,20,.14);
  --mesh-a:rgba(212,165,60,.3);
  --mesh-b:rgba(232,196,110,.26);
  --mesh-c:rgba(196,186,208,.34);
  --mesh-op:.7;
  --grain-op:.03;
  --grain-blend:multiply;
  --on-gold:#fff8e6;
  --gold-rim:rgba(90,64,10,.42);
  --copy-warm:rgba(201,154,46,.2);
  --haze:rgba(248,245,239,.9);
  --haze-2:rgba(248,245,239,.42);
  --panel-rgb:255,253,248;
  --logo-bg:#fffaf0;
  --shadow-soft:rgba(60,48,26,.14);
  --shadow-deep:rgba(60,48,26,.2);
  /* The white layers stay low, or they bleach the wall off the page. The GOLD
     one does not: it is what gives the dark theme its warm pool behind the
     figure and the copy, and on paper it reads as amber light rather than haze,
     so it can carry more here than the whites can. */
  --glow-warm:rgba(196,143,32,.5);
  --glow-mid:rgba(255,250,232,.3);
  --glow-deep:rgba(255,253,247,.44);
  --scrim-1:rgba(246,243,236,.55);
  --scrim-2:rgba(246,243,236,.85);
  --scrim-3:rgba(246,243,236,.95);
}

/* The theme swap itself is instant. What the eye reads as a smooth change is the
   flash overlay below crossing over it, so nothing here animates: a global
   transition on colour would make 200 elements tween at slightly different rates
   and the page would smear rather than switch. */
html{-webkit-text-size-adjust:100%}
/* clip, not hidden. overflow-x:hidden makes the body a scroll container, which
   means anything overflowing it adds scrollable HEIGHT as well, and the page
   ended up with a screenful of empty space under the footer. clip suppresses the
   overflow without creating a scrollport. */
body{font-family:var(--sans);background:var(--bg);color:var(--ink);
  -webkit-font-smoothing:antialiased;overflow-x:clip;line-height:1.5}
html{overflow-x:clip}
/* The hero mixes units on purpose and the drift is accounted for in the gutter
   below: the copy columns are positioned from 50% (the content box, scrollbar
   excluded) while the figure's width budget is computed from 50vw (scrollbar
   included), so the budget overestimates the space it has by half a scrollbar.
   Do NOT express that correction as a custom property holding `calc(100vw -
   100%)`. A percentage inside a custom property is resolved against whatever
   property finally consumes it, and --fig-h is consumed as a height, so the
   term silently collapses the figure to zero. The gutter carries it instead. */
a{color:inherit;text-decoration:none}
img{display:block;max-width:100%}
::selection{background:var(--g2);color:var(--on-gold)}
.only-desk{display:inline}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}

.grad-text{background:var(--grad);-webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent}

/* ============ MESH GRADIENT BACKGROUND ============ */
.mesh{position:fixed;inset:0;z-index:-2;overflow:hidden;
  background:radial-gradient(140% 100% at 50% -20%,var(--mesh-top) 0%,var(--bg) 60%)}
.blob{position:absolute;border-radius:50%;filter:blur(100px);opacity:var(--mesh-op);will-change:transform}
.b1{width:60vw;height:60vw;left:-8vw;top:-12vw;background:radial-gradient(circle,var(--mesh-a),transparent 62%);animation:d1 28s var(--ease) infinite alternate}
.b2{width:52vw;height:52vw;right:-10vw;top:6vh;background:radial-gradient(circle,var(--mesh-b),transparent 62%);animation:d2 34s var(--ease) infinite alternate}
.b3{width:48vw;height:48vw;left:22vw;bottom:-16vw;background:radial-gradient(circle,var(--mesh-c),transparent 62%);animation:d3 30s var(--ease) infinite alternate}
.b4{width:40vw;height:40vw;right:8vw;bottom:-6vw;background:radial-gradient(circle,var(--mesh-b),transparent 62%);animation:d1 32s var(--ease) infinite alternate}
@keyframes d1{to{transform:translate(10vw,8vh) scale(1.15)}}
@keyframes d2{to{transform:translate(-8vw,10vh) scale(1.12)}}
@keyframes d3{to{transform:translate(8vw,-10vh) scale(1.2)}}
.grain{position:absolute;inset:0;opacity:var(--grain-op);pointer-events:none;mix-blend-mode:var(--grain-blend);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* ============ GLASS + FLUID BUTTONS ============ */
.glass{position:relative;isolation:isolate;
  background:linear-gradient(135deg,rgba(var(--hi-rgb),.10),rgba(var(--hi-rgb),.02)),var(--glass);
  backdrop-filter:blur(22px) saturate(160%);-webkit-backdrop-filter:blur(22px) saturate(160%);
  border:1px solid var(--glass-brite);
  box-shadow:inset 0 1px 0 rgba(var(--hi-rgb),.20),inset 0 -1px 0 rgba(0,0,0,.25),0 14px 40px rgba(0,0,0,.34)}
.glass::before{content:"";position:absolute;inset:0;border-radius:inherit;z-index:-1;pointer-events:none;
  background:radial-gradient(120% 80% at 15% 0%,rgba(var(--hi-rgb),.28),transparent 42%)}
.btn-fluid{position:relative;overflow:hidden;transition:transform .5s var(--ease),box-shadow .5s var(--ease),color .3s}
.btn-fluid::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(115deg,transparent 30%,rgba(var(--hi-rgb),.35) 50%,transparent 70%);
  transform:translateX(-120%);transition:transform .7s var(--ease)}
.btn-fluid:hover::after{transform:translateX(120%)}
.btn-fluid:hover{transform:translateY(-2px)}
.btn-fluid:active{transform:translateY(0) scale(.97)}
.grad{background:var(--grad);background-size:200% 200%;background-position:0% 50%;color:var(--on-gold);border:none;
  transition:background-position .6s var(--ease),transform .5s var(--ease),box-shadow .5s var(--ease)}
.grad:hover{background-position:100% 50%;box-shadow:0 16px 44px rgba(212,165,60,.40)}

/* ---- buttons ----
   Two only. .btn-gold is the single action that matters on a screen, .btn-ghost
   is everything else. Three competing button styles means no primary. */
.btn-gold,.btn-ghost{display:inline-flex;align-items:center;justify-content:center;
  gap:.7rem;font-family:var(--sans);font-size:.98rem;font-weight:600;
  letter-spacing:-.01em;padding:.9rem 1.6rem;border-radius:100px;cursor:pointer;
  white-space:nowrap;
  transition:transform .38s var(--ease),box-shadow .38s var(--ease),
             background-position .6s var(--ease),border-color .38s,background .3s}
.btn-gold{color:var(--on-gold);border:1px solid var(--gold-rim);
  background:var(--grad);background-size:210% 100%;background-position:0% 50%;
  box-shadow:var(--rim-lit),0 10px 26px rgba(0,0,0,.42)}
.btn-gold:hover{background-position:100% 50%;transform:translateY(-2px);
  box-shadow:var(--rim-lit),0 16px 40px rgba(0,0,0,.48),0 0 46px rgba(212,165,60,.34)}
.btn-gold:active{transform:translateY(0) scale(.978)}
.btn-ghost{color:var(--ink);border:1px solid var(--glass-brite);
  background:rgba(var(--hi-rgb),.05);
  backdrop-filter:blur(16px) saturate(150%);-webkit-backdrop-filter:blur(16px) saturate(150%);
  box-shadow:var(--rim)}
.btn-ghost:hover{border-color:rgba(242,217,138,.4);transform:translateY(-2px);
  background:rgba(var(--hi-rgb),.08)}
.btn-ghost:active{transform:translateY(0) scale(.978)}

/* ============ NAV, liquid-glass pill ============
   Translucent, heavily blurred and saturated, with a specular top edge and an
   inner rim light. One floating capsule rather than edge-anchored controls. */
.nav{position:fixed;top:0;left:0;right:0;z-index:100;display:flex;justify-content:center;
  perspective:900px;
  padding-block:clamp(1rem,2.1vw,1.6rem);padding-inline:var(--pad-x);will-change:transform;
  pointer-events:none}
.nav-pill{position:relative;pointer-events:auto;display:flex;align-items:center;gap:clamp(.9rem,3vw,3.2rem);
  max-width:100%;padding:.26rem .26rem .26rem 1.3rem;border-radius:100px;isolation:isolate;
  transform-style:preserve-3d;will-change:transform;
  background:linear-gradient(180deg,rgba(var(--hi-rgb),.13),rgba(var(--hi-rgb),.05));
  backdrop-filter:blur(26px) saturate(190%);-webkit-backdrop-filter:blur(26px) saturate(190%);
  border:1px solid rgba(var(--hi-rgb),.16);
  box-shadow:0 10px 30px rgba(0,0,0,.3),0 2px 8px rgba(0,0,0,.18)}
.nav-pill::before{content:"";position:absolute;inset:0;border-radius:inherit;z-index:-1;pointer-events:none;
  background:radial-gradient(120% 90% at 20% 0%,rgba(var(--hi-rgb),.07),transparent 52%)}
.nav-brand{display:inline-flex;align-items:center;flex:0 0 auto;padding:.15rem}
.nav-brand img{width:24px;height:24px;object-fit:contain;transition:transform .4s var(--ease)}
.nav-brand:hover img{transform:translateY(-2px) scale(1.14)}

.nav-links{display:flex;align-items:center;gap:clamp(.5rem,1.6vw,1.6rem)}
.nav-links a{position:relative;font-size:.9rem;font-weight:500;color:var(--ink-dim);
  padding:.32rem .2rem;white-space:nowrap;
  transition:color .3s,transform .38s var(--ease)}
.nav-links a:hover{transform:translateY(-3px) scale(1.07)}
.nav-links a::after{content:"";position:absolute;left:0;right:0;bottom:.15rem;height:1.5px;
  border-radius:2px;background:var(--grad);transform:scaleX(0);transform-origin:50%;
  transition:transform .35s var(--ease)}
.nav-links a:hover{color:var(--ink)}
.nav-links a:hover::after{transform:scaleX(1)}

.nav-cta{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  padding:.5rem 1.3rem;border-radius:100px;font-size:.92rem;font-weight:600;color:var(--on-gold);
  background:var(--grad);background-size:200% 200%;background-position:0% 50%;white-space:nowrap;
  box-shadow:0 6px 18px rgba(212,165,60,.34);
  transition:background-position .6s var(--ease),transform .35s var(--ease),box-shadow .35s var(--ease)}
.nav-cta:hover{background-position:100% 50%;transform:translateY(-1px);box-shadow:0 10px 26px rgba(212,165,60,.46)}
.nav-cta:active{transform:translateY(0) scale(.97)}

@media(max-width:640px){
  .nav-pill{padding-left:.6rem;gap:.5rem}
  .nav-links a{font-size:.86rem}
  .nav-cta{padding:.55rem .9rem;font-size:.84rem}
}

/* Marks that ship in both inks. The wrong one is removed from layout rather than
   hidden, so a stacked pair never leaves a gap where the other used to be. */
.on-light{display:none}
[data-theme="light"] .on-dark{display:none}
[data-theme="light"] .on-light{display:block}

/* ============ THEME SWITCH ============
   Top right, above everything, on the same vertical line as the nav pill. */
.theme-sw{position:fixed;top:clamp(.9rem,2.2vh,1.5rem);right:clamp(.9rem,3vw,2rem);z-index:120;
  width:clamp(40px,4vw,46px);aspect-ratio:1;border:0;padding:0;cursor:pointer;
  border-radius:50%;display:grid;place-items:center;isolation:isolate;
  background:linear-gradient(160deg,rgba(var(--hi-rgb),.1),rgba(var(--hi-rgb),.03)),var(--glass);
  border:1px solid rgba(var(--hi-rgb),.14);
  box-shadow:var(--rim),0 6px 18px var(--shadow-soft);
  backdrop-filter:blur(18px) saturate(160%);-webkit-backdrop-filter:blur(18px) saturate(160%);
  -webkit-tap-highlight-color:transparent;
  transition:border-color .5s var(--ease),scale .35s var(--ease)}
.theme-sw:hover{border-color:rgba(var(--hi-rgb),.3);scale:1.06}
.theme-sw:active{scale:.94}
.theme-sw:focus-visible{outline:2px solid var(--g2);outline-offset:3px}

/* a gold ring that sweeps round on the change, so the button itself reacts */
.theme-sw-ring{position:absolute;inset:-2px;border-radius:50%;pointer-events:none;
  background:conic-gradient(from 0deg,transparent 0deg,var(--g3) 40deg,transparent 120deg);
  opacity:0;transition:opacity .4s var(--ease)}
.theme-sw.is-turning .theme-sw-ring{opacity:.9;animation:swring .7s var(--ease)}
@keyframes swring{ from{rotate:0deg} to{rotate:360deg} }

/* The two icons ride one arc. The outgoing one falls away and spins out while
   the incoming one arrives on the same path, which reads as a single object
   turning rather than two things cross-fading. */
.theme-sw-ico{grid-area:1/1;display:grid;place-items:center;color:var(--ink);
  transition:rotate .55s var(--ease),scale .55s var(--ease),opacity .4s var(--ease),
             translate .55s var(--ease)}
.theme-sw-moon{rotate:0deg;scale:1;opacity:1;translate:0 0}
.theme-sw-sun {rotate:-70deg;scale:.4;opacity:0;translate:0 12px}
.theme-sw[aria-checked="true"] .theme-sw-moon{rotate:70deg;scale:.4;opacity:0;translate:0 -12px}
.theme-sw[aria-checked="true"] .theme-sw-sun {rotate:0deg;scale:1;opacity:1;translate:0 0}

/* ---- the flash ----
   The switch is instant; this is what the eye actually reads. A bloom opens from
   the switch itself, peaks white, and the theme is swapped underneath it at the
   peak, so the change happens inside the glare the way it does when a light comes
   on in a room. Going back to dark there is no glare, only a fall, so the same
   element runs a darker, slower curve. Never display:none, because a hidden
   element cannot be transitioned from. */
.theme-flash{position:fixed;inset:0;z-index:200;pointer-events:none;opacity:0;
  background:radial-gradient(circle at var(--fx,92%) var(--fy,4%),
             rgba(255,252,242,1) 0%,rgba(255,248,230,.92) 26%,rgba(255,244,214,.55) 52%,
             rgba(255,240,206,0) 78%)}
.theme-flash.is-dark{background:radial-gradient(circle at var(--fx,92%) var(--fy,4%),
             rgba(8,8,10,.96) 0%,rgba(10,10,12,.9) 30%,rgba(10,10,12,.5) 58%,
             rgba(10,10,12,0) 82%)}
@media(prefers-reduced-motion:reduce){
  .theme-sw-ico,.theme-sw-ring{transition:none;animation:none}
  .theme-flash{display:none}
}

/* ============ HERO ============
   One 3D scene, built from the reference composite's own layers. Every element is
   a plane at its own depth inside a single preserve-3d space, so tilting the stage
   with the cursor gives real parallax: the labels nearest the viewer sweep further
   than the headline behind the head, because perspective says they must.

   The perspective and the overflow live on .hero, not on .hero-stage. An element's
   perspective applies to its children rather than to itself, and any overflow other
   than visible forces a flattening context, so putting either one on the preserve-3d
   element silently collapses the whole scene to 2D. */
.hero{position:relative;z-index:3;overflow:clip;perspective:1400px;
  perspective-origin:50% 42%}
.hero-stage{position:relative;height:100svh;min-height:600px;
  transform-style:preserve-3d;isolation:isolate;will-change:transform}

/* Depth lives in GSAP's transform cache, not in a CSS transform here. GSAP folds
   any `transform` / `translate` / `scale` it finds into its own matrix and then
   zeroes the standalone properties, so a depth declared in CSS would survive the
   first tween only by luck. heroScene() sets z and the counter-scale through GSAP
   instead, which leaves x and y free for the idle drift to write every frame. */
.hero-glow,.hero-figure,.hero-ground,.hero-tag{transform-style:preserve-3d}

/* ---- the wall ----
   The real work drifting behind everything, alternate columns running opposite
   ways. It sits at the very back of the scene and at a quarter opacity, so it is
   texture the eye reads as motion rather than content it tries to watch. Cells
   are 16:9 and small: at this size the grid reads as a field, and a vertical cell
   would fight the figure for the same tall shape. */
.reelwall{position:absolute;inset:-16% -8%;z-index:0;pointer-events:none;opacity:var(--wall-op,.44);
  /* Clips its own columns. They run to about 14000px so the loop has spare
     track, and a 3D descendant can escape an ancestor's overflow, so the page
     was growing by hundreds of px as the wall drifted. */
  overflow:hidden;contain:paint;
  display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);
  gap:clamp(.35rem,.7vw,.7rem);
  -webkit-mask-image:radial-gradient(120% 100% at 50% 46%,#000 22%,rgba(0,0,0,.5) 60%,transparent 92%);
          mask-image:radial-gradient(120% 100% at 50% 46%,#000 22%,rgba(0,0,0,.5) 60%,transparent 92%)}
.rw-col{display:flex;flex-direction:column;gap:clamp(.35rem,.7vw,.7rem);
  min-width:0;will-change:transform}
/* A column is one format the whole way down, so the frame is never cropped to a
   shape it was not shot in. heroWall() sets the track widths to match. */
.rw-cell{position:relative;flex:0 0 auto;width:100%;overflow:hidden;
  border-radius:7px;background:var(--well-2);
  border:1px solid rgba(var(--hi-rgb),.05)}
.rw-long .rw-cell{aspect-ratio:16/9}
.rw-short .rw-cell{aspect-ratio:9/16;border-radius:9px}
.rw-cell img,.rw-cell video{width:100%;height:100%;object-fit:cover;display:block;
  filter:grayscale(.72) brightness(.78) contrast(1.06)}
/* Heaviest exactly where he and the headline are. Without this the wall is
   loudest in the middle of the frame, which is the one place it must not be:
   the centre has to stay quiet enough that nothing competes with his face. */
.reelwall::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(46% 52% at 50% 48%,var(--wall-veil) 0%,var(--wall-veil-2) 62%,transparent 100%),
    linear-gradient(180deg,var(--wall-veil-2) 0%,transparent 26%,transparent 72%,var(--wall-veil) 100%)}
/* The centre stop stays near solid, that is what keeps his face clear of the
   frames. The outer stop comes down a long way: at .62 it was smothering the
   whole wall, which is why the dark page read as empty where the light one
   reads as a studio. */
:root{--wall-veil:rgba(10,10,11,.93);--wall-veil-2:rgba(10,10,11,.4)}
[data-theme="light"]{--wall-veil:rgba(246,243,236,.93);--wall-veil-2:rgba(246,243,236,.26)}
/* the frames have to stay darker than the paper to be seen at all. Blowing them
   out toward white, which is the instinct on a light page, makes them vanish. */
[data-theme="light"] .reelwall{--wall-op:.55}
[data-theme="light"] .rw-cell img,[data-theme="light"] .rw-cell video{
  filter:grayscale(.8) brightness(.95) contrast(.9)}
[data-theme="light"] .rw-cell{border-color:rgba(var(--hi-rgb),.07)}

/* ---- holding the dark hero together ----
   With the wall now actually reading on the dark page, the two things in front
   of it have to be pushed back up or the frames start competing with them. On
   paper this comes free: dark type on a pale page separates by itself, and the
   figure is the darkest object in the frame. On the dark theme the type and the
   cutout sit in the same tonal band as the wall, so each one is given its own
   separation: a scrim under each copy block, a contact shadow on him, and the
   dimmed inks carried a step brighter than the site-wide values.
   Written as :not([data-theme="light"]) rather than [data-theme="dark"], because
   the attribute is not on the element until the head script or themeToggle()
   sets it, and the first paint must already be right. */
html:not([data-theme="light"]) .hero-amal{
  filter:saturate(1.06) contrast(1.05) brightness(1.05)
         drop-shadow(0 26px 64px rgba(0,0,0,.72))}
/* The copy still needs something under it, but a plate of page colour read as a
   black disc parked beside him. Gold instead, and warm brown rather than neutral
   black underneath it: the shade is now the falloff of the same light the brain
   is throwing, so it belongs in the frame instead of sitting on it.
   Three things do the blending. The stops step down in small increments rather
   than running one colour straight to transparent, which is what draws an edge.
   The oval is wider than it is tall, matching the shape of a block of text
   rather than fighting it. And the whole pseudo-element is blurred, so whatever
   edge survives the ramp is dissolved outright. */
html:not([data-theme="light"]) .hero-quote::before,
html:not([data-theme="light"]) .hero-about::before{
  background:
    radial-gradient(62% 56% at 50% 50%,rgba(242,217,138,.13) 0%,
      rgba(212,165,60,.1) 34%,rgba(163,118,31,.055) 58%,
      rgba(163,118,31,.02) 74%,transparent 88%),
    radial-gradient(78% 70% at 50% 52%,rgba(28,19,7,.62) 0%,
      rgba(26,18,7,.44) 40%,rgba(22,16,7,.2) 66%,transparent 86%);
  filter:blur(26px)}
html:not([data-theme="light"]) .hero-roles{color:rgba(var(--ink-rgb),.48)}
html:not([data-theme="light"]) .hero-roles span:first-child{color:rgba(var(--ink-rgb),.78)}
html:not([data-theme="light"]) .hero-say .ln:not(:last-child) .tw{opacity:.95}
html:not([data-theme="light"]) .hero-by{color:rgba(var(--ink-rgb),.72)}
html:not([data-theme="light"]) .hero-about-p{color:rgba(var(--ink-rgb),.8)}

/* ---- the light ----
   A warm pool where he stands and a cold falloff everywhere else, so the frame
   reads as a lit studio rather than a cutout dropped on black. It also lifts the
   background just enough that the hair edge reads as rim light.

   Every stop ends transparent, never at var(--bg). This plane sits in front of
   the wall, so an opaque final stop turns it into a sheet of page colour and the
   wall behind it is simply gone. That is exactly what it did on the light theme,
   where the paper colour made the loss obvious. */
.hero-glow{position:absolute;inset:-14%;z-index:0;pointer-events:none;
  background:
    radial-gradient(42% 40% at 50% 62%,var(--glow-warm),transparent 68%),
    radial-gradient(66% 58% at 50% 46%,var(--glow-mid),transparent 72%),
    radial-gradient(120% 88% at 50% 40%,var(--glow-deep),transparent 78%)}

/* ---- the two side panels ----
   He stands in the middle, so the copy takes the gutters. Both blocks share a
   top edge and a measure, and the hierarchy inside each is carried by weight
   rather than by size alone: small wide roles, heavy quote, light byline. */
/* Both blocks are placed off the figure, not off the page edges: each one starts
   exactly --side-gap from his silhouette. Pinned to the page edges instead, the
   gap is whatever is left over after the container, which is how it ended up at
   8px on a wide screen. Anchoring to the centre makes the two gutters identical
   by arithmetic and keeps them that way at every width.

   0.4523 is half the figure's aspect ratio (2871/3174), so --fig-half is half its
   rendered width without JS having to measure anything. */
.hero-stage{
  /* Three terms, and the third is the one that matters. The figure used to be
     sized off height alone, so a viewport that was tall for its width (every
     tablet in portrait, a 4:3 monitor, a short laptop rotated) grew him until
     the two copy columns had nowhere left to go and were pushed clean off both
     edges. The last term is the width budget: half the viewport, less a copy
     column, less the two gaps, less a page gutter, is the widest half-figure
     that still leaves the About block inside the page. Whichever is smallest
     wins, so the columns cannot clip at any aspect ratio.

     That gutter used to be a flat 1rem, which kept the copy on the page and
     nothing more. It read as a bug: between about 1260px and 1520px the budget
     is the binding term, so the quote and the About block ran right up to the
     frame, 31px from the left edge and 2px past the right one at 1280. It is a
     real gutter now, and the figure gives up the difference. Above 1520 the
     height term wins instead, so 1920 and every ultrawide are untouched. */
  /* Bigger than the margin it has to produce, on purpose. The budget is layout
     maths and the columns are not laid out flat: each sits on a rotated plane
     inside the 3D stage, so it paints about 10px wider than its box on the
     outer edge, and the budget's own 50vw overcounts by half a scrollbar. The
     extra covers both, so the measured margin lands near 25px rather than 5. */
  --hero-gutter:clamp(1.5rem,3.1vw,3rem);
  --fig-h:min(62svh,calc(80vw * 1.1055),
    calc((50vw - var(--side-w) - var(--side-gap) - var(--about-push)
          - var(--hero-gutter)) / .4523));
  --fig-half:calc(var(--fig-h) * .4523);
  --side-gap:clamp(1.5rem,3.4vw,4rem);
  --side-w:min(28rem,26vw);
  --about-push:clamp(1rem,2.6vw,3.2rem)}
.hero-quote,.hero-about{position:absolute;top:42svh;z-index:3;
  width:var(--side-w);pointer-events:none;isolation:isolate}
/* the ambient behind the two copy blocks. On the dark theme this comes free from
   the glow's falloff; on paper the falloff lands on white and disappears, so the
   warmth has to be placed under each block deliberately. */
.hero-quote::before,.hero-about::before{content:"";position:absolute;
  inset:-38% -30%;z-index:-1;pointer-events:none;
  background:radial-gradient(58% 54% at 50% 50%,var(--copy-warm),transparent 72%)}
.hero-quote{right:calc(50% + var(--fig-half) + var(--side-gap));left:auto}
/* the right block is pushed out past the left one on purpose: he reads the
   quote first and the About second, and the extra air gives that order */
.hero-about{left:calc(50% + var(--fig-half) + var(--side-gap) + var(--about-push));right:auto}

.hero-roles{display:flex;flex-direction:column;gap:.1rem;
  font-size:clamp(.66rem,.72vw,.78rem);letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-faint)}
/* the first role is the one he leads with, so it is the one that is set solid */
.hero-roles span:first-child{color:var(--ink-dim);font-weight:600}
.hero-roles .row i{font-style:normal;opacity:.45;margin-inline:.42em;font-weight:300}

.hero-say{margin-top:clamp(.9rem,1.8svh,1.3rem);
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.1rem,1.62vw,1.62rem);line-height:1.02;
  /* caps need positive tracking; the negative value that suits lowercase
     display type jams capitals together */
  letter-spacing:.014em;font-weight:800;
  color:var(--g3)}

/* ---- the quote's shape ----
   Three lines set identically read as a paragraph in caps. The setup is held
   back in plain ink and the payoff carries the gold, so the eye is told where
   the sentence lands. A short gold rule opens it, the way a pull-quote is
   marked in print. */
.hero-say .ln{display:block}
.hero-say .ln + .ln{margin-top:.16em}
.hero-say::before{content:"";display:block;
  width:clamp(1.8rem,3vw,2.6rem);height:2px;border-radius:2px;
  margin-bottom:clamp(.7rem,1.4svh,1.05rem);
  background:var(--grad)}
/* the setup lines: same size, less voltage */
.hero-say .ln:not(:last-child) .tw{
  background:none;-webkit-text-fill-color:currentColor;color:var(--ink);
  font-weight:700;opacity:.82}
/* The gradient is on the word, not on the heading. background-clip:text does not
   clip to text inside an inline-block descendant, so with the words wrapped for
   animation the whole headline painted as nothing. Per word it always renders,
   and at this tracking the ramp still reads as one continuous sweep. */
.hero-say .tw{display:inline-block;
  background:var(--grad);-webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent}
.hero-by{display:block;margin-top:.8rem;font-style:italic;
  font-size:clamp(.82rem,.94vw,1rem);font-weight:500;letter-spacing:.03em;
  color:var(--ink-dim)}

/* The "About Me" label above this is gone. It was naming what the paragraph
   already says in its first three words, and the block sits opposite the quote
   where nothing else is labelled either. The top margin goes with it, so the
   paragraph starts on the same line as the roles across the figure. */
/* Measured in ch, not px. A line wants roughly 45 characters to stay easy to
   scan, and at the block's full width this was running past 55 and reading as a
   slab. The block keeps its width so the two sides stay symmetric; only the
   paragraph's measure narrows. */
.hero-about-p{margin-top:0;max-width:33ch;
  font-size:clamp(.92rem,1.02vw,1.06rem);line-height:1.58;color:var(--ink-dim);
  font-weight:400}
/* the numbers are the only thing in the paragraph set solid, so they read as the
   claim and the rest reads as context */
.hero-about-p b{font-weight:600;color:var(--ink)}
.hero-about-p .w{display:inline-block;white-space:pre}

/* ---- him ----
   Centred without a transform, because the transform slot is spoken for by the
   depth. Lifted clear of the bottom so the ground copy gets its own air instead of
   landing on the brain, which is the one thing in the frame worth looking at.
   Height is capped by width as well, so the figure never outgrows a phone.

   The mask goes on the image, not on the figure: the figure has to stay a
   preserve-3d box for the labels' depth, and the coat needs to dissolve rather
   than end on the hard horizontal edge the cutout was cropped at. */
.hero-figure{position:absolute;bottom:16svh;left:0;right:0;margin-inline:auto;z-index:2;
  height:var(--fig-h);aspect-ratio:2871/3174;
  pointer-events:none}
.hero-amal{width:100%;height:100%;object-fit:contain;object-position:bottom;display:block;
  filter:saturate(1.02) contrast(1.02);
  /* the brain reaches 81.9% down the cutout, so the dissolve cannot start before
     that or it eats the one thing worth looking at */
  -webkit-mask-image:linear-gradient(180deg,#000 84%,transparent 100%);
          mask-image:linear-gradient(180deg,#000 84%,transparent 100%)}

/* ---- the brain ----
   Measured off the cutout: centre 51.6% x 74.1%, spanning 37.5 to 63.9 across.
   Screen blend so it adds light to what is already there rather than laying a
   disc of colour on top of him, and a slow breath so it reads as lit, not drawn. */
.hero-brainglow{position:absolute;left:51.6%;top:74.1%;translate:-50% -50%;
  width:52%;aspect-ratio:1;border-radius:50%;pointer-events:none;z-index:1;
  mix-blend-mode:screen;
  background:radial-gradient(circle,
    rgba(255,236,178,.5) 0%,rgba(247,201,92,.34) 26%,
    rgba(232,166,44,.16) 46%,transparent 68%);
  animation:brainbreathe 4.2s var(--ease) infinite alternate}
@keyframes brainbreathe{
  from{opacity:.62;scale:.94}
  to  {opacity:1;  scale:1.06}}

/* ---- the embers ----
   Seven specks drifting off the brain. Sized in vw so they stay specks rather
   than growing into dots on a large screen, and each one carries its own delay,
   drift and duration, because seven things on the same clock read as a machine.
   Pure CSS: this is decoration, and decoration should not own a frame budget. */
.hero-sparks{position:absolute;left:51.6%;top:74.1%;translate:-50% -50%;
  width:34%;aspect-ratio:1;pointer-events:none;z-index:1;mix-blend-mode:screen}
.hero-sparks i{position:absolute;left:50%;top:56%;
  width:clamp(1.5px,.16vw,3px);aspect-ratio:1;border-radius:50%;
  background:#ffe9ae;box-shadow:0 0 6px 1px rgba(255,214,120,.8);
  opacity:0;animation:ember var(--d,5s) var(--ease) var(--t,0s) infinite}
.hero-sparks i:nth-child(1){--x:-46px;--y:-92px;--d:5.4s;--t:.2s}
.hero-sparks i:nth-child(2){--x:38px; --y:-104px;--d:6.2s;--t:1.1s}
.hero-sparks i:nth-child(3){--x:-14px;--y:-120px;--d:4.8s;--t:2.4s}
.hero-sparks i:nth-child(4){--x:62px; --y:-70px; --d:6.8s;--t:3.3s}
.hero-sparks i:nth-child(5){--x:-66px;--y:-64px; --d:5.9s;--t:4.1s}
.hero-sparks i:nth-child(6){--x:18px; --y:-134px;--d:7.2s;--t:1.8s}
.hero-sparks i:nth-child(7){--x:-30px;--y:-52px; --d:5.1s;--t:5.2s}
@keyframes ember{
  0%      {opacity:0;   translate:0 0;                 scale:.5}
  12%     {opacity:.95;                                scale:1}
  70%     {opacity:.5}
  100%    {opacity:0;   translate:var(--x) var(--y);   scale:.35}}
@media(prefers-reduced-motion:reduce){
  .hero-sparks{display:none}
  .hero-brainglow{animation:none;opacity:.85}}

/* ---- the four labels ----
   Positions are the reference composite's geometry, converted from canvas
   percentages to percentages of the figure box, so the arrangement he drew holds
   at every viewport width. In front of him in z, exactly as in the reference. */
.hero-tag{position:absolute;height:auto;display:block;
  filter:drop-shadow(0 10px 26px rgba(0,0,0,.5))}
.t-think{left:11.11%;top:29.08%;width:21.59%}
.t-plan {left:0.00%; top:53.59%;width:21.00%}
.t-edit {left:73.21%;top:34.53%;width:21.87%}
.t-grow {left:78.05%;top:54.76%;width:19.92%}

/* ---- the ground copy ----
   Sits in the clear band under him. It still carries a light scrim, because the
   coat's dissolve lands just above it and the last of it should not compete with
   the sub-line. */
.hero-ground{position:absolute;left:0;right:0;bottom:clamp(6rem,15svh,10rem);z-index:3;
  padding-inline:var(--edge);text-align:center}
.hero-ground::before{content:"";position:absolute;left:-10vw;right:-10vw;
  top:-120%;bottom:-560%;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,transparent,var(--scrim-1) 44%,
             var(--scrim-2) 70%,var(--scrim-3) 100%)}
.hero-act{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:.8rem}
/* ---- the shiny button ----
   Three separate pieces of light, which is what the reference is actually doing:

     1. a stroke travelling round the perimeter. The ring is a conic gradient
        painted over the whole button and then masked down to a 2px band by
        XOR-ing a content-box fill against a border-box fill. Only the difference
        between the two survives, which is the border. The arc moves by animating
        the gradient's own start angle, not by rotating the element, because
        rotating a pill-shaped box would swing the outline round with it.
     2. a specular band sweeping across the face, under the label.
     3. a gold glow beneath the whole thing.

   --ring-a has to be registered with @property or it is just a string to the
   animation engine and will not interpolate. */
@property --ring-a{ syntax:'<angle>'; initial-value:0deg; inherits:false }

.hero-act .btn-gold{position:relative;overflow:hidden;isolation:isolate;
  padding:1.25rem 4rem;font-size:1.12rem;font-weight:650;
  min-width:clamp(260px,24vw,340px);justify-content:center;border:0;
  box-shadow:0 0 0 1px var(--gold-rim),0 0 26px 2px rgba(212,165,60,.36),
             0 10px 30px rgba(212,165,60,.2),0 14px 40px var(--shadow-deep);
  animation:ctaglow 3.4s var(--ease) infinite alternate;
  transition:scale .4s var(--ease)}
.hero-act .btn-gold:hover{scale:1.03}
.btn-label{position:relative;z-index:1}

.btn-ring{--ring-a:0deg;
  position:absolute;inset:0;border-radius:inherit;z-index:0;pointer-events:none;
  padding:2px;
  background:conic-gradient(from var(--ring-a),
    transparent 0deg,rgba(255,252,240,.15) 22deg,#fffdf3 58deg,
    rgba(255,252,240,.15) 94deg,transparent 128deg,transparent 360deg);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  animation:btnring 2.8s linear infinite}
@keyframes btnring{ to{ --ring-a:360deg } }

.hero-act .btn-gold::after{content:"";position:absolute;top:-60%;bottom:-60%;
  width:34%;z-index:0;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.7),transparent);
  transform:skewX(-22deg);
  animation:ctashine 3.6s cubic-bezier(.55,0,.35,1) infinite}
@keyframes ctashine{
  0%      {left:-45%}
  55%,100%{left:125%}}
@keyframes ctaglow{
  from{box-shadow:0 0 0 1px var(--gold-rim),0 0 20px 1px rgba(212,165,60,.26),
                  0 10px 30px rgba(212,165,60,.16),0 14px 40px var(--shadow-deep)}
  to  {box-shadow:0 0 0 1px var(--gold-rim),0 0 38px 4px rgba(212,165,60,.5),
                  0 10px 34px rgba(212,165,60,.3),0 14px 40px var(--shadow-deep)}}
@media(prefers-reduced-motion:reduce){
  .hero-act .btn-gold{animation:none}
  .hero-act .btn-gold::after,.btn-ring{animation:none}
}
.hero-cta-ico{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;
  flex:0 0 auto;background:rgba(20,16,6,.16);border:1px solid rgba(20,16,6,.22);
  transition:transform .5s var(--ease)}
.btn-gold:hover .hero-cta-ico{transform:translateX(3px)}

/* scroll cue: a hairline that fills, not an arrow that bounces. Parked in the
   corner rather than centred, because the centre now belongs to the CTA. */
.hero-scroll{position:absolute;right:clamp(1rem,3vw,2.4rem);bottom:clamp(1rem,2.6svh,1.8rem);z-index:4;
  display:flex;flex-direction:column;align-items:center;gap:.6rem;
  font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-faint);
  pointer-events:none}
.hero-scroll i{display:block;width:1px;height:44px;background:rgba(var(--ink-rgb),.14);overflow:hidden}
.hero-scroll i::after{content:"";display:block;width:100%;height:40%;background:var(--g3);
  animation:scrollcue 2.6s var(--ease) infinite}
@keyframes scrollcue{0%{transform:translateY(-100%)}60%,100%{transform:translateY(250%)}}

/* ---- TABLET: the same column a phone gets, at tablet size ----
   Three columns need roughly 71vw of copy, gaps and padding before the figure
   gets a pixel, so under about 1180px there is no arrangement of them that both
   fits and looks like anything. Squeezing was what broke it: the quote and the
   About block were sitting most of the way off the left and right edges on every
   iPad. A tablet has height to spare, so it gets the phone's stack, sized in rem
   rather than vw because 3vw of type on a 1024px screen is a headline. */
@media(min-width:681px) and (max-width:1179px){
  .hero{overflow:clip}
  .hero-stage{height:auto;min-height:0;display:flex;flex-direction:column;
    align-items:center;gap:clamp(1rem,2.2svh,1.6rem);
    padding:clamp(6rem,11svh,7.5rem) var(--edge) clamp(2.5rem,5svh,4rem)}

  .hero-quote,.hero-about,.hero-ground{position:relative;inset:auto;
    width:100%;text-align:center}
  .hero-figure{position:relative;inset:auto;margin-inline:auto;
    width:auto;height:min(42svh,calc(46vw * 1.1055))}

  .hero-quote {order:1}
  .hero-figure{order:2}
  .hero-about {order:3}
  .hero-ground{order:4}

  .hero-roles{flex-direction:row;flex-wrap:wrap;justify-content:center;
    gap:.25rem .9rem;font-size:.72rem;letter-spacing:.18em}
  .hero-say{font-size:clamp(1.5rem,3.2vw,2.2rem);line-height:1.06}
  .hero-say::before{margin-inline:auto}
  .hero-about-p{max-width:56ch;margin-inline:auto;margin-top:0;
    font-size:clamp(.9rem,1.35vw,1.02rem);line-height:1.55}
  .hero-quote::before,.hero-about::before{inset:-24% -12%}

  .hero-ground::before{display:none}
  .hero-act{justify-content:center}
  .hero-scroll{display:none}
}
/* ---- The same stack, on a tablet lying down ----
   Every viewport in the band above was treated as though it had a portrait's
   height to spend. It does not: a tablet in landscape is 768 to 834 tall, and
   the column as sized above needs about 838, so the button was sliced in half
   by the bottom edge on an iPad landscape, a 1024x768 laptop and an 11in iPad
   at 1179x820. The button is the only thing the hero is asking anyone to do,
   so it does not get to fall below the fold. The figure gives back the height:
   32svh instead of 42, and the paddings and gaps come in with it. The cutoff
   is 900px because tablet portrait heights start at 1024 and landscape ones
   stop at 834, so nothing real sits near the boundary. */
@media(min-width:681px) and (max-width:1179px) and (max-height:900px){
  .hero-stage{gap:clamp(.7rem,1.5svh,1.1rem);
    padding:clamp(4.5rem,8.5svh,5.5rem) var(--edge) clamp(1.5rem,3svh,2.2rem)}
  .hero-figure{height:min(32svh,calc(40vw * 1.1055))}
  .hero-say{font-size:clamp(1.35rem,2.8vw,1.9rem)}
  .hero-about-p{font-size:clamp(.85rem,1.2vw,.95rem);line-height:1.5}
}
/* Below this the figure is nearly the full width, so there are no gutters left to
   flank it with. The whole stage drops out of absolute positioning and becomes a
   normal column: quote, him, About, button. Positioned absolutely with fixed
   percentage tops, the four blocks were landing on top of each other, roughly
   20px of the quote sitting on his head and another 20 of About on his coat.
   In flow they cannot overlap, whatever the phone's height turns out to be. */
@media(max-width:680px){
  .hero{overflow:clip}
  /* the column is budgeted against one screen: nav clearance, quote, him,
     About, button, all inside the first frame with the button whole. Every
     value here was taken down until that held on a 390x700 visible viewport,
     which is a 844pt phone with the browser bars showing. */
  .hero-stage{height:auto;min-height:0;display:flex;flex-direction:column;
    align-items:center;gap:clamp(.6rem,1.6svh,1rem);
    padding:clamp(4.6rem,10.5svh,5.8rem) var(--edge) clamp(1.4rem,3svh,2rem)}

  .hero-quote,.hero-about,.hero-ground{position:relative;inset:auto;
    width:100%;text-align:center}
  .hero-figure{position:relative;inset:auto;margin-inline:auto;
    width:auto;height:min(28svh,calc(58vw * 1.1055))}
  /* DOM order is quote, About, him, because that is what the desktop columns
     need. On a phone he belongs in the middle: the claim, the man, the detail,
     the button. */
  .hero-quote {order:1}
  .hero-figure{order:2}
  .hero-about {order:3}
  .hero-ground{order:4}

  /* The two role lines read as one stacked label, not two separate lines, so the
     row gap is almost nothing and the line height is set tight enough that the
     descenders of the first line nearly meet the caps of the second. The block
     also sits lower than the nav capsule wants it to: at 393px the capsule ends
     at 81px and the label was starting at 84, close enough to look like a
     collision. The top margin buys it clear air. */
  .hero-roles{flex-direction:row;flex-wrap:wrap;justify-content:center;
    gap:0 .7rem;line-height:1.12;margin-top:clamp(.7rem,2.4svh,1.35rem);
    font-size:.64rem;letter-spacing:.14em}
  /* sized so the longest authored line still fits one row at 390px; any larger
     and "GREAT CONTENT ISN'T LUCK," breaks in two and the three-line shape,
     which is the whole point of the setting, becomes four */
  .hero-say{font-size:clamp(1.05rem,5.3vw,1.5rem);line-height:1.06}
  .hero-say::before{margin-inline:auto}
  .hero-say .ln + .ln{margin-top:.12em}
  /* the About block pays for the button. On a phone the whole hero has to land
     inside one screen, ending on "Work with me", and this paragraph was the one
     element still set at desktop size. Smaller body, tighter leading, and now
     one sentence longer: enough to keep the CTA in the first frame without the
     paragraph reading as fine print. */
  .hero-about-p{max-width:36ch;margin-inline:auto;margin-top:0;
    font-size:clamp(.74rem,3.15vw,.83rem);line-height:1.44}
  .hero-quote::before,.hero-about::before{inset:-20% -14%}

  /* the ground copy carried a scrim sized for the desktop overlap it no longer has */
  .hero-ground::before{display:none}
  .hero-act{flex-direction:column;align-items:stretch}
  .hero-act .btn-gold{width:100%;min-width:0;justify-content:center;padding-inline:1.5rem}
  .hero-scroll{display:none}
}

/* ============ WORKED WITH ============
   Faces and marks in circles, because most of these are people, and a circle is
   what a person's picture wants to be.

   The gold ring is a real gradient, not a border. border-image does not follow a
   border-radius, so the ring is the parent's background showing through 2px of
   padding: the only way to get a gradient stroke on a circle without an SVG.

   No panel, no rules, no background of its own. This used to be a boxed strip
   between the hero and the work, and the box was the thing you could see. It sits
   on the page now and the row simply dissolves at both ends. */
/* Off-canvas rather than display:none, because a heading that is not rendered is
   also not read and not counted. Used for the two sections whose heading is
   carried by the numbers themselves and would be noise on screen. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

.worked{position:relative;z-index:2;padding:clamp(3rem,7vh,4.6rem) 0}
/* it is an h2 for the outline's sake, so the two things the UA sheet gives an h2
   and this label does not want, a top margin and bold weight, are taken back */
.worked-l{text-align:center;margin:0 0 clamp(1.8rem,3.4vh,2.6rem);
  padding-inline:var(--edge);font-weight:500;
  font-size:clamp(.68rem,.78vw,.8rem);letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-faint)}

/* The fade is a mask on the row itself, so the circles go to nothing rather than
   sliding under a tinted panel. A coloured overlay was what put a dark band at
   each end and made the edges visible in the first place. The ramp is long and
   starts early, so a face is already half gone before you notice it leaving. */
/* The padding is what stops a hovered circle being sliced. It scales to 1.07,
   and with the box hugging the row exactly, overflow clipped the extra off the
   top and bottom. The padding gives that growth somewhere to go. */
.marquee{position:relative;overflow:hidden;
  width:min(1080px,92vw);margin-inline:auto;
  padding-block:clamp(6px,1vw,10px);
  -webkit-mask-image:linear-gradient(90deg,transparent 0%,rgba(0,0,0,.35) 8%,
                     #000 26%,#000 74%,rgba(0,0,0,.35) 92%,transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0%,rgba(0,0,0,.35) 8%,
                     #000 26%,#000 74%,rgba(0,0,0,.35) 92%,transparent 100%)}
.marquee-row{display:flex;align-items:center;list-style:none;
  gap:clamp(1.1rem,2.2vw,2rem);width:max-content;will-change:transform}

.mq-item{flex:0 0 auto;padding:2px;border-radius:50%;
  width:clamp(62px,6.6vw,96px);aspect-ratio:1;
  background:var(--grad);
  transition:scale .5s var(--ease)}
.mq-item img{width:100%;height:100%;border-radius:50%;object-fit:cover;display:block;
  background:var(--well-2)}
.mq-item:hover{scale:1.07}

/* ---- the haze ----
   Backdrop blur with no colour behind it, masked so the blur itself ramps up
   toward the edge. Blur and fade land together, which is what makes a face look
   like it is dissolving rather than being covered. */
/* The blur panes carried a hard top and bottom edge, which read as two faint
   bands at each end of the row. A second mask on the vertical axis, intersected
   with the horizontal one, fades those edges out so the pane has no boundary
   anywhere. */
.mq-haze{position:absolute;top:0;bottom:0;width:clamp(70px,14vw,220px);
  pointer-events:none;z-index:2;
  backdrop-filter:blur(5px);-webkit-backdrop-filter:blur(5px);
  -webkit-mask-composite:source-in;mask-composite:intersect}
.mq-haze-l{left:0;
  -webkit-mask-image:linear-gradient(90deg,#000 0%,rgba(0,0,0,.55) 42%,transparent 100%),
                     linear-gradient(180deg,transparent 0%,#000 16%,#000 84%,transparent 100%);
          mask-image:linear-gradient(90deg,#000 0%,rgba(0,0,0,.55) 42%,transparent 100%),
                     linear-gradient(180deg,transparent 0%,#000 16%,#000 84%,transparent 100%)}
.mq-haze-r{right:0;
  -webkit-mask-image:linear-gradient(270deg,#000 0%,rgba(0,0,0,.55) 42%,transparent 100%),
                     linear-gradient(180deg,transparent 0%,#000 16%,#000 84%,transparent 100%);
          mask-image:linear-gradient(270deg,#000 0%,rgba(0,0,0,.55) 42%,transparent 100%),
                     linear-gradient(180deg,transparent 0%,#000 16%,#000 84%,transparent 100%)}

@media(prefers-reduced-motion:reduce){ .marquee-row{flex-wrap:wrap;width:auto;justify-content:center} }
@media(max-width:680px){ .worked-l{margin-bottom:1.4rem} }

/* ============ SHARED HEADINGS ============ */
/* same size-specific tracking as the hero headline, on this heading's own curve */
.h2{font-family:var(--display);font-weight:600;line-height:.98;font-size:clamp(2.2rem,5.5vw,4.6rem);
  letter-spacing:clamp(-.038em,calc(-.02em - .13vw),-.02em)}
.h2.center{text-align:center}
.lead{color:var(--ink-dim);font-size:clamp(1rem,1.6vw,1.2rem);max-width:44ch;line-height:1.55}
.section-head{display:flex;flex-direction:column;align-items:center;gap:1rem;margin-bottom:3rem;text-align:center}

/* ============ WORK ============ */
.work{padding-block:12vh;padding-inline:var(--edge)}
.sf-head{display:flex;align-items:center;justify-content:space-between;margin:0 0 1rem}
.lf-head{margin-top:4.5rem}
.tag-pill{display:inline-flex;align-items:center;gap:.5rem;font-size:.8rem;font-weight:600;letter-spacing:.02em;
  padding:.4rem .9rem;border-radius:100px;border:1px solid var(--glass-brite);background:var(--glass);backdrop-filter:blur(12px)}
.drag-hint{font-size:.82rem;letter-spacing:.012em;color:var(--ink-faint)}

/* ---- CARD-FAN CAROUSEL ----
   Each slot rotates about a pivot far BELOW the card (--fan-pivot). That one
   origin produces the fan angle and the arc drop together, exactly like cards
   held in a hand. Scale lives on the inner .fan-card so it pivots about its own
   centre instead of the far origin. */
/* Card is ~19vw to match the reference. The fan spans ~4.5x a card at 3 a side,
   so the step drops to 7deg, at 8.7 a card this big overran the container. */
.fan{--fan-w:clamp(180px,19vw,286px);--fan-step:7deg;--fan-pivot:282%;
  position:relative;width:100%;margin-top:1rem;outline:none;touch-action:pan-y;
  /* guard: clip sideways only, so a wide fan can never push the page horizontally
     while the cards' arc and shadows still overflow vertically */
  overflow-x:clip;overflow-y:visible}
.fan-track{position:relative;height:calc(var(--fan-w) * 16 / 9 * 1.3);
  cursor:grab;user-select:none}
.fan.dragging .fan-track{cursor:grabbing}

/* JS sets --rot / --sc / --dim; :hover layers --lift and --pop on top, so a
   hover never has to fight the inline transform that positions the fan */
.fan-slot{position:absolute;left:50%;top:0;width:var(--fan-w);
  margin-left:calc(var(--fan-w) / -2);transform-origin:50% var(--fan-pivot);
  transform:rotate(var(--rot,0deg));
  transition:transform .78s var(--ease),opacity .5s var(--ease);will-change:transform}
/* Once script.js takes over, the rotation is written every frame by a spring
   that carries the finger's release velocity, so a CSS transition on the same
   property can only fight it, and a transition cannot be grabbed and reversed
   mid-flight, which is the whole point of the drag. Opacity keeps its ease. */
.fan.is-live .fan-slot{transition:opacity .5s var(--ease)}
/* while the finger is down the card tracks 1:1, no smoothing on the scale */
.fan.dragging .fan-card{
  transition:filter .4s var(--ease),box-shadow .4s var(--ease),border-color .4s}
/* press feedback on pointer-down, not on release */
.fan-card:active{--pop:.985;transition:transform .1s ease-out}
.fan-card{position:relative;width:100%;aspect-ratio:9/16;border-radius:22px;overflow:hidden;
  background:var(--bg);transform-origin:50% 50%;
  transform:translateY(var(--lift,0px)) scale(calc(var(--sc,1) * var(--pop,1)));
  filter:brightness(var(--dim,1));
  border:1px solid rgba(var(--hi-rgb),.10);
  box-shadow:0 2px 6px rgba(0,0,0,.4),0 18px 40px rgba(0,0,0,.45),0 40px 80px rgba(0,0,0,.35);
  transition:transform .5s var(--ease),filter .4s var(--ease),box-shadow .4s var(--ease),border-color .4s}
.fan-card video{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none}
.fan-slot.is-active .fan-card{border-color:rgba(242,217,138,.42);
  box-shadow:0 2px 6px rgba(0,0,0,.4),0 22px 50px rgba(0,0,0,.5),0 0 90px rgba(212,165,60,.28)}
.fan-slot.is-hidden{opacity:0;pointer-events:none}

/* A small nudge under the cursor, nothing more. There is deliberately NO
   z-index bump here: script.js gives the centre slot the highest z (90 - 10a),
   and the old `z-index:70!important` overrode that, so hovering a side reel
   threw it in front of the centre one. The centre card now always wins. */
@media(hover:hover) and (pointer:fine){
  .fan-slot:hover .fan-card{--lift:-9px;--pop:1.025;--dim:1;
    border-color:rgba(242,217,138,.5);
    box-shadow:0 4px 10px rgba(0,0,0,.45),0 16px 34px rgba(0,0,0,.45),0 0 60px rgba(212,165,60,.22)}
}

/* The cards carry no label now: the work speaks without a caption over it, and
   the bottom scrim only existed to make that caption readable. */
/* centre play/pause, always visible while paused, on hover while playing */
.fan-play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:4;
  width:56px;height:56px;border-radius:50%;display:grid;place-items:center;cursor:pointer;color:#fff;
  border:1px solid rgba(var(--hi-rgb),.45);background:rgba(var(--panel-rgb),.5);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  opacity:0;transition:opacity .3s var(--ease),transform .35s var(--ease),background .3s}
.fan-play:hover{background:rgba(163,118,31,.6);transform:translate(-50%,-50%) scale(1.1)}
.fan-play .ico-pause{display:none}
.fan-play.on .ico-pause{display:block}.fan-play.on .ico-play{display:none}
.fan-play .ico-play{margin-left:3px}
.fan-slot.is-active.is-paused .fan-play{opacity:1}
@media(hover:hover) and (pointer:fine){ .fan-slot.is-active:hover .fan-play{opacity:1} }

.fan-sound{position:absolute;top:12px;right:12px;z-index:5;width:34px;height:34px;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;color:#fff;opacity:0;transform:scale(.8);
  border:1px solid rgba(var(--hi-rgb),.25);background:rgba(var(--panel-rgb),.5);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  transition:opacity .35s var(--ease),transform .35s var(--ease),background .3s}
.fan-slot.is-active .fan-sound{opacity:1;transform:scale(1)}
.fan-sound:hover{background:rgba(163,118,31,.6)}
.fan-sound .ico-sound{display:none}
.fan-sound.on .ico-sound{display:block}.fan-sound.on .ico-muted{display:none}

/* controls */
.fan-ui{display:flex;align-items:center;justify-content:center;gap:1rem;margin-top:1.4rem}
.fan-btn{width:2.1rem;height:2.1rem;display:grid;place-items:center;padding:0;cursor:pointer;
  border-radius:50%;border:1px solid rgba(var(--ink-rgb),.18);background:rgba(var(--hi-rgb),.04);color:var(--ink);
  transition:transform .25s cubic-bezier(.22,1,.36,1),border-color .25s,background .25s}
.fan-btn svg{width:.85rem;height:.85rem;opacity:.8}
.fan-btn:hover{transform:scale(1.1);border-color:var(--g2);background:rgba(212,165,60,.14)}
.fan-btn:active{transform:scale(.94)}
.fan-dots{display:flex;align-items:center;gap:.45rem}
.fan-dot{width:6px;height:6px;padding:0;border:none;border-radius:50%;cursor:pointer;
  background:rgba(var(--ink-rgb),.26);transition:.35s var(--ease)}
.fan-dot.on{width:20px;border-radius:100px;background:var(--grad)}

/* play / mute / tag, live inside .iphone-media */
.pf-play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:4;width:58px;height:58px;
  border-radius:50%;border:1px solid rgba(var(--hi-rgb),.5);cursor:pointer;color:#fff;display:grid;place-items:center;
  background:rgba(var(--panel-rgb),.55);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);padding-left:3px;
  transition:transform .4s var(--ease),opacity .35s var(--ease),background .3s}
.pf-play:hover{transform:translate(-50%,-50%) scale(1.12);background:rgba(163,118,31,.60)}
.is-playing .pf-play{opacity:0;pointer-events:none;transform:translate(-50%,-50%) scale(.6)}
.pf-mute{position:absolute;top:12px;right:12px;z-index:4;width:34px;height:34px;border-radius:50%;
  border:1px solid rgba(var(--hi-rgb),.25);cursor:pointer;color:#fff;display:grid;place-items:center;
  background:rgba(var(--panel-rgb),.50);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  opacity:0;transform:scale(.8);transition:.35s var(--ease)}
.sf-item:hover .pf-mute,.lf-card:hover .pf-mute,.is-playing .pf-mute{opacity:1;transform:scale(1)}
.pf-mute .ico-sound{display:none}
.pf-mute.on .ico-sound{display:block}.pf-mute.on .ico-muted{display:none}

/* LONG-FORM landscape grid, uniform 16:9 cards, first is full-width feature */
/* capped and centred, full-bleed 16:9 pairs were overwhelming the page */
/* three up, two rows, for the six long-form pieces. The measure widens with the
   column count or each card ends up too small to read a face in. */
.lf-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(.8rem,1.4vw,1.15rem);
  width:100%;max-width:1240px;margin-inline:auto}
@media(max-width:900px){ .lf-grid{grid-template-columns:repeat(2,1fr)} }
@media(max-width:560px){ .lf-grid{grid-template-columns:1fr} }
/* The arrows belong to the swipe track, and the track only exists under 680px.
   Above that the grid never overflows, so the pair sat under the row doing
   nothing at all. Hidden by default, the mobile block turns them back on. */
.lf-nav{display:none}
.lf-card{position:relative;border-radius:16px;overflow:hidden;border:1px solid var(--line);
  transition:box-shadow .5s var(--ease),transform .5s var(--ease)}
.lf-card:hover{transform:translateY(-4px);box-shadow:0 30px 70px rgba(212,165,60,.30);border-color:rgba(242,217,138,.45)}
.lf-screen{position:relative;width:100%;aspect-ratio:16/9;background:var(--well)}
.lf-screen video{width:100%;height:100%;object-fit:cover;display:block}
.lf-card .pf-play{width:54px;height:54px}
.lf-card .pf-mute{z-index:5}

/* ============ STATS ============ */
.stats-wrap{padding-block:9vh;padding-inline:var(--edge);border-top:1px solid var(--line)}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:2rem 1rem;
  width:100%;max-width:1000px;margin-inline:auto;text-align:center}
/* block, not column-flex, the number and its suffix must share one line */
.stat{display:block}
/* the figure carries the weight, the label underneath stays quiet */
.stat-n{font-family:var(--display);font-weight:800;font-size:clamp(2.6rem,6vw,4.6rem);letter-spacing:-.035em;line-height:1;display:inline}
.stat-suffix{font-family:var(--display);font-weight:800;font-size:clamp(1.4rem,3vw,2.2rem);margin-left:3px;letter-spacing:-.02em}
.stat p{color:var(--ink-dim);font-size:.86rem;margin-top:.6rem;letter-spacing:.055em;
  text-transform:uppercase;font-weight:500}

/* ============ PROCESS (bento) ============ */
.proc{padding-block:12vh 2vh;padding-inline:var(--edge)}
.proc .section-head{margin-bottom:3.4rem}
/* 6 tracks so the top row splits 2-2-2 and the bottom row 3-3.
   perspective lives here so each card can lean toward the cursor. */
.proc-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:1rem;
  width:100%;max-width:1180px;margin-inline:auto;perspective:1400px}
.proc-card{grid-column:span 2;position:relative;isolation:isolate;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:2.2rem 1.8rem 2.1rem;border-radius:20px;border:1px solid var(--line);
  background:linear-gradient(180deg,rgba(var(--hi-rgb),.05),rgba(var(--hi-rgb),.014));
  transform-style:preserve-3d;will-change:transform;
  transition:border-color .5s var(--ease),box-shadow .5s var(--ease)}
/* liquid-glass specular, a soft lens that tracks the pointer across the card */
.proc-card::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  opacity:0;transition:opacity .45s var(--ease);
  background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),
    rgba(var(--hi-rgb),.09),rgba(242,217,138,.045) 42%,transparent 68%)}
@media(hover:hover) and (pointer:fine){
  .proc-card:hover{border-color:var(--glass-brite);
    box-shadow:0 26px 60px rgba(0,0,0,.42),0 0 60px rgba(212,165,60,.10)}
  .proc-card:hover::after{opacity:1}
}
.proc-step{position:absolute;top:1.25rem;left:1.4rem;z-index:2;
  font-size:.66rem;font-weight:600;letter-spacing:.2em;color:var(--ink-faint)}

/* ---- artwork frame ---- */
.proc-art{position:relative;display:grid;place-items:center;
  width:100%;height:170px;margin-bottom:1.65rem;flex:0 0 auto;
  transform-style:preserve-3d;will-change:transform}
/* shared look for every animated scene: thin white line art, no fills */
/* Two weights across every scene in this section: --proc-outline for the shape
   that holds the object, --proc-inline for everything drawn inside it. The
   default here stays at the mid weight, so small standalone marks that are
   their own outline (the drifting platform bubbles) are unaffected. */
.proc-scene{--proc-outline:2.7;--proc-inline:1.15;
  color:var(--ink);fill:none;stroke:currentColor;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;overflow:visible}
.proc-scene .fill{fill:currentColor;stroke:none}

/* ---- 01 · phone, hunting magnifier, drifting platform bubbles ---- */
.sc1{width:auto;height:152px}
/* Only the outer shell of each scene carries the heavy stroke. Everything
   drawn inside it steps down to --proc-inline, so the object reads as one
   silhouette with detail in it rather than a tangle of equal lines. The
   magnifier is the exception: it is the point of the drawing, not detail. */
.sc1-phone{opacity:.92;stroke-width:var(--proc-outline)}
.sc1-notch{stroke-width:var(--proc-inline);opacity:.5}
.sc1-hair{fill:currentColor;stroke:none;opacity:.45}
.sc1-media{fill:rgba(var(--hi-rgb),.085);stroke:rgba(var(--ink-rgb),.4);stroke-width:1.2}
.sc1-head{stroke-width:1.5;opacity:.8}
.sc1-rail circle{fill:currentColor;stroke:none;opacity:.6}
.sc1-av{stroke-width:1.3;opacity:.75}
/* four reels, the last a copy of the first, so the reset never shows */
.sc1-feed{animation:sc1Scroll 9s cubic-bezier(.6,0,.25,1) infinite}
@keyframes sc1Scroll{
  0%,20%  {transform:translateY(0)}
  25%,45% {transform:translateY(-86px)}
  50%,70% {transform:translateY(-172px)}
  75%,100%{transform:translateY(-258px)}}
.sc1-bub{stroke:rgba(var(--ink-rgb),.2);fill:rgba(var(--hi-rgb),.035)}
.sc1-mark{opacity:.72;stroke-width:2.6}
.sc1-float{transform-box:fill-box;transform-origin:center}
.sc1-f1{animation:sc1Drift 7.5s ease-in-out infinite}
.sc1-f2{animation:sc1Drift 9s ease-in-out infinite -3s}
.sc1-f3{animation:sc1Drift 8.2s ease-in-out infinite -5.5s}
@keyframes sc1Drift{
  0%  {transform:translate(0,0)}
  33% {transform:translate(2.5px,-6px)}
  66% {transform:translate(-3px,-2px)}
  100%{transform:translate(0,0)}}
/* bolder rim so it reads as glass over the feed */
.sc1-mag{stroke-width:2.7;opacity:.98;
  animation:sc1Hunt 6.5s cubic-bezier(.45,0,.25,1) infinite}
.sc1-glint{stroke-width:1.6;opacity:.55}
@keyframes sc1Hunt{
  0%,14%  {transform:translate(-13px,-17px) scale(.93)}
  26%,38% {transform:translate(11px,-13px) scale(1)}
  52%,62% {transform:translate(13px,13px) scale(.96)}
  76%,86% {transform:translate(-11px,16px) scale(1.02)}
  100%    {transform:translate(-13px,-17px) scale(.93)}}

/* ---- 02 · sheet drifts while three hooks type in ---- */
.sc2-wrap{display:grid;place-items:center;width:100%}
.sc2{width:auto;height:150px}
/* no fold, it just breathes, and the page stays open the whole loop */
.sc2-sheet{transform-box:fill-box;transform-origin:center;
  animation:sc2Float 7s ease-in-out infinite}
@keyframes sc2Float{
  0%  {transform:translateY(0) rotate(0deg)}
  50% {transform:translateY(-5px) rotate(-.8deg)}
  100%{transform:translateY(0) rotate(0deg)}}
.sc2-page{stroke-width:var(--proc-outline)}
.sc2-h{font-family:var(--sans);font-size:8.2px;font-weight:600;letter-spacing:.07em;
  fill:currentColor;stroke:none}
.sc2-l{fill:currentColor;stroke:none;opacity:.4}
.sc2-caret{fill:currentColor;stroke:none;
  animation:sc2Caret 11s steps(1,end) infinite,sc2Blink .9s steps(1,end) infinite}
.sc2-body{animation:sc2Body 11s linear infinite}
@keyframes sc2Body{0%,2%{opacity:0}5%,93%{opacity:1}98%,100%{opacity:0}}
@keyframes sc2Blink{0%,50%{opacity:1}51%,100%{opacity:.15}}
/* every reveal animates the SVG `width`, so caret and text finish on one frame */
@keyframes sc2WA{0%,4%{width:0}11%,100%{width:38px}}
@keyframes sc2L1{0%,12%{width:0}18%,100%{width:44px}}
@keyframes sc2L2{0%,19%{width:0}25%,100%{width:34px}}
@keyframes sc2WB{0%,30%{width:0}37%,100%{width:38px}}
@keyframes sc2L3{0%,38%{width:0}44%,100%{width:46px}}
@keyframes sc2L4{0%,45%{width:0}51%,100%{width:36px}}
@keyframes sc2WC{0%,56%{width:0}63%,100%{width:38px}}
@keyframes sc2L5{0%,64%{width:0}70%,100%{width:42px}}
@keyframes sc2L6{0%,71%{width:0}77%,100%{width:47px}}
.sc2-wa{animation:sc2WA 11s linear infinite}
.sc2-wb{animation:sc2WB 11s linear infinite}
.sc2-wc{animation:sc2WC 11s linear infinite}
.sc2-l1{animation:sc2L1 11s linear infinite}
.sc2-l2{animation:sc2L2 11s linear infinite}
.sc2-l3{animation:sc2L3 11s linear infinite}
.sc2-l4{animation:sc2L4 11s linear infinite}
.sc2-l5{animation:sc2L5 11s linear infinite}
.sc2-l6{animation:sc2L6 11s linear infinite}
@keyframes sc2Caret{
  0%  {transform:translate(0,0)}       11% {transform:translate(38px,0)}
  12% {transform:translate(0,15px)}    18% {transform:translate(44px,15px)}
  19% {transform:translate(0,22px)}    25% {transform:translate(34px,22px)}
  30% {transform:translate(0,30px)}    37% {transform:translate(38px,30px)}
  38% {transform:translate(0,45px)}    44% {transform:translate(46px,45px)}
  45% {transform:translate(0,52px)}    51% {transform:translate(36px,52px)}
  56% {transform:translate(0,60px)}    63% {transform:translate(38px,60px)}
  64% {transform:translate(0,75px)}    70% {transform:translate(42px,75px)}
  71% {transform:translate(0,82px)}    77% {transform:translate(47px,82px)}
  100%{transform:translate(47px,82px)}}

/* ---- 03 · iPhone 17 Pro, rolling ---- */
.sc3{width:auto;height:170px}
.sc3-phone{fill:rgba(var(--hi-rgb),.028);stroke-width:var(--proc-outline)}
.sc3-inner{fill:none;stroke:rgba(var(--ink-rgb),.16);stroke-width:1}
.sc3-btn{fill:currentColor;stroke:none;opacity:.42}
/* the 17 Pro plateau runs the full width rather than sitting in the corner */
.sc3-plate{fill:rgba(var(--hi-rgb),.05);stroke:rgba(var(--ink-rgb),.6);stroke-width:var(--proc-inline)}
.sc3-lens circle{stroke-width:var(--proc-inline);fill:rgba(var(--hi-rgb),.06)}
.sc3-flash{fill:rgba(var(--hi-rgb),.16);stroke:rgba(var(--ink-rgb),.6);stroke-width:var(--proc-inline)}
.sc3-lidar{fill:rgba(var(--hi-rgb),.08);stroke:rgba(var(--ink-rgb),.45);stroke-width:1.2}
/* REC tag sits off the phone and holds the blinking light */
.sc3-rec-box{fill:rgba(var(--panel-rgb),.8);stroke:rgba(var(--ink-rgb),.28);stroke-width:1.2}
.sc3-rec-t{font-family:var(--sans);font-size:6.4px;font-weight:600;letter-spacing:.07em;
  fill:currentColor;stroke:none;opacity:.85}
.sc3-tally{fill:var(--g1);stroke:none;animation:sc3Tally 1.4s steps(1,end) infinite}
@keyframes sc3Tally{0%,55%{opacity:1}56%,100%{opacity:.16}}
/* handheld float now the tripod is gone */
.sc3-rig{transform-box:fill-box;transform-origin:center;
  animation:sc3Sway 8s ease-in-out infinite}
@keyframes sc3Sway{
  0%  {transform:translateY(0) rotate(-1.2deg)}
  50% {transform:translateY(-4px) rotate(1.2deg)}
  100%{transform:translateY(0) rotate(-1.2deg)}}

/* ---- copy ---- */
.proc-t{font-family:var(--display);font-weight:600;
  font-size:clamp(1.18rem,1.32vw,1.34rem);line-height:1.22;letter-spacing:-.025em;
  color:var(--ink);text-wrap:balance;max-width:18ch;margin-inline:auto}
/* reserve two lines across the top row so every body copy starts on one baseline */
.proc-card:not(.proc-wide) .proc-t{min-height:2.44em;
  display:flex;align-items:center;justify-content:center}
.proc-b{margin-top:.8rem;color:rgba(var(--ink-rgb),.56);
  font-size:.905rem;line-height:1.64;letter-spacing:.002em;
  max-width:34ch;margin-inline:auto;text-wrap:pretty}

/* ---- bottom row: copy left, artwork bleeding off the right edge ---- */
.proc-wide{grid-column:span 3;flex-direction:row;align-items:stretch;text-align:left;
  gap:1.4rem;padding:2.2rem 0 2.2rem 2.2rem}
/* no badge any more, the copy just centres against the artwork */
/* anchored, not centred: at some widths one title wraps to three lines and
   centring pushed the two cards' titles off each other */
.proc-side{flex:1 1 52%;min-width:0;display:flex;flex-direction:column;
  justify-content:flex-start;padding-top:2.9rem}
.proc-wide .proc-t,.proc-wide .proc-b{margin-inline:0}
/* two-line box here too, so cards 04 and 05 centre to the same baselines
   even though one title wraps and the other doesn't */
.proc-wide .proc-t{max-width:15ch;font-size:clamp(1.24rem,1.46vw,1.5rem);
  min-height:2.44em;display:flex;align-items:center;justify-content:flex-start}
.proc-wide .proc-b{max-width:34ch;margin-top:.9rem}

/* ---- 04 · laptop panel ---- */
.proc-panel{position:relative;flex:1 1 48%;align-self:center;
  display:grid;place-items:center;padding-right:1.2rem;
  transform-style:preserve-3d;will-change:transform}
.proc-mac{--proc-outline:2.7;--proc-inline:1.15;
  width:100%;max-width:330px;height:auto;color:var(--ink);
  fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;
  transform-origin:50% 78%;animation:sc4Tilt 11s cubic-bezier(.45,0,.35,1) infinite}
/* a slow lean away and back, so the laptop reads as a solid object in space */
@keyframes sc4Tilt{
  0%,6%   {transform:rotate(0deg) translateY(0)}
  26%,34% {transform:rotate(-2deg) translateY(-2px)}
  52%,58% {transform:rotate(0deg) translateY(0)}
  76%,84% {transform:rotate(1.6deg) translateY(-1px)}
  100%    {transform:rotate(0deg) translateY(0)}}
.sc4-lid{fill:rgba(var(--hi-rgb),.022);stroke:rgba(var(--ink-rgb),.55);stroke-width:var(--proc-outline)}
.sc4-screen{fill:url(#sc4Glass);stroke:rgba(var(--ink-rgb),.16);stroke-width:1}
.sc4-base{fill:rgba(var(--hi-rgb),.055);stroke:rgba(var(--ink-rgb),.5);stroke-width:var(--proc-outline)}
.sc4-hinge{stroke:rgba(var(--ink-rgb),.3);stroke-width:1.2}
.sc4-notchcut{fill:rgba(var(--hi-rgb),.09);stroke:rgba(var(--ink-rgb),.28);stroke-width:1}
.sc4-slot{fill:none;stroke:rgba(var(--ink-rgb),.42);stroke-width:var(--proc-inline)}

.sc4-chrome,.sc4-rail{stroke:rgba(var(--ink-rgb),.16);stroke-width:1}
.sc4-prev{fill:rgba(var(--hi-rgb),.045);stroke:rgba(var(--ink-rgb),.2);stroke-width:1}
.sc4-play{opacity:.5;stroke-width:1.3}
.sc4-play .fill{fill:currentColor;stroke:none}
.sc4-scrub{fill:rgba(var(--hi-rgb),.14);stroke:none}
.sc4-scrub-on{fill:var(--g2);stroke:none;animation:sc4Scrubbar 9s cubic-bezier(.45,0,.35,1) infinite}
@keyframes sc4Scrubbar{0%{width:0}50%{width:154px}100%{width:0}}
.sc4-tool{fill:rgba(var(--hi-rgb),.14);stroke:none}
.sc4-ticks{stroke:rgba(var(--ink-rgb),.26);stroke-width:1}
.sc4-vid rect{fill:rgba(var(--hi-rgb),.17);stroke:rgba(var(--hi-rgb),.32);stroke-width:1}
.sc4-aud rect{fill:rgba(242,217,138,.15);stroke:rgba(242,217,138,.36);stroke-width:1}
.sc4-b3  rect{fill:rgba(var(--hi-rgb),.07);stroke:none}
.sc4-head{stroke:var(--g2);stroke-width:1.5}
.sc4-head-cap{fill:var(--g2);stroke:none}
/* three strips drift at slightly different rates, reads as a real scrub */
.sc4-vid{animation:sc4Scrub  9s cubic-bezier(.45,0,.35,1) infinite}
.sc4-aud{animation:sc4ScrubB 9s cubic-bezier(.45,0,.35,1) infinite}
.sc4-b3 {animation:sc4ScrubC 9s cubic-bezier(.45,0,.35,1) infinite}
@keyframes sc4Scrub {0%{transform:translateX(0)}50%{transform:translateX(-58px)}100%{transform:translateX(0)}}
@keyframes sc4ScrubB{0%{transform:translateX(0)}50%{transform:translateX(-50px)}100%{transform:translateX(0)}}
@keyframes sc4ScrubC{0%{transform:translateX(0)}50%{transform:translateX(-64px)}100%{transform:translateX(0)}}

/* ---- 05 · status pills, all flush right ---- */
.proc-pills{flex:1 1 46%;align-self:center;display:flex;flex-direction:column;
  align-items:flex-end;gap:.9rem;padding-right:2.1rem;
  transform-style:preserve-3d;will-change:transform}
/* the three capsules drift, meet, and ease off one another, A nudges B early
   in the cycle, B nudges C later. Their badges are absolute children, so they
   travel along with the capsule. */
.proc-pills > .proc-pill:nth-child(1){animation:pillA 11s cubic-bezier(.4,0,.2,1) infinite}
.proc-pills > .proc-pill:nth-child(2){animation:pillB 11s cubic-bezier(.4,0,.2,1) infinite}
.proc-pills > .proc-pill:nth-child(3){animation:pillC 11s cubic-bezier(.4,0,.2,1) infinite}
@keyframes pillA{
  0%   {transform:translate(0,0) rotate(0deg)}
  20%  {transform:translate(-4px,6px) rotate(-.5deg)}
  27%  {transform:translate(-2px,1px) rotate(.3deg)}
  48%  {transform:translate(3px,-3px) rotate(.4deg)}
  74%  {transform:translate(-2px,2px) rotate(-.2deg)}
  100% {transform:translate(0,0) rotate(0deg)}}
@keyframes pillB{
  0%   {transform:translate(0,0) rotate(0deg)}
  20%  {transform:translate(3px,-5px) rotate(.4deg)}
  27%  {transform:translate(1px,0) rotate(-.3deg)}
  46%  {transform:translate(-3px,2px) rotate(-.3deg)}
  62%  {transform:translate(-2px,5px) rotate(-.5deg)}
  70%  {transform:translate(0,1px) rotate(.2deg)}
  100% {transform:translate(0,0) rotate(0deg)}}
@keyframes pillC{
  0%   {transform:translate(0,0) rotate(0deg)}
  30%  {transform:translate(4px,3px) rotate(.3deg)}
  62%  {transform:translate(-3px,-5px) rotate(-.4deg)}
  70%  {transform:translate(-1px,-1px) rotate(.3deg)}
  88%  {transform:translate(2px,3px) rotate(.2deg)}
  100% {transform:translate(0,0) rotate(0deg)}}
.proc-pill{display:inline-flex;align-items:center;gap:.5rem;width:max-content;
  position:relative;font-size:.86rem;font-weight:500;color:var(--ink);
  padding:.45rem .9rem;border-radius:100px;
  border:1px solid var(--glass-brite);background:rgba(var(--panel-rgb),.72);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
/* badge sitting off the capsule's left edge, matching the counter and bubbles */
.pthumb{position:absolute;right:calc(100% + .5rem);top:50%;margin-top:-14px;
  display:grid;place-items:center;width:28px;height:28px;border-radius:50%;
  border:1px solid var(--glass-brite);background:rgba(var(--panel-rgb),.94);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}
.pthumb svg{width:15px;height:15px;fill:none;stroke:#7fe0a0;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
  transform-origin:60% 80%;animation:pthumbTap 3.4s var(--ease) infinite}
@keyframes pthumbTap{
  0%,8%   {transform:rotate(-16deg) translateY(2px) scale(.92)}
  18%     {transform:rotate(6deg)  translateY(-2px) scale(1.08)}
  26%     {transform:rotate(0deg)  translateY(0)    scale(1)}
  34%     {transform:rotate(3deg)  translateY(-1px) scale(1.03)}
  44%,100%{transform:rotate(0deg)  translateY(0)    scale(1)}}

.ptick{width:15px;height:15px;fill:none;stroke:#4fd67d;stroke-width:2.6;
  stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:24;stroke-dashoffset:24;animation:ptick 3.4s var(--ease) infinite}
@keyframes ptick{0%,8%{stroke-dashoffset:24}26%,86%{stroke-dashoffset:0}96%,100%{stroke-dashoffset:24}}
.pup{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;opacity:.85;overflow:visible}
.pup-tray{opacity:.55}
.pup-arrow{transform-box:view-box;transform-origin:center;
  animation:pupGo 2.4s cubic-bezier(.4,0,.25,1) infinite}
@keyframes pupGo{
  0%,10%  {transform:translateY(0);opacity:1}
  46%     {transform:translateY(-5px);opacity:0}
  47%     {transform:translateY(4px);opacity:0}
  72%,100%{transform:translateY(0);opacity:1}}

/* platform badges arc off the capsule's left edge and pop in turn */
.plogs{position:absolute;right:calc(100% + .95rem);top:50%;width:0;height:0}
/* No backdrop-filter here. The background is already 94% opaque, so an 8px
   blur behind it is close to invisible, and it costs a full blur pass every
   frame on an element that is scaling the whole time. Dropping it is most of
   what made these move smoothly. */
.plog{position:absolute;display:grid;place-items:center;width:26px;height:26px;
  margin:-13px 0 0 -13px;border-radius:50%;
  border:1px solid var(--glass-brite);background:rgba(var(--panel-rgb),.94);
  opacity:0;will-change:transform,opacity;
  animation:plogA 4.5s linear infinite}
.plog svg{width:15px;height:15px;fill:none;stroke:currentColor;
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.plog svg .fill{fill:currentColor;stroke:none}
/* the three sit on a shallow curve bulging away from the pill */
/* each drifts in from its own side, top, middle, bottom, and their phases
   overlap, so one is always inflating while the last is on its way out */
.plog-1,.plog-2,.plog-3{left:0;top:0}
.plog-1{animation-name:plogA}
.plog-2{animation-name:plogB;animation-delay:1.5s}
.plog-3{animation-name:plogC;animation-delay:3s}
/* bubble physics: inflates small -> full, wobbles, then bursts. 6s cycle,
   2s apart, so one is always mid-inflate as the last one pops. */
@keyframes plogA{
  0%   {opacity:0;  transform:translate(-13px,-21px) scale(.12);
        animation-timing-function:cubic-bezier(.17,.72,.28,1)}
  16%  {opacity:1}
  54%  {opacity:1;  transform:translate(0,0) scale(1.05);
        animation-timing-function:cubic-bezier(.4,0,.5,1)}
  66%  {opacity:1;  transform:translate(0,0) scale(1);
        animation-timing-function:cubic-bezier(.55,0,.9,.4)}
  78%  {opacity:0;  transform:translate(1px,1px) scale(1.68)}
  100% {opacity:0;  transform:translate(-13px,-21px) scale(.12)}}
@keyframes plogB{
  0%   {opacity:0;  transform:translate(-24px,2px) scale(.12);
        animation-timing-function:cubic-bezier(.17,.72,.28,1)}
  16%  {opacity:1}
  54%  {opacity:1;  transform:translate(0,0) scale(1.05);
        animation-timing-function:cubic-bezier(.4,0,.5,1)}
  66%  {opacity:1;  transform:translate(0,0) scale(1);
        animation-timing-function:cubic-bezier(.55,0,.9,.4)}
  78%  {opacity:0;  transform:translate(1px,1px) scale(1.68)}
  100% {opacity:0;  transform:translate(-24px,2px) scale(.12)}}
@keyframes plogC{
  0%   {opacity:0;  transform:translate(-13px,21px) scale(.12);
        animation-timing-function:cubic-bezier(.17,.72,.28,1)}
  16%  {opacity:1}
  54%  {opacity:1;  transform:translate(0,0) scale(1.05);
        animation-timing-function:cubic-bezier(.4,0,.5,1)}
  66%  {opacity:1;  transform:translate(0,0) scale(1);
        animation-timing-function:cubic-bezier(.55,0,.9,.4)}
  78%  {opacity:0;  transform:translate(1px,1px) scale(1.68)}
  100% {opacity:0;  transform:translate(-13px,21px) scale(.12)}}
/* the film left behind by the pop */
.plog::after{content:"";position:absolute;inset:-1px;border-radius:50%;
  border:1px solid rgba(255,214,170,.75);opacity:0;pointer-events:none;
  animation:plogBurst 4.5s var(--ease) infinite}
.plog-2::after{animation-delay:1.5s}
.plog-3::after{animation-delay:3s}
@keyframes plogBurst{
  0%,68%  {opacity:0;transform:scale(1)}
  72%     {opacity:.8;transform:scale(1.26)}
  84%,100%{opacity:0;transform:scale(2.2)}}

.peye{width:16px;height:16px;fill:none;stroke:currentColor;
  stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;opacity:.85;
  transform-origin:center;animation:peyeBlink 3.6s steps(1,end) infinite}
.peye-iris{fill:rgba(var(--ink-rgb),.18)}
/* lids squeeze shut for two frames, twice a cycle */
@keyframes peyeBlink{
  0%,44%   {transform:scaleY(1)}
  46%      {transform:scaleY(.12)}
  49%,72%  {transform:scaleY(1)}
  74%      {transform:scaleY(.12)}
  77%,100% {transform:scaleY(1)}}

/* view counter ticks up beside the eye; 13th value repeats the 1st so the
   loop reset never shows */
.pcount-badge{position:absolute;right:calc(100% + .5rem);top:50%;
  display:grid;place-items:center;height:28px;padding:0 .58rem;
  transform:translateY(-50%);border-radius:100px;
  border:1px solid rgba(242,217,138,.4);background:rgba(var(--panel-rgb),.9);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}
.pcount{display:block;overflow:hidden;height:1.18em;width:3.35em;
  font-size:.78rem;color:var(--g3);font-weight:600;
  font-variant-numeric:tabular-nums;text-align:center}
.pcount-track{display:block;animation:pcountRoll 10.4s steps(1,end) infinite}
.pcount i{display:block;height:1.18em;line-height:1.18em;font-style:normal}
@keyframes pcountRoll{
  0%    {transform:translateY(0)}
  7.7%  {transform:translateY(-1.18em)}
  15.4% {transform:translateY(-2.36em)}
  23.1% {transform:translateY(-3.54em)}
  30.8% {transform:translateY(-4.72em)}
  38.5% {transform:translateY(-5.90em)}
  46.2% {transform:translateY(-7.08em)}
  53.8% {transform:translateY(-8.26em)}
  61.5% {transform:translateY(-9.44em)}
  69.2% {transform:translateY(-10.62em)}
  76.9% {transform:translateY(-11.80em)}
  84.6% {transform:translateY(-12.98em)}
  100%  {transform:translateY(-14.16em)}}

@media(prefers-reduced-motion:reduce){
  .sc1-mag,.sc1-float,.sc1-feed,.sc2-sheet,.sc2-body,.sc2-caret,
  /* the type-in drives SVG geometry, so these have to be listed too or the
     hooks keep typing themselves with motion turned off */
  .sc2-wa,.sc2-wb,.sc2-wc,.sc2-l1,.sc2-l2,.sc2-l3,.sc2-l4,.sc2-l5,.sc2-l6,
  .sc3-rig,.sc3-tally,.sc4-vid,.sc4-aud,.sc4-b3,.sc4-scrub-on,
  .ptick,.pup-arrow,.peye,.plog,.plog::after,.pcount-track,.pthumb svg,
  .proc-mac,.proc-pills > .proc-pill{animation:none}
  .sc4-scrub-on{width:92px}
  /* pinned open: the sheet reads as a finished script rather than a blank page */
  .sc2-wa,.sc2-wb,.sc2-wc{width:38px}
  .sc2-l1{width:44px}.sc2-l2{width:34px}.sc2-l3{width:46px}
  .sc2-l4{width:36px}.sc2-l5{width:42px}.sc2-l6{width:47px}
  .sc2-caret{opacity:0}
  .ptick{stroke-dashoffset:0}
  /* without their entry paths all three badges land on one spot, so only one
     would ever be visible, park them on the arc instead */
  .plog{opacity:1}
  .plog-1{transform:translate(-13px,-21px)}
  .plog-2{transform:translate(-24px,2px)}
  .plog-3{transform:translate(-13px,21px)}
}

/* ============ FAQ, DM thread ============ */
.faq{padding-block:11vh 4vh;padding-inline:var(--edge)}
.faq .section-head{margin-bottom:2.6rem}
.lead.center{text-align:center;margin-inline:auto}
/* 44ch broke this one across two lines, widen so it sits on a single line */
.faq .lead{max-width:66ch}
/* the one CTA in this section, underline that thickens on hover */
.lead-link{color:var(--ink);font-weight:600;text-decoration:underline;
  text-decoration-color:rgba(242,217,138,.5);text-underline-offset:4px;
  text-decoration-thickness:1.5px;
  transition:color .3s var(--ease),text-decoration-color .3s var(--ease)}
.lead-link:hover{color:#f2d98a;text-decoration-color:#f2d98a}
.lead-link:focus-visible{outline:2px solid var(--g2);outline-offset:3px;border-radius:4px}
.faq-thread{width:100%;max-width:760px;margin-inline:auto;
  display:flex;flex-direction:column;gap:.55rem}
.faq-stamp{align-self:center;margin-bottom:.9rem;font-size:.74rem;letter-spacing:.06em;
  color:var(--ink-faint)}

.faq-row{position:relative}
/* the question, incoming message, hugs the left rail */
/* full-width row so the bubble's percentage max-width has something real to
   resolve against; the bubble itself still hugs its text */
.faq-row summary{display:flex;align-items:center;gap:.55rem;cursor:pointer;list-style:none;
  width:100%;perspective:800px}
.faq-row summary::-webkit-details-marker{display:none}
.faq-q{position:relative;isolation:isolate;overflow:hidden;
  width:fit-content;max-width:min(78%,540px);padding:.72rem 1.05rem;
  border-radius:19px 19px 19px 7px;
  font-size:.94rem;font-weight:500;line-height:1.4;color:var(--ink);
  border:1px solid rgba(var(--hi-rgb),.11);
  background:linear-gradient(180deg,rgba(var(--hi-rgb),.085),rgba(var(--hi-rgb),.035));
  backdrop-filter:blur(16px) saturate(1.3);-webkit-backdrop-filter:blur(16px) saturate(1.3);
  box-shadow:inset 0 1px 0 rgba(var(--hi-rgb),.14),0 10px 26px rgba(0,0,0,.3);
  transform-style:preserve-3d;will-change:transform;
  transition:border-color .4s var(--ease),box-shadow .4s var(--ease)}
/* specular that tracks the pointer, the glass catches the light */
.faq-q::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  opacity:0;transition:opacity .4s var(--ease);
  background:radial-gradient(160px circle at var(--mx,50%) var(--my,50%),
    rgba(var(--hi-rgb),.16),rgba(242,217,138,.07) 45%,transparent 70%)}
@media(hover:hover) and (pointer:fine){
  .faq-row summary:hover .faq-q{border-color:var(--glass-brite);
    box-shadow:inset 0 1px 0 rgba(var(--hi-rgb),.22),0 14px 32px rgba(0,0,0,.36),
               0 0 34px rgba(212,165,60,.13)}
  .faq-row summary:hover .faq-q::after{opacity:1}
}
.faq-row summary:focus-visible .faq-q{outline:2px solid var(--g2);outline-offset:3px}

/* plus that rotates into a minus */
.faq-tog{position:relative;flex:0 0 auto;width:14px;height:14px;opacity:.5;
  transition:opacity .35s var(--ease)}
.faq-tog::before,.faq-tog::after{content:"";position:absolute;top:50%;left:0;
  width:100%;height:1.6px;margin-top:-.8px;border-radius:2px;background:var(--ink);
  transition:transform .45s var(--ease),background .35s var(--ease)}
.faq-tog::after{transform:rotate(90deg)}
.faq-row summary:hover .faq-tog{opacity:.9}
.faq-row[open] .faq-tog{opacity:1}
.faq-row[open] .faq-tog::before{background:var(--g2)}
.faq-row[open] .faq-tog::after{transform:rotate(0);background:var(--g2)}

/* reaction pip, like a DM heart */
.faq-row[data-react]::before{content:attr(data-react);position:absolute;
  left:-9px;top:-7px;z-index:3;font-size:.78rem;line-height:1;pointer-events:none;
  filter:drop-shadow(0 2px 4px rgba(0,0,0,.5))}

/* the answer, outgoing reply, hugs the right rail */
.faq-a{display:flex;justify-content:flex-end;margin:.42rem 0 .5rem}
.faq-a p{max-width:min(80%,580px);padding:.8rem 1.1rem;
  border-radius:19px 19px 7px 19px;
  font-size:.92rem;line-height:1.6;color:var(--on-gold);
  background:linear-gradient(180deg,rgba(247,243,234,.96),rgba(232,226,214,.92));
  border:1px solid rgba(var(--hi-rgb),.5);
  box-shadow:0 12px 30px rgba(0,0,0,.34),inset 0 1px 0 rgba(var(--hi-rgb),.7)}
/* the reply lands like a message arriving */
.faq-row[open] .faq-a{animation:faqIn .48s var(--ease) both}
@keyframes faqIn{
  from{opacity:0;transform:translateY(-8px) scale(.96)}
  to{opacity:1;transform:none}}

@media(max-width:680px){
  .faq{padding-block:9vh 3vh}
  .faq-thread{gap:.5rem}
  .faq-q{max-width:86%;font-size:.9rem;padding:.66rem .95rem}
  .faq-a p{max-width:88%;font-size:.88rem;padding:.72rem 1rem}
}
@media(prefers-reduced-motion:reduce){
  .faq-row[open] .faq-a{animation:none}
}

/* ============ TESTIMONIALS ============ */
.voices{padding-block:12vh 6vh;padding-inline:var(--edge)}
.voices .h2{margin-bottom:3.2rem}
/* ---- counter-rotating scroll reel ----
   Geometry must stay in lockstep with script.js: one step moves the middle
   column by 3 tiles, so STEP = 3 * (CELL + GAP). */
.voices{perspective:1400px}
.reel{--cell:121.33px;--gap:8px;transform-style:preserve-3d;will-change:transform;
  position:relative;display:flex;flex-direction:column;align-items:stretch;gap:.625rem;
  width:100%;max-width:1060px;margin-inline:auto;overflow:hidden;border-radius:18px;
  border:1px solid var(--line);background:rgba(var(--panel-rgb),.55);
  box-shadow:inset 0 1px 0 rgba(var(--hi-rgb),.06),0 30px 70px rgba(0,0,0,.4);
  outline:none}
.reel:focus-visible{box-shadow:inset 0 1px 0 rgba(var(--hi-rgb),.06),0 0 0 2px var(--g2)}

.reel-stage{position:relative;height:17rem;width:100%;flex:0 0 auto;overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,transparent 0,#000 14%,#000 86%,transparent 100%),
                     linear-gradient(to bottom,transparent 0,#000 10%,#000 90%,transparent 100%);
  mask-image:linear-gradient(to right,transparent 0,#000 14%,#000 86%,transparent 100%),
             linear-gradient(to bottom,transparent 0,#000 10%,#000 90%,transparent 100%);
  -webkit-mask-composite:source-in;mask-composite:intersect}
/* ambient warmth sits BEHIND the tiles, above them it washes out the portrait */
.reel-stage::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(60% 60% at 50% 50%,rgba(212,165,60,.10),transparent 70%)}
.reel-cols{position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;gap:var(--gap)}
.reel-col{display:flex;flex-direction:column;gap:var(--gap);flex:0 0 auto;will-change:transform}

/* blurred filler tile */
.reel-cell{flex:0 0 auto;width:var(--cell);height:var(--cell);border-radius:12px;
  border:1px solid rgba(var(--hi-rgb),.07);filter:blur(1px);
  background:linear-gradient(180deg,rgba(var(--ink-rgb),.075),rgba(var(--ink-rgb),.02));
  box-shadow:0 1px 2px rgba(0,0,0,.3),inset 0 1px 0 rgba(var(--hi-rgb),.07)}

/* portrait tile: desaturated photo under a warm diagonal sheen */
.reel-face{position:relative;flex:0 0 auto;width:var(--cell);height:var(--cell);
  border-radius:12px;overflow:hidden;background:var(--warm-solid);
  box-shadow:0 4px 3px -2px rgba(0,0,0,.17),0 11px 8px -3px rgba(0,0,0,.15),
             0 32px 23px -4px rgba(0,0,0,.2),0 60px 42px -5px rgba(0,0,0,.16),
             inset 0 1px 0 rgba(var(--hi-rgb),.16),inset 0 -1px 0 rgba(0,0,0,.6)}
.reel-face img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:center 30%;filter:grayscale(1) contrast(1.05)}
/* a brand mark keeps its own colour and is contained, not cropped */
.reel-face.is-logo{background:var(--logo-bg)}
.reel-face.is-logo img{filter:none;object-fit:contain;object-position:center;padding:12%}
.reel-face.is-logo::after{opacity:.35}
.reel-face::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  filter:blur(6px);mix-blend-mode:overlay;
  background:linear-gradient(220.99deg,rgba(212,165,60,0) 32%,rgb(163,118,31) 41%,
    rgb(212,165,60) 47%,rgba(242,217,138,.57) 54%,rgba(242,217,138,0) 65%)}

/* ---- content side ---- */
.reel-body{display:flex;flex-direction:column;justify-content:space-between;flex:1 1 auto;
  min-width:0;padding:1.75rem 1.5rem}
.reel-mark{width:2.6rem;height:2.6rem;color:rgba(var(--ink-rgb),.22);margin-bottom:.5rem}
.reel-text{position:relative;width:100%;max-width:420px;overflow:hidden}
.reel-ghost{visibility:hidden;display:flex;flex-direction:column;gap:1.15rem;min-height:186px}
.reel-live{position:absolute;left:0;right:0;top:0;display:flex;flex-direction:column;gap:1.15rem;
  will-change:transform,opacity}
.reel-q{font-size:clamp(1.12rem,1.7vw,1.44rem);font-weight:500;line-height:1.3;
  letter-spacing:-.02em;color:var(--ink)}
.reel-a{font-size:.9rem;font-weight:500;line-height:1.3;color:var(--ink-dim)}

/* per-character rise */
.reel-char{display:inline-block;animation:reelChar .58s var(--ease) both}
@keyframes reelChar{from{opacity:0;transform:translateY(.7em)}to{opacity:1;transform:none}}
.reel-word{display:inline-block;white-space:nowrap}
/* exiting block leaves as one piece; kill in-flight per-char rises */
.reel-live.exiting{animation:reelExit 240ms ease both}
.reel-live.exiting .reel-char{animation:none}
@keyframes reelExit{to{opacity:0;transform:translateY(-10px);filter:blur(4px)}}

.reel-nav{display:flex;align-items:center;gap:.4rem;margin-top:1.5rem}
.reel-btn{width:1.6rem;height:1.6rem;display:grid;place-items:center;padding:0;cursor:pointer;
  border-radius:50%;border:1px solid rgba(var(--ink-rgb),.18);background:transparent;color:var(--ink);
  transition:transform .2s cubic-bezier(.22,1,.36,1),opacity .2s,border-color .2s}
.reel-btn svg{width:.75rem;height:.75rem;opacity:.7}
.reel-btn:hover:enabled{transform:scale(1.08);border-color:var(--g2)}
.reel-btn:active:enabled{transform:scale(.94)}
.reel-btn:disabled{cursor:default;opacity:.35}

/* side-by-side once there is room; stacked below */
@media(min-width:768px){
  .reel{flex-direction:row;min-height:400px}
  .reel-stage{width:380px;height:auto;align-self:stretch}
  .reel-body{padding:2.5rem 1.75rem}
  .reel-nav{margin-top:0}
}

/* ============ CTA ============ */
/* generous TOP padding reserves room for the card, which opens above the capsule */
.cta-final{min-height:auto;display:grid;place-items:center;text-align:center;
  padding-block:clamp(4rem,9vh,7rem) clamp(1rem,2vh,1.6rem);padding-inline:var(--edge);perspective:1200px;
  overflow-x:clip}
.pf{position:relative;width:100%;display:flex;flex-direction:column;align-items:center;
  transform-style:preserve-3d}
.pf-3d{position:relative;display:grid;place-items:center;width:100%;
  transform-style:preserve-3d;will-change:transform}

/* stacked name, the two lines sit in a grid cell with the portrait on top */
.pf-name{grid-area:1/1;font-family:var(--display);font-weight:600;text-transform:uppercase;
  line-height:.82;font-size:clamp(3.2rem,13vw,11.5rem);
  /* the largest type on the page, so it takes the tightest tracking */
  letter-spacing:clamp(-.055em,calc(-.025em - .22vw),-.025em);
  display:flex;flex-direction:column;align-items:center;transform-style:preserve-3d;
  background:var(--grad);-webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent}
.pf-line{display:block;will-change:transform;transform-style:preserve-3d}
.pf-in{display:block;transform:translateZ(26px)}
/* One span per glyph so the name can appear letter by letter. display:inline
   is load-bearing, .pf-name clips the brand gradient to its own text, and an
   inline-block child becomes a separate layout box the clip cannot reach, so
   the gradient escapes the glyphs and paints as solid rectangles. Inline keeps
   each letter inside the parent's text run, and opacity still animates. */
.pf-ch{display:inline}

/* the capsule, and the anchor the card + hint hang off */
.pf-anchor{grid-area:1/1;position:relative;z-index:2;
  width:clamp(158px,14vw,210px);aspect-ratio:5/8}
.pf-photo{position:absolute;inset:0;padding:0;background:none;cursor:pointer;
  border-radius:999px;overflow:hidden;border:1px solid rgba(var(--hi-rgb),.14);
  box-shadow:0 20px 50px rgba(0,0,0,.55),0 50px 100px rgba(0,0,0,.4),
             0 0 90px rgba(212,165,60,.22),inset 0 1px 0 rgba(var(--hi-rgb),.14);
  will-change:transform;-webkit-tap-highlight-color:transparent;
  transition:box-shadow .45s var(--ease),transform .45s var(--ease)}
.pf-photo img{width:100%;height:100%;object-fit:cover;object-position:center 28%;
  transition:filter .5s var(--ease),transform .6s var(--ease)}
/* soft radial gradient rather than filter:blur(), same look, and it does not
   force a blurred layer to re-rasterise on every scroll frame */
.pf-photo::after{content:"";position:absolute;inset:-30%;z-index:-1;pointer-events:none;
  background:radial-gradient(closest-side,rgba(212,165,60,.34),rgba(212,165,60,.12) 55%,transparent 78%)}
.pf-photo:hover{box-shadow:0 22px 56px rgba(0,0,0,.55),0 50px 100px rgba(0,0,0,.4),
  0 0 110px rgba(212,165,60,.34),inset 0 1px 0 rgba(var(--hi-rgb),.2)}
.pf-photo:hover img{transform:scale(1.04)}
.pf-photo:focus-visible{outline:2px solid var(--g2);outline-offset:8px}

/* "click me" nudge, same language as the hero phone hint, pushed forward in Z
   so it picks up the group's cursor parallax */
.pf-hint{position:absolute;top:-6%;right:calc(100% - 18px);z-index:6;pointer-events:none;
  display:flex;flex-direction:column;align-items:flex-start;gap:.1rem;width:max-content;
  transform:translateZ(60px);transition:opacity .35s var(--ease)}
.pf-hint-box{display:inline-flex;align-items:center;gap:.5rem;font-size:.82rem;color:var(--ink);
  padding:.5rem .9rem;border-radius:100px;border:1px solid var(--glass-brite);
  background:rgba(var(--panel-rgb),.82);box-shadow:0 12px 34px rgba(0,0,0,.45)}
.pf-hint-curve{width:74px;height:56px;color:#fff;margin-left:2.6rem;
  filter:drop-shadow(0 2px 6px rgba(0,0,0,.5));animation:tapbob 1.8s ease-in-out infinite}

.pf-tagline{margin-top:clamp(.9rem,2.2vw,1.5rem);color:var(--ink-dim);
  font-size:clamp(1rem,1.7vw,1.3rem);letter-spacing:-.01em}

/* ---- contact card ----
   It used to hide inside a collapsing drawer behind a click on his portrait.
   The portrait is gone, so the card is the section: always open, no toggle. The
   drawer element stays as the centring wrapper. */
.pf-drawer{display:grid;grid-template-rows:1fr;width:100%}
/* the perspective the ticket is seen through. It has to be here, on the parent,
   not inside the ticket's own transform. */
.pf-drawer-in{min-height:0;display:flex;justify-content:center;
  perspective:1100px;perspective-origin:50% 50%}
/* ---- the ticket ----
   The shape is cut, not drawn. Six radial gradients composited with
   mask-composite:intersect punch two notches at the perforation and four concave
   corners straight out of the element, so the background shows through the bites
   and the edge stays a real torn edge at any size. A border cannot do this, and
   neither can border-radius: those round the corner outward, this eats into it.

   --tk-perf is the perforation's position and every hole is placed off it, so
   moving the stub moves the notches with it.

   The fill is fixed gold in both themes. The card is the colour, the way the
   reference's is, and dark ink on gold only works if the gold does not move. */
.ticket{--tk-perf:76%;--tk-notch:20px;--tk-corner:22px;
  --tk-ink:#2a1c06;
  position:relative;isolation:isolate;
  width:min(1060px,94vw);aspect-ratio:106/40;margin-top:1.6rem;
  /* the perforation IS the column boundary, so one variable places the seam, the
     notches and the stub together */
  display:grid;grid-template-columns:var(--tk-perf) 1fr;
  background:linear-gradient(112deg,#a9761c 0%,#c8942c 30%,#e0b551 58%,#a06b12 100%);
  border-radius:18px;
  /* a mask clips box-shadow, so the shadow is a filter on the element instead:
     drop-shadow follows the cut edge, notches and all */
  filter:drop-shadow(0 26px 46px rgba(0,0,0,.5)) drop-shadow(0 4px 10px rgba(0,0,0,.35));
  transform-style:preserve-3d;will-change:transform;
  opacity:0;transition:opacity .5s var(--ease)}
.pf.card-open .ticket{opacity:1}



/* The torn shape needs six mask layers composited together. A browser that
   cannot do that must not get a partial mask, or the card renders sliced, so
   the whole thing is gated and the fallback is the rounded rectangle above. */
@supports (mask-composite: intersect) or (-webkit-mask-composite: source-in){
  .ticket{
    border-radius:0;
  -webkit-mask:
    radial-gradient(circle var(--tk-notch) at var(--tk-perf) 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-notch) at var(--tk-perf) 100%,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 0 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 100% 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 0 100%,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 100% 100%,transparent 99%,#000 100%);
  -webkit-mask-composite:source-in;
          mask:
    radial-gradient(circle var(--tk-notch) at var(--tk-perf) 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-notch) at var(--tk-perf) 100%,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 0 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 100% 0,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 0 100%,transparent 99%,#000 100%),
    radial-gradient(circle var(--tk-corner) at 100% 100%,transparent 99%,#000 100%);
          mask-composite:intersect;
  }
}

/* the perforation itself, a dashed rule down the seam */
.ticket::after{content:"";position:absolute;top:var(--tk-notch);bottom:var(--tk-notch);
  left:var(--tk-perf);width:2px;transform:translateX(-1px);z-index:3;pointer-events:none;
  background:repeating-linear-gradient(180deg,rgba(42,28,6,.42) 0 7px,transparent 7px 15px)}

/* holds the moving layers inside the card so they cannot grow the page */
.tk-fx{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;
  transform-style:flat}

/* ---- the light on it ----
   Two fields turning against each other at different speeds. Rotation is the one
   motion that loops without a seam: it ends exactly where it began, so there is
   no reversal and no jump. Because the periods do not divide into each other
   (23s against 14s), the interference between them takes minutes to repeat, and
   the surface reads as flowing rather than as a loop playing again.

   The scale breath is on its own timing so the pair never settles into a pattern. */
.tk-wash{position:absolute;inset:-55%;z-index:0;pointer-events:none;
  background:
    radial-gradient(30% 34% at 26% 24%,rgba(255,245,216,.9),transparent 62%),
    radial-gradient(26% 30% at 72% 34%,rgba(255,232,172,.7),transparent 64%),
    radial-gradient(34% 38% at 40% 76%,rgba(150,96,12,.6),transparent 66%),
    radial-gradient(24% 28% at 82% 78%,rgba(120,74,6,.55),transparent 62%);
  filter:blur(26px);opacity:.8;
  animation:tkspin-a 23s linear infinite,tkbreathe 11s var(--ease) infinite alternate}
@keyframes tkspin-a{ to{ rotate:360deg } }
@keyframes tkbreathe{ from{ scale:1 } to{ scale:1.16 } }

/* the grain is the whole texture of the reference: without it the gold is paint */
.tk-grain{position:absolute;inset:0;z-index:1;pointer-events:none;
  opacity:.72;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* ---- body ---- */
/* The inset clears the corner cutouts before any type starts, which is what the
   reference does and what made mine look jammed against the left edge. */
.tk-body{position:relative;z-index:2;
  padding:clamp(2.2rem,7.5%,3.6rem) clamp(4.5rem,11%,5.5rem) clamp(2.2rem,7.5%,3.6rem) clamp(3.4rem,12%,6rem);
  display:flex;flex-direction:column;justify-content:space-between;
  align-items:flex-start;text-align:left;color:var(--tk-ink);
  transform-style:preserve-3d}
/* only .tk-top is a depth layer. The two blocks holding links stay flat so
   nothing inside them is projected independently of the card. */
.tk-top{width:100%;transform-style:preserve-3d}
.tk-mid,.tk-foot{width:100%;transform-style:flat}
/* the signature holds the bottom-left corner the status used to, with the social
   row balancing it on the right */
.tk-foot{display:flex;align-items:flex-end;width:100%}
.tk-name{font-family:var(--display);font-weight:700;text-transform:uppercase;
  font-size:clamp(2.1rem,6.4vw,4.3rem);line-height:.9;letter-spacing:-.038em}
.tk-actions{display:flex;align-items:center;gap:clamp(.9rem,2vw,1.5rem);flex-wrap:wrap}
.tk-wa{width:clamp(54px,5.4vw,64px);aspect-ratio:1;flex:0 0 auto;border-radius:50%;
  display:grid;place-items:center;color:#f6ecd2;background:var(--tk-ink);
  transition:scale .4s var(--ease),background .4s var(--ease)}
.tk-wa:hover{scale:1.08;background:#3d290c}
.tk-book{display:inline-flex;align-items:center;gap:.6rem;
  padding:1.1rem 3rem;border-radius:100px;
  font-size:clamp(1rem,1.25vw,1.22rem);font-weight:600;color:var(--tk-ink);
  border:1.5px solid rgba(42,28,6,.55);
  transition:background .4s var(--ease),scale .4s var(--ease)}
.tk-book:hover{background:rgba(42,28,6,.1);scale:1.03}
.tk-book svg,.tk-wa svg{pointer-events:none}
.tk-book svg{transition:translate .4s var(--ease)}
.tk-book:hover svg{translate:3px 0}
/* ---- stub ----
   Reads top to bottom on the right, with the year sitting behind it a size
   larger and paler, exactly as the reference stacks them. */
.tk-stub{position:relative;z-index:2;display:grid;place-items:center;
  min-width:0;padding-block:1.2rem}
.tk-stub-t{position:relative;z-index:1;writing-mode:vertical-rl;
  font-family:var(--display);font-weight:700;text-transform:uppercase;
  font-size:clamp(1.3rem,3.2vw,2.3rem);letter-spacing:.02em;line-height:1;
  color:var(--tk-ink);white-space:nowrap}
.tk-year{position:absolute;inset:0;display:grid;place-items:center;
  writing-mode:vertical-rl;pointer-events:none;
  font-family:var(--display);font-weight:800;
  font-size:clamp(3.4rem,9vw,6.4rem);letter-spacing:-.05em;
  color:rgba(255,247,224,.58)}

/* ---- signature + socials, the footer folded in ---- */
.tk-sign{display:block;line-height:0;transition:scale .5s var(--ease)}
.tk-sign:hover{scale:1.04}
/* px and vw only: a percentage height here resolves against an auto-height
   parent, which is indefinite, so the clamp silently fell through to the
   image's intrinsic size */
.tk-sign img{height:clamp(32px,3vw,46px);width:auto;
  /* the dark-ink signature is the only one that works on gold, in either theme */
  opacity:.92}
/* A column against the perforation, so the row of icons and the tear line read
   as one edge treatment rather than two competing horizontals. */
.tk-social{position:absolute;right:clamp(1.1rem,2.4%,1.8rem);top:50%;translate:0 -50%;
  display:flex;flex-direction:column;align-items:center;gap:clamp(.4rem,1.1%,.65rem)}
.tk-social a{width:clamp(40px,4vw,48px);aspect-ratio:1;display:grid;place-items:center;border-radius:50%;
  color:var(--tk-ink);border:1.5px solid rgba(42,28,6,.4);
  transition:background .35s var(--ease),scale .35s var(--ease),border-color .35s}
.tk-social a:hover{background:rgba(42,28,6,.12);border-color:rgba(42,28,6,.7);scale:1.1}
.tk-social svg{width:19px;height:19px;pointer-events:none}

/* ---- the flow ----
   The counter-turn. Slower, wider, and going the other way, which is what keeps
   the light from ever sweeping in one consistent direction. */
.tk-flow{position:absolute;inset:-50%;z-index:0;pointer-events:none;opacity:.6;
  background:
    conic-gradient(from 0deg at 42% 46%,transparent 0deg,rgba(255,247,222,.7) 58deg,
      transparent 132deg,rgba(140,88,10,.6) 214deg,transparent 302deg),
    conic-gradient(from 210deg at 64% 58%,transparent 0deg,rgba(255,238,190,.55) 74deg,
      transparent 160deg,rgba(110,68,4,.5) 244deg,transparent 336deg);
  filter:blur(24px);
  animation:tkspin-b 14s linear infinite}
@keyframes tkspin-b{ to{ rotate:-360deg } }

@media(prefers-reduced-motion:reduce){ .tk-wash,.tk-flow{animation:none} }
@media(max-width:760px){
  .ticket{--tk-perf:78%;aspect-ratio:auto;min-height:0}
  .tk-body{gap:clamp(1.1rem,4vw,1.6rem);justify-content:flex-start}
  .tk-name{font-size:clamp(1.7rem,8vw,2.6rem)}
  .tk-stub-t{font-size:clamp(1rem,4vw,1.5rem)}
  .tk-year{font-size:clamp(2rem,9vw,3.2rem)}
}
@media(max-width:520px){
  .ticket{--tk-perf:80%;--tk-notch:15px;--tk-corner:16px;width:min(440px,94vw)}
  .tk-foot-row{gap:.7rem}
  .tk-social a{width:29px;height:29px}
  .tk-book{padding:.62rem 1.1rem}
}

/* ============ FOOTER ============ */
.tiny-foot{margin-top:clamp(2rem,5vh,3.2rem);padding-bottom:clamp(1.6rem,4vh,2.6rem);
  text-align:center;font-size:.82rem;letter-spacing:.03em;color:var(--ink-faint)}
.tiny-foot a{color:var(--ink-dim);text-decoration:underline;
  text-underline-offset:3px;text-decoration-thickness:1px;
  text-decoration-color:rgba(var(--ink-rgb),.28);
  transition:color .35s var(--ease),text-decoration-color .35s var(--ease)}
.tiny-foot a:hover{color:var(--ink);text-decoration-color:var(--g2)}

/* merged with the contact block above, no divider, no separate surface */
/* ============ RESPONSIVE ============ */
@media(max-width:1000px){
  .lf-grid{grid-template-columns:repeat(2,1fr)}
  .lf-card.wide{grid-column:span 2}
  .stats{grid-template-columns:repeat(2,1fr);gap:2rem 1rem}
  /* 01+02 pair up, 03 and both wide cards go full width */
  .proc-grid{grid-template-columns:repeat(2,1fr)}
  .proc-card{grid-column:span 1}
  .proc-c,.proc-wide{grid-column:span 2}
  .proc-wide .proc-b{max-width:38ch}
}
@media(max-width:680px){
  .only-desk{display:none}
  /* The capsule used to be hidden outright below 680, which left a phone with no
     route to Contact and no way back to the top, every other section link has
     its own heading on the page, the CTA does not. Keep the capsule, drop the
     link list. (heroPortals() also measures against .nav-pill, and a display:none
     nav made it fall back to a guessed 64px clearance.) */
  .nav{display:flex}
  .nav-links{display:none}
  .nav-pill{padding:.3rem .3rem .3rem 1rem;gap:.9rem}
  .lf-grid{grid-template-columns:1fr}
  /* these two used to force flex-start, which knocked the (now centred)
     section heading and the whole footer over to the left edge */
  .section-head{align-items:center;text-align:center}
  .foot-top{align-items:center}
  /* pill and drag hint collided side by side, stack and centre them */
  .sf-head{flex-direction:column;align-items:center;gap:.6rem;text-align:center}
  .lf-head{margin-top:3.4rem}
  /* one card per row; the wide cards stack their artwork under the copy */
  .proc-grid{grid-template-columns:1fr;gap:.85rem}
  .proc-card,.proc-c,.proc-wide{grid-column:span 1}
  .proc-card{padding:1.9rem 1.5rem 1.8rem}
  .proc-art,.proc-art-cam{height:148px}
  .proc-t,.proc-b{max-width:none}
  .proc-wide{flex-direction:column;align-items:stretch;padding:1.9rem 1.5rem 1.8rem}
  .proc-side{padding-top:1.2rem}
  .proc-wide .proc-t,.proc-wide .proc-b{max-width:none}
  .proc-panel{flex:none;padding:1.5rem 0 .2rem}
  .proc-mac{width:92%}
  /* the platform arc needs clearance on its left, so the pills sit right here too */
  .proc-pills{flex:none;align-items:flex-end;padding:1.8rem 0 1.9rem;gap:.8rem}
  /* stack instead of overlaying: photo on top, name below. The frame stays
     portrait-ish, a 4/3 box crops the source (620x992) so hard it cut his
     chin off, and it no longer buries the name now that they're stacked. */
  .pf-3d{display:flex;flex-direction:column;align-items:center;gap:1.4rem}
  .pf-anchor{order:-1;grid-area:auto;width:clamp(190px,56vw,260px);aspect-ratio:4/5;
    margin-inline:auto;align-self:center}
  .pf-photo{border-radius:22px}
  .pf-photo img{object-position:center 22%}
  .pf-name{grid-area:auto;font-size:clamp(2.6rem,11.5vw,4.4rem);text-align:center}
  /* JS splits the two lines left/right on desktop; stacked and centred here,
     that drift just reads as crooked, so both lines stay put */
  .pf-first,.pf-last{transform:none!important}
  /* sits above the photo now, not beside it, it was clipping off-screen */
  .pf-hint{top:auto;bottom:calc(100% + 4px);right:auto;left:0}
  .pf-hint-box{font-size:.74rem;padding:.42rem .75rem}
  .pf-hint-curve{width:58px;height:44px;margin-left:1.6rem}
  /* no tap needed on mobile, the card sits open under the photo and name */
  .pf-drawer{grid-template-rows:1fr}
  .ticket{opacity:1;transform:none}
}
/* the fan spans roughly 4.5x a card, so narrow screens need a smaller card
   and a tighter spread or the outer cards run off the viewport */
@media(max-width:900px){ .fan{--fan-w:168px} }
@media(max-width:700px){ .fan{--fan-w:clamp(150px,42vw,212px)} }  /* script.js drops to 1 a side */

@media(prefers-reduced-motion:reduce){
  .blob,.grain,.btn-fluid::after,
  /* slow looping oscillations and the pulsing status dot are exactly the
     vestibular triggers this query exists for */
  .pf-hint-curve,
  .reel-char,.reel-live.exiting{animation:none!important}
  .reel-col{transition:none!important}
  /* heroCrown() parks its rings; this covers the CSS side */
  .cr-card{transition:none!important}
  /* the fan's spring is JS-side and already gated on REDUCE; this covers the
     CSS fallback path so a slot can never ease into place on its own */
  .fan-slot,.fan-card{transition:none!important}
  /* heroPortals() parks one clip and two chips at rest instead of looping them */
  *{scroll-behavior:auto!important}
}
/* Frost the glass rather than dropping the surface: every translucent layer on
   the page, not just the four that had it, a half-covered set reads as broken
   rather than as a preference being honoured. */
@media(prefers-reduced-transparency:reduce){
  .glass,.tag-pill,.marquee,
  .nav-pill,.hero-cta,.faq-q,.proc-pill,.pthumb,.plog,.pcount-badge,
  .pf-hint-box,.fan-play,.fan-sound,.pf-play,.pf-mute{
    background:rgba(var(--panel-rgb),.96);backdrop-filter:none;-webkit-backdrop-filter:none}
  .reel,.marquee{background:rgba(var(--panel-rgb),.96)}
}
/* Near-solid backgrounds and a defined border, so nothing depends on a hairline
   of translucency to separate it from what is behind it. */
@media(prefers-contrast:more){
  :root{--ink-dim:rgba(var(--ink-rgb),.86);--ink-faint:rgba(var(--ink-rgb),.7);
        --line:rgba(var(--ink-rgb),.34);--glass-brite:rgba(255,201,158,.5)}
  .glass,.nav-pill,.hero-cta,.faq-q,.tag-pill,.proc-card,.lf-card,.reel,
  .fan-play,.fan-sound,.pf-play,.pf-mute,.tk-book{
    background:var(--warm-solid);backdrop-filter:none;-webkit-backdrop-filter:none;
    border:1px solid rgba(var(--ink-rgb),.5)}
  .fan-card,.reel-face{border:1px solid rgba(var(--ink-rgb),.45)}
  .grain{display:none}
  .tk-social a{border-color:rgba(42,28,6,.75)}
}

/* ============ MOBILE PASS ============
   Everything below 680px only. The desktop layout is untouched.

   The page was roughly 8500px on a phone, most of it air: every section carried
   12vh of padding top and bottom, which is generous on a wide screen and a dead
   scroll on a narrow one. Plus six long-form cards stacked to 1200px and a
   five-card process column at 2180px. This pass is about density. */
@media(max-width:680px){

  /* ---- section rhythm ---- */
  .work,.proc,.voices{padding-block:clamp(2.6rem,7vh,3.6rem) clamp(2rem,5vh,3rem)}
  .stats-wrap{padding-block:clamp(2.4rem,6.5vh,3.4rem)}
  .faq{padding-block:clamp(2.6rem,7vh,3.6rem) clamp(1.4rem,3vh,2rem)}
  .worked{padding-block:clamp(2rem,5.5vh,3rem)}
  .cta-final{padding-block:clamp(2.4rem,6vh,3.4rem) clamp(1rem,2vh,1.6rem)}
  .section-head,.sf-head,.lf-head{margin-bottom:clamp(1.2rem,3vh,1.8rem)}

  /* ---- long-form: a swipeable track, not a column ----
     scroll-padding makes a snapped card land inset from the edge rather than
     flush against it, so the next one peeks and the track reads as continuous. */
  .lf-wrap{position:relative}
  .lf-grid{display:flex;grid-template-columns:none;
    overflow-x:auto;overflow-y:visible;
    scroll-snap-type:x mandatory;scroll-padding-inline:var(--edge);
    gap:.7rem;max-width:none;
    padding-inline:var(--edge);margin-inline:calc(var(--edge) * -1);
    -webkit-overflow-scrolling:touch;scrollbar-width:none}
  .lf-grid::-webkit-scrollbar{display:none}
  .lf-card{flex:0 0 84%;scroll-snap-align:start}
  .lf-nav{display:flex;justify-content:center;gap:.7rem;margin-top:1.1rem}
  .lf-arrow{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;
    color:var(--ink);background:var(--glass);border:1px solid rgba(var(--hi-rgb),.16);
    backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
    transition:opacity .3s var(--ease),scale .3s var(--ease)}
  .lf-arrow:active{scale:.92}
  .lf-arrow:disabled{opacity:.3}

  /* ---- process: five rows, one per step ----
     Two up gave every tile 152px of measure, which put "Raw Clips In,
     Rewatchables Out" on three lines over a body set four words wide, and left
     the two tiles in a row stretched to whichever of them was taller. Five full
     width rows instead: the number in a rail on the left, the words to the right
     of it, every card the height of its own copy. It reads as a numbered list,
     which is what the section is.

     The five cards are not built alike, 01 to 03 carry their copy directly and
     04 and 05 nest it in .proc-side, so the row is laid out on the card and the
     wrapper is flattened with display:contents rather than restyled twice. */
  .proc-grid{grid-template-columns:1fr;gap:.5rem;perspective:none}
  .proc-card,.proc-card.proc-wide,.proc-card.proc-c,.proc-card:last-child{
    grid-column:span 1}
  .proc-card{display:grid;grid-template-columns:1.85rem 1fr;
    align-items:start;column-gap:.5rem;row-gap:.28rem;
    padding:.95rem 1rem 1rem;border-radius:14px;text-align:left}
  .proc-side{display:contents}
  .proc-txt{display:contents}
  /* out of the corner and into the rail, so nothing sits on top of the title */
  .proc-step{position:static;grid-column:1;grid-row:1;
    font-size:.72rem;font-weight:700;letter-spacing:.06em;
    color:var(--g2);padding-top:.06em}
  /* both halves of the pair are named, the desktop rule that centres the title
     in a two-line box is written .proc-card:not(.proc-wide) .proc-t and outranks
     a bare .proc-t whatever order it lands in */
  .proc-card:not(.proc-wide) .proc-t,.proc-wide .proc-t{grid-column:2;grid-row:1;
    display:block;min-height:0;margin-inline:0;max-width:none;
    font-size:.95rem;line-height:1.28;letter-spacing:-.02em}
  .proc-b,.proc-wide .proc-b{grid-column:2;grid-row:2;
    margin-top:0;margin-inline:0;max-width:none;
    font-size:.815rem;line-height:1.5}

  /* ---- testimonials ----
     The stage is sized by an invisible ghost holding the LONGEST quote, so the
     arrows sit wherever that longest one ends no matter which quote is showing.
     On a phone that left a hole under every short quote. The ghost keeps doing
     its job horizontally; vertically the block just closes up. */
  .reel{gap:.4rem}
  .reel-stage{height:11.5rem}
  .voices .section-head{margin-bottom:1.2rem}
  .reel-body{padding:1.1rem 1.1rem 1rem}
  .reel-text{min-height:0}
  .reel-nav{margin-top:.75rem}
  .reel-a{margin-top:.5rem}

  /* ---- process: every graphic goes ----
     At two-up each thumb was about 130px of a 160px-wide card, so the drawing
     was most of the tile and the words were the afterthought. On a phone the
     words are the point. The laptop on 04 and the status pills on 05 go with
     them: shrunk to a phone they were a stamp floating in dead space, and they
     were the reason those two rows were twice the height of the copy in them. */
  .proc-art,.pthumb,.proc-panel,.proc-pills{display:none}

  /* ---- stats: four across ----
     Stacked two-up they took a screen to say four numbers. */
  .stats{grid-template-columns:repeat(4,1fr);gap:.6rem .3rem}
  .stat-n{font-size:clamp(1.15rem,5.4vw,1.7rem);letter-spacing:-.04em}
  .stat-suffix{font-size:clamp(.7rem,2.9vw,.95rem);margin-left:1px}
  .stat p{font-size:.56rem;letter-spacing:.045em;margin-top:.35rem;line-height:1.25}

  /* ---- the ticket: no 3D on a phone ----
     The card was rendering half painted after a scroll down, up and down again,
     while measuring correct at every position, so it is the compositing and not
     the layout. The stack it sat in is the worst case a compositor can be handed:
     a six-layer mask-composite shape, two drop-shadows as a filter, a
     mix-blend-mode child, will-change:transform, and preserve-3d inside a
     perspective, all promoting the same subtree to its own layer whose paint
     bounds then go stale.

     None of that is doing any work here. The tilt it exists for is cursor-driven
     and contactBlock() now leaves it alone on a coarse pointer, so on a phone the
     depth is machinery with nothing to drive it. The shape keeps its mask and its
     shadow, which are what the card looks like, and gives up the promotion, which
     is only what it looked like it might need. */
  .cta-final,.pf-drawer-in{perspective:none}
  .pf,.pf-3d,.ticket,.tk-body,.tk-top{transform-style:flat}
  .pf-3d,.ticket{will-change:auto}
  /* belt and braces: if a stray pointermove ever reaches the tilt, a rotation
     left inline on the card cannot survive here */
  .ticket{transform:none}

  /* ---- the ticket ----
     At 367px the three-column ticket had 73px of stub, a 293px body and a
     social column fighting for the same space. The stub thins right down, the
     socials go back to a row under the signature, and the whole thing stacks. */
  /* 82% left the stub 72px wide with the type 29px off the edge and the year
     invisible behind it, which reads as a card sliced down the side rather than
     a ticket with a stub. 70% gives it 120px and the shape comes back. */
  .ticket{--tk-perf:70%;--tk-notch:13px;--tk-corner:14px;
    width:min(400px,94vw);aspect-ratio:auto}
  /* Everything on the ticket comes down a size on a phone. At 393px the card was
     260px tall and every element inside it was sized for a desktop card that had
     been narrowed rather than redrawn, so the name, the button, the WhatsApp
     circle and the four social buttons all read as too big for the space they
     were in. Each value below is a step down, and the padding and gaps come in
     with them, which is where most of the height is recovered. */
  .tk-body{padding:1.05rem 1.05rem 1rem;gap:.65rem}
  /* the name is authored as "Amal<br />Damodar" for the desktop card, where two
     stacked lines are the look. On a phone the card is wide and short, so the
     break is dropped and the whole name sits on one line. */
  /* Measured against the text, not the box: "Amal Damodar" runs 170px inside a
     225px content box at 393px and 157 inside 203 at 360px, so nowrap has about
     50px of headroom even if a fallback face loads wider than the display one. */
  .tk-name{font-size:clamp(1.15rem,5.6vw,1.6rem);line-height:.95;white-space:nowrap}
  .tk-name br{display:none}
  .tk-actions{width:100%;gap:.55rem}
  .tk-book{flex:1 1 auto;justify-content:center;padding:.62rem 1rem;font-size:.84rem}
  .tk-wa{width:40px}
  .tk-foot{flex-direction:column;align-items:flex-start;gap:.55rem}
  .tk-social{position:static;translate:none;flex-direction:row;gap:.42rem}
  /* height as well as width. An earlier breakpoint pins both to 29px, so setting
     width alone left these 32 wide and 29 tall: ovals, not circles. flex-shrink
     is off too, because in a row that runs out of room flex would squeeze them
     back out of round. */
  .tk-social a{width:32px;height:32px;flex:0 0 auto}
  .tk-sign img{height:22px}
  .tk-stub-t{font-size:clamp(.78rem,3.2vw,.98rem);letter-spacing:.03em}
  /* the watermark shrinks with the rest, and a smaller one sits behind the stub
     label instead of straight through it */
  .tk-year{font-size:clamp(1.7rem,7.2vw,2.4rem)}
  /* The copyright is the last element on the page and the viewport meta carries
     viewport-fit=cover, so on a notched phone the page runs under the home
     indicator and Safari's bottom bar. 1.6rem of padding put this line inside
     that strip, where it is either half cut or not visible at all. Nothing else
     on the site ends that low, which is why this was the only line affected.
     The inset is read from the device and the old value stays as the floor for
     every phone that has no inset to report. */
  .tiny-foot{margin-top:1.8rem;font-size:.76rem;
    padding-bottom:max(1.6rem,calc(env(safe-area-inset-bottom) + 1.2rem))}
  /* it also must not be inside anything that can be promoted with the ticket */
  .tiny-foot{position:relative;z-index:1}
}

