/* ============================================================
   Arkam Kabeer — portfolio
   Racing-livery palette: deep red, white, gold, black
   ============================================================ */

:root{
  /* ── surfaces ─────────────────────────────────────────── */
  /* --bg is sampled from the backdrop of assets/portrait.png so the photo's
     own background disappears into the page. Change the photo, resample. */
  --bg:        #950202;              /* page red                    */
  --bg-soft:   #7a0101;              /* deeper red                  */
  --bg-card:   rgba(0,0,0,.17);      /* translucent card on red     */
  --bg-card-2: rgba(0,0,0,.28);      /* pressed / secondary card    */
  --line:      rgba(255,255,255,.14);

  /* ── ink ──────────────────────────────────────────────── */
  --ink:       #ffffff;
  --ink-60:    rgba(255,255,255,.74);
  --ink-45:    rgba(255,255,255,.55);

  /* ── accent ───────────────────────────────────────────── */
  --yellow:    #c9a063;              /* gold — the accent           */
  --gold-line: rgba(201,160,99,.42); /* hairline borders            */
  --on-gold:   #4a0308;              /* text sitting on gold        */

  /* ── the work stretch — warm off-black, not a hard #000 ─ */
  --dark:      #141110;
  --dark-card: #1e1917;
  --white:     #fff;

  --dock-w:    252px;
  --gutter:    clamp(20px, 3.2vw, 56px);
  /* The dock is fixed over the left edge, so content centred in the content box
     reads slightly left of the space it actually sits in. Centred sections
     nudge right by this much to correct for it — one value so they all agree. */
  --optical-shift: clamp(10px, 2vw, 40px);
  /* fitMark() overwrites both on load and resize; these are pre-JS fallbacks. */
  --mark: clamp(90px, 24vw, 420px);
  --letters-bottom: 40vh;

  /* tighter than the original build — closer to a pack than a pill */
  --r-sm:      8px;
  --r-md:      10px;
  --r-lg:      12px;
  --r-xl:      14px;

  --ease: cubic-bezier(.22,1,.36,1);
}

*,*::before,*::after{ box-sizing:border-box; }
html,body{ margin:0; padding:0; }
html{ -webkit-text-size-adjust:100%; }

body{
  /* Three layers, painted bottom-up: the flat red, a soft glow off the top
     centre, then a vignette that darkens the corners. Fixed attachment so the
     lighting stays put while the page scrolls, the way it would on a printed
     poster rather than sliding along with the content. */
  background:
    radial-gradient(115% 75% at 50% 0%,   rgba(255,255,255,.09) 0%, transparent 58%),
    radial-gradient(110% 95% at 50% 45%,  transparent 38%, rgba(0,0,0,.40) 100%),
    var(--bg);
  background-attachment:fixed;
  color:var(--ink);
  font-family:'Switzer',-apple-system,BlinkMacSystemFont,'Segoe UI',Arial,sans-serif;
  font-weight:400;
  font-size:16px;
  line-height:1.45;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
/* Film grain over the background. Generated by an SVG turbulence filter inlined
   as a data URI — no image request, no asset to keep track of, and it tiles
   seamlessly via stitchTiles.

   It sits at z-index 0, which puts it above the body background but below both
   the hero (z-index auto, and later in the DOM) and .main (z-index 10). That is
   deliberate: grain laid over the whole page would sit on top of body copy and
   soften it. This way it textures the red and nothing else — the black work
   section and the white band paint over it with their own backgrounds. */
body::before{
  content:'';
  position:fixed; inset:0; z-index:0;
  pointer-events:none;
  /* Two scales, like the reference: fine grain over broad blotching. One
     turbulence pass at a high baseFrequency gives the grain, a second at a very
     low one gives the soft cloudy variation that stops the red reading as a
     printed flat. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23g)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='600' height='600' filter='url(%23m)'/%3E%3C/svg%3E");
  background-size:180px 180px, 620px 620px;
  opacity:.22;
  mix-blend-mode:overlay;
}

/* overflow alone is enough to hold scrolling. height:100vh also collapsed the
   document while the intro ran, so ScrollTrigger measured every section
   against a one-screen page. */
body.is-locked{ overflow:hidden; }

img,svg{ display:block; max-width:100%; }
/* Kills the native drag-off ghost, so the portrait can't be pulled out of the
   page onto the desktop. WebKit/Blink honour the property; Firefox needs the
   dragstart handler in main.js. See the note there — this deters casual copying,
   it is not protection. */
img{ -webkit-user-drag:none; user-select:none; -webkit-user-select:none; }
a{ color:inherit; text-decoration:none; }
ul{ margin:0; padding:0; list-style:none; }
button{ font:inherit; color:inherit; border:0; background:none; cursor:pointer; }
h1,h2,h3,h4,p{ margin:0; }
::selection{ background:var(--yellow); color:var(--on-gold); }

/* ── scrollbar ─────────────────────────────────────────────
   Hidden. Its track is painted against the root background, so over the black
   work section it read as a red stripe down the edge. Scrolling is smooth-
   driven anyway, and losing the bar also makes 100vw equal the content width,
   which kills the sliver those full-bleed sections used to leave. */
html{ scrollbar-width:none; -ms-overflow-style:none; }
::-webkit-scrollbar{ width:0; height:0; }

/* ============================================================
   PRELOADER
   ============================================================ */
/* No preloader element any more. The page background is already the hero red,
   so the intro animates the real hero into place rather than covering it.

   `intro-armed` is set on <html> by the inline script in index.html, before
   first paint. It holds the hero's opening pose so nothing flashes finished
   while the deferred scripts load; main.js removes it when the timeline ends.
   Everything here is transform/opacity only — no layout properties — so the
   finished frame is whatever the normal CSS says it is. */
/* Stage 1 is the name alone on the red. The page background is already that
   exact red and every other hero element is hidden below, so no overlay and
   no second red shade is needed — which is also why the title never has to be
   swapped or reparented later.

   The heading is parked at the vertical centre; its line box is .79em tall,
   so half of that off 50vh centres it. JS re-measures exactly — this value
   only has to stop a flash before the timeline starts. */
.intro-armed .hero__mark{ transform:translate3d(0, calc(50vh - .395em), 0); }
.intro-armed .hero__mark .l{ opacity:0; will-change:transform, opacity, filter; }
.intro-armed .hero__cut{ opacity:0; }
.intro-armed .hero__nav,
.intro-armed .hero__kicker,
.intro-armed .hero__note,
.intro-armed .hero__copy,
.intro-armed .hero__stat,
.intro-armed .hero__traits{ opacity:0; }


/* ============================================================
   CURSOR
   ============================================================ */
.cursor{
  position:fixed; top:0; left:0; z-index:8000;
  width:74px; height:74px; margin:-37px 0 0 -37px;
  border-radius:50%; background:var(--yellow); color:var(--on-gold);
  display:flex; align-items:center; justify-content:center;
  font-size:11px; font-weight:800; letter-spacing:.12em; text-transform:uppercase;
  pointer-events:none; opacity:0; transform:scale(.2);
  will-change:transform;
}
@media (hover:none){ .cursor{ display:none; } }

/* ============================================================
   BUTTONS / PILLS
   ============================================================ */
.btn{
  position:relative; isolation:isolate; overflow:hidden;
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  height:50px; padding:0 26px; border-radius:var(--r-sm);
  font-weight:700; font-size:16px; letter-spacing:-.01em;
  transition:transform .4s var(--ease), box-shadow .4s var(--ease);
  will-change:transform;
}
/* fill sweeps up from the bottom edge on hover */
.btn::before{
  content:''; position:absolute; inset:0; z-index:-1;
  background:#e8cf9c; transform:translateY(101%);
  transition:transform .45s var(--ease);
}
.btn:hover::before,.btn:focus-visible::before{ transform:translateY(0); }
.btn__ico{
  width:15px; height:15px; flex:none;
  transition:transform .4s var(--ease);
}
.btn:hover .btn__ico{ transform:translate(3px,-3px); }

/* Label roll — the visible line lifts out while its clone rises in.
   Built by buttonRoll() in main.js; these are the resting styles. */
.roll{
  position:relative; display:inline-block; overflow:hidden;
  vertical-align:top;
}
.roll > span{ display:block; white-space:nowrap; }
.roll__b{ position:absolute; left:0; top:0; width:100%; }

.btn--yellow{ background:var(--yellow); color:var(--on-gold); }
.btn--yellow:hover,.btn--yellow:focus-visible{
  transform:translateY(-3px); box-shadow:0 14px 30px rgba(0,0,0,.36);
}
.btn--lg{ height:58px; padding:0 34px; font-size:18px; }

.pill{
  display:inline-flex; align-items:center; height:26px; padding:0 12px;
  border:1.5px solid var(--yellow); border-radius:99px; color:var(--yellow);
  font-size:11px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
}
.pill--dark{ border-color:var(--yellow); color:var(--yellow); }

/* ============================================================
   TYPE
   ============================================================ */
.h-xl{
  font-weight:800; letter-spacing:-.045em; line-height:.94;
  font-size:clamp(40px, 6.4vw, 96px);
}
.h-xl--light{ color:#fff; }
.lead{
  max-width:46ch; color:var(--ink-60);
  font-size:clamp(15px,1.15vw,18px); line-height:1.55;
}
.lead--light{ color:rgba(255,255,255,.62); }

.sec{ position:relative; padding:clamp(90px,11vw,180px) var(--gutter); }
/* First section after the hero. Barely any top padding — the hero's own tail
   is the breathing room, and anything more reads as a blank screen. */
.about{ padding-top:clamp(24px,3vw,56px); }
.sec__head{ max-width:1200px; }
.sec__head .pill{ margin-bottom:22px; }
.sec__head .h-xl{ margin-bottom:26px; }
.sec__head--center{ text-align:center; margin:0 auto; }
.sec__head--center .lead{ margin-inline:auto; }
.sec__head--row{ display:flex; justify-content:space-between; align-items:flex-end; gap:30px; flex-wrap:wrap; }

/* visually hidden, still read by search engines and screen readers */
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}

/* reveal helpers */
[data-rev]{ opacity:0; transform:translateY(18px); }
.split-line{ display:block; overflow:hidden; }
.split-line > span{ display:block; }

/* ============================================================
   HERO
   ============================================================ */
/* The morph scrubs across height-minus-one-viewport. Whatever is left after
   the timeline finishes is dead scroll, so this is kept just long enough for
   the morph and the exit tweens are stretched to fill it. */
.hero{ height:175vh; position:relative; }
.hero__stage{
  position:sticky; top:0; height:100vh; overflow:hidden;
  display:block;
}

/* Wordmark layer — sits behind him. Archivo's width axis is pulled in to
   match the artwork's condensed proportion (its cap A measures 440x598,
   ratio .736) rather than horizontally squashing a normal-width face,
   which would thin the vertical stems. fitMark() sets --mark. */
/* Clips the heading's entrance so it can start off-screen right without
   widening the document. Purely a mask — no layout of its own. */
.hero__mark-clip{
  position:absolute; inset:0; z-index:1;
  overflow:hidden; pointer-events:none;
}
.hero__mark{
  position:absolute; top:0; left:0; width:100%;
  padding:0 var(--gutter);
  font-family:'Archivo','Switzer',-apple-system,Arial,sans-serif;
  font-weight:900; font-variation-settings:'wdth' 66,'wght' 900;
  color:#fff;
  font-size:var(--mark);
  line-height:.79; letter-spacing:-.015em;
  white-space:nowrap;
  transform-origin:left top;
  will-change:transform;
}
.hero__mark .l{ display:inline-block; }

/* Cut-out layer — in front, so the letters pass behind him. Same crop as the
   composite used, and the same source frame, so he lands identically. */
.hero__cut{
  position:absolute; inset:0; z-index:2;
  overflow:hidden;
  will-change:transform,filter,opacity;
}
.hero__cut picture, .hero__cut img{
  display:block; width:100%; height:100%;
}
.hero__cut img{ object-fit:cover; object-position:50% 0%; }

/* nav row — sits just under the baked-in letters, whose position
   fitMark() measures and publishes as --letters-bottom */
.hero__nav{
  position:absolute; top:calc(var(--letters-bottom, 44vh) + 10px); left:0; width:100%;
  padding:0 var(--gutter);
  display:flex; justify-content:space-between; z-index:4;
  pointer-events:auto;
}
.hero__nav-group{ display:flex; gap:0; }
.hero__nav-group li{ display:flex; align-items:center; }
.hero__nav-group li + li::before{
  content:'|'; margin:0 14px; opacity:.45; font-weight:400; color:var(--yellow);
}
.hero__nav a{
  font-weight:700; font-size:clamp(11px,1.05vw,15px);
  letter-spacing:.02em; text-transform:uppercase; white-space:nowrap;
  display:inline-block; will-change:transform; color:#fff;
}

/* glass cards — thin gold rule, barely-there fill */
.glass{
  background:rgba(0,0,0,.10);
  border:1px solid var(--gold-line);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  border-radius:var(--r-sm);
}
.hero__stat{
  position:absolute; z-index:3; display:flex; align-items:center; gap:14px;
  padding:16px 20px; will-change:transform,opacity;
}
/* the cards tuck in beside him rather than hugging the page edge */
/* far enough right to tuck against him and overlap his edge, as in the reference */
.hero__stat--a{ left:clamp(var(--gutter), 24vw, 420px); top:61%; }
.hero__stat--b{ left:clamp(var(--gutter), 25vw, 435px); top:78%; flex-direction:column; gap:2px; padding:14px 22px; }
.hero__stat-ico{ width:52px; color:var(--yellow); }
.hero__stat-big{ font-size:42px; font-weight:900; color:var(--yellow); line-height:1; letter-spacing:-.04em; }
.hero__stat-txt{ font-size:14px; font-weight:700; color:var(--yellow); line-height:1.15; text-align:center; }
.hero__stat--a .hero__stat-txt{ text-align:left; }
.hero__stat-txt strong{ display:block; font-size:16px; }

.hero__traits{
  /* pinned under the nav row so it can never sit on top of it, and pulled in
     from the right edge so it tucks against his shoulder as in the reference */
  position:absolute; right:clamp(var(--gutter), 17vw, 300px);
  top:calc(var(--letters-bottom) + 100px); z-index:3;
  padding:16px 22px; will-change:transform,opacity;
}
.hero__traits li{
  display:flex; align-items:center; gap:12px;
  font-size:16px; font-weight:700; color:#fff; padding:4px 0;
}
.tico{ width:18px; height:18px; background:var(--yellow); display:block; }
.tico--1{ clip-path:circle(50% at 50% 50%); }
.tico--2{ clip-path:polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%); }
.tico--3{ clip-path:polygon(0 100%,0 25%,25% 55%,50% 5%,75% 55%,100% 25%,100% 100%); }
.tico--4{ clip-path:polygon(50% 0,100% 30%,100% 70%,50% 100%,0 70%,0 30%); }
.tico--5{ clip-path:polygon(30% 0,50% 30%,70% 0,100% 30%,70% 50%,100% 70%,70% 100%,50% 70%,30% 100%,0 70%,30% 50%,0 30%); }

/* Kicker and note — a matched pair sitting low in the hero, one hugging each
   gutter and sharing a baseline. Same face, weight and colour; they differ
   only in which edge their text aligns to. */
.hero__kicker,
.hero__note{
  position:absolute; bottom:7%; z-index:5;
  font-size:clamp(12px,1.05vw,17px); font-weight:700; line-height:1.45;
  letter-spacing:-.015em; color:var(--yellow);
}
.hero__kicker{ left:var(--gutter);  text-align:left;  }
.hero__note  { right:var(--gutter); text-align:right; }

.hero__kicker .line, .hero__note .line{ display:block; overflow:hidden; }
/* the breaks are authored, so never let a line re-wrap on its own */
.hero__kicker .line > span, .hero__note .line > span{ display:block; white-space:nowrap; }

/* buttons sit low and centred, as in the reference composition */
.hero__copy{
  position:absolute; left:50%; bottom:7%; transform:translateX(-50%);
  z-index:5; width:fit-content; max-width:86vw;
  will-change:transform,opacity;
}
.hero__cta{ display:flex; gap:14px; justify-content:center; }

/* ============================================================
   DOCK
   ============================================================ */
.dock{
  position:fixed; left:var(--gutter); top:0; z-index:60;
  width:var(--dock-w); height:100vh;
  padding:22px 0;
  display:flex; flex-direction:column; gap:12px; justify-content:center;
  pointer-events:none; opacity:0;
}
/* The dock is faded out over the hero but still occupies its full column, and
   a child with pointer-events:auto stays clickable even when its parent is
   none — which left the invisible menu card swallowing clicks on the hero's
   own "About Me" and "Work" links. Children stay inert until the morph
   reveals the dock and switches them on (see heroMorph). */
.dock > *{ pointer-events:none; }
.dock__card{
  background:var(--bg-card); border:1px solid var(--gold-line);
  backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px);
  border-radius:var(--r-md); padding:16px;
  opacity:0; transform:translateX(-26px);
}
.dock__brand-top{ display:flex; align-items:center; justify-content:space-between; }
.dock__logo{
  background:var(--yellow); color:var(--on-gold); padding:2px 8px; border-radius:4px;
  font-weight:900; font-size:19px; letter-spacing:-.03em;
}
.dock__logo sup{ font-size:.5em; }
.dock__social{ display:flex; gap:6px; }
.dock__social a{
  width:24px; height:24px; border-radius:5px; background:var(--yellow);
  display:grid; place-items:center;
}
.dock__social svg{ width:12px; height:12px; fill:var(--on-gold); }
.dock__bio{ margin-top:14px; font-size:12.5px; line-height:1.5; color:var(--ink-60); }

.dock__stats{ display:flex; align-items:center; gap:10px; padding:18px 10px; }
.dock__stat{ flex:1; text-align:center; font-size:11px; font-weight:800; line-height:1.2; color:var(--yellow); }
.dock__stat-sep{ width:1px; align-self:stretch; background:var(--gold-line); }
.dock__stat-num{ font-size:28px; font-weight:900; color:var(--yellow); line-height:1; margin-bottom:4px; letter-spacing:-.04em; }
.dock__stat strong{ display:block; }
.dock__stat span{ display:block; }

.dock__menu{ display:flex; flex-direction:column; gap:3px; padding:14px 12px; }
.dock__link{
  display:flex; align-items:center; gap:10px;
  padding:6px 10px; border-radius:4px;
  font-size:13px; font-weight:800; letter-spacing:.02em; text-transform:uppercase;
  align-self:flex-start;
  transition:background .3s var(--ease), color .3s;
}
.dock__link:hover{ background:rgba(255,255,255,.09); }
.dock__link.is-active{ background:var(--yellow); color:var(--on-gold); }
.mico{ width:16px; height:16px; flex:none; color:#fff; display:block; }
.dock__link.is-active .mico{ color:var(--on-gold); }
.mico svg{
  width:100%; height:100%;
  fill:none; stroke:currentColor; stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round;
}

.dock__marquee{ padding:10px 0; overflow:hidden; }
.marq{ overflow:hidden; }
.marq__row{ display:flex; gap:26px; width:max-content; align-items:center; }
.marq__row span{
  font-size:13px; font-weight:800; letter-spacing:.04em; color:var(--ink-60); white-space:nowrap;
}

.dock__mail{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  text-align:left; width:100%; padding:12px 14px;
}
.dock__mail-txt{ font-size:12.5px; color:var(--ink-60); }
.dock__mail-ico{ color:var(--yellow); }
.dock__mail-ico svg{ width:15px; height:15px; }
.dock__mail.is-copied .dock__mail-txt{ color:var(--yellow); font-weight:700; }

.dock__book{
  display:flex; align-items:center; justify-content:center;
  height:48px; border-radius:6px; background:var(--yellow); color:var(--on-gold);
  font-weight:800; font-size:16px;
  opacity:0; transform:translateX(-26px);
  transition:transform .35s var(--ease);
}
.dock__book:hover{ transform:translateY(-2px); }

/* over the black work section the cards go solid black */
.dock.is-dark .dock__card,
.dock.is-dark .dock__mail{
  background:rgba(12,12,12,.82); border-color:rgba(201,160,99,.34);
}

.burger{ display:none; }

/* ============================================================
   MAIN
   ============================================================ */
/* Pulled up so About starts arriving while the hero is still dissolving —
   without the overlap there is a stretch of empty stage between the two,
   which reads as the page having stalled. .main sits above the hero stage,
   so it slides over it cleanly. */
.main{
  position:relative; z-index:10; margin-top:-18vh;
  padding-left:calc(var(--dock-w) + var(--gutter) + 20px);
}

/* ============================================================
   JOURNEY
   ============================================================ */
.journey{ position:relative; margin-top:clamp(60px,7vw,120px); }
.journey__path{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.journey__path path{ stroke:var(--yellow); }
.journey__items{ position:relative; }

.jitem{
  position:relative; width:min(430px,74%); margin-bottom:clamp(60px,7vw,110px);
  background:var(--bg-card); border:1px solid var(--gold-line);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  border-radius:var(--r-md); padding:24px 26px 22px;
  opacity:0; transform:translateY(40px);
}
.jitem--r{ margin-left:auto; }
.jitem__year{
  font-size:clamp(46px,5.4vw,74px); font-weight:900; color:var(--yellow);
  line-height:.9; letter-spacing:-.05em; margin-bottom:10px;
  display:flex; align-items:baseline;
}
.jitem__title{ font-size:clamp(19px,1.8vw,26px); font-weight:800; letter-spacing:-.03em; margin-bottom:8px; }
.jitem__txt{ font-size:15px; color:var(--ink-60); line-height:1.5; }
.jitem__foot{ display:flex; align-items:center; gap:12px; margin-top:20px; }
.jitem__ava{
  width:48px; height:48px; border-radius:8px; flex:none;
  background:rgba(0,0,0,.4); color:var(--yellow); border:1px solid var(--gold-line);
  display:grid; place-items:center; font-weight:900; font-size:13px; letter-spacing:-.02em;
}
.jitem__meta{ font-size:14px; color:var(--ink-45); line-height:1.25; }
.jitem__meta b{ display:block; font-weight:500; color:var(--ink-60); }
.jitem__more{
  margin-left:auto; height:38px; padding:0 18px; border-radius:5px;
  background:var(--bg-card-2); border:1px solid var(--gold-line);
  font-size:14px; font-weight:600; color:var(--ink);
  display:inline-flex; align-items:center;
  transition:background .3s, color .3s, transform .3s var(--ease);
}
.jitem__more:hover{ background:var(--yellow); color:var(--on-gold); transform:translateY(-2px); }
.jitem__full{
  display:grid; grid-template-rows:0fr; transition:grid-template-rows .55s var(--ease);
}
.jitem__full > div{ overflow:hidden; }
.jitem.is-open .jitem__full{ grid-template-rows:1fr; }
.jitem__full p{ padding-top:16px; font-size:15px; line-height:1.55; color:var(--ink-60); }

.jdot{
  position:absolute; width:11px; height:11px; border-radius:50%;
  background:var(--yellow); border:1.6px solid var(--bg); z-index:3;
  transform:translate(-50%,-50%) scale(0);
  transition:transform .4s var(--ease);
}

/* ============================================================
   WORK (pinned horizontal, black stretch)
   ============================================================ */
.projects{
  /* A warm glow off the upper left plus a vignette, so the black has some
     modelling instead of reading as one flat fill. Kept very low-contrast —
     the cards are the subject here and the backdrop should stay behind them. */
  padding:0; width:100vw;
  background:
    radial-gradient(90% 70% at 22% 8%, rgba(201,160,99,.10) 0%, transparent 60%),
    radial-gradient(120% 100% at 50% 50%, transparent 45%, rgba(0,0,0,.55) 100%),
    var(--dark);
  margin-left:calc(-1 * (var(--dock-w) + var(--gutter) + 20px));
  padding-left:calc(var(--dock-w) + var(--gutter) + 20px);
}

/* Same grain as the red stretch, so the two halves of the site share a surface.
   It needs its own layer because .projects paints an opaque background over the
   one on body::before. Carried at a higher opacity than the red: overlay against
   a near-black base compresses hard toward black, so the same .22 would be
   invisible here. Sits under the cards and the heading, and takes no pointer
   events, so the horizontal drag still works. */
.projects::before{
  content:'';
  position:absolute; inset:0; z-index:0;
  pointer-events:none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='pg'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23pg)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='pm'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='600' height='600' filter='url(%23pm)'/%3E%3C/svg%3E");
  background-size:180px 180px, 620px 620px;
  opacity:.42;
  mix-blend-mode:overlay;
}
/* the pinned content has to sit above that layer */
.projects__pin{ position:relative; z-index:1; }
.projects__pin{ height:100vh; overflow:hidden; display:flex; flex-direction:column; justify-content:center; padding-right:var(--gutter); }
.projects .h-xl{ font-size:clamp(34px,4.5vw,68px); }
.projects__head{
  display:flex; justify-content:space-between; align-items:flex-end; gap:40px;
  padding-bottom:clamp(24px,2.8vw,44px); flex-wrap:wrap;
}
.projects__head .pill{ margin-bottom:16px; }
.projects__head .h-xl{ margin-bottom:0; }
.projects__track{ display:flex; gap:26px; width:max-content; will-change:transform; }
.pcard{
  position:relative; width:clamp(300px,29vw,420px); height:min(54vh,540px);
  border-radius:var(--r-md); overflow:hidden; background:var(--dark-card);
  border:1px solid rgba(255,255,255,.07);
  display:flex; flex-direction:column; justify-content:flex-end;
  isolation:isolate;
}
.pcard__bg{
  position:absolute; inset:0; z-index:-2;
  background-size:cover; background-position:center; background-repeat:no-repeat;
  transition:transform .7s var(--ease);
}
.pcard:hover .pcard__bg{ transform:scale(1.05); }
.pcard::after{
  content:''; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(to top,rgba(16,13,12,.9) 0%,rgba(16,13,12,.32) 48%,transparent 72%);
}
.pcard__top{
  position:absolute; top:16px; left:16px; right:16px; z-index:2;
  display:flex; align-items:center; justify-content:space-between; gap:10px;
}
.pcard__no{
  width:34px; height:34px; border-radius:50%;
  border:1.4px solid var(--gold-line); color:var(--yellow);
  display:grid; place-items:center; font-size:12px; font-weight:700;
}
.pcard__tags{ display:flex; gap:6px; flex-wrap:wrap; justify-content:flex-end; }
.pcard__tags span{
  height:27px; padding:0 12px; border-radius:99px;
  border:1px solid rgba(255,255,255,.3); background:rgba(0,0,0,.35);
  color:#fff; font-size:11.5px; font-weight:600; display:inline-flex; align-items:center;
  backdrop-filter:blur(6px);
}
.pcard__body{ position:relative; z-index:2; padding:26px; }
.pcard__title{ color:#fff; font-size:clamp(22px,2.1vw,30px); font-weight:800; letter-spacing:-.035em; }
.pcard__desc{ color:rgba(255,255,255,.66); font-size:14.5px; line-height:1.45; margin-top:8px; max-width:34ch; }
.pcard__go{
  position:absolute; right:22px; bottom:22px; z-index:3;
  width:44px; height:44px; border-radius:50%; background:var(--yellow);
  display:grid; place-items:center;
  transition:transform .35s var(--ease);
}
.pcard:hover .pcard__go{ transform:rotate(45deg) scale(1.08); }
.pcard__go svg{ width:16px; height:16px; }

.projects__prog{
  margin-top:26px; height:3px; background:rgba(255,255,255,.16); border-radius:99px; overflow:hidden;
}
.projects__prog i{ display:block; height:100%; width:0%; background:var(--yellow); }

/* ============================================================
   WHAT YOU GET
   ============================================================ */
/* Losing the card grid left this section only ~425px tall. Padding alone can't
   fix that: enough of it to keep Services off-screen pushes the heading down,
   and enough to lift the heading lets the Services pill peek in underneath —
   both sections sit on the same red, so there's no edge to hide behind.
   Owning a full viewport solves both. The content centres in that screen and
   Services starts cleanly below the fold, on its own tight padding. */
.what{
  text-align:center;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  justify-content:center;
  padding-top:clamp(40px,5vw,90px);
  padding-bottom:clamp(40px,5vw,90px);
}

/* Nudged off the content-box centre — see --optical-shift. */
.what__big,
.what__mid{ transform:translateX(var(--optical-shift)); }
.what__big{
  font-size:clamp(64px,13vw,200px); font-weight:900; letter-spacing:-.055em;
  line-height:.86; text-align:center; color:#fff;
}
/* The heading runs at 200px with .86 leading, so it already carries ~28px of
   empty line box under the last line. Its own margin is kept small so the
   statement reads as part of the same block rather than a detached paragraph. */
/* No bottom margin — the statement is now the last thing in the section, so the
   section's own padding sets the gap to Services. The chip pop-ups expand ~118px
   below their line, and that padding clears them. */
.what__mid{ margin:clamp(8px,1.2vw,22px) auto 0; max-width:1000px; }
.what__mid .pill{ margin-bottom:26px; }
.what__stmt{
  font-size:clamp(26px,3.6vw,56px); font-weight:800; letter-spacing:-.04em;
  line-height:1.12; color:#fff;
}
/* A chip is a capability folded down to an icon. Hovering unfolds it into the
   full card — which, with the grid gone, is the only place this copy appears. */
/* The chip keeps a fixed footprint in the sentence; the pill that grows out of
   it is absolutely positioned, so the expansion is purely visual and can never
   re-wrap the paragraph. Growing it inline was what caused the flicker: the
   reflow moved the chip out from under the cursor, hover dropped, it snapped
   shut, and the two states chased each other. */
.chip{
  position:relative; display:inline-block; vertical-align:middle;
  width:1.35em; height:.92em; margin:0 .1em;
  padding:0; border:0; background:none;
  font:inherit; line-height:1; cursor:pointer;
}
/* The pop is the chip's own box grown into a full card. Collapsed it is
   exactly the chip's size; on hover it opens downward, overlaying the
   sentence. Because it is absolute, nothing around it moves. */
.chip__pop{
  position:absolute; left:50%; top:50%; z-index:4;
  transform:translate(-50%,-50%);      /* grows out from the chip's centre */
  box-sizing:border-box;
  width:1.35em; height:.92em;              /* identical to the chip */
  overflow:hidden;
  border-radius:.16em;
  background:var(--bg-card-2); border:1px solid var(--gold-line);
  color:var(--yellow);
  transition:width .45s var(--ease), height .45s var(--ease),
             border-radius .45s var(--ease), background .3s, border-color .3s;
}
.chip__ico{
  position:absolute; left:50%; top:50%;
  width:.42em; height:.42em; background:currentColor;
  transform:translate(-50%,-50%);
  transition:left .45s var(--ease), top .45s var(--ease),
             width .45s var(--ease), height .45s var(--ease), transform .45s var(--ease);
}
.chip__txt{
  position:absolute; left:20px; right:20px; top:70px;
  opacity:0; transform:translateY(10px); text-align:left;
  transition:opacity .3s .1s, transform .4s .1s var(--ease);
}
.chip__txt b{
  display:block; margin-bottom:9px;
  font-size:18px; font-weight:800; letter-spacing:-.02em; color:#fff;
}
.chip__txt em{
  display:block; font-style:normal;
  font-size:13.5px; font-weight:500; line-height:1.5; letter-spacing:0;
  color:var(--ink-60);
}

.chip:hover .chip__pop,
.chip:focus-visible .chip__pop{
  width:300px; height:236px; z-index:9;
  border-radius:12px;
  background:var(--bg-soft); border-color:var(--yellow);
}
.chip:hover .chip__ico,
.chip:focus-visible .chip__ico{
  left:20px; top:22px; width:26px; height:26px; transform:none;
}
.chip:hover .chip__txt,
.chip:focus-visible .chip__txt{ opacity:1; transform:none; }

.chip--1 .chip__ico{ clip-path:polygon(0 20%,18% 100%,34% 45%,50% 100%,68% 20%); }
.chip--2 .chip__ico{ clip-path:polygon(0 100%,0 40%,30% 40%,30% 100%,40% 100%,40% 0,70% 0,70% 100%); }
.chip--3 .chip__ico{ clip-path:polygon(50% 0,63% 37%,100% 50%,63% 63%,50% 100%,37% 63%,0 50%,37% 37%); }
.chip--4 .chip__ico{ clip-path:circle(50% at 50% 50%); }
.chip--5 .chip__ico{ clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); }



/* ============================================================
   SERVICES
   ============================================================ */
/* Padding kept well under the usual section value — What You Get above it sits on
   the same red, so the two paddings read as one gap rather than two, and the head
   would otherwise start a long way down the screen. */
.services{ padding-top:clamp(24px,3vw,56px); }

/* No optical nudge here. The card grid fills the content box edge to edge, so it
   has no slack to move into: shifting it right either ran it off the viewport or
   narrowed the cards to pay for the move. Left centred in the space beside the
   dock, which is where the section actually sits. */

.plans{
  /* Pulled closer to the lead above. The section head already ends with 26px of
     its own margin, so a full 90px on top of that read as a detached block. */
  margin-top:clamp(24px,2.9vw,46px);
  display:grid; gap:16px; grid-template-columns:repeat(auto-fit,minmax(290px,1fr));
  align-items:stretch;
}
.plan{
  background:var(--bg-card); border:1px solid var(--gold-line);
  border-radius:var(--r-lg); padding:30px 28px 32px;
  display:flex; flex-direction:column; min-height:100%;
  opacity:0; transform:translateY(30px);
}
.plan__head{ display:flex; align-items:center; gap:12px; margin-bottom:26px; }
.plan__ico{ width:36px; height:36px; border-radius:7px; background:var(--yellow); display:grid; place-items:center; }
.plan__ico svg{ width:18px; height:18px; }
.plan__name{ font-size:21px; font-weight:800; letter-spacing:-.03em; }
.plan__price{ font-size:30px; font-weight:800; letter-spacing:-.04em; display:flex; align-items:baseline; gap:8px; color:var(--yellow); }
.plan__price em{ font-style:normal; font-size:14px; font-weight:500; color:var(--ink-45); }
.plan__desc{ margin-top:16px; font-size:14.5px; color:var(--ink-60); line-height:1.55; }
.plan__list{ margin-top:26px; display:flex; flex-direction:column; gap:12px; }
.plan__list li{ display:flex; gap:10px; font-size:14.5px; line-height:1.4; }
.plan__list li::before{
  content:''; width:13px; height:13px; margin-top:4px; flex:none;
  border-radius:50%; border:2px solid var(--yellow);
}

/* ============================================================
   CTA
   ============================================================ */
.cta{ padding-block:clamp(110px,13vw,200px); text-align:center; }
.cta__title{
  font-weight:900; letter-spacing:-.05em; line-height:.92;
  font-size:clamp(46px,8.4vw,132px);
}
.cta__l1,.cta__l2{ display:block; color:#fff; }
/* The mask and each word must be exactly the same height, or the window shows a
   slice of the next word under the current one. 1.28em rather than the title's
   .92 line-height because that box is shorter than the glyphs — it clipped the
   descenders on "Tracking" and "Strategy" (1.2em still cut them by half a pixel;
   half of any extra leading goes below the baseline). The word centres in the
   taller box, and only one is ever visible, so the headroom costs nothing. */
.cta__rot{
  display:block; height:1.28em; overflow:hidden; position:relative; color:var(--yellow);
}
/* Stacked, not stepped through — a swap animates two words at once, so they have
   to occupy the same line. Pinned to both edges rather than just the left, so
   each word centres itself in the mask despite being out of flow — the words are
   different widths and would otherwise all hang off the left. */
.cta__rot b{
  position:absolute; left:0; right:0; top:0;
  height:1.28em; line-height:1.28; font-weight:900; white-space:nowrap;
}
/* <i> is only a per-letter hook; the font-style reset is what stops it going
   italic. */
.cta__rot i{
  display:inline-block; font-style:normal;
  will-change:transform, opacity, filter;
}
/* .lead is max-width capped, so it needs the auto margins to sit centred. */
.cta .lead{ margin:36px auto 0; }
.cta__row{ display:flex; align-items:flex-start; justify-content:center; gap:16px; margin-top:44px; }
.cta__ava{
  width:46px; height:46px; border-radius:50%; flex:none;
  background:linear-gradient(140deg,var(--yellow),#7a5c2e);
}
.cta__bubble{
  display:inline-block; padding:10px 20px; border-radius:99px;
  background:var(--bg-card-2); border:1px solid var(--gold-line);
  font-size:16px; color:var(--ink-60);
  margin-bottom:12px;
}
.cta__row > div{ display:flex; flex-direction:column; align-items:center; }

/* ============================================================
   TESTIMONIALS
   ============================================================ */
.tst__dots{ display:flex; gap:7px; align-items:center; }
.tst__dots i{
  display:block; width:26px; height:4px; border-radius:99px;
  background:rgba(255,255,255,.25); transition:background .3s;
}
.tst__dots i.is-on{ background:var(--yellow); }
.tst__viewport{
  margin-top:clamp(40px,5vw,70px); overflow:hidden; cursor:grab;
  margin-right:calc(-1 * var(--gutter));
}
.tst__viewport.is-drag{ cursor:grabbing; }
.tst__track{ display:flex; gap:18px; width:max-content; will-change:transform; }
.tcard{
  width:clamp(300px,34vw,520px);
  background:var(--bg-card); border:1px solid var(--gold-line);
  border-radius:var(--r-lg); padding:32px 30px;
  display:flex; flex-direction:column;
  user-select:none;
}
.tcard__q{
  align-self:flex-end; width:28px; height:28px; border-radius:5px;
  background:var(--yellow); color:var(--on-gold);
  display:grid; place-items:center; font-weight:900; font-size:17px; line-height:1;
  margin-top:-6px;
}
.tcard__head{ display:flex; justify-content:space-between; gap:16px; align-items:flex-start; }
.tcard__title{ font-size:clamp(19px,1.8vw,26px); font-weight:800; letter-spacing:-.035em; line-height:1.15; }
.tcard__body{ margin-top:18px; font-size:15px; line-height:1.55; color:var(--ink-60); }
.tcard__foot{ display:flex; align-items:center; gap:14px; margin-top:auto; padding-top:34px; }
.tcard__ava{
  width:52px; height:52px; border-radius:50%; flex:none;
  display:grid; place-items:center; font-weight:800; color:#fff; font-size:15px;
}
.tcard__who b{ display:block; font-size:16px; font-weight:700; }
.tcard__who span{ display:block; font-size:13.5px; color:var(--ink-45); }
.tcard__who i{ display:block; font-style:normal; font-size:13.5px; color:var(--yellow); text-decoration:underline; }

/* ============================================================
   BAND — the white chevron
   ============================================================ */
.band{
  background:#fff; padding:16px 0; overflow:hidden; width:100vw;
  margin-left:calc(-1 * (var(--dock-w) + var(--gutter) + 20px));
}
.band__row{ display:flex; gap:26px; align-items:center; width:max-content; }
.band__row span{ font-size:clamp(20px,2.4vw,34px); font-weight:900; letter-spacing:-.03em; white-space:nowrap; color:var(--bg); }
.band__row i{ font-style:normal; font-size:clamp(16px,1.8vw,26px); color:var(--yellow); }

/* ============================================================
   FAQ
   ============================================================ */
.faq{ overflow:hidden; }
.faq__mark{
  font-size:clamp(90px,20vw,300px); font-weight:900; color:#fff;
  letter-spacing:-.05em; line-height:.78; margin-bottom:clamp(50px,7vw,110px);
  white-space:nowrap; will-change:transform;
}
.faq__grid{
  margin-top:clamp(40px,5vw,70px);
  display:grid; gap:12px; grid-template-columns:repeat(2,minmax(0,1fr));
  align-items:start;
}
@media (max-width:760px){ .faq__grid{ grid-template-columns:1fr; } }
.faq__item{
  background:var(--bg-card); border:1px solid var(--gold-line);
  border-radius:var(--r-sm); overflow:hidden;
  opacity:0; transform:translateY(18px);   /* GSAP reveals these */
}
.faq__q{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:20px;
  padding:22px 24px; text-align:left;
  font-size:clamp(15px,1.3vw,18px); font-weight:700; letter-spacing:-.02em;
}
.faq__q i{ font-style:normal; font-size:22px; line-height:1; color:var(--yellow); transition:transform .4s var(--ease); flex:none; }
.faq__item.is-open .faq__q i{ transform:rotate(45deg); }
.faq__a{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .5s var(--ease); }
.faq__a > div{ overflow:hidden; }
.faq__item.is-open .faq__a{ grid-template-rows:1fr; }
.faq__a p{ padding:0 24px 24px; font-size:15px; line-height:1.55; color:var(--ink-60); }

/* ============================================================
   FOOTER
   ============================================================ */
.foot{
  padding:clamp(50px,6vw,90px) var(--gutter) 40px;
  border-top:1px solid var(--line);
}
.foot__top{ display:flex; justify-content:space-between; align-items:center; gap:24px; flex-wrap:wrap; }
.foot__brand{ font-size:34px; font-weight:900; letter-spacing:-.04em; color:#fff; }
.foot__brand sup{ font-size:.4em; color:var(--yellow); }
.foot__links{ display:flex; gap:22px; font-size:14px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; }
.foot__links a{ opacity:.7; transition:opacity .25s, color .25s; }
.foot__links a:hover{ opacity:1; color:var(--yellow); }
.foot__bottom{
  margin-top:40px; padding-top:22px; border-top:1px solid var(--line);
  display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap;
  font-size:13px; color:var(--ink-45);
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width:1180px){
  :root{ --dock-w:210px; }
  .tcard{ width:clamp(280px,44vw,460px); }
}

@media (max-width:980px){
  /* The dock is a top bar down here, not a left rail, so there is nothing on the
     left edge to correct for — centred sections centre honestly. */
  :root{ --optical-shift: 0px; }

  /* The -18vh pull exists to eat the dead tail of the desktop hero's 175vh
     scroll. Down here the hero is a single static 100svh screen with no tail, so
     that same pull dragged About up *into* the live hero — its "Start Small Grow
     Big" pill landed on top of the hero's Book a Call buttons. */
  .main{ padding-left:0; margin-top:0; }
  .projects{ margin-left:0; padding-left:0; }
  .band{ margin-left:0; }

  .dock{
    left:0; top:0; width:100%; height:auto;
    padding:12px var(--gutter);
    flex-direction:row; align-items:center; gap:10px; justify-content:flex-start;
    background:rgba(150,12,20,.9); backdrop-filter:blur(14px);
    border-bottom:1px solid var(--gold-line);
  }
  .dock__brand{ display:flex; align-items:center; padding:8px 12px; }
  .dock__bio,.dock__stats,.dock__marquee,.dock__mail{ display:none; }
  .dock__brand-top{ gap:14px; }
  .dock__menu{
    position:fixed; left:var(--gutter); right:var(--gutter); top:74px;
    padding:16px; gap:4px; background:rgba(120,8,15,.96);
    opacity:0; pointer-events:none; transform:translateY(-12px);
    transition:opacity .35s var(--ease), transform .35s var(--ease);
  }
  .dock.is-open .dock__menu{ opacity:1; pointer-events:auto; transform:none; }
  .dock__link{ align-self:stretch; font-size:15px; padding:10px 14px; }
  /* nowrap or the label breaks onto three lines and spills out of the pill.
     transform/opacity are the desktop morph's opening pose — there is no morph
     down here to animate them away, and the leftover -26px slid the button back
     over the brand card no matter how much room the layout gave it. */
  .dock__book{
    margin-left:auto; margin-right:52px; height:42px; padding:0 20px;
    font-size:14px; white-space:nowrap;
    transform:none; opacity:1;
  }

  .burger{
    display:flex; flex-direction:column; justify-content:center; gap:5px;
    position:fixed; right:var(--gutter); top:20px; z-index:70;
    width:40px; height:40px; align-items:center;
    border-radius:50%; background:var(--yellow);
    opacity:0; pointer-events:none;
  }
  .burger.is-ready{ opacity:1; pointer-events:auto; }
  .burger span{ display:block; width:16px; height:2px; background:var(--on-gold); border-radius:2px; transition:transform .3s var(--ease); }
  .dock.is-open ~ .burger span:first-child{ transform:translateY(3.5px) rotate(45deg); }
  .dock.is-open ~ .burger span:last-child{ transform:translateY(-3.5px) rotate(-45deg); }

  /* no morph on small screens — the hero is a single, static screen */
  .hero{ height:100svh; }
  .hero__stage{ position:relative; height:100svh; }
  .hero__traits{ display:none; }
  /* Height of the fixed top bar. The artwork is pushed down by it, and anything
     positioned from --letters-bottom has to add it back: fitMark() publishes
     that value as a fraction of the font size, measured from the mark's own box,
     so it knows nothing about this offset. Missing it put the kicker 72px up
     inside the wordmark. */
  :root{ --hero-top: 70px; }

  .hero__mark{ top:var(--hero-top); }
  /* --letters-ink is the measured bottom of the glyphs; --letters-bottom is the
     line-box estimate and sits ~14% of the font size too high, which at tablet
     sizes is enough to drop these straight onto the wordmark. */
  .hero__nav{ top:calc(var(--hero-top) + var(--letters-ink, 44vh) + 14px); }

  /* Zoomed out and stood on the floor of the hero. object-fit:cover was scaling
     a 1800x1018 landscape photo to fill a tall narrow box, so it only showed the
     middle third of the frame — cropped tight to his face. Widening the box past
     the viewport and switching to contain lets the whole figure back in; the
     cut-out is transparent, so the extra width is just red. Anchored bottom so
     he stands at the base of the screen and leaves clear space overhead. */
  /* The width sets the zoom: contain scales to min(boxW/1800, boxH/1018), so a
     wider box means a bigger figure. ~313% reproduces the old cover crop (too
     tight, face only); 175% left him small with a dead gap under the wordmark.
     230% is the middle — most of the figure, no void. */
  .hero__cut{
    top:var(--hero-top); left:50%; width:230%; transform:translateX(-50%);
  }
  .hero__cut img{ object-fit:contain; object-position:50% 100%; }

  /* Below the wordmark and in the clear red above his head, rather than across
     his hair where it was unreadable. */
  /* Clears the nav row, which is still on screen at tablet widths and shares
     this left edge. Phones drop back to a tighter offset below, where the nav
     is hidden and this much space would push the kicker onto his head. */
  .hero__kicker{
    top:calc(var(--hero-top) + var(--letters-ink, 44vh) + 57px); bottom:auto;
  }
  /* no room for the note here — the dock bio covers the same ground */
  .hero__note{ display:none; }
  .hero__stat{ padding:12px 16px; }
  .hero__stat--a{ left:var(--gutter); top:auto; bottom:34%; }
  .hero__stat--b{ left:auto; right:var(--gutter); top:auto; bottom:34%; flex-direction:row; gap:10px; }
  .hero__stat--b .hero__stat-txt{ text-align:left; }
  /* full width so the buttons can centre against the screen, not against a
     left-anchored block */
  .hero__copy{
    top:auto; bottom:7%; left:0; transform:none;
    width:100%; max-width:100%; padding:0 var(--gutter);
  }
  .hero__cta{ justify-content:center; margin-top:22px; }

  .jitem{ width:100%; }
  .jitem--r{ margin-left:0; }
  .journey__path{ display:none; }
  .jdot{ display:none; }

  .projects__pin{ height:auto; padding:90px var(--gutter); }
  .projects__track{ width:100%; flex-direction:column; }
  .pcard{ width:100%; height:70vh; }
  .projects__prog{ display:none; }

  .what__big{ text-align:center; }
  .tst__viewport{ margin-right:calc(-1 * var(--gutter)); }
}

@media (max-width:620px){
  .hero__nav{ display:none; }
  /* nav is gone, so the kicker moves back up under the wordmark */
  .hero__kicker{ top:calc(var(--hero-top) + var(--letters-ink, 44vh) + 30px); }
  /* Each card shrinks toward the edge it is anchored to. --b is pinned right, so
     scaling it from the left held its left edge in place and grew the gap on the
     right instead — which walked it into --a and overlapped the two by 29px. */
  .hero__stat--a{ transform:scale(.86); transform-origin:left bottom; }
  .hero__stat--b{ transform:scale(.86); transform-origin:right bottom; }
  .btn{ height:46px; padding:0 20px; font-size:15px; }
  .sec__head--row{ align-items:flex-start; }
  .foot__links{ gap:14px; font-size:12px; }
}

/* Small phones. The two stat cards sit on one line and, at .86, still leave only
   a couple of pixels between them at 360px — one longer number and they touch. */
@media (max-width:400px){
  .hero__stat--a{ transform:scale(.78); }
  .hero__stat--b{ transform:scale(.78); }

  /* The top bar is tight here: brand + Book a Call + the burger's reserved 52px
     have to fit a 320px content box. */
  .dock__brand{ padding:8px 10px; }
  .dock__brand-top{ gap:10px; }
  .dock__book{ padding:0 14px; font-size:13px; }
}

/* Even tightened, the bar is 1px short at 360px. The X icon gives way rather
   than the LinkedIn one — it currently points at "#" and goes nowhere, whereas
   LinkedIn has no other home on the page. Restore this once X has a real URL and
   the icon will simply reappear above 380px, where it already fits. */
@media (max-width:380px){
  .dock__social a[href="#"]{ display:none; }
}

@media (prefers-reduced-motion:reduce){
  *{ animation-duration:.001s !important; transition-duration:.001s !important; }
}
