/* ============================================================================
   Suraj Varma — portfolio
   Black canvas, mint accent, thin display type, micro-interactions throughout.
   ==========================================================================*/

:root{
  --bg:        #000;
  --bg-soft:   #0f0e0e;
  --ink:       #fff;
  --muted:     #ababab;
  --muted-2:   #6f6f6f;
  --line:      rgba(255,255,255,.12);
  --line-2:    rgba(255,255,255,.22);
  --accent:    #8cff2e;
  --accent-dim: rgba(140,255,46,.14);

  --display: "Blinker", ui-sans-serif, system-ui, sans-serif;
  --body:    "Sulphur Point", ui-sans-serif, system-ui, sans-serif;

  /* Hero-only for now (see .hero-title/.hero-sub) — the rest of the site's
     headings and eyebrow labels still run on --display/Blinker above. */
  --font-display: "Outfit", system-ui, sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, monospace;
  --ink-soft:     var(--muted);

  --wrap: 1500px;
  --pad:  clamp(20px, 5vw, 56px);
  --r:    18px;
  --nav-h: 76px;

  /* View all button — rest/hover dimensions and the overshoot-then-settle
     pop between them. Tune here; nothing below hardcodes these. */
  --btn-w:173px;    --btn-h:56px;
  --btn-w-hi:189px; --btn-h-hi:61px;
  --pop-in:  .56s cubic-bezier(.22, 2.0, .36, 1);
  --pop-out: .40s cubic-bezier(.16, 1, .3, 1);
}

*,*::before,*::after{ box-sizing:border-box; }

html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--nav-h) + 16px);
}

body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--body);
  font-size:17px;
  line-height:1.6;
  letter-spacing:.02em;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

img,video,svg{ display:block; max-width:100%; }
a{ color:inherit; text-decoration:none; }
ul,ol{ margin:0; padding:0; list-style:none; }

h1,h2,h3{
  font-family:var(--display);
  font-weight:300;
  letter-spacing:-.01em;
  line-height:1.02;
  margin:0;
}

::selection{ background:var(--accent); color:#000; }
:focus-visible{ outline:2px solid var(--accent); outline-offset:4px; border-radius:6px; }

.wrap{ width:100%; max-width:var(--wrap); margin-inline:auto; padding-inline:var(--pad); }

.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

.skip{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--accent); color:#000; padding:12px 18px; border-radius:0 0 10px 0;
}
.skip:focus{ left:0; }

/* ─────────────── custom cursor ───────────────
   A solid warm-white dot, with a soft glow lagging behind it. The native
   cursor is only hidden once JS confirms it has taken over (html.has-cursor). */
:root{ --cursor-ink:#f2efe9; }

/* The wrapper only carries position (JS writes translate3d to it). The ring
   inside holds a constant translate(-50%,-50%), so the two size states can
   animate width/height without ever scaling — a scale() would soften the
   difference-blend edge mid-transition. */
/* Inversion is done with backdrop-filter, not mix-blend-mode.
   mix-blend-mode composites against the backdrop of the PARENT stacking
   context, so it broke twice over: this wrapper's z-index made the ring
   blend against nothing, and once that was fixed it blended against the
   hero's mint glow and turned the circle purple. backdrop-filter samples
   the already-rendered backdrop directly, so stacking contexts are
   irrelevant and grayscale() keeps the result neutral over colour photos. */
.cursor{
  position:fixed; top:0; left:0; z-index:301;
  pointer-events:none; opacity:0;
  transition:opacity .3s ease;
}
.cursor.is-on{ opacity:1; }

.cursor__ring{
  position:absolute; left:0; top:0;
  transform:translate(-50%,-50%);
  display:grid; place-items:center;
  width:16px; height:16px;
  border-radius:50%;
  background:transparent;
  mix-blend-mode:normal;
  /* brightness() after the invert pushes the light side to pure white without
     touching the dark side — inverted black stays black, so text still flips
     cleanly while the dot reads white instead of mid-grey over the glow. */
  -webkit-backdrop-filter:invert(1) grayscale(1) brightness(1.6);
  backdrop-filter:invert(1) grayscale(1) brightness(1.6);
  font-family:var(--display); font-weight:600; letter-spacing:.02em;
  font-size:0; color:#000; white-space:nowrap; user-select:none;
  transition:width .4s cubic-bezier(.16,1,.3,1),
             height .4s cubic-bezier(.16,1,.3,1),
             font-size .3s ease;
}

/* Named size states, driven by the value of [data-cursor] — see the
   cursor() IIFE in app.js for the class it adds/removes. */
.cursor.on-button .cursor__ring{
  width:44px; height:44px;
  font-size:0;
}
.cursor.on-heading .cursor__ring{
  width:82px; height:82px;
  font-size:10px;
}

.cursor-glow{
  position:fixed; top:0; left:0; z-index:300;
  width:150px; height:150px; margin:-75px 0 0 -75px;
  border-radius:50%; pointer-events:none; opacity:0;
  background:radial-gradient(circle,
              rgba(242,239,233,.26) 0%,
              rgba(242,239,233,.11) 32%,
              rgba(242,239,233,.04) 52%,
              transparent 72%);
  filter:blur(8px);
  transition:opacity .45s ease, transform .35s ease;
}
.cursor-glow.is-on{ opacity:1; }
.cursor-glow.is-hover{ transform:scale(1.45); }

html.has-cursor,
html.has-cursor *{ cursor:none !important; }

@media (hover:none), (pointer:coarse){
  .cursor, .cursor-glow{ display:none; }
}

/* ─────────────── buttons ─────────────── */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  font-family:var(--display); font-size:16px; font-weight:400; letter-spacing:.02em;
  padding:13px 26px; border-radius:999px; border:1px solid transparent;
  cursor:pointer; white-space:nowrap;
  transition:transform .25s cubic-bezier(.2,.8,.2,1), background .25s ease,
             color .25s ease, border-color .25s ease, box-shadow .25s ease;
}
.btn:hover{ transform:translateY(-2px) scale(1.03); }
.btn--accent{ background:var(--accent); color:#000; }
.btn--accent:hover{ box-shadow:0 10px 34px -12px var(--accent); }
.btn--ghost{ border-color:var(--line-2); color:var(--ink); }
.btn--ghost:hover{ border-color:var(--accent); color:var(--accent); }

/* ─────────────── nav pill ─────────────── */
.nav{
  position:fixed; inset-inline:0; top:0; z-index:100;
  display:flex; flex-direction:column; align-items:center;
  padding:14px clamp(12px,3vw,20px) 0;
  pointer-events:none;
}

.pill{
  pointer-events:auto;
  /* flex-start, not space-between: the links carry margin-left:auto, so all
     the slack collapses into one gap after the name and the links sit tight
     against the icons on the right. space-between would split that slack in
     two, leaving a gap between the links and the icons as well. */
  display:flex; align-items:center; justify-content:flex-start; gap:18px;
  width:100%; max-width:1400px;
  padding:8px 10px 8px 8px;
  border:1px solid var(--line); border-radius:999px;
  background:rgba(0,0,0,.34);
  backdrop-filter:blur(14px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
  transition:max-width .55s cubic-bezier(.2,.8,.2,1), background .45s ease,
             box-shadow .45s ease, padding .45s ease;
}
/* condenses to a compact pill once you scroll — the reference's signature move */
/* Opaque once condensed — it sits directly over scrolling content.
   Narrows to roughly the reference's 440px, plus room for the two icons. */
.nav.is-stuck .pill{
  max-width:500px;
  background:rgba(6,6,6,.94);
  box-shadow:0 18px 50px -18px #000;
}

.brand{ display:flex; align-items:center; gap:11px; flex:0 0 auto; }

.brand__avatar{
  position:relative; display:block; flex:0 0 auto;
  transition:transform .3s ease-out;
}
.brand:hover .brand__avatar{ transform:rotate(-6deg) scale(1.1); }
/* the wordmark drifts a touch as the avatar tilts */
.brand__wordmark{ transition:transform .3s ease-out; }
.brand:hover .brand__wordmark{ transform:translateX(2px); }

.brand__avatar img{
  width:44px; height:44px; border-radius:50%; object-fit:cover;
  box-shadow:0 0 0 1px rgba(255,255,255,.22);
}
/* Status dot — shrinks and spins rather than pulsing a ring, matching the
   reference's dot-loop (1.8s, alternating). */
.brand__status{
  position:absolute; right:-1px; bottom:-1px;
  width:12px; height:12px; border-radius:50%;
  background:var(--accent); border:2px solid #000;
  will-change:transform,opacity;
  animation:dot-loop 1.8s ease-in-out infinite alternate;
}
@keyframes dot-loop{
  0%  { opacity:1;  transform:scale(1)  rotate(0deg); }
  100%{ opacity:.7; transform:scale(.2) rotate(360deg); }
}

/* the hero's availability dot keeps a soft pulse of its own */
@keyframes pulse{
  0%,100%{ box-shadow:0 0 0 0 rgba(140,255,46,.55); }
  70%    { box-shadow:0 0 0 7px rgba(140,255,46,0); }
}

.brand__wordmark{
  font-family:var(--display); font-size:18px; font-weight:400;
  letter-spacing:.01em; white-space:nowrap;
}
.brand__dot{ color:var(--accent); }

/* max-width (not width:auto) is what makes this animate at all — browsers
   can't tween to/from "auto", they just snap. A fixed ceiling comfortably
   past the content's real width gives the transition real numbers to ease
   between, so it glides instead of popping open. */
.pill__links{
  display:flex; align-items:center; gap:clamp(14px,2vw,30px); margin-left:auto;
  max-width:640px; opacity:1; visibility:visible; overflow:visible;
  transition:opacity .5s cubic-bezier(.2,.8,.2,1), visibility .5s cubic-bezier(.2,.8,.2,1),
             max-width .55s cubic-bezier(.2,.8,.2,1);
}
.pill__links a{
  position:relative; font-family:var(--display); font-size:15.5px; color:rgba(255,255,255,.72);
  padding:6px 2px; transition:color .25s ease, transform .25s ease;
}
.pill__links a::after{
  content:""; position:absolute; left:0; right:100%; bottom:2px; height:1px;
  background:var(--accent); transition:right .3s cubic-bezier(.2,.8,.2,1);
}
.pill__links a:hover{ color:var(--ink); transform:translateY(-1px); }
.pill__links a:hover::after{ right:0; }

/* the condensed pill drops the links so only image + name + icons remain —
   margin-left stays auto throughout (never toggled), so the only things
   actually animating are opacity/visibility/max-width above. */
.nav.is-stuck .pill__links{
  opacity:0; visibility:hidden; max-width:0; overflow:hidden;
}

.pill__icons{ display:flex; align-items:center; gap:8px; flex:0 0 auto; margin-left:14px; }
/* Only while the links are actually hidden. With the links visible they
   already carry margin-left:auto, and a second auto margin here would split
   the slack evenly between the two — which centres the links instead of
   keeping them tight against the icons. */
.nav.is-stuck:not(.is-open):not(:hover) .pill__icons{ margin-left:auto; }

/* Official brand marks, centred inside a circle. */
.icon{
  position:relative;
  display:grid; place-items:center; width:38px; height:38px;
  border-radius:50%; overflow:visible;
  transition:transform .3s cubic-bezier(.2,.8,.2,1), box-shadow .3s ease;
}
.icon svg{ width:38px; height:38px; border-radius:50%; display:block; }
.icon:hover{ transform:translateY(-3px) scale(1.1); }
.icon--li:hover{ box-shadow:0 10px 24px -10px #0A66C2; }
.icon--gm:hover{ box-shadow:0 10px 24px -10px rgba(234,67,53,.85); }
/* tooltip on the icons */
.icon::after{
  content:attr(data-tip);
  position:absolute; top:calc(100% + 9px); left:50%;
  transform:translate(-50%,4px);
  font-family:var(--display); font-size:11.5px; letter-spacing:.14em; text-transform:uppercase;
  color:#000; background:var(--accent); padding:3px 9px; border-radius:999px;
  opacity:0; pointer-events:none; white-space:nowrap;
  transition:opacity .25s ease, transform .25s ease;
}
.icon:hover::after{ opacity:1; transform:translate(-50%,0); }

/* three-dot typing indicator — appears once the pill condenses */
.typing{
  display:none; align-items:center; gap:5px;
  max-width:0; padding:0; margin:0; overflow:hidden;
  background:transparent; border:0; cursor:pointer;
  opacity:0;
  transition:opacity .5s cubic-bezier(.2,.8,.2,1), max-width .55s cubic-bezier(.2,.8,.2,1),
             padding .55s cubic-bezier(.2,.8,.2,1), margin .55s cubic-bezier(.2,.8,.2,1);
}
.typing span{
  display:block; width:7px; height:7px; border-radius:50%; background:var(--accent);
  animation:dot-wave 1.4s ease-in-out infinite;
}
.typing span:nth-child(2){ animation-delay:.18s; }
.typing span:nth-child(3){ animation-delay:.36s; }
@keyframes dot-wave{
  0%,60%,100%{ opacity:.45; transform:translateY(0); }
  30%        { opacity:1;   transform:translateY(-3px); }
}

/* only while condensed, and only when the menu isn't already open */
.nav.is-stuck .typing{
  display:flex; max-width:60px; padding:8px 10px; margin-right:4px; opacity:1;
}

/* Expanded state, reached either by clicking the typing dots (is-open,
   sticky until closed again) or by hovering the condensed pill (releases
   the moment the cursor leaves) — same end state, same values, so both
   share one rule and animate identically. */
.nav.is-stuck.is-open .pill,
.nav.is-stuck:hover .pill{ max-width:1400px; }
.nav.is-stuck.is-open .pill__links,
.nav.is-stuck:hover .pill__links{
  opacity:1; visibility:visible; max-width:640px; overflow:visible;
}
.nav.is-stuck.is-open .typing{ display:none; }
.nav.is-stuck:hover .typing{ opacity:0; max-width:0; padding:0; margin-right:0; }

.burger{
  display:none; width:38px; height:38px; padding:0;
  background:rgba(255,255,255,.03); border:1px solid var(--line); border-radius:50%;
  cursor:pointer;
}
.burger span{
  display:block; width:15px; height:1.4px; margin:3.4px auto;
  background:#fff; transition:transform .25s ease;
}
.burger[aria-expanded="true"] span:first-child{ transform:translateY(2.4px) rotate(45deg); }
.burger[aria-expanded="true"] span:last-child{ transform:translateY(-2.4px) rotate(-45deg); }

/* Pinned to the very top edge of the viewport, under the floating pill. */
.nav__progress{
  position:fixed; top:0; left:0;
  width:0; height:2px;
  background:var(--accent); box-shadow:0 0 10px rgba(140,255,46,.6);
  transition:width .12s linear;
}

.drawer{ display:none; }
.drawer[hidden]{ display:none !important; }
@media (max-width:900px){
  .drawer:not([hidden]){
    pointer-events:auto;
    position:fixed; top:calc(var(--nav-h) + 6px); inset-inline:clamp(12px,3vw,20px); z-index:99;
    display:grid; gap:2px;
    padding:10px 18px 16px;
    border:1px solid var(--line); border-radius:var(--r);
    background:rgba(0,0,0,.9); backdrop-filter:blur(14px);
    animation:drawerIn .3s cubic-bezier(.2,.8,.2,1);
  }
}
@keyframes drawerIn{ from{ opacity:0; transform:translateY(-8px); } to{ opacity:1; transform:none; } }
.drawer a{
  font-family:var(--display); font-size:19px; padding:10px 0;
  border-bottom:1px solid var(--line);
}
.drawer a:last-child{ border-bottom:0; color:var(--accent); }

/* ─────────────── hero ─────────────── */
.hero{
  position:relative;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  padding: 90px 24px 100px;
  background:var(--bg-soft);
  overflow:hidden;
}

/* Heading + subline live in here, centred as one block inside the
   full-viewport-height .hero. Nothing in this box may pick up transform,
   opacity<1, filter, will-change or isolation — the custom cursor needs to
   keep inverting cleanly over this text (see .hero-title/.hero-sub). */
.hero-inner{
  width:100%;
  max-width:1200px;
  text-align:center;
  position:relative;
  z-index:3;
}

/* ─────────────── cursor glow, scoped to a section ───────────────
   The section clips it (overflow:hidden) and `isolation:isolate` keeps the
   blend mode from reaching anything outside it. The blur is what feathers
   the edge — the gradient alone still reads as a hard disc. */
[data-glow]{
  position:relative;
  overflow:hidden;
  isolation:isolate;
}

.glow{
  position:absolute; top:0; left:0;
  width:720px; height:720px;
  margin:-360px 0 0 -360px;          /* so translate() centres on the pointer */
  border-radius:50%;
  pointer-events:none;
  /* Negative z-index keeps the glow above the section's own background but
     behind all its content, so the content needs no positioning of its own.
     (It previously sat at z-index:0, which forced every sibling to
     position:relative + z-index:1 — that broke .scroll's left:50% centring
     and collapsed the .trail layer.) */
  z-index:-1;
  opacity:0;
  /* Five stops so it falls off gradually. Peak is pulled back from the
     spec's 0.5 — at full strength `screen` on black washes out the body
     copy the glow passes over. */
  background:radial-gradient(circle,
              rgba(140,255,46,.36) 0%,
              rgba(140,255,46,.21) 25%,
              rgba(140,255,46,.10) 45%,
              rgba(140,255,46,.035) 58%,
              rgba(140,255,46,0)   70%);
  filter:blur(60px);
  mix-blend-mode:screen;
  transition:opacity .3s ease;
  will-change:transform;
}
.glow.is-lit{ opacity:1; }

/* No pointer, or reduced motion: park a softer glow in the middle so the
   section still has depth rather than going flat. */
@media (hover:none), (pointer:coarse){
  .glow{ opacity:.55; left:50%; top:45%; transform:none;
         margin:-360px 0 0 -360px; }
}
@media (prefers-reduced-motion:reduce){
  .glow{ opacity:.5; left:50%; top:45%; transform:none; transition:none; }
}

/* image trail — sits above the headline, below the nav, clipped by the hero */
.trail{ position:absolute; inset:0; z-index:2; pointer-events:none; }
.trail img{
  position:absolute; top:0; left:0;
  width:clamp(96px,10vw,148px); aspect-ratio:4/5;
  object-fit:cover; border-radius:10px;
  opacity:0; will-change:transform,opacity;
}

.hero__kicker{
  position:relative;
  display:inline-flex; align-items:center; gap:10px;
  margin:0 0 44px; padding:7px 17px;
  border:1px solid var(--line); border-radius:999px;
  background:rgba(255,255,255,.03);
  font-family:var(--display); font-size:13.5px; letter-spacing:.06em; color:var(--muted);
}
.dot{
  width:7px; height:7px; border-radius:50%; background:var(--accent);
  animation:pulse 2.4s ease-in-out infinite;
}

.hero-title{
  font-family: var(--font-display);   /* Outfit — NOT JetBrains Mono */
  font-size: clamp(38px, 7.4vw, 108px);
  font-weight: 300;                    /* light weight, not 400 or 500 */
  letter-spacing: -.018em;             /* slightly tightened, not default */
  line-height: 1.06;
  white-space: nowrap;
  min-height: 1.12em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
}
.caret{
  display: inline-block;
  width: 2px;
  height: .82em;
  background: var(--ink);
  animation: blink 1s steps(1,end) infinite;
}
@keyframes blink{
  0%,   50%   { opacity: 1; }
  50.01%,100% { opacity: 0; }
}

.hero-sub{
  /* wide enough that the intro breaks after "design thinking," into
     exactly two lines, matching the reference */
  max-width: 620px;
  margin: clamp(40px, 6vw, 88px) auto 0;
  font-size: clamp(13px, 1.15vw, 15px);
  font-weight: 300;
  line-height: 1.95;
  letter-spacing: .055em;
  color: var(--ink-soft);
}

.hero__cta{ position:relative; display:flex; flex-wrap:wrap; gap:12px; justify-content:center; margin-bottom:44px; }

.tags{
  position:relative;
  display:flex; flex-wrap:wrap; gap:9px 12px; justify-content:center; align-items:center;
}
.tags li{
  display:flex; align-items:center; gap:12px;
  font-family:var(--display); font-size:13.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--muted-2);
  transition:color .25s ease;
}
.tags li:hover{ color:var(--ink); }
.tags li:not(:last-child)::after{ content:"✳"; color:var(--accent); font-size:9px; opacity:.7; }

.scroll{
  position:absolute; left:50%; bottom:34px; transform:translateX(-50%);
  display:grid; justify-items:center; gap:12px;
  font-family:var(--display); font-size:11.5px; letter-spacing:.36em;
  color:var(--muted-2); transition:color .25s ease;
}
.scroll:hover{ color:var(--accent); }
/* Scroll cue — a lit segment travelling down the rail, matching the
   reference's scroll-cue timing and easing. */
.scroll__line{
  display:block; width:1px; height:54px; background:var(--line-2);
  overflow:hidden; position:relative;
}
.scroll__line::after{
  content:""; position:absolute; inset-inline:0; top:0; height:60%;
  background:linear-gradient(to bottom, transparent, var(--accent) 45%, transparent);
  animation:scroll-cue 1.8s cubic-bezier(.76,0,.24,1) infinite;
}
@keyframes scroll-cue{
  0%  { transform:translateY(-100%); }
  100%{ transform:translateY(250%); }
}

/* ─────────────── sections ─────────────── */
.section{ padding:clamp(78px,11vw,148px) 0; }
.section--tight{ padding:clamp(40px,6vw,72px) 0; }

.shead{ max-width:62ch; margin-bottom:clamp(40px,6vw,66px); }
.shead--center{ margin-inline:auto; text-align:center; }

.kick{
  display:inline-flex; align-items:center; gap:11px; margin-bottom:22px;
  font-family:var(--display); font-size:12.5px; letter-spacing:.24em;
  text-transform:uppercase; color:var(--muted);
}
.kick i{
  width:7px; height:7px; border-radius:50%; background:var(--accent);
  box-shadow:0 0 12px var(--accent);
}
.shead h2, .about__h{
  font-size:clamp(30px,5.2vw,64px); letter-spacing:-.015em; margin-bottom:20px;
}
.shead p{ margin:0; color:var(--muted); font-size:clamp(15px,1.6vw,18px); letter-spacing:.05em; max-width:56ch; }
.shead--center p{ margin-inline:auto; }

/* ─────────────── cards ─────────────── */
.card{
  border:1px solid var(--line); border-radius:var(--r);
  background:rgba(255,255,255,.025);
}
.card--glass{ backdrop-filter:blur(6px); }
.card--quiet{ padding:22px 24px; }
.card--quiet p{ margin:0; color:var(--muted); font-size:16px; }
.card__k{
  display:block; margin-bottom:8px;
  font-family:var(--display); font-size:11.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--muted-2);
}

/* ─────────────── stats ─────────────── */
.statbar{
  display:grid; grid-template-columns:repeat(4,1fr); gap:1px;
  background:var(--line); border:1px solid var(--line); border-radius:var(--r); overflow:hidden;
}
.stat{
  background:#000; padding:30px clamp(18px,2.4vw,30px);
  transition:background .4s ease;
}
.stat:hover{ background:#111114; }
.stat__v{
  display:block; margin-bottom:10px;
  font-family:var(--display); font-weight:300; letter-spacing:-.02em;
  font-size:clamp(30px,4.6vw,56px); line-height:1; color:var(--accent);
}
.stat__l{ display:block; font-size:15.5px; line-height:1.4; }
.stat__n{ display:block; font-size:13.5px; color:var(--muted-2); margin-top:4px; }

/* ─────────────── marquee ───────────────
   Each track holds the same run of items twice, so translating it -50%
   lands exactly where it started and the loop is seamless. */
/* A white band running the full width, dark type — the one light strip on
   the page, sitting between the hero and the intro. */
.marquee{
  display:grid; gap:14px;
  padding:clamp(10px,1.3vw,16px) 0;
  background:#f4f3ef;
  overflow:hidden;
}

.marquee__row{ overflow:hidden; }

.marquee__track{
  display:flex; width:max-content; gap:0;
  animation:marquee var(--speed,45s) linear infinite;
  will-change:transform;
}
.marquee__track--reverse{ animation-direction:reverse; }

.marquee__item{
  display:inline-flex; align-items:center;
  padding-right:clamp(46px,6vw,96px);
  font-family:var(--display); font-weight:500;
  font-size:clamp(26px,3.4vw,44px);
  letter-spacing:-.015em; white-space:nowrap;
  color:#0d0d0d;
}

@keyframes marquee{
  from{ transform:translate3d(0,0,0); }
  to  { transform:translate3d(-50%,0,0); }
}

/* ─────────────── intro ───────────────
   Words light up as the paragraph scrolls through the viewport. The reveal
   animates `color`, not opacity — opacity below 1 would create a stacking
   context on every word and interfere with the cursor's inversion. */
.intro{ padding:clamp(70px,10vw,130px) 0; }

.intro__grid{
  display:grid; gap:clamp(28px,5vw,72px);
  grid-template-columns:minmax(180px,.55fr) minmax(0,1.6fr);
  align-items:start;
}

.intro__aside{ display:flex; align-items:center; gap:14px; }
.intro__dot{
  width:11px; height:11px; border-radius:50%;
  background:var(--ink);
}
.intro__label{
  font-family:var(--display); font-weight:300;
  font-size:clamp(30px,4vw,52px); letter-spacing:-.01em;
  color:var(--ink); margin:0;
}

.intro__text{
  margin:0;
  font-family:var(--display); font-weight:300;
  font-size:clamp(20px,2.5vw,34px);
  line-height:1.5; letter-spacing:-.005em;
}
.intro__word{
  color:#3a3a3a;
  transition:color .45s cubic-bezier(.16,1,.3,1);
}
.intro__word.lit{ color:var(--ink); }

@media (max-width:760px){
  .intro__grid{ grid-template-columns:1fr; }
}

@media (prefers-reduced-motion:reduce){
  .marquee__track{ animation:none; }
}

/* ─────────────── filters ─────────────── */
.filters{ display:flex; flex-wrap:wrap; gap:9px; margin-bottom:16px; }
.chip{
  font-family:var(--display); font-size:14.5px; letter-spacing:.04em;
  padding:8px 18px; border-radius:999px; cursor:pointer;
  background:transparent; border:1px solid var(--line); color:var(--muted);
  transition:all .28s cubic-bezier(.2,.8,.2,1);
}
.chip:hover{ border-color:var(--line-2); color:var(--ink); transform:translateY(-2px); }
.chip[aria-pressed="true"]{ background:var(--accent); border-color:var(--accent); color:#000; }

.counter{ font-size:14px; color:var(--muted-2); margin:0 0 24px; letter-spacing:.08em; }

/* Smaller than the shared .shead h2 default — scoped to this section only. */
#shortform .shead h2{ font-size:clamp(26px,3.4vw,44px); }

/* ─────────────── short-form fisheye carousel ───────────────
   Cards sit in one horizontal reel that scrolls forever. app.js drives
   every frame: it warps each card's x-position through a sine curve and
   scales/blurs/fades it by distance from the container's centre, so the
   row reads as a lens sweeping across the cards rather than a flat strip.
   All the tunable numbers live in SHORTFORM.carousel in data.js. */
.fisheye{
  position:relative; margin-top:6px;
  overflow:hidden;
  cursor:grab;
  touch-action:pan-y;
  user-select:none;
  -webkit-mask-image:linear-gradient(to right, transparent 0%, #000 14%, #000 86%, transparent 100%);
          mask-image:linear-gradient(to right, transparent 0%, #000 14%, #000 86%, transparent 100%);
}
.fisheye.is-dragging{ cursor:grabbing; }
.fisheye__track{ position:relative; width:100%; height:100%; }

.fcard{
  position:absolute; top:0; left:0;
  display:block; overflow:hidden;
  border-radius:12px; border:1px solid rgba(255,255,255,.09); background:#0a0a0a;
  will-change:transform, filter, opacity;
  -webkit-user-drag:none; user-drag:none;
}
.fcard__rank{
  position:absolute; top:12px; left:12px; z-index:2;
  font-family:var(--display); font-size:11px; letter-spacing:.14em;
  padding:5px 10px; border-radius:999px;
  background:rgba(0,0,0,.55); color:#fff;
  backdrop-filter:blur(6px);
}
.fcard__thumb{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  -webkit-user-drag:none; user-drag:none; pointer-events:none;
}
.fcard__overlay{
  position:absolute; inset-inline:0; bottom:0; padding:36px 14px 14px;
  background:linear-gradient(to top, rgba(0,0,0,.95) 18%, transparent);
}
.fcard__title{
  font-family:var(--display); font-size:14.5px; line-height:1.25; margin:0 0 4px; color:#fff;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.fcard__stat{ margin:0; font-size:12px; color:var(--muted-2); }

/* ─────────────── view all ─────────────── */
/* The angle has to be a registered property, otherwise the browser treats
   it as an opaque string, can't interpolate it, and the rim jumps between
   keyframes instead of rotating. This is the whole trick. */
@property --rim-angle{
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

.viewall-wrap{ display:flex; justify-content:center; margin-top:52px; }

/* No z-index and no isolation on the <a>, so it never becomes a stacking
   context and the cursor's backdrop-filter keeps inverting over the label.
   Paint order is handled by DOM order alone — glow, rim, fill, then label.
   Background lives on .viewall__fill, not here, so the halo can bleed
   outside the pill instead of being clipped by it. */
.viewall{
  position:relative;
  width:var(--btn-w); height:var(--btn-h);
  display:inline-flex; align-items:center; justify-content:center;
  border-radius:999px;
  background:transparent; color:#fff;
  font-family:var(--display); font-size:12.5px; font-weight:500;
  text-transform:uppercase; letter-spacing:.22em;
  --rim-speed:4.2s;                       /* one full lap */
  transition:width var(--pop-out), height var(--pop-out), font-size var(--pop-out);
}
/* Width/height/font-size do the pop, not transform — a transform would give
   the anchor its own stacking context and the cursor's backdrop-filter
   invert would stop reading through onto the label. Enter and leave use
   different curves: the ".22,2.0,.36,1" bezier is what overshoots past the
   hover size before settling — swap it for a plain ease and the spring
   disappears. */
.viewall:hover{
  width:var(--btn-w-hi); height:var(--btn-h-hi); font-size:13.6px;
  --rim-speed:1.9s;                       /* rim speeds up on hover */
  transition:width var(--pop-in), height var(--pop-in), font-size var(--pop-in);
}

/* The travelling gradient, shared by the rim and the halo so the bright
   spot in the blur sits exactly under the bright spot on the ring. Two
   hotspots — one bright at 96deg, a dimmer one opposite at 278deg. */
.viewall__rim,
.viewall__glow{
  position:absolute; border-radius:inherit; pointer-events:none;
  background:conic-gradient(from var(--rim-angle),
    rgba(255,255,255,.05)   0deg,
    rgba(255,255,255,.09)  48deg,
    rgba(255,255,255,.95)  96deg,
    rgba(255,255,255,.30) 132deg,
    rgba(255,255,255,.05) 186deg,
    rgba(255,255,255,.09) 232deg,
    rgba(255,255,255,.62) 278deg,
    rgba(255,255,255,.14) 312deg,
    rgba(255,255,255,.05) 360deg);
  animation:rimSpin var(--rim-speed) linear infinite;
}

/* The hairline ring itself — mask-composite punches out the middle so only
   the 1.6px border band of the conic gradient survives. */
.viewall__rim{
  inset:0; padding:1.6px;
  -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;
}

/* Soft halo bleeding outward — same gradient, unmasked and blurred, so the
   glow feathers out from wherever the rim is currently brightest. */
.viewall__glow{
  inset:-3px; filter:blur(11px); opacity:.55;
  transition:opacity var(--pop-out), filter var(--pop-out);
}
.viewall:hover .viewall__glow{
  opacity:.9; filter:blur(15px);
  transition:opacity var(--pop-in), filter var(--pop-in);
}

/* The dark centre the ring sits around. */
.viewall__fill{
  position:absolute; inset:1.6px; border-radius:999px;
  background:#0a0a0b; pointer-events:none;
  transition:background .3s ease;
}
.viewall:hover .viewall__fill{ background:#131316; }

/* Label sits last in DOM, so it paints on top without needing z-index. */
.viewall__label{
  position:relative;
  display:inline-flex; align-items:center; gap:13px; white-space:nowrap;
}
.viewall__arrow{
  width:15px; height:15px; flex:none;
  transition:transform .3s cubic-bezier(.2,.8,.2,1);
}
.viewall:hover .viewall__arrow{ transform:translateX(5px); }

@keyframes rimSpin{
  to{ --rim-angle:360deg; }
}

/* Fallback: without @property the angle can't animate, so show a static
   rim rather than one that stutters between whole laps. */
@supports not (background: conic-gradient(from var(--rim-angle), #000, #fff)){
  .viewall__rim, .viewall__glow{
    background:linear-gradient(135deg,
      rgba(255,255,255,.9) 0%, rgba(255,255,255,.16) 30%,
      rgba(255,255,255,.06) 50%, rgba(255,255,255,.28) 72%,
      rgba(255,255,255,.88) 100%);
    animation:none;
  }
}

@media (prefers-reduced-motion:reduce){
  .viewall__rim, .viewall__glow{ animation:none; }
  .viewall:hover .viewall__arrow{ transform:none; }
}

/* ─────────────── growth ─────────────── */
.growth__card{ padding:clamp(22px,3.2vw,38px); margin-bottom:clamp(16px,2vw,22px); }
.growth__top{
  display:flex; flex-wrap:wrap; gap:24px; justify-content:space-between; align-items:flex-start;
  padding-bottom:26px; margin-bottom:30px; border-bottom:1px solid var(--line);
}
.growth__channel{ font-size:clamp(24px,3.4vw,38px); margin-bottom:8px; }
.growth__meta{ margin:0; font-size:14.5px; color:var(--muted-2); letter-spacing:.05em; }

.growth__head{ display:flex; flex-wrap:wrap; gap:14px 34px; }
.growth__head li{ min-width:120px; }
.growth__head .k{
  display:block; margin-bottom:6px;
  font-family:var(--display); font-size:11.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--muted-2);
}
.growth__head .v{
  display:block; font-family:var(--display); font-weight:300;
  font-size:22px; line-height:1.1; color:var(--accent);
}

.chart{ margin:0; }
.chart__svg{ overflow-x:auto; -webkit-overflow-scrolling:touch; }
.chart__svg svg{ width:100%; height:auto; }
@media (max-width:640px){ .chart__svg svg{ min-width:540px; } }
/* Chart motion is written per-frame from scroll position by paintChart() —
   opacity/transform on the area, the dots and the comet are set inline, so
   there must be no CSS animation or transition on them here. A CSS
   animation would override the inline values outright, and a transition
   would lag them behind the scrollbar. */
.chart__area{ opacity:0; }
.chart__dot{ opacity:0; }
.chart__comet{ opacity:0; }

/* The endpoint pulse is the one piece that is genuinely a loop rather than
   a read of scroll position, so it stays a CSS animation — gated until the
   line has finished arriving. */
.chart__pulse{ opacity:0; }
#chart.is-done .chart__pulse{ animation:chartPulse 2.6s ease-out .2s infinite; }
@keyframes chartPulse{
  0%  { opacity:.85; transform:scale(1); }
  70% { opacity:0;   transform:scale(3.6); }
  100%{ opacity:0;   transform:scale(3.6); }
}

/* ── chart scrubbing ─────────────────────────────────────────────────────
   pan-y keeps vertical page scrolling working on touch while the chart
   claims horizontal drags for itself. */
.chart__svg{ position:relative; touch-action:pan-y; outline:none; }
.chart__svg:focus-visible{ outline:1px solid rgba(140,255,46,.5); outline-offset:6px; }

.chart__scrub{ opacity:0; transition:opacity .22s ease; pointer-events:none; }
#chart.is-scrub .chart__scrub{ opacity:1; }
.chart__halo{ opacity:.55; }

/* The resting end label and the tooltip occupy the same spot on the last
   two months — one has to yield. */
.chart__end{ transition:opacity .22s ease; }
#chart.hide-end .chart__end{ opacity:0; }

.chart__tip{
  position:absolute; top:0; left:0; z-index:3;
  display:grid; gap:4px;
  padding:11px 14px; border-radius:10px;
  background:rgba(14,14,17,.96);
  border:1px solid #26262a;
  -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
  pointer-events:none; white-space:nowrap;
  opacity:0; transition:opacity .22s ease;
}
#chart.is-scrub .chart__tip{ opacity:1; }
.chart__tip-m{
  font-family:var(--display); font-size:10.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted-2);
}
.chart__tip-v{ font-family:var(--display); font-size:12.5px; color:var(--muted-2); }
.chart__tip-v b{
  font-family:var(--display); font-weight:400; font-size:23px;
  color:var(--accent); margin-right:6px;
}
.chart__tip-d{ font-size:12px; color:var(--muted); }

.chart__hint{
  margin:14px 0 0; font-family:var(--display);
  font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:#3f3f45;
}

.chart__cap{ margin-top:16px; font-size:14px; color:var(--muted-2); letter-spacing:.04em; }
.chart__note{ display:block; font-size:13px; color:#4d4d4d; }

.levers{
  display:grid; gap:1px; background:var(--line);
  border:1px solid var(--line); border-radius:var(--r); overflow:hidden;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
}
.lever{ background:#000; padding:28px clamp(20px,2.2vw,28px); transition:background .35s ease; }
.lever:hover{ background:#0c0c0c; }
.lever__n{
  display:block; margin-bottom:14px;
  font-family:var(--display); font-size:12.5px; letter-spacing:.2em; color:var(--accent);
}
.lever h3{ font-size:19px; margin-bottom:9px; }
.lever p{ margin:0; font-size:15px; color:var(--muted); }

/* ─────────────── craft ─────────────── */
.craft{
  display:grid; gap:clamp(26px,4vw,54px);
  grid-template-columns:minmax(0,1.5fr) minmax(250px,.85fr);
  align-items:start;
}
.craft > *{ min-width:0; }

.steps{ border-top:1px solid var(--line); }
.step{
  display:grid; grid-template-columns:64px 1fr; gap:0 22px;
  padding:26px 0; border-bottom:1px solid var(--line);
  transition:padding-left .35s cubic-bezier(.2,.8,.2,1), background .35s ease;
}
.step:hover{ padding-left:14px; background:rgba(255,255,255,.02); }
.step__n{
  font-family:var(--display); font-size:15px; letter-spacing:.14em;
  color:var(--muted-2); padding-top:5px; transition:color .3s ease;
}
.step:hover .step__n{ color:var(--accent); }
.step h3{ font-size:22px; margin-bottom:8px; }
.step p{ margin:0; font-size:15.5px; color:var(--muted); max-width:52ch; }

.services{ padding:28px 26px; position:sticky; top:calc(var(--nav-h) + 24px); }
.services__h{ font-family:var(--display); font-size:17px; margin-bottom:18px; }
.services__list li{
  position:relative; padding:10px 0 10px 26px; font-size:15px; color:var(--muted);
  border-bottom:1px solid rgba(255,255,255,.06);
  transition:color .28s ease, padding-left .28s ease;
}
.services__list li:last-child{ border-bottom:0; }
.services__list li::before{
  content:"→"; position:absolute; left:0; top:10px; color:var(--accent);
  transition:transform .28s ease;
}
.services__list li:hover{ color:var(--ink); padding-left:32px; }
.services__list li:hover::before{ transform:translateX(4px); }

/* ─────────────── long-form ─────────────── */
.longform{
  display:grid; gap:clamp(14px,2vw,20px);
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
}
/* Cards read as a stated direction, not an empty portfolio slot: a status
   label at the top, the format underneath, and no invented metrics. */
.slot{
  display:flex; flex-direction:column; align-items:flex-start; gap:14px;
  aspect-ratio:16/9; padding:22px 24px;
  border:1px dashed rgba(255,255,255,.18); border-radius:var(--r);
  color:var(--muted-2); background:rgba(255,255,255,.015);
  transition:border-color .35s ease, color .35s ease, transform .35s cubic-bezier(.2,.8,.2,1);
}
.slot:hover{ border-color:var(--accent); color:var(--muted); transform:translateY(-5px); }

/* same treatment as the section eyebrow labels */
.slot__status{
  font-family:var(--display); font-size:12px; letter-spacing:.24em;
  text-transform:uppercase; color:var(--muted-2);
}
.slot b{
  font-family:var(--display); font-weight:400; font-size:20px;
  letter-spacing:-.01em; color:rgba(255,255,255,.82);
  margin-top:auto;
}

.lf{
  display:block; overflow:hidden; border-radius:var(--r);
  border:1px solid var(--line); background:rgba(255,255,255,.025);
  transition:transform .4s cubic-bezier(.2,.8,.2,1), border-color .35s ease;
}
.lf:hover{ transform:translateY(-6px); border-color:rgba(140,255,46,.45); }
.lf__media{ aspect-ratio:16/9; background:#0d0d0d; overflow:hidden; }
.lf__media img{ width:100%; height:100%; object-fit:cover; transition:transform .6s ease; }
.lf:hover .lf__media img{ transform:scale(1.05); }
.lf__body{ padding:18px 20px 22px; }
.lf__t{ font-family:var(--display); font-size:19px; margin:0 0 6px; }
.lf__meta{ margin:0 0 8px; font-size:13px; color:var(--accent); letter-spacing:.1em; text-transform:uppercase; }
.lf__text{ margin:0; font-size:15px; color:var(--muted); }

/* ─────────────── credits ─────────────── */
.credits{
  display:grid; gap:clamp(16px,2.2vw,24px);
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
}
.credit{
  display:flex; flex-direction:column;
  padding:clamp(24px,3vw,34px);
  border:1px solid var(--line); border-radius:var(--r); background:rgba(255,255,255,.025);
  transition:transform .4s cubic-bezier(.2,.8,.2,1), border-color .35s ease, background .35s ease;
}
.credit:hover{ transform:translateY(-6px); border-color:var(--line-2); background:rgba(255,255,255,.045); }
.credit__ch{ font-size:26px; margin-bottom:9px; }
.credit__role{
  margin:0 0 16px; font-family:var(--display); font-size:12px;
  letter-spacing:.2em; text-transform:uppercase; color:var(--accent);
}
.credit__scope{ margin:0 0 20px; font-size:15.5px; color:var(--muted); }
.credit__pts{ display:grid; gap:10px; margin-top:auto; padding-top:18px; border-top:1px solid var(--line); }
.credit__pts li{ position:relative; padding-left:22px; font-size:15px; color:var(--muted); }
.credit__pts li::before{
  content:""; position:absolute; left:2px; top:10px;
  width:6px; height:6px; border-radius:50%; background:var(--accent);
}

/* ─────────────── about ─────────────── */
.about{
  display:grid; gap:clamp(30px,4vw,60px);
  grid-template-columns:minmax(0,1.6fr) minmax(240px,.8fr);
  align-items:start;
}
.about__body p{ margin:0 0 20px; color:var(--muted); max-width:62ch; font-size:17px; }
.about__h{ margin-bottom:26px; }

.about__side{ display:grid; gap:16px; }

/* ─────────────── experience timeline: journey ───────────────
   Left column is sticky and carries a thin scroll-linked progress rail
   (see timelineProgress() in app.js); the right column is the timeline
   itself, each entry fading in as it's scrolled to (.rv, same reveal
   system as the rest of the site). */
/* Two columns again, like the original — "My Creative Journey" on the
   left, the timeline on the right — but even (1fr 1fr) instead of the
   original .85fr/1.6fr split, so the seam between them falls exactly on
   the page's centre line instead of left-of-centre. */
.exp{
  display:grid; gap:clamp(30px,4vw,64px);
  grid-template-columns:1fr 1fr;
  align-items:start;
  margin-top:clamp(72px,9vw,120px);
}
.exp__intro{ position:sticky; top:calc(var(--nav-h) + 24px); }
.exp__h{ font-size:clamp(28px,4vw,44px); letter-spacing:-.015em; margin:0 0 clamp(24px,3.5vw,36px); }
.exp__progress-row{
  display:flex; justify-content:space-between;
  font-family:var(--display); font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted-2); margin-bottom:10px;
}
.exp__progress-track{ position:relative; height:1px; background:var(--line); }
.exp__progress-fill{
  position:absolute; left:0; top:0; height:100%; width:var(--fill,0%);
  background:var(--accent); box-shadow:0 0 10px rgba(140,255,46,.6);
  transition:width .12s linear;
}

.timeline{
  position:relative;
  padding-left:28px;
  border-left:1px solid var(--line);
}
.timeline__item{ position:relative; padding-bottom:clamp(38px,5vw,58px); }
.timeline__item:last-child{ padding-bottom:0; }
.timeline__dot{
  position:absolute; left:-32.5px; top:7px;
  width:9px; height:9px; border-radius:50%;
  background:var(--accent); box-shadow:0 0 12px var(--accent);
}
.timeline__co{
  display:block; margin-bottom:6px;
  font-family:var(--display); font-weight:600; font-size:12px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--accent);
}
.timeline__period{
  display:block; margin-bottom:16px;
  font-family:var(--display); font-size:11.5px;
  letter-spacing:.1em; text-transform:uppercase; color:var(--muted-2);
}
.timeline__role{
  font-weight:400; font-size:clamp(22px,3vw,32px); letter-spacing:-.01em;
  color:var(--ink); margin:0 0 12px;
}
.timeline__text{ margin:0; font-size:15.5px; line-height:1.7; color:var(--muted); max-width:52ch; }

/* ─────────────── about me: portrait + floating labels ─────────────── */
.me{ text-align:center; margin-bottom:clamp(56px,8vw,96px); }
.kick--center{ justify-content:center; }

.me__h{
  font-size:clamp(30px,6.4vw,84px); letter-spacing:-.02em; line-height:1;
  margin-bottom:24px;
}
.me__lines{
  margin:0 auto; max-width:60ch;
  font-size:clamp(15px,1.9vw,21px); line-height:1.9;
  letter-spacing:.09em; color:var(--muted);
}

.stage{
  position:relative; margin:clamp(40px,7vw,80px) auto 0;
  width:min(620px,100%); aspect-ratio:1/.86;
}
.stage__glow{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:78%; aspect-ratio:1; border-radius:50%;
  background:radial-gradient(circle, rgba(140,255,46,.14) 0%, rgba(140,255,46,.04) 45%, transparent 70%);
  animation:stagePulse 5s ease-in-out infinite;
}
@keyframes stagePulse{
  0%,100%{ opacity:.65; transform:translate(-50%,-50%) scale(1); }
  50%    { opacity:1;   transform:translate(-50%,-50%) scale(1.06); }
}

.avatar{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  margin:0; width:min(250px,42%); aspect-ratio:1;
  border-radius:50%;
  background:#111;
  box-shadow:0 0 0 1px var(--line), 0 0 0 7px #000, 0 30px 70px -26px rgba(140,255,46,.4);
}
.avatar img{
  width:100%; height:100%; border-radius:50%; object-fit:cover;
  /* full colour, as asked */
  filter:saturate(1.06) contrast(1.03);
  transition:transform .7s cubic-bezier(.2,.8,.2,1);
}
.avatar:hover img{ transform:scale(1.05); }

.avatar__hi{
  position:absolute; left:50%; bottom:-14px; transform:translateX(-50%);
  padding:6px 15px; border-radius:999px; white-space:nowrap;
  background:var(--bg); border:1px solid var(--accent); color:var(--accent);
  font-family:var(--display); font-size:11.5px; font-weight:600;
  letter-spacing:.14em; text-transform:uppercase;
}

/* role tags — enter from their own corner, once, as the stage scrolls into
   view (see stageBubbles() in app.js), instead of floating at random. */
.bubbles{ position:absolute; inset:0; }
.bubble{
  position:absolute;
  padding:9px 18px; border-radius:999px; white-space:nowrap;
  font-family:var(--display); font-size:clamp(12px,1.5vw,14.5px); font-weight:400;
  letter-spacing:.02em; color:var(--muted);
  background:rgba(10,10,10,.72); border:1px solid var(--line);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  opacity:0;
  transition:opacity .8s cubic-bezier(.16,1,.3,1), transform .8s cubic-bezier(.16,1,.3,1),
             border-color .3s ease, color .3s ease;
}
.bubble:hover{ border-color:var(--accent); color:var(--ink); }

.bubble--tl{ left:0;  top:22%;    transform:translate(-26px,-18px); transition-delay:0ms; }
.bubble--tr{ right:0; top:18%;    transform:translate(26px,-18px);  transition-delay:90ms; }
.bubble--bl{ left:4%; bottom:22%; transform:translate(-26px,18px);  transition-delay:180ms; }
.bubble--br{ right:2%;bottom:10%; transform:translate(26px,18px);   transition-delay:270ms; }

.bubble.in{ opacity:1; transform:translate(0,0); }

.chips{ display:flex; flex-wrap:wrap; gap:9px; margin-top:30px; }
.chips li{
  font-family:var(--display); font-size:14px; letter-spacing:.04em;
  padding:8px 16px; border-radius:999px;
  border:1px solid var(--line); color:var(--muted);
  transition:all .28s cubic-bezier(.2,.8,.2,1);
}
.chips li:hover{ color:var(--accent); border-color:var(--accent); transform:translateY(-2px); }

/* ─────────────── collaborate ─────────────── */
/* Distinct closing panel: a hair lighter than the pure-black sections above
   it, with a hard seam (border-top) at the boundary rather than a gradient
   fade — a fade still reads as continuous with whatever's above it at the
   point they actually meet. The footer continues the same tone so the two
   feel like one zone. */
.collab{
  display:grid; place-items:center;
  min-height:56svh; padding:clamp(44px,6vw,86px) var(--pad);
  text-align:center;
  background:var(--bg-soft);
  border-top:1px solid var(--line);
}
.collab__h{
  position:relative;
  font-size:clamp(50px,13vw,185px);
  line-height:.94; letter-spacing:-.015em; font-weight:300;
}
/* Each line moves on its own. The section's own overflow:hidden (from
   [data-glow]) is what clips them at the edges while they're still spread
   apart, so nothing ever pushes the page into horizontal scroll.
   nowrap keeps "Work Together" on one line — a mid-phrase wrap would break
   the two-line structure the convergence animation depends on. */
.collab__w{ display:block; white-space:nowrap; will-change:transform; }

/* No override here on purpose — this is the same glow recipe as the hero's
   (720px, mint, screen blend) rather than the smaller neutral wash it used
   to be, so the two cursor-lit moments on the page actually match. */

/* ─────────────── footer ─────────────── */
.foot{
  background:var(--bg-soft);
  border-top:1px solid var(--line);
  padding:clamp(34px,4.5vw,52px) 0 30px;
}

.foot__grid{
  display:grid; gap:clamp(26px,4vw,40px);
  grid-template-columns:repeat(3,minmax(0,1fr));
  margin-bottom:clamp(30px,4vw,44px);
}
.foot__k{
  display:block; margin-bottom:17px;
  font-family:var(--display); font-size:12px; letter-spacing:.28em;
  text-transform:uppercase; color:var(--muted-2);
}
.foot__list{ display:grid; gap:12px; }
.foot__list a{
  display:inline-flex; align-items:center; gap:7px;
  font-family:var(--display); font-size:clamp(17px,2vw,21px); color:var(--muted);
  transition:color .28s ease, transform .28s cubic-bezier(.2,.8,.2,1);
}
.foot__list a:hover{ color:var(--ink); transform:translateX(5px); }
.foot__list a i{
  font-style:normal; font-size:.8em; color:var(--muted-2);
  transition:transform .28s ease, color .28s ease;
}
.foot__list a:hover i{ transform:translate(2px,-2px); color:var(--accent); }

.foot__mail{
  display:inline-block; margin-bottom:17px;
  font-family:var(--display); font-size:clamp(19px,2.4vw,27px);
  letter-spacing:-.01em; overflow-wrap:anywhere;
  transition:color .28s ease;
}
.foot__mail:hover{ color:var(--accent); }
.foot__avail{
  display:flex; align-items:flex-start; gap:10px; margin:0;
  font-size:15px; color:var(--muted);
}
.foot__avail .dot{ flex:0 0 auto; margin-top:9px; }

.foot__bottom{
  display:flex; flex-wrap:wrap; gap:12px 20px; justify-content:space-between;
  padding-top:22px; border-top:1px solid var(--line);
  font-size:14.5px; color:var(--muted-2); letter-spacing:.05em;
}
.foot__top{ display:inline-flex; gap:7px; transition:color .28s ease, transform .28s ease; }
.foot__top:hover{ color:var(--accent); transform:scale(1.06); }
.foot__top span{ display:inline-block; transition:transform .3s ease; }
.foot__top:hover span{ transform:rotate(45deg); }

/* ─────────────── reveal on scroll ─────────────── */
/* FadeUp: 30px rise on an ease-out curve. Children of a [data-stagger]
   container get an incremental delay set by JS via --d. */
html.reveal-on .rv{
  opacity:0; transform:translateY(30px);
  transition:opacity .75s cubic-bezier(.16,1,.3,1) var(--d,0ms),
             transform .75s cubic-bezier(.16,1,.3,1) var(--d,0ms);
}
html.reveal-on .rv.in{ opacity:1; transform:none; }

/* ─────────────── responsive ─────────────── */
@media (max-width:1080px){
  .pill__links{ gap:16px; }
  .pill__links a{ font-size:14.5px; }
}

@media (max-width:900px){
  .pill__links{ display:none; }
  .burger{ display:block; }
  /* the typing dots stay on small screens too — they're part of the look,
     not just a menu affordance */
  .nav.is-stuck .typing{ display:flex; padding:8px 6px; }
  .nav.is-stuck .pill{ max-width:520px; }
  .craft, .about, .exp{ grid-template-columns:1fr; }
  .services, .exp__intro{ position:static; }
  .statbar{ grid-template-columns:repeat(2,1fr); }
}

@media (max-width:760px){
  .foot__grid{ grid-template-columns:1fr 1fr; }
  .foot__col--hello{ grid-column:1 / -1; }
}

@media (max-width:640px){
  /* clearance so the tag row never runs into the SCROLL indicator */
  .hero{ padding-bottom:136px; }
  .collab{ min-height:44svh; }

  /* give the floating labels room so they stop covering the portrait */
  .stage{ aspect-ratio:1/1.12; }
  .avatar{ width:min(190px,40%); }
  .bubble{ padding:7px 13px; font-size:12.5px; }
  .bubble--tl{ top:12%; }
  .bubble--tr{ top:4%; }
  .bubble--bl{ left:0; bottom:26%; }
  .bubble--br{ right:0; bottom:8%; }
  .growth__top{ flex-direction:column; }
  .step{ grid-template-columns:44px 1fr; gap:0 14px; }
  .icon::after{ display:none; }
}

@media (max-width:420px){ .statbar{ grid-template-columns:1fr; } }

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{ transition-duration:.01ms !important; animation-duration:.01ms !important; }
  html.reveal-on .rv{ opacity:1; transform:none; }
  .cursor{ display:none; }
}
