/* ════════════════════════════════════════════════════════════
   stage.css — the WebGL centrepiece sections
   One fixed canvas behind the content; each pinned section owns
   it while it is on screen, and the cards move around it.
   ════════════════════════════════════════════════════════════ */

.gl{
  position:fixed; inset:0; z-index:2;
  pointer-events:none;
  opacity:0;
  transition:opacity .45s ease;
}
.gl.is-on{ opacity:1; }
.gl__cv{ display:block; width:100%; height:100%; }

/* the grain belongs on top of everything, including the canvas */
.grain{ z-index:6; }

/* ─────────── a centrepiece section ─────────── */
.stage3d{ height:520vh; height:520svh; position:relative; }
@media (max-width:900px){ .stage3d{ height:460vh; height:460svh; } }

.stage3d__pin{
  position:sticky; top:0; height:100vh; height:100svh;
  overflow:hidden;
}

.stage3d__head{
  position:absolute; top:0; left:0; right:0; z-index:4;
  padding:clamp(84px,13vh,128px) var(--gutter) clamp(20px,4vh,40px);
  text-align:center; pointer-events:none;
  background:linear-gradient(180deg, var(--ink) 30%, rgba(8,9,10,.8) 62%, transparent);
}
.stage3d__n{
  font-family:var(--mono); font-size:11px; letter-spacing:.3em;
  text-transform:uppercase; color:var(--gold); display:block; margin-bottom:12px;
}
.stage3d__head h2{
  font-family:var(--serif); font-size:clamp(28px,4.4vw,62px);
  line-height:1.02; letter-spacing:-.028em;
}
.stage3d__head p{
  margin:12px auto 0; max-width:52ch;
  font-size:clamp(13.5px,.5vw + 12px,16px); color:var(--muted);
}

/* the cards that move around the object */
.stage3d__card{
  --a:0;
  position:absolute; top:50%; z-index:5;
  width:min(390px, 40vw);
  padding:clamp(20px,2.2vw,30px);
  border-radius:18px;
  opacity:var(--a);
  pointer-events:none;
}
.stage3d__card--l{
  left:clamp(20px,6vw,92px);
  transform:translateY(-50%) translateX(calc((1 - var(--a)) * -60px)) rotateY(calc((1 - var(--a)) * 22deg));
}
.stage3d__card--r{
  right:clamp(20px,6vw,92px);
  transform:translateY(-50%) translateX(calc((1 - var(--a)) * 60px)) rotateY(calc((1 - var(--a)) * -22deg));
}
.stage3d__card b{
  display:block; font-family:var(--serif); font-weight:400;
  font-size:clamp(20px,2vw,29px); letter-spacing:-.018em;
  color:var(--ivory); margin-bottom:10px;
}
.stage3d__card p{ margin:0; font-size:14px; color:var(--muted); }
.stage3d__card em{
  display:block; font-family:var(--mono); font-style:normal;
  font-size:10px; letter-spacing:.24em; text-transform:uppercase;
  color:var(--gold); margin-bottom:10px;
}
.stage3d__card code{ color:var(--gold); font-size:.88em; }

/* the progress rail down the side */
.stage3d__rail{
  position:absolute; left:50%; bottom:clamp(24px,5vh,54px);
  transform:translateX(-50%);
  display:flex; gap:8px; z-index:6;
}
.stage3d__rail i{
  display:block; width:26px; height:2px; border-radius:2px;
  background:rgba(239,237,231,.16);
  transition:background-color .3s ease;
}
.stage3d__rail i.on{ background:var(--gold); }

/* phones: the object stays behind, the card sits at the bottom.
   The card needs a solid backing here — glass over a lit 3D object is
   pretty and unreadable. */
@media (max-width:900px){
  .stage3d__card{
    width:auto; left:var(--gutter); right:var(--gutter);
    top:auto; bottom:clamp(58px,11vh,92px);
    transform:translateY(calc((1 - var(--a)) * 24px)) !important;
    background:rgba(10,11,13,.90);
    border-color:rgba(255,255,255,.14);
  }
  @supports (backdrop-filter:blur(4px)) or (-webkit-backdrop-filter:blur(4px)){
    .stage3d__card{
      background:rgba(10,11,13,.78);
      backdrop-filter:blur(26px) saturate(1.3);
      -webkit-backdrop-filter:blur(26px) saturate(1.3);
    }
  }
  .stage3d__card::after{ opacity:.35; }
  .stage3d__head{ padding-top:clamp(76px,11vh,104px); }
}

/* no WebGL — the object is gone, so the section becomes a plain stack */
.no-gl .stage3d{ height:auto !important; }
.no-gl .stage3d__pin{ position:static; height:auto; padding:clamp(60px,9vh,100px) 0; }
.no-gl .stage3d__head{ position:static; background:none; padding-inline:var(--gutter); }
.no-gl .stage3d__card{
  position:static; --a:1; opacity:1; transform:none !important;
  width:auto; max-width:none; margin:0 var(--gutter) 14px;
}
.no-gl .stage3d__rail{ display:none; }

/* ─────────── the condensed commit strip ─────────── */
.commits{ padding:clamp(50px,8vh,96px) 0 clamp(70px,11vh,130px); overflow:hidden; }
.commits__head{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:20px; flex-wrap:wrap; margin-bottom:clamp(20px,3vw,34px);
}
.commits__head h3{ font-family:var(--serif); font-size:clamp(22px,2.6vw,34px); letter-spacing:-.02em; }
.commits__head span{
  font-family:var(--mono); font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--muted-2);
}
/* the old timeline markup, restyled as a tight ledger of rows */
.commits__rows{ position:static; padding-left:0; }
.commits__rows .tl__items{ display:grid; gap:5px; }
.commits__rows .tl__items li{
  --c:0;
  position:relative;
  display:grid; grid-template-columns:104px 68px 1fr; gap:clamp(10px,1.6vw,22px);
  align-items:baseline;
  padding:11px clamp(12px,1.6vw,20px);
  border-radius:10px;
  background:rgba(239,237,231,calc(.012 + var(--c) * .05));
  opacity:calc(.36 + var(--c) * .64);
  transform:translateX(calc((1 - var(--c)) * 10px));
  transition:opacity .12s linear, transform .12s linear, background-color .12s linear;
}
.commits__rows .tl__items li::before{ display:none; }
.commits__rows .tl__items time{ font-family:var(--mono); font-size:11px; color:var(--muted-2); }
.commits__rows .tl__repo{
  justify-self:start; font-family:var(--mono); font-weight:400;
  font-size:9.5px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--gold); border:1px solid var(--line-2); border-radius:100px; padding:3px 9px;
}
.commits__rows .tl__items p{ margin:0; font-size:14.5px; color:var(--ivory); }
@media (max-width:700px){
  .commits__rows .tl__items li{ grid-template-columns:1fr; gap:4px; }
  .commits__rows .tl__items p{ font-size:14px; }
}

/* ─────────── scroll cues ───────────
   A persistent, animated hint on every pinned section that says which way the
   content is going to move. It dims once that section is under way rather than
   disappearing, so it never reads as something you missed. */
/* Phones only. On a desktop the pointer and the scrollbar already say this. */
.cue{ display:none; }
@media (max-width:900px){
  .cue{
    position:absolute; left:50%; bottom:clamp(14px,2.8vh,26px);
    transform:translateX(-50%);
    z-index:12; pointer-events:none;
    display:flex; align-items:center; gap:9px;
    padding:7px 15px 7px 13px;
    border:1px solid rgba(255,255,255,.10);
    border-radius:100px;
    background:rgba(10,11,13,.66);
  }
}
@supports (backdrop-filter:blur(4px)) or (-webkit-backdrop-filter:blur(4px)){
  .cue{ backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); }
}
.cue span{
  font-family:var(--mono); font-size:9.5px; letter-spacing:.24em;
  text-transform:uppercase; color:var(--muted);
  white-space:nowrap;
}
.cue i{
  position:relative; display:block; flex:none;
  width:26px; height:12px; overflow:hidden;
}
/* the travelling dot */
.cue i::before{
  content:""; position:absolute; top:50%; left:0;
  width:5px; height:5px; margin-top:-2.5px; border-radius:50%;
  background:var(--gold);
  animation:cueX 1.9s cubic-bezier(.55,0,.45,1) infinite;
}
/* the track it runs along */
.cue i::after{
  content:""; position:absolute; top:50%; left:0; right:0; height:1px;
  margin-top:-.5px; background:rgba(203,169,107,.20);
}
@keyframes cueX{
  0%   { transform:translateX(0);    opacity:0; }
  18%  { opacity:1; }
  72%  { opacity:1; }
  100% { transform:translateX(21px); opacity:0; }
}

/* every cue points down — it is always the page scroll that drives things */
.cue i{ width:12px; height:26px; }
.cue i::before{ margin-top:0; top:0; left:50%; margin-left:-2.5px; animation-name:cueY; }
.cue i::after{ top:0; bottom:0; left:50%; right:auto; width:1px; height:auto; margin:0 0 0 -.5px; }
@keyframes cueY{
  0%   { transform:translateY(0);    opacity:0; }
  18%  { opacity:1; }
  72%  { opacity:1; }
  100% { transform:translateY(21px); opacity:0; }
}

@media (prefers-reduced-motion:reduce){
  .cue i::before{ animation:none; opacity:1; }
}

/* ─────────── milestones ─────────── */
.mile{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:1px; background:var(--line-2); border:1px solid var(--line-2);
  border-radius:12px; overflow:hidden;
  margin-bottom:clamp(40px,6vw,72px);
}
.mile article{
  --c:0; background:var(--ink);
  padding:clamp(18px,2vw,26px); display:grid; gap:7px; align-content:start;
}
@supports (background:color-mix(in srgb,#000 50%,#fff)){
  .mile article{ background:color-mix(in srgb, var(--surface) calc(var(--c) * 55%), var(--ink)); }
}
.mile em{
  font-family:var(--mono); font-style:normal; font-size:9.5px;
  letter-spacing:.18em; text-transform:uppercase; color:var(--gold);
}
.mile b{ font-family:var(--serif); font-weight:400; font-size:clamp(17px,1.5vw,21px); letter-spacing:-.014em; }
.mile p{ margin:0; font-size:13.5px; color:var(--muted); }

/* ─────────── the tape ─────────── */
.tape{
  --c:0;
  margin:0 0 clamp(18px,2.4vw,30px);
  border:1px solid var(--line);
  border-radius:14px;
  overflow:hidden;
  background:linear-gradient(180deg,#0C0E10,#08090A);
  box-shadow:0 40px 90px -60px rgba(0,0,0,1);
}
.tape canvas{
  display:block; width:100%;
  height:clamp(220px, 34vh, 380px);
}
.tape figcaption{
  display:flex; align-items:center; gap:clamp(12px,2vw,26px); flex-wrap:wrap;
  padding:11px clamp(14px,1.8vw,22px);
  border-top:1px solid var(--line-2);
  font-family:var(--mono); font-size:10.5px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--muted-2);
}
.tape figcaption span{ display:inline-flex; align-items:center; gap:7px; }
.tape figcaption em{ margin-left:auto; font-style:normal; color:var(--gold); letter-spacing:.1em; }
.tape__k{ width:14px; height:2px; border-radius:2px; display:block; }
.tape__k--e{ background:#EFEDE7; }
.tape__k--s{ background:#C4564E; }
.tape__k--t{ background:#4FA97A; }
.tape__note{ max-width:66ch; color:var(--muted); font-size:14px; margin:0 0 clamp(30px,4vw,52px); }

/* ─────────── capability list ─────────── */
.caps{ display:grid; gap:1px; background:var(--line-2); border:1px solid var(--line-2); border-radius:12px; overflow:hidden; }
.caps li{
  background:var(--ink); padding:12px clamp(14px,1.6vw,20px);
  font-size:14.5px; color:var(--ivory);
  display:flex; align-items:baseline; gap:12px;
}
.caps li::before{
  content:""; flex:none; width:5px; height:5px; border-radius:50%;
  background:var(--gold); transform:translateY(-2px);
}

@media (prefers-reduced-motion:reduce){
  .gl{ display:none; }
  .stage3d{ height:auto !important; }
  .stage3d__pin{ position:static; height:auto; padding:clamp(60px,9vh,100px) 0; }
  .stage3d__head{ position:static; background:none; padding-inline:var(--gutter); }
  .stage3d__card{ position:static; --a:1; opacity:1; transform:none !important;
                  width:auto; margin:0 var(--gutter) 14px; }
  .stage3d__rail{ display:none; }
  .commits__row{ opacity:1; transform:none; }
}
