/* ============================================================
   aran-sandhu.com
   ============================================================ */

/* ---------- tokens ---------- */
:root{
  --bg:#07080A;
  --bg-1:#0B0D10;
  --bg-2:#111419;
  --bg-3:#171B21;

  --line:rgba(255,255,255,.075);
  --line-2:rgba(255,255,255,.16);

  --fg:#EEF1F4;
  --fg-2:#A6AFB8;
  --fg-3:#707A83;   /* 4.58:1 on --bg; #6B747D was 4.22 and failed AA */

  --accent:#89CFF0;
  --accent-2:#BFE4F7;
  --accent-3:#4E9BC4;
  --accent-wash:rgba(137,207,240,.10);

  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  /* Display: high-contrast Didone. Thin strokes, sharp terminals.
     Full fallback chain -- a bare "Inter" here silently dropped every
     heading to Times when the webfont failed. */
  --disp:"Bodoni Moda","LM Roman 10","TeX Gyre Termes",Didot,"Bodoni 72","Playfair Display",Georgia,serif;
  --sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;


  --pad:clamp(20px,5vw,64px);
  --max:1280px;
  --prose:68ch;

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

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  margin:0;
  background:var(--bg);
  color:var(--fg-2);
  font-family:var(--sans);
  font-size:17px;
  line-height:1.68;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}

img{max-width:100%;display:block}
a{color:inherit}

::selection{background:var(--accent);color:#04070A}

/* ---------- type ---------- */
h1,h2,h3,h4{
  font-family:var(--disp);
  color:var(--fg);
  line-height:1.06;
  margin:0;
  text-wrap:balance;
}
/* Thin + sharp: display sizes carry light weights and tight tracking.
   Body copy stays at 400 -- thin strokes on a dark ground bloom and
   lose legibility below display size. */
h1{font-size:clamp(2.6rem,6.8vw,5.3rem);font-weight:400;letter-spacing:-.012em}
h2{font-size:clamp(1.9rem,3.8vw,3.1rem);font-weight:400;letter-spacing:-.008em}
h3{font-size:clamp(1.35rem,2.2vw,1.78rem);font-weight:400;letter-spacing:-.004em;line-height:1.18}
h4{font-size:1.08rem;font-weight:500;letter-spacing:0}

p{margin:0 0 1.35em}
p:last-child{margin-bottom:0}
strong{color:var(--fg);font-weight:600}
em{color:var(--fg);font-style:italic}

.label{
  font-family:var(--mono);
  font-size:.68rem;
  font-weight:500;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--fg-3);
  display:block;
}
.label--accent{color:var(--accent-3)}

.lead{
  font-size:clamp(1.1rem,1.9vw,1.32rem);
  line-height:1.6;
  color:var(--fg);
  letter-spacing:-.012em;
}

/* ---------- layout ---------- */
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--pad)}

/* Prose is full-bleed; only text is measure-constrained, so figures,
   stats and link rows can breathe wider than the reading column. */
.prose{max-width:none}
.prose > p,
.prose > h3,
.prose > h4,
.prose > ul,
.prose > .quote,
.prose > .summary{max-width:var(--prose)}
.prose > figure{max-width:1000px}
.prose > .links,
.prose > .mediacard{max-width:860px}
.prose > .stats{max-width:none}
.prose > * + h3{margin-top:2.6em}
.prose h3 + p{margin-top:.9em}
.prose ul{padding-left:1.15em;margin:0 0 1.3em}
.prose li{margin-bottom:.45em}
.prose li::marker{color:var(--accent-3)}

section{position:relative}
.rule{height:1px;background:var(--line);border:0;margin:0}

/* ---------- nav ---------- */
.nav{
  position:sticky;top:0;z-index:60;
  background:rgba(7,8,10,.72);
  backdrop-filter:blur(14px) saturate(1.4);
  -webkit-backdrop-filter:blur(14px) saturate(1.4);
  border-bottom:1px solid var(--line);
}
.nav__in{
  max-width:var(--max);margin:0 auto;padding:0 var(--pad);
  height:62px;display:flex;align-items:center;justify-content:space-between;gap:20px;
}
.nav__brand{
  font-family:var(--mono);font-size:.74rem;font-weight:500;
  letter-spacing:.2em;text-transform:uppercase;color:var(--fg);
  text-decoration:none;white-space:nowrap;
  transition:color .25s var(--ease);
}
.nav__brand:hover{color:var(--accent)}
.nav__links{display:flex;align-items:center;gap:clamp(14px,2.4vw,30px)}
.nav__link{
  font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--fg-3);text-decoration:none;
  transition:color .25s var(--ease);white-space:nowrap;
}
.nav__link:hover,.nav__link[aria-current="page"]{color:var(--fg)}
.nav__link--cta{color:var(--accent)}
.nav__link--cta:hover{color:var(--accent-2)}
@media (max-width:620px){
  .nav__link--hide{display:none}
}
/* Three nav items plus the brand overflow a phone at the desktop metrics,
   and the company link is too important to hide. Tighten the tracking and
   the gaps instead of dropping it. */
@media (max-width:460px){
  .nav__in{gap:12px;padding:0 16px}
  .nav__brand{font-size:.68rem;letter-spacing:.14em}
  .nav__links{gap:12px}
  .nav__link{font-size:.63rem;letter-spacing:.08em}
}

/* ---------- hero (home) ---------- */
/* The cover is a full-bleed layer that dissolves into the page rather than a
   framed photograph sitting beside the text. Two masks are intersected: one
   fading left-to-right across the image, one fading the top and bottom edges,
   so the picture has no hard boundary on any side. */
.hero{
  position:relative;
  padding:clamp(56px,10vw,132px) 0 clamp(52px,8vw,96px);
  min-height:clamp(600px,78vh,840px);   /* narrower range = less framing drift */
  display:flex;align-items:center;
  isolation:isolate;
}
.hero__media{
  position:absolute;inset:0 auto 0 0;
  width:clamp(420px,64%,1060px);
  z-index:-1;pointer-events:none;
  /* ONE mask layer only. Two stacked gradients plus mask-composite:intersect
     is unreliable across engines and silently dropped the vertical fade,
     leaving a hard cut along the bottom. The horizontal dissolve is done
     here; the vertical one is painted by the overlay below, fading to the
     page colour, which needs no compositing support at all. */
  -webkit-mask-image:linear-gradient(to right,#000 0%,#000 40%,rgba(0,0,0,.62) 68%,transparent 97%);
  mask-image:linear-gradient(to right,#000 0%,#000 40%,rgba(0,0,0,.62) 68%,transparent 97%);
}
.hero__media img{
  width:100%;height:100%;object-fit:cover;
  /* Framed on Aran, not on the ceiling. The source is portrait in a landscape
     box, so cover only ever crops vertically and the X value has no effect.
     75% keeps his head between roughly 26% and 43% down the frame across every
     viewport height; higher anchors clip his head off the top on short screens. */
  object-position:50% 75%;
}
/* Two washes: a vertical one that dissolves the top and bottom edges into the
   page, and a diagonal one that builds toward the type so it stays crisp. */
.hero__media::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(to bottom,
      var(--bg) 0%, rgba(7,8,10,0) 13%,
      rgba(7,8,10,0) 62%, rgba(7,8,10,.72) 88%, var(--bg) 100%),
    linear-gradient(96deg,
      rgba(7,8,10,0) 0%, rgba(7,8,10,0) 36%,
      rgba(7,8,10,.42) 64%, rgba(7,8,10,.88) 86%, var(--bg) 100%);
}
.hero__media--ph{
  background:repeating-linear-gradient(45deg,transparent,transparent 9px,rgba(255,255,255,.02) 9px,rgba(255,255,255,.02) 18px),var(--bg-2);
}
.hero__ph{
  position:absolute;inset:0;display:grid;place-items:center;
  color:var(--fg-3);font-family:var(--mono);font-size:.68rem;
  letter-spacing:.16em;text-transform:uppercase;text-align:center;padding:24px;
}
.hero .wrap{width:100%}
.hero__grid{
  display:grid;grid-template-columns:minmax(0,.72fr) minmax(0,1fr);
  gap:clamp(28px,5vw,64px);align-items:center;
}
.hero__name{margin-bottom:.9rem}
.hero__line{
  font-size:clamp(1.08rem,1.85vw,1.34rem);line-height:1.42;
  color:var(--fg);font-family:var(--disp);letter-spacing:-.004em;font-weight:400;
  margin:0 0 1.5rem;max-width:46ch;text-wrap:balance;
}
.hero__line b{color:var(--accent);font-weight:500}
.hero__bio{max-width:52ch;margin-bottom:2rem}
.hero__meta{
  display:flex;flex-wrap:wrap;gap:10px 26px;
  padding-top:1.4rem;border-top:1px solid var(--line);
}
.hero__meta span{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--fg-3);
}
.hero__meta span b{color:var(--fg-2);font-weight:400}

/* Narrow screens: the image stacks above the text and fades only at the
   bottom, so it still runs into the page instead of ending on an edge. */
@media (max-width:900px){
  .hero{display:block;min-height:0;padding-top:0}
  .hero__grid{grid-template-columns:1fr;gap:0}
  .hero__gap{display:none}
  .hero__media{
    position:relative;inset:auto;width:auto;z-index:0;
    /* already outside .wrap, so it is full-bleed without a negative margin.
       The old calc() pushed it past both viewport edges and caused 20px of
       horizontal scroll on phones. */
    margin:0 0 clamp(20px,5vw,36px);
    height:clamp(320px,62vh,520px);
  }
  .hero__media{
    -webkit-mask-image:none;mask-image:none;
  }
  .hero__media::after{
    background:linear-gradient(180deg,
      rgba(7,8,10,.10) 0%, rgba(7,8,10,.06) 42%,
      rgba(7,8,10,.70) 82%, var(--bg) 100%);
  }
  .hero__media::after{
    background:linear-gradient(180deg,rgba(7,8,10,.15) 0%,rgba(7,8,10,.1) 45%,var(--bg) 100%);
  }
}

/* ---------- section head ---------- */
.shead{
  display:flex;align-items:baseline;gap:18px;
  padding-bottom:20px;margin-bottom:clamp(28px,4vw,48px);
  border-bottom:1px solid var(--line);
}
.shead__n{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.18em;
  color:var(--accent-3);text-transform:uppercase;flex:none;
}
.shead__t{font-family:var(--disp);font-size:clamp(1.5rem,2.8vw,2.15rem);font-weight:400;letter-spacing:-.006em}
.shead__x{
  margin-left:auto;font-family:var(--mono);font-size:.66rem;
  letter-spacing:.14em;text-transform:uppercase;color:var(--fg-3);flex:none;
}
@media (max-width:620px){.shead__x{display:none}}

/* ---------- project list ---------- */
/* the section head already draws a rule above, so only close the bottom */
.plist{display:grid;gap:1px;background:var(--line);border-bottom:1px solid var(--line)}
.pitem{
  background:var(--bg);
  display:grid;grid-template-columns:78px minmax(0,1fr) 210px;
  gap:clamp(18px,3vw,40px);align-items:center;
  padding:clamp(20px,3vw,30px) clamp(4px,1.5vw,18px);
  text-decoration:none;position:relative;
  transition:background .35s var(--ease);
}
.pitem:hover{background:var(--bg-2)}
.pitem::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:2px;
  background:var(--accent);transform:scaleY(0);transform-origin:top;
  transition:transform .4s var(--ease);
}
.pitem:hover::before{transform:scaleY(1)}
.pitem__n{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.14em;
  color:var(--fg-3);padding-left:clamp(8px,1.5vw,16px);
}
.pitem:hover .pitem__n{color:var(--accent-3)}
.pitem__t{
  display:block;
  font-family:var(--disp);
  font-size:clamp(1.22rem,2.2vw,1.66rem);font-weight:400;color:var(--fg);
  letter-spacing:-.005em;line-height:1.2;margin-bottom:.5rem;
}
.pitem__s{display:block;font-size:.95rem;color:var(--fg-3);line-height:1.5;max-width:56ch}
.pitem__n,.pitem__thumb{display:block}
.pitem__thumb{
  aspect-ratio:16/10;overflow:hidden;background:var(--bg-2);
  border:1px solid var(--line);position:relative;
}
.pitem__thumb img{
  width:100%;height:100%;object-fit:cover;
  filter:grayscale(.55) contrast(1.04) brightness(.82);
  transition:filter .5s var(--ease),transform .7s var(--ease);
}
.pitem:hover .pitem__thumb img{filter:none;transform:scale(1.045)}
.pitem__thumb--none{
  display:grid;place-items:center;
  background:repeating-linear-gradient(45deg,transparent,transparent 8px,rgba(255,255,255,.022) 8px,rgba(255,255,255,.022) 16px),var(--bg-2);
}
.pitem__thumb--none span{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--fg-3);text-align:center;padding:0 10px;
}
@media (max-width:860px){
  .pitem{grid-template-columns:52px minmax(0,1fr);gap:16px}
  .pitem__thumb{grid-column:1/-1;aspect-ratio:16/9;margin-top:4px}
}

/* ---------- project page header ---------- */
.phead{padding:clamp(44px,7vw,88px) 0 clamp(28px,4vw,44px)}
.phead__back{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--fg-3);text-decoration:none;
  display:inline-flex;align-items:center;gap:9px;margin-bottom:clamp(24px,4vw,42px);
  transition:color .25s var(--ease),gap .25s var(--ease);
}
.phead__back:hover{color:var(--accent);gap:14px}
.phead__kicker{margin-bottom:1.1rem}
.phead__title{margin-bottom:1.2rem;max-width:18ch}
.phead__sub{font-size:clamp(1.05rem,2vw,1.3rem);color:var(--fg-2);max-width:50ch;line-height:1.55}

/* ---------- summary block ---------- */
.summary{
  border:1px solid var(--line-2);background:var(--bg-1);
  padding:clamp(22px,3.4vw,34px);margin:clamp(30px,5vw,56px) 0;
}
.summary__grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(165px,1fr));
  gap:clamp(18px,3vw,30px);
}
.summary__k{margin-bottom:.5rem}
.summary__v{color:var(--fg);font-size:.97rem;line-height:1.45;font-weight:500}
.summary__v a{color:var(--accent);text-decoration:none;border-bottom:1px solid rgba(137,207,240,.3)}
.summary__v a:hover{border-color:var(--accent)}

/* ---------- stats ---------- */
.stats{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:1px;background:var(--line);border:1px solid var(--line);
  margin:clamp(32px,5vw,60px) 0;
}
.stat{background:var(--bg-1);padding:clamp(22px,3vw,32px)}
.stat__n{
  font-size:clamp(2.1rem,4.6vw,3.1rem);font-family:var(--disp);font-weight:400;color:var(--accent);
  letter-spacing:-.018em;line-height:1;margin-bottom:.7rem;
  font-variant-numeric:lining-nums tabular-nums;font-variant-numeric:tabular-nums;
}
.stat__l{font-size:.92rem;color:var(--fg-2);line-height:1.5}
.stat__src{
  font-family:var(--mono);font-size:.62rem;letter-spacing:.1em;
  color:var(--fg-3);margin-top:.8rem;text-transform:uppercase;
}

/* ---------- body content ---------- */
.body{padding-bottom:clamp(50px,8vw,100px)}
.body h3{margin:clamp(46px,6vw,74px) 0 1.1rem;max-width:28ch}
.body h3:first-child{margin-top:0}
/* A links row opening the body sits under the summary block, whose own bottom
   margin already does the separating: left alone the two stack to ~150px. The
   negative top pulls that back to match the space put underneath, so the row
   sits evenly between the summary and the first paragraph rather than being
   flung down onto it. */
.prose > .links:first-child{
  margin-top:calc(-1 * clamp(16px,3vw,36px));
  margin-bottom:clamp(42px,5vw,64px);
}

.quote{
  border-left:2px solid var(--accent);padding:.2rem 0 .2rem 28px;
  margin:clamp(34px,5vw,56px) 0;max-width:56ch;
}
.quote p{
  font-family:var(--disp);font-size:clamp(1.35rem,2.7vw,1.9rem);line-height:1.38;color:var(--fg);
  font-weight:400;font-style:italic;letter-spacing:0;margin:0;
}
.quote cite{
  display:block;margin-top:1rem;font-style:normal;
  font-family:var(--mono);font-size:.66rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--fg-3);
}

/* ---------- figures ---------- */
figure{margin:clamp(34px,5vw,58px) 0}
.fig__img{
  border:1px solid var(--line);background:var(--bg-2);
  overflow:hidden;cursor:zoom-in;position:relative;display:block;width:100%;padding:0;
}
.fig__img img{width:100%;height:auto;transition:transform .8s var(--ease)}
.fig__img:hover img{transform:scale(1.02)}
figcaption{
  margin-top:.95rem;font-size:.88rem;color:var(--fg-3);line-height:1.55;max-width:62ch;
  padding-left:14px;border-left:1px solid var(--line);
}
.figrow{
  display:grid;gap:clamp(10px,1.6vw,18px);
  grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr));
}
.figrow--2{grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr))}
.figrow .fig__img{height:100%}
.figrow .fig__img img{height:100%;object-fit:cover}
.fig--wide{max-width:none}

/* ---------- link rows ---------- */
.links{border-top:1px solid var(--line);margin:clamp(34px,5vw,56px) 0 0}
.linkrow{
  display:flex;align-items:center;gap:18px;
  padding:18px 4px;border-bottom:1px solid var(--line);
  text-decoration:none;transition:padding-left .35s var(--ease),background .3s var(--ease);
}
.linkrow:hover{padding-left:14px;background:var(--bg-1)}
.linkrow__type{
  font-family:var(--mono);font-size:.62rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent-3);
  border:1px solid rgba(137,207,240,.26);padding:4px 9px;flex:none;
}
.linkrow__t{color:var(--fg);font-weight:500;font-size:1rem;line-height:1.35;flex:1;min-width:0}
.linkrow__a{color:var(--fg-3);flex:none;transition:transform .35s var(--ease),color .3s var(--ease)}
.linkrow:hover .linkrow__a{color:var(--accent);transform:translateX(4px)}

/* ---------- media placeholder ---------- */
.mediacard{
  border:1px solid var(--line-2);background:var(--bg-1);
  display:flex;align-items:center;gap:clamp(16px,2.5vw,26px);
  padding:clamp(18px,2.6vw,26px);margin:clamp(12px,2vw,18px) 0;
  text-decoration:none;transition:border-color .35s var(--ease),background .35s var(--ease);
}
.mediacard:hover{border-color:var(--accent-3);background:var(--bg-2)}
.mediacard__play{
  width:46px;height:46px;flex:none;border:1px solid var(--line-2);border-radius:50%;
  display:grid;place-items:center;color:var(--accent);
  transition:border-color .35s var(--ease),background .35s var(--ease);
}
.mediacard:hover .mediacard__play{border-color:var(--accent);background:var(--accent-wash)}
.mediacard__t{display:block;color:var(--fg);font-weight:500;margin-bottom:.3rem;line-height:1.35}
.mediacard__s{display:block;font-family:var(--mono);font-size:.64rem;letter-spacing:.13em;text-transform:uppercase;color:var(--fg-3)}

/* Before metadata loads a <video> has an intrinsic 300x150, so width:100% alone
   renders a squat letterbox sliver. Hold a 16/9 box until the real dimensions
   are known, then hand sizing back to the file (data-ar is set on
   loadedmetadata) so vertical phone clips are not stretched. */
video.native{
  width:100%;height:auto;aspect-ratio:16/9;object-fit:contain;
  display:block;border:1px solid var(--line);background:#000;
}
video.native[data-ar]{aspect-ratio:auto}

/* youtube facade */
.yt{
  position:relative;aspect-ratio:16/9;border:1px solid var(--line);
  cursor:pointer;overflow:hidden;width:100%;padding:0;display:block;
  background:
    repeating-linear-gradient(45deg,transparent,transparent 9px,rgba(255,255,255,.02) 9px,rgba(255,255,255,.02) 18px),
    var(--bg-2);
}
.yt img[data-broken]{display:none}
.yt img{width:100%;height:100%;object-fit:cover;opacity:.62;transition:opacity .4s var(--ease),transform .8s var(--ease)}
.yt:hover img{opacity:.8;transform:scale(1.03)}
.yt__btn{
  position:absolute;inset:0;display:grid;place-items:center;pointer-events:none;
}
.yt__btn span{
  width:66px;height:66px;border-radius:50%;border:1px solid rgba(255,255,255,.5);
  background:rgba(7,8,10,.5);backdrop-filter:blur(6px);
  display:grid;place-items:center;color:#fff;transition:background .35s var(--ease),border-color .35s var(--ease);
}
.yt:hover .yt__btn span{background:var(--accent);border-color:var(--accent);color:#04070A}
.yt iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

/* ---------- questions block ---------- */
.qs{background:var(--bg-1);border-block:1px solid var(--line);padding:clamp(52px,8vw,104px) 0}
.qs__list{
  display:grid;gap:1px;background:var(--line);
  border:1px solid var(--line);margin-top:clamp(26px,4vw,40px);
}
.qs__i{
  background:var(--bg-1);padding:clamp(18px,2.6vw,26px) clamp(18px,2.6vw,28px);
  display:flex;gap:20px;align-items:flex-start;
  transition:background .35s var(--ease);
}
.qs__i:hover{background:var(--bg-2)}
.qs__n{
  font-family:var(--mono);font-size:.64rem;letter-spacing:.12em;
  color:var(--accent-3);flex:none;padding-top:.42em;
}
.qs__q{
  color:var(--fg);font-family:var(--disp);font-size:clamp(1.1rem,2vw,1.32rem);
  line-height:1.45;letter-spacing:-.002em;font-weight:400;
}

/* ---------- next project ---------- */
.next{border-top:1px solid var(--line)}
.next a{
  display:flex;align-items:center;justify-content:space-between;gap:24px;
  padding:clamp(32px,5vw,58px) 0;text-decoration:none;
  transition:background .35s var(--ease);
}
.next a:hover{background:var(--bg-1)}
.next__t{font-family:var(--disp);font-size:clamp(1.4rem,2.8vw,2.1rem);font-weight:400;color:var(--fg);letter-spacing:-.008em}
.next a:hover .next__t{color:var(--accent)}
.next__a{color:var(--fg-3);flex:none;transition:transform .35s var(--ease),color .3s var(--ease)}
.next a:hover .next__a{color:var(--accent);transform:translateX(8px)}

/* ---------- footer ---------- */
.foot{border-top:1px solid var(--line);padding:clamp(52px,7vw,88px) 0 clamp(30px,4vw,44px);background:var(--bg-1)}
.foot__grid{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:clamp(30px,5vw,60px);align-items:start;
}
@media (max-width:760px){.foot__grid{grid-template-columns:1fr}}
.foot__cta{
  font-family:var(--disp);font-size:clamp(1.7rem,4.2vw,2.8rem);font-weight:400;color:var(--fg);
  letter-spacing:-.01em;line-height:1.12;max-width:16ch;margin-bottom:1.6rem;
}
.foot__mail{
  font-size:clamp(1rem,2vw,1.2rem);color:var(--accent);text-decoration:none;
  border-bottom:1px solid rgba(137,207,240,.32);transition:border-color .3s var(--ease);
}
.foot__mail:hover{border-color:var(--accent)}
.foot__links{display:flex;flex-direction:column;gap:12px}
.foot__links a{
  font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--fg-3);text-decoration:none;display:flex;align-items:center;gap:10px;
  transition:color .28s var(--ease),gap .28s var(--ease);
}
.foot__links a:hover{color:var(--fg);gap:15px}
.foot__base{
  margin-top:clamp(40px,6vw,72px);padding-top:24px;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:12px 26px;justify-content:space-between;
}
.foot__base span{font-family:var(--mono);font-size:.62rem;letter-spacing:.13em;text-transform:uppercase;color:var(--fg-3)}

/* ---------- lightbox ---------- */
.lb{
  position:fixed;inset:0;z-index:200;background:rgba(4,5,7,.96);
  display:none;place-items:center;padding:clamp(16px,4vw,56px);
  backdrop-filter:blur(6px);
}
.lb[open],.lb.on{display:grid}
.lb img{max-width:100%;max-height:88vh;width:auto;object-fit:contain;border:1px solid var(--line-2)}
.lb__cap{
  margin-top:16px;font-size:.85rem;color:var(--fg-3);text-align:center;
  max-width:70ch;margin-inline:auto;line-height:1.5;
}
.lb__x{
  position:absolute;top:clamp(14px,3vw,28px);right:clamp(14px,3vw,28px);
  width:42px;height:42px;border:1px solid var(--line-2);background:transparent;
  color:var(--fg-2);cursor:pointer;display:grid;place-items:center;
  transition:border-color .3s var(--ease),color .3s var(--ease);
}
.lb__x:hover{border-color:var(--accent);color:var(--accent)}

/* ---------- reveal ---------- */
/* Progressive enhancement: only hide content when JS is actually running.
   Without the .js class (script blocked, failed, or disabled) everything
   renders immediately instead of leaving a blank page. */
.js .rv{opacity:0;transform:translateY(16px);transition:opacity .8s var(--ease),transform .8s var(--ease)}
.js .rv.in{opacity:1;transform:none}
.rv-d1{transition-delay:.07s}
.rv-d2{transition-delay:.14s}
.rv-d3{transition-delay:.21s}

@media (prefers-reduced-motion:reduce){
  .js .rv{opacity:1;transform:none;transition:none}
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
}

/* ---------- focus ---------- */
a:focus-visible,button:focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;border-radius:1px;
}
.skip{
  position:absolute;left:-9999px;top:0;background:var(--accent);color:#04070A;
  padding:12px 20px;font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;text-decoration:none;z-index:100;
}
.skip:focus{left:var(--pad);top:12px}

/* ---------- gallery / slideshow ----------
   Collapses a run of images into one frame. Slides cross-fade rather than
   slide, because the set mixes portrait and landscape and a horizontal track
   would lurch between aspect ratios. Images are contained, never cropped, so
   a notebook page or a poster stays readable. */
.gal{margin:clamp(34px,5vw,58px) 0;max-width:1000px}
.gal__frame{
  position:relative;
  height:clamp(320px,52vh,580px);
  background:var(--bg-1);
  border:1px solid var(--line);
  overflow:hidden;
}
.gal__slide{
  position:absolute;inset:0;
  opacity:0;visibility:hidden;
  transition:opacity .55s var(--ease),visibility 0s linear .55s;
  border:0;padding:0;margin:0;background:none;width:100%;
  cursor:zoom-in;display:block;
}
.gal__slide.on{opacity:1;visibility:visible;transition-delay:0s,0s}
@media (prefers-reduced-motion:reduce){.gal__bg{filter:blur(34px) brightness(.42)}}
/* A blurred, darkened copy of the same file fills the frame behind a portrait
   image, so a tall photo in a wide frame does not sit in two dead black bars.
   Same src as the slide, so it costs no extra request. */
.gal__bg{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:blur(34px) saturate(1.15) brightness(.42);
  transform:scale(1.18);
}
.gal__img{position:relative;width:100%;height:100%;object-fit:contain;z-index:1}

/* controls */
.gal__bar{
  display:flex;align-items:center;gap:14px;
  margin-top:14px;
}
.gal__btn{
  width:38px;height:38px;flex:none;
  border:1px solid var(--line-2);background:transparent;color:var(--fg-2);
  display:grid;place-items:center;cursor:pointer;
  transition:border-color .3s var(--ease),color .3s var(--ease),background .3s var(--ease);
}
.gal__btn:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-wash)}
.gal__btn:disabled{opacity:.3;cursor:default}
.gal__btn:disabled:hover{border-color:var(--line-2);color:var(--fg-2);background:transparent}
.gal__count{
  font-family:var(--mono);font-size:.66rem;letter-spacing:.16em;
  color:var(--fg-3);flex:none;font-variant-numeric:tabular-nums;
}
.gal__dots{display:flex;gap:7px;margin-left:auto;flex-wrap:wrap}
.gal__dot{
  width:7px;height:7px;border-radius:50%;padding:0;cursor:pointer;
  border:1px solid var(--fg-3);background:transparent;
  transition:background .3s var(--ease),border-color .3s var(--ease),transform .3s var(--ease);
}
.gal__dot:hover{border-color:var(--accent)}
.gal__dot[aria-current="true"]{background:var(--accent);border-color:var(--accent);transform:scale(1.25)}

/* captions share one grid cell so the tallest sets the height and nothing
   jumps as the slides change */
.gal__caps{display:grid;margin-top:.9rem}
.gal__caps figcaption{
  grid-area:1/1;margin:0;
  opacity:0;transition:opacity .45s var(--ease);
  pointer-events:none;
}
.gal__caps figcaption.on{opacity:1;pointer-events:auto}

@media (max-width:620px){
  .gal__frame{height:clamp(260px,44vh,380px)}
  .gal__dots{display:none}
}
@media (prefers-reduced-motion:reduce){
  .gal__slide,.gal__caps figcaption{transition:none}
}

.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;
}

/* ---------- interactive model (syringe plunger lock) ---------- */
.lk{margin:clamp(30px,5vw,54px) 0 0;max-width:1000px}
.lk__stage{
  position:relative;background:var(--bg-1);border:1px solid var(--line-2);
  height:min(62vh,540px);overflow:hidden;
}
.lk__stage canvas{display:block;width:100%;height:100%;touch-action:none}
/* The placeholder note sits under the canvas and is covered once the model
   draws, so a blocked CDN or a dead GPU leaves words rather than a void. */
.lk__ph{
  position:absolute;inset:0;display:grid;place-items:center;padding:0 24px;
  text-align:center;color:var(--fg-3);font-family:var(--mono);
  font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;
}
.lk__stage[data-live] .lk__ph{display:none}
.lk__hint,.lk__legend{
  position:absolute;font-family:var(--mono);font-size:.62rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--fg-3);pointer-events:none;
}
.lk__hint{left:14px;top:12px}
.lk__legend{left:14px;bottom:12px;display:flex;flex-wrap:wrap;gap:14px}
.lk__legend i{
  width:9px;height:9px;display:inline-block;margin-right:7px;
  vertical-align:0;border:1px solid var(--line-2);
}
.lk__ctl{display:grid;grid-template-columns:1.25fr 1fr;gap:14px;margin-top:14px}
.lk__panel{border:1px solid var(--line-2);background:var(--bg-1);padding:clamp(16px,2.4vw,22px)}
.lk__fill{display:block;margin-bottom:10px;color:var(--fg);font-size:.95rem;font-weight:500}
.lk__panel input[type=range]{width:100%;accent-color:var(--accent-3)}
.lk__read{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:16px}
.lk__read b{display:block;font-family:var(--disp);font-size:1.45rem;font-weight:400;color:var(--fg);line-height:1.1}
.lk__read span{display:block;font-family:var(--mono);font-size:.58rem;letter-spacing:.12em;text-transform:uppercase;color:var(--fg-3);margin-top:5px}
.lk__btns{display:flex;flex-wrap:wrap;gap:9px}
.lk__btns button{
  font:inherit;font-size:.8rem;font-weight:500;padding:9px 14px;cursor:pointer;
  background:transparent;color:var(--fg);border:1px solid var(--line-2);
  transition:background .3s var(--ease),border-color .3s var(--ease);
}
.lk__btns button:hover{background:var(--bg-2);border-color:var(--accent-3)}
.lk__btns button.is-primary{border-color:var(--accent-3);color:var(--accent)}
.lk__btns button[aria-pressed="true"]{background:var(--accent-wash);border-color:var(--accent-3);color:var(--accent)}
.lk__btns button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.lk__status{margin:14px 0 0;min-height:4.5em;font-size:.92rem;color:var(--fg-2)}
.lk__toggle{display:block;margin-top:12px;font-size:.85rem;color:var(--fg-3)}
.lk__cap{
  margin:12px 0 0;font-family:var(--mono);font-size:.62rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--fg-3);
}
@media (max-width:760px){
  .lk__ctl{grid-template-columns:1fr}
  .lk__stage{height:min(54vh,420px)}
  .lk__legend{display:none}
}
