/* White Dream by Måns Grebäck — personal-use license, see assets/fonts/WhiteDream-LICENSE.txt */
@font-face{
  font-family:'White Dream';
  src: url('assets/fonts/WhiteDream-Regular.otf') format('opentype');
  font-weight:400; font-style:normal;
  font-display: swap;
}

:root{
  --bg: 5,5,5;
  --fg: 232,228,216;
  --accent: 138,133,120;
  --accent2: 90,84,74;
  --grain: 0.55;
  --scan: 0;
  --beam: 1;
  --strip: 0.5;
  --grid: 0;
  --flick: 1;
  --e1: 1; --e2: 0; --e3: 0; --e4: 0;
  /* overall strength of the drifting poster rails — raise toward .30 if you
     switch to real poster photographs, which read fainter than line art */
  --poster-op: 0.26;
  --rail-w: 58px;
  --section-w: 1320px;
}
*{ box-sizing:border-box; margin:0; padding:0; }
html{ scroll-behavior:smooth; }
body{
  background: rgb(var(--bg));
  color: rgb(var(--fg));
  font-family:'EB Garamond', serif;
  overflow-x:hidden;
  transition: background .15s linear, color .15s linear;
}
::selection{ background: rgba(var(--accent),.4); }

a{ color:inherit; text-decoration:none; }

/* ---------- animated background layers ---------- */
.bg-layers{ position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden; }

/* projector beam sweeping from top-left */
.beam{
  position:absolute; top:-30vh; left:50%;
  width:120vw; height:170vh;
  transform-origin:50% 0%;
  opacity: calc(var(--beam) * .32);
  background: conic-gradient(from 172deg at 50% 0%,
    transparent 0deg,
    rgba(var(--accent),.14) 5deg,
    rgba(var(--accent),.30) 8deg,
    rgba(var(--accent),.10) 12deg,
    transparent 17deg);
  filter: blur(14px);
  animation: beam-sway 19s ease-in-out infinite alternate;
  transition: opacity .2s linear;
}
.beam.b2{
  animation-duration: 27s; animation-direction: alternate-reverse;
  opacity: calc(var(--beam) * .18); filter: blur(28px);
}
@keyframes beam-sway{
  from{ transform: translateX(-50%) rotate(-11deg); }
  to  { transform: translateX(-50%) rotate(10deg); }
}

/* projector flicker — subtle brightness pulse */
.flicker-layer{
  position:absolute; inset:0;
  background: rgba(255,255,255,.05);
  opacity: 0;
  animation: proj-flicker 3.1s steps(1) infinite;
}
@keyframes proj-flicker{
  0%,100%{ opacity:0; }
  3%{ opacity: calc(var(--flick) * .55); }
  5%{ opacity:0; }
  41%{ opacity: calc(var(--flick) * .30); }
  43%{ opacity:0; }
  47%{ opacity: calc(var(--flick) * .70); }
  49%{ opacity:0; }
  76%{ opacity: calc(var(--flick) * .25); }
  78%{ opacity:0; }
}

/* ghosted filmstrips rolling through the background */
.strip{
  position:absolute; top:-60%; height:220%; width:190px;
  opacity: calc(var(--strip) * .5);
  border-left:1px solid rgba(var(--accent),.35);
  border-right:1px solid rgba(var(--accent),.35);
  background:
    repeating-linear-gradient(to bottom,
      rgba(var(--accent),.13) 0 2px, transparent 2px 128px),
    linear-gradient(to right,
      rgba(var(--accent),.10) 0 16px, transparent 16px calc(100% - 16px), rgba(var(--accent),.10) calc(100% - 16px) 100%);
  transform: rotate(9deg);
  animation: strip-roll 26s linear infinite;
  transition: opacity .2s linear;
}
.strip::before, .strip::after{
  content:''; position:absolute; top:0; bottom:0; width:8px;
  background-image: radial-gradient(circle 3.5px at 50% 12px, rgba(var(--accent),.5) 98%, transparent 100%);
  background-size: 100% 32px; background-repeat: repeat-y;
}
.strip::before{ left:4px; }
.strip::after{ right:4px; }
.strip.s1{ left:12%; }
.strip.s2{ left:64%; width:150px; transform: rotate(-7deg); animation-duration: 38s; opacity: calc(var(--strip) * .32); }
@keyframes strip-roll{
  from{ background-position: 0 0, 0 0; }
  to  { background-position: 0 -1280px, 0 0; }
}

/* digital-era grid drifting upward */
.grid-bg{
  position:absolute; inset:-10%;
  opacity: calc(var(--grid) * .5);
  background-image:
    linear-gradient(to right, rgba(var(--accent),.16) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--accent),.16) 1px, transparent 1px);
  background-size: 74px 74px;
  animation: grid-drift 14s linear infinite;
  transition: opacity .2s linear;
}
@keyframes grid-drift{
  from{ background-position: 0 0, 0 0; }
  to  { background-position: 0 -74px, 0 -74px; }
}

/* drifting poster rails — original compositions in each era's design language */
.poster-rail{
  position:fixed; top:0; bottom:0; width:158px; z-index:0;
  pointer-events:none; overflow:hidden; filter: blur(.4px);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
}
.poster-rail.left{ left: calc(var(--rail-w) + 14px); }
.poster-rail.right{ right: 14px; }
@media (max-width: 900px){ .poster-rail{ display:none; } }

.poster-layer{ position:absolute; inset:0; transition: opacity .25s linear; }
.poster-layer.e1{ opacity: calc(var(--e1) * var(--poster-op)); }
.poster-layer.e2{ opacity: calc(var(--e2) * var(--poster-op)); }
.poster-layer.e3{ opacity: calc(var(--e3) * var(--poster-op)); }
.poster-layer.e4{ opacity: calc(var(--e4) * var(--poster-op)); }

.pcol{
  position:absolute; top:0; left:0; width:100%;
  animation: poster-slide 95s linear infinite;
}
.poster-rail.right .pcol{ animation-duration: 128s; animation-direction: reverse; }
@keyframes poster-slide{
  from{ transform: translateY(0); }
  to  { transform: translateY(-50%); }
}
.pster{
  width:126px; height:189px; margin:0 auto 52px;
  border:1px solid currentColor; color: rgb(var(--accent));
  padding:7px; transition: color .15s linear;
}
.pster svg{ width:100%; height:100%; display:block; }
/* real poster photographs */
.pster.img{ padding:0; border-color: rgba(0,0,0,.4); }
.pster.img img{ width:100%; height:100%; object-fit:cover; display:block; }
.poster-layer.e1 .pster.img img{ filter: grayscale(1) contrast(1.15); }
.poster-layer.e2 .pster.img img{ filter: sepia(.45) saturate(.85); }
.poster-layer.e3 .pster.img img{ filter: saturate(.75) contrast(1.05); }
.poster-layer.e4 .pster.img img{ filter: none; }

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

#dust-canvas{
  position:fixed; inset:0; z-index:1; pointer-events:none;
}
/* silent-era print damage: scratches, dust, hairs, cue marks */
#damage-canvas{
  position:fixed; inset:0; z-index:42; pointer-events:none;
}
/* gate weave — the unsteady frame of a hand-cranked projector */
@keyframes gate-weave{
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(0.5px, -1.1px); }
  40%  { transform: translate(-0.6px, 0.7px); }
  60%  { transform: translate(0.3px, 1.2px); }
  80%  { transform: translate(-0.4px, -0.5px); }
  100% { transform: translate(0, 0); }
}

@media (prefers-reduced-motion: reduce){
  .beam, .flicker-layer, .strip, .grid-bg{ animation:none !important; }
  .flicker-layer{ opacity:0 !important; }
  #damage-canvas{ display:none !important; }
}

/* ---------- ambient overlays ---------- */
.grain-overlay{
  position:fixed; inset:0; z-index:40; pointer-events:none;
  opacity: var(--grain);
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  transition: opacity .2s linear;
}
.vignette{
  position:fixed; inset:0; z-index:39; pointer-events:none;
  background: radial-gradient(ellipse at center, transparent 45%, rgba(0,0,0,.55) 100%);
  opacity:.8;
}
.scanline-overlay{
  position:fixed; inset:0; z-index:41; pointer-events:none;
  opacity: var(--scan);
  background: repeating-linear-gradient(to bottom, rgba(255,255,255,.06) 0 1px, transparent 1px 3px);
  mix-blend-mode:overlay;
  transition: opacity .2s linear;
}

/* ---------- sprocket rail ---------- */
.sprocket-rail{
  --sprocket-step: 62px;
  --sprocket-dot: 10px;
  position:fixed; left:0; top:0; bottom:0; width:var(--rail-w);
  z-index:50; border-right:1px solid rgba(var(--accent),.6);
  background: rgba(var(--bg),.9);
  display:flex; flex-direction:column; align-items:center;
  transition: background .15s linear, border-color .15s linear;
}
.sprocket-track{
  flex:1; width:100%;
  /* hole centers land on 50% ± n·step so nav can sit on them */
  background-image: radial-gradient(
    circle calc(var(--sprocket-dot) / 2) at 50% 50%,
    rgb(var(--accent)) 98%, transparent 100%
  );
  background-size: 100% var(--sprocket-step);
  background-position: 0 calc(50% - var(--sprocket-step) / 2);
  background-repeat: repeat-y;
  opacity:.75;
  transition: background-image .15s linear;
}
.frame-info{
  position:absolute; bottom:18px; left:50%; transform:translateX(-50%) rotate(-90deg);
  transform-origin:left bottom;
  white-space:nowrap;
  font-family:'JetBrains Mono', monospace;
  font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color: rgb(var(--accent));
  display:flex; gap:14px; align-items:center;
  pointer-events:none;
}

/* ---------- section nav — 5 sprocket holes on the strip ---------- */
.dot-nav{
  position:absolute; inset:0;
  z-index:2;
  pointer-events:none;
}
.dot-nav a{
  pointer-events:auto;
  position:absolute; left:50%;
  width:28px; height:28px;
  margin-left:-14px;
  border:none; background:transparent; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  transition: transform .2s ease;
}
/* sit exactly on track holes at 50% ± 2 steps */
.dot-nav a:nth-child(1){ top:calc(50% - 2 * var(--sprocket-step)); transform:translateY(-50%); }
.dot-nav a:nth-child(2){ top:calc(50% - 1 * var(--sprocket-step)); transform:translateY(-50%); }
.dot-nav a:nth-child(3){ top:50%; transform:translateY(-50%); }
.dot-nav a:nth-child(4){ top:calc(50% + 1 * var(--sprocket-step)); transform:translateY(-50%); }
.dot-nav a:nth-child(5){ top:calc(50% + 2 * var(--sprocket-step)); transform:translateY(-50%); }

/* Every section is marked, always: an open circle for the ones you aren't on
   and a filled one for the one you are. The solid background is doing real
   work — the reel paints a filled sprocket dot at each of these positions, so
   without it that dot shows straight through the middle of the ring. Slightly
   wider than the reel's own hole so the ring reads as deliberate. */
.dot-nav{ --nav-dot: 13px; }
.dot-nav a::before{
  content:'';
  width:var(--nav-dot); height:var(--nav-dot);
  border-radius:50%;
  background:rgb(var(--bg));
  border:1.5px solid rgba(var(--accent),.7);
  box-shadow: 0 0 0 3px rgb(var(--bg));
  transition: background .2s ease, border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.dot-nav a:hover::before{ border-color:rgb(var(--accent)); transform:scale(1.15); }
.dot-nav a.active::before{
  background:rgb(var(--accent));
  border-color:rgb(var(--accent));
  box-shadow: 0 0 0 3px rgb(var(--bg)), 0 0 0 5px rgb(var(--accent));
}

.dot-nav a span{
  position:absolute; left:calc(var(--rail-w) / 2 + 26px); top:50%;
  transform:translateY(-50%);
  font-family:'JetBrains Mono', monospace; font-size:11px; letter-spacing:.08em;
  white-space:nowrap; text-transform:uppercase;
  color:rgb(var(--fg)); opacity:.45;
  /* the drifting poster rail starts 14px past the sprocket rail, right where
     these sit — a halo in the page colour keeps them readable over artwork */
  text-shadow: 0 0 4px rgb(var(--bg)), 0 0 9px rgb(var(--bg));
  transition:opacity .2s ease, color .2s ease;
  /* the label is part of the target: it sits outside the 28px anchor box, but
     it is still a child of the <a>, so clicks on it navigate */
  pointer-events:auto; cursor:pointer;
}
.dot-nav a:hover span{ opacity:.8; }
.dot-nav a.active span{ opacity:1; color:rgb(var(--accent)); }

@media (max-width: 860px){
  .sprocket-rail{ width:28px; }
  .sprocket-track{ opacity:.45; }
  .frame-info{ display:none; }
  .dot-nav a{ width:22px; height:22px; margin-left:-11px; }
  .dot-nav a span{ display:none; }
}

section{
  min-height:100vh; width:100%;
  /* the left gutter has a floor now that the rail's section labels are always
     on screen — at 6vw alone "Experience" runs under the body copy below
     ~1600px wide. 96px clears the longest label plus a little air. */
  padding: 8vh 6vw 8vh calc(var(--rail-w) + max(6vw, 96px));
  display:flex; flex-direction:column; justify-content:center;
  position:relative; z-index:2;
}
@media (max-width:860px){ section{ padding:12vh 6vw 8vh calc(28px + 6vw); } }

.eyebrow{
  font-family:'JetBrains Mono', monospace; font-size:12px;
  letter-spacing:.25em; text-transform:uppercase;
  color:rgb(var(--accent)); margin-bottom:18px;
}

/* ================= HERO — SILENT ERA ================= */
#hero{ align-items:center; text-align:center; }
.card-frame{
  border:2px solid rgb(var(--accent));
  /* wide enough for the name to sit on one line at full size */
  padding:6vh 4vw; max-width:min(1180px, 100%);
  position:relative;
  animation: iris-in 1.6s ease-out both, gate-weave .55s steps(5) infinite;
}
.card-frame::before, .card-frame::after{
  content:''; position:absolute; width:22px; height:22px;
  border:2px solid rgb(var(--accent));
}
.card-frame::before{ top:-2px; left:-2px; border-right:none; border-bottom:none; }
.card-frame::after{ bottom:-2px; right:-2px; border-left:none; border-top:none; }
@keyframes iris-in{
  from{ clip-path: circle(0% at 50% 50%); opacity:0; }
  /* ends wide open — at 75% the circle permanently clipped the ends off a
     single-line title, since fill-mode:both keeps the final frame applied */
  to{ clip-path: circle(150% at 50% 50%); opacity:1; }
}
.hero-title{
  font-family:'White Dream', 'Cinzel', serif; font-weight:400;
  /* script face: small x-height for its em size, so it runs larger than the
     Cinzel it replaced, with no tracking (letter-spacing breaks the joins)
     and headroom for the ascender swashes */
  /* one line, title-card style: the name is sized off viewport width so it
     never wraps — nowrap alone would just overflow on narrow screens */
  white-space:nowrap;
  font-size:min(6.4rem, 8vw); line-height:1.25; letter-spacing:0;
  padding:.08em .12em;
  /* the hand-set tilt of a real title card — remove this line for dead level */
  transform: rotate(-1.5deg);
}
.hero-tagline{
  margin-top:22px; font-style:italic; font-size:1.05rem; opacity:.85; max-width:520px;
  margin-left:auto; margin-right:auto;
}
.scroll-cue{
  margin-top:52px; font-family:'JetBrains Mono',monospace; font-size:11px;
  letter-spacing:.2em; text-transform:uppercase; opacity:.7;
  animation: flicker 3.4s infinite;
}
@keyframes flicker{
  0%,100%{ opacity:.7; } 42%{ opacity:.3; } 44%{ opacity:.75; } 88%{ opacity:.45; }
}
@media (prefers-reduced-motion: reduce){
  .card-frame{ animation:none; clip-path:none; opacity:1; }
  .scroll-cue{ animation:none; }
}

#about,
#projects,
#experience,
#contact{
  max-width: var(--section-w);
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

/* ================= ABOUT — GOLDEN AGE ================= */
/* top-aligned, not centred: the left column runs taller than the prose now that
   it carries the portrait as well as the star, and centring floated the heading
   down the page away from the top of the photo */
.about-grid{
  display:grid; grid-template-columns: 260px 1fr; gap:48px; align-items:start;
}
@media (max-width:760px){ .about-grid{ grid-template-columns:1fr; } }
.about-left{ display:flex; flex-direction:column; align-items:center; }
/* publicity still — framed like the star below it so the two read as a pair,
   and given the same settle-in animation on a short delay */
.portrait{
  width:240px; margin:0 auto 22px; position:relative;
  border:1px solid rgba(var(--accent),.45);
  box-shadow: 0 8px 22px rgba(0,0,0,.55);
  animation: star-settle 1s ease-out both;
}
.portrait img{
  display:block; width:100%; height:auto; aspect-ratio:4/5; object-fit:cover;
  filter: saturate(.88) contrast(1.03);
}
.portrait figcaption{
  font-family:'JetBrains Mono',monospace; font-size:9.5px; letter-spacing:.14em;
  text-transform:uppercase; color:rgb(var(--accent)); opacity:.75;
  text-align:center; padding:8px 6px 9px;
  border-top:1px solid rgba(var(--accent),.25);
}
@media (max-width:760px){ .portrait{ width:220px; } }

/* sits at the end of the credits roll, just above the fin card */
.walk-star{
  width:240px; height:240px; margin:64px auto 0;
  overflow:hidden; position:relative;
  border-radius:12px;
  box-shadow: 0 8px 22px rgba(0,0,0,.55);
  animation: star-settle 1s ease-out both;
}
.walk-star-scene{
  width:1000px; height:1000px;
  transform:scale(0.24); transform-origin:top left;
  position:relative; overflow:hidden;
  background:
    radial-gradient(circle at 20% 30%, #2a2f3a 0%, #14171d 40%),
    radial-gradient(circle at 80% 80%, #232833 0%, #0d0f14 60%),
    #0f1116;
  font-family:'Cinzel', serif;
}
.walk-star-speckle{ position:absolute; inset:0; pointer-events:none; }
.walk-star-speckle--sidewalk{
  background-image:
    radial-gradient(circle at 12% 22%, rgba(230,232,240,0.55) 0 1.4px, transparent 2px),
    radial-gradient(circle at 34% 8%, rgba(200,205,220,0.4) 0 1.1px, transparent 1.8px),
    radial-gradient(circle at 63% 18%, rgba(240,242,250,0.5) 0 1.6px, transparent 2.2px),
    radial-gradient(circle at 84% 12%, rgba(190,196,210,0.45) 0 1.2px, transparent 1.9px),
    radial-gradient(circle at 8% 55%, rgba(235,238,246,0.5) 0 1.5px, transparent 2px),
    radial-gradient(circle at 27% 72%, rgba(205,210,224,0.4) 0 1.1px, transparent 1.7px),
    radial-gradient(circle at 48% 88%, rgba(240,244,252,0.5) 0 1.7px, transparent 2.3px),
    radial-gradient(circle at 72% 66%, rgba(200,206,220,0.45) 0 1.3px, transparent 2px),
    radial-gradient(circle at 91% 78%, rgba(232,236,244,0.5) 0 1.4px, transparent 2px),
    radial-gradient(circle at 58% 42%, rgba(210,214,228,0.35) 0 1px, transparent 1.6px),
    radial-gradient(circle at 18% 90%, rgba(238,240,248,0.45) 0 1.5px, transparent 2px),
    radial-gradient(circle at 78% 34%, rgba(198,204,218,0.4) 0 1.2px, transparent 1.8px);
  background-size: 140px 140px, 170px 170px, 120px 120px, 190px 190px, 150px 150px, 130px 130px, 160px 160px, 180px 180px, 145px 145px, 200px 200px, 125px 125px, 175px 175px;
  opacity:.9;
}
.walk-star-shape{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:880px; height:880px;
}
.walk-star-brass{
  position:absolute; inset:0;
  clip-path: polygon(50% 0%, 61.8% 35.5%, 98% 35.5%, 68.5% 57.5%, 79.6% 100%, 50% 72.5%, 20.4% 100%, 31.5% 57.5%, 2% 35.5%, 38.2% 35.5%);
  background: linear-gradient(135deg, #f4d98a 0%, #c9a44e 30%, #e8c976 55%, #b78d3d 80%, #f0d488 100%);
}
.walk-star-pink{
  position:absolute; inset:9px;
  clip-path: polygon(50% 0%, 61.8% 35.5%, 98% 35.5%, 68.5% 57.5%, 79.6% 100%, 50% 72.5%, 20.4% 100%, 31.5% 57.5%, 2% 35.5%, 38.2% 35.5%);
  background: radial-gradient(circle at 40% 30%, #b3707a 0%, #9c5b66 55%, #8a4c57 100%);
}
.walk-star-speckle--pink{
  background-image:
    radial-gradient(circle at 20% 30%, rgba(245,235,238,0.7) 0 1.6px, transparent 2.2px),
    radial-gradient(circle at 55% 18%, rgba(120,60,70,0.6) 0 1.8px, transparent 2.4px),
    radial-gradient(circle at 78% 40%, rgba(250,240,242,0.6) 0 1.4px, transparent 2px),
    radial-gradient(circle at 33% 62%, rgba(130,70,80,0.5) 0 1.6px, transparent 2.2px),
    radial-gradient(circle at 68% 72%, rgba(248,238,240,0.65) 0 1.7px, transparent 2.3px),
    radial-gradient(circle at 15% 82%, rgba(140,80,90,0.5) 0 1.3px, transparent 1.9px),
    radial-gradient(circle at 88% 82%, rgba(246,236,238,0.6) 0 1.5px, transparent 2.1px),
    radial-gradient(circle at 45% 45%, rgba(235,220,224,0.4) 0 1.1px, transparent 1.7px),
    radial-gradient(circle at 60% 90%, rgba(150,90,100,0.45) 0 1.4px, transparent 2px);
  background-size: 90px 90px, 110px 110px, 80px 80px, 120px 120px, 95px 95px, 105px 105px, 85px 85px, 130px 130px, 100px 100px;
}
.walk-star-name{
  position:absolute; top:383px; left:50%; transform:translate(-50%,-50%);
  width:60%; text-align:center; white-space:nowrap;
  color:#f2dfae; font-size:55px; font-weight:600; letter-spacing:.5px; line-height:1.15;
  text-shadow: 0 1px 1px rgba(80,40,50,0.55), 0 -1px 0 rgba(255,245,220,0.3);
}
.walk-star-emblem{
  position:absolute; top:60%; left:50%; transform:translate(-50%,-50%);
  width:120px; height:120px; border-radius:50%;
  background: radial-gradient(circle at 40% 35%, #f0dfa0 0%, #d8bd6a 55%, #b8993f 100%);
  border:4px solid #a5842f;
  box-shadow: inset 0 2px 6px rgba(255,250,220,0.5), inset 0 -3px 8px rgba(90,60,20,0.5), 0 2px 4px rgba(0,0,0,0.3);
  display:flex; align-items:center; justify-content:center;
}
.walk-star-emblem svg{
  width:82px; height:82px;
  filter: drop-shadow(0 1px 1px rgba(90,60,20,0.4));
}
@keyframes star-settle{
  from{ opacity:0; transform:translateY(10px); }
  to{ opacity:1; transform:translateY(0); }
}
@media (max-width:760px){
  .walk-star{ width:220px; height:220px; margin-top:48px; }
  .walk-star-scene{ transform:scale(0.22); }
}
.about h2{
  font-family:'Playfair Display', serif; font-weight:700; font-style:italic;
  font-size:clamp(2rem,4.4vw,3.2rem); color:rgb(var(--accent)); margin-bottom:20px;
}
.about p{ font-size:1.08rem; line-height:1.75; margin-bottom:14px; }
.about p a{
  color:rgb(var(--accent)); text-decoration:underline; text-underline-offset:3px;
}
.about p a:hover{ opacity:.85; }
.vitals{
  margin-top:28px; display:grid; grid-template-columns:1fr 1fr; gap:14px 30px;
  font-family:'JetBrains Mono', monospace; font-size:12.5px;
}
.vitals dt{ text-transform:uppercase; letter-spacing:.1em; color:rgb(var(--accent)); }
.vitals dd{ opacity:.9; margin-top:2px; line-height:1.6; }
.vitals .wide{ grid-column: 1 / -1; }

/* coursework list — a full-width panel below .about-grid rather than a child of
   its right-hand column, so opening it cannot re-centre the grid and shove the
   star down; it also gives the class list the whole section width to run across */
.courses{ --disc-pad-x:20px; --disc-pad-y:15px; margin-top:26px; }
.courses-body{ padding:20px 20px 22px; display:grid; gap:22px; }
.school-head{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 12px;
  font-family:'JetBrains Mono', monospace;
  font-size:11px; font-weight:500; letter-spacing:.16em; text-transform:uppercase;
  color:rgb(var(--accent));
  padding-bottom:10px; margin-bottom:14px;
  border-bottom:1px solid rgba(var(--accent),.2);
}
.school-head em{ font-style:normal; opacity:.5; letter-spacing:.1em; font-size:10px; }
/* multi-column: the undated schools are one long alphabetical list, and letting
   it flow down columns beats a grid that would leave a tall gap under every
   short entry. Steps down on its own as space runs out. */
.terms{ columns:5 215px; column-gap:28px; }
.term{ break-inside:avoid; margin-bottom:18px; }
.term:last-child{ margin-bottom:0; }
/* the dated terms read instead as a calendar: four per row, oldest top-left,
   newest bottom-right, so a full four-year degree lands as two tidy rows.
   Grid (not columns) because grid fills row by row — columns would run the
   terms down the first column before starting the second. */
.terms-cal{
  columns:auto; display:grid; gap:26px 28px;
  grid-template-columns:repeat(4, minmax(0,1fr));
}
.terms-cal .term{ margin-bottom:0; }
@media (max-width:1100px){ .terms-cal{ grid-template-columns:repeat(2, minmax(0,1fr)); } }
@media (max-width:620px){ .terms-cal{ grid-template-columns:1fr; } }
.term.flow{ break-inside:auto; }   /* undated schools are one long list, let it flow */
.term li{ break-inside:avoid; }
.term h5{
  font-family:'JetBrains Mono', monospace;
  font-size:10px; font-weight:500; letter-spacing:.16em; text-transform:uppercase;
  color:rgb(var(--accent)); opacity:.65; margin-bottom:8px;
}
/* upcoming terms are marked, so a planned schedule never reads as a record of
   classes already taken; placeholder rows dim one step further */
.term h5 em{ font-style:normal; opacity:.55; letter-spacing:.1em; }
.term li.tbd{ opacity:.45; }
.term ul{ list-style:none; display:grid; gap:6px; }
.term li{
  font-family:'JetBrains Mono', monospace; font-size:11.5px; line-height:1.45;
  opacity:.9; display:grid; gap:1px;
}
.term li span{ color:rgb(var(--accent)); opacity:.85; letter-spacing:.04em; }
.school--berkeley .term li span[role="button"]{
  justify-self:start; cursor:pointer; text-decoration:underline; text-decoration-style:dotted;
  text-decoration-thickness:1px; text-underline-offset:3px;
  transition:color .18s ease, opacity .18s ease;
}
.school--berkeley .term li span[role="button"]:hover,
.school--berkeley .term li span[role="button"]:focus-visible{
  color:rgb(var(--fg)); opacity:1; outline:none;
}
.school--berkeley .term li span[role="button"]:focus-visible{
  outline:1px solid rgb(var(--accent)); outline-offset:3px;
}
.vitals-left{
  width:100%; max-width:240px;
  grid-template-columns:1fr; margin-top:22px;
}
@media (max-width:760px){ .vitals-left{ max-width:280px; } }

/* ================= PROJECTS — NEW HOLLYWOOD ================= */
.marquee{
  font-family:'Bebas Neue', sans-serif; font-size:clamp(2.4rem,7vw,4.6rem);
  letter-spacing:.03em; color:rgb(var(--accent)); line-height:.95; margin-bottom:8px;
}
.marquee-sub{ font-family:'JetBrains Mono',monospace; font-size:12px; letter-spacing:.18em; text-transform:uppercase; opacity:.75; margin-bottom:46px; }
.poster-grid{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(250px,1fr)); gap:28px;
  perspective: 900px;
}
.poster{
  border:1px solid rgba(var(--accent),.5); padding:26px 22px;
  background: linear-gradient(160deg, rgba(var(--accent),.08), transparent 60%);
  display:flex; flex-direction:column; min-height:260px;
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform .12s ease-out, border-color .25s ease, box-shadow .25s ease;
}
.poster:hover{
  border-color:rgb(var(--accent));
  box-shadow: 0 10px 22px rgba(0,0,0,.18);
}
.poster.is-settling{
  transition: transform .6s cubic-bezier(.22,1,.36,1), border-color .25s ease, box-shadow .25s ease;
}
@media (prefers-reduced-motion: reduce){
  .poster:hover{ transform: translateY(-4px); }
}
.poster .rating{
  align-self:flex-start; font-family:'JetBrains Mono',monospace; font-size:10px;
  letter-spacing:.1em; text-transform:uppercase; color:rgb(var(--bg));
  background:rgb(var(--accent)); padding:3px 8px; margin-bottom:16px;
}
.poster h3{
  font-family:'Bebas Neue', sans-serif; font-size:1.7rem; letter-spacing:.02em;
  margin-bottom:6px; color:rgb(var(--fg));
}
.poster .run-dates{
  font-family:'JetBrains Mono', monospace; font-size:11px;
  letter-spacing:.08em; text-transform:uppercase;
  color:rgb(var(--accent)); opacity:.85; margin-bottom:12px;
}
.poster .logline{ font-size:.96rem; line-height:1.55; opacity:.85; flex:1; margin-bottom:18px; }
.tags{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:18px; }
.tags span{
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.05em;
  border:1px solid rgba(var(--accent2),.7); padding:3px 8px; text-transform:uppercase;
  color:rgb(var(--accent2));
}
.poster .watch{
  font-family:'JetBrains Mono',monospace; font-size:11.5px; letter-spacing:.1em;
  text-transform:uppercase; color:rgb(var(--accent)); border-top:1px solid rgba(var(--accent),.4);
  padding-top:14px;
}
.poster .watch:hover{ text-decoration:underline; }

.poster.poster-masq{
  background: linear-gradient(160deg, rgba(var(--accent2),.22), rgba(var(--accent),.08) 55%, transparent 75%);
  border-color: rgba(var(--accent2),.65);
}

/* back catalogue */
.archive-wrap{ margin-top:58px; border-top:1px solid rgba(var(--accent),.35); padding-top:26px; }
.archive-wrap h3{
  font-family:'Bebas Neue', sans-serif; font-size:1.5rem; letter-spacing:.05em;
  color:rgb(var(--accent)); margin-bottom:6px;
}
.archive-wrap .note{
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; opacity:.6; margin-bottom:22px;
}
.archive-list{ display:flex; flex-wrap:wrap; gap:10px 12px; }
.archive-list a{
  font-family:'JetBrains Mono',monospace; font-size:12px;
  border:1px solid rgba(var(--accent2),.6); padding:7px 12px;
  transition:.2s; display:inline-flex; gap:9px; align-items:baseline;
}
.archive-list a em{ font-style:normal; opacity:.55; font-size:10px; text-transform:uppercase; letter-spacing:.06em; }
.archive-list a:hover{ border-color:rgb(var(--accent)); color:rgb(var(--accent)); }

/* ================= EXPERIENCE — DIGITAL AGE ================= */
#experience{ font-family:'JetBrains Mono', monospace; }
#experience h2, #contact h2{
  font-family:'JetBrains Mono', monospace; font-weight:700; font-size:clamp(1.6rem,4vw,2.4rem);
  color:rgb(var(--accent)); margin-bottom:6px;
}
.term-hint{ font-size:12px; opacity:.6; margin-bottom:36px; }
.log-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:22px;
  margin-bottom:22px; align-items:stretch;
}
.log-grid .log:last-child:nth-child(odd){ grid-column: 1 / -1; }
@media (max-width:760px){ .log-grid{ grid-template-columns:1fr; } .log-grid .log:last-child:nth-child(odd){ grid-column:auto; } }
.log{
  border:1px solid rgba(var(--accent),.35); background:rgba(255,255,255,.02);
  padding:26px 28px; position:relative;
  display:flex; flex-direction:column; height:100%;
  transition: transform .25s ease, border-color .25s ease, background .25s ease, box-shadow .25s ease;
}
.log:hover{
  transform: translateY(-3px);
  border-color: rgba(var(--accent),.75);
  background: rgba(var(--accent),.06);
  box-shadow: 0 10px 24px rgba(0,0,0,.2);
}
@media (prefers-reduced-motion: reduce){
  .log:hover{ transform: none; }
}

/* ---------- experience categories ----------
   Every .log carries one cat-* modifier, and everything below reads the single
   --cat it sets: tint, chip and hover all follow from that one
   colour. The chip spells the category out, so colour is never the only cue
   (amber and terracotta are close for red-green colour blindness). */
.log{ --cat: var(--accent); }
.cat-technical{ --cat: 201,154,74; }   /* brass  */
.cat-research { --cat: 96,151,148; }   /* patina */
.cat-service  { --cat: 196,110,96; }   /* rust   */
.cat-work     { --cat: 133,137,190; }  /* slate  */

.log.cat{
  border-color: rgba(var(--cat),.32);
  background:
    linear-gradient(100deg, rgba(var(--cat),.09), rgba(var(--cat),.02) 42%, transparent 72%),
    rgba(255,255,255,.02);
}
.log.cat:hover{
  border-color: rgba(var(--cat),.7);
  background:
    linear-gradient(100deg, rgba(var(--cat),.17), rgba(var(--cat),.05) 45%, transparent 75%),
    rgba(255,255,255,.02);
  box-shadow: 0 10px 24px rgba(0,0,0,.28);
}

.log-cat{
  position:absolute; top:16px; right:18px; pointer-events:none;
  font-family:'JetBrains Mono',monospace; font-size:10px;
  letter-spacing:.14em; text-transform:uppercase;
  color: rgb(var(--cat));
  border:1px solid rgba(var(--cat),.45);
  background: rgba(var(--cat),.1);
  padding:4px 9px;
}
/* keep the title clear of the chip — the meta line already clears its bottom */
.log.cat h3{ padding-right:118px; }
/* one column: the chip is the card's first child, so dropping it out of
   absolute flow parks it above the title instead of beside it */
@media (max-width:760px){
  .log-cat{ position:static; align-self:flex-start; margin-bottom:12px; }
  .log.cat h3{ padding-right:0; }
}

/* legend — the bars match each card's left edge */
#experience .term-hint:has(+ .cat-legend){ margin-bottom:16px; }
.cat-legend{
  display:flex; flex-wrap:wrap; gap:10px 20px; margin-bottom:34px;
  font-size:11px; letter-spacing:.1em; text-transform:uppercase;
}
.cat-legend button{
  display:inline-flex; align-items:center; gap:9px; opacity:.72; padding:4px 0; cursor:pointer;
  background:none; border:none; border-bottom:1px solid transparent; color:inherit;
  font:inherit; letter-spacing:inherit; text-transform:inherit;
  transition:opacity .2s ease, color .2s ease, border-color .2s ease;
}
.cat-legend button:hover{ opacity:1; }
.cat-legend button:focus-visible{ outline:1px solid rgba(var(--cat),.8); outline-offset:4px; opacity:1; }
.cat-legend i{ width:20px; height:3px; background:rgb(var(--cat)); transition:width .2s ease; }
/* one picked: it lights up in its colour, the rest step back */
.cat-legend.is-filtering button{ opacity:.35; }
.cat-legend.is-filtering button:hover{ opacity:.7; }
.cat-legend button[aria-pressed="true"]{ opacity:1; color:rgb(var(--cat)); border-bottom-color:rgba(var(--cat),.6); }
.cat-legend button[aria-pressed="true"] i{ width:28px; }
.log-grid .log.is-hidden{ display:none; }
/* while filtering, the odd card out spans the row (the :last-child rule above can't see hidden cards) */
.log-grid.is-filtered .log:last-child:nth-child(odd){ grid-column:auto; }
.log-grid.is-filtered .log.is-wide{ grid-column:1 / -1; }
@media (max-width:760px){ .log-grid.is-filtered .log.is-wide{ grid-column:auto; } }
.log h3{ font-family:'Inter',sans-serif; font-weight:600; font-size:1.25rem; margin-bottom:4px; color:rgb(var(--fg)); }
/* the title links out to the org. It keeps the heading's look and only
   declares itself on hover, the same way .log-link and .poster .watch do */
.log h3 a{ color:inherit; }
.log h3 a:hover{ color:rgb(var(--accent)); text-decoration:underline; text-underline-offset:3px; }
.log .meta{ font-size:12px; opacity:.65; margin-bottom:14px; }
.log p{ font-family:'Inter',sans-serif; font-size:.94rem; line-height:1.65; opacity:.9; flex:1; }
/* opens the case-detail overlay; styled as a sibling of .log-link */
.log-more-btn{
  align-self:flex-start; margin-top:16px;
  background:transparent; border:1px solid rgba(var(--accent),.4); border-radius:0;
  padding:9px 14px; cursor:pointer;
  font-family:'JetBrains Mono',monospace; font-size:11.5px; letter-spacing:.1em;
  text-transform:uppercase; color:rgb(var(--accent));
  transition: border-color .2s ease, background .2s ease;
}
.log-more-btn:hover{ border-color:rgb(var(--accent)); background:rgba(var(--accent),.08); }

.log-link{
  display:inline-block; margin-top:14px; align-self:flex-start;
  font-family:'JetBrains Mono',monospace; font-size:11.5px; letter-spacing:.1em;
  text-transform:uppercase; color:rgb(var(--accent));
}
.log-link:hover{ text-decoration:underline; }
/* tech stack along the bottom of technical cards; <p> is flex:1, so these sit flush at the base */
.log-tags{ margin:18px 0 0; }
.log.cat .log-tags span{ border-color:rgba(var(--cat),.6); color:rgb(var(--cat)); }

/* ---------- shared collapsible panel ----------
   used by the high school archive (#experience) and the coursework list
   (#about); script.js animates the height of anything with .disclosure.
   --disc-pad sets the panel's inset — override it per panel, the summary
   padding and the divider inset both follow from it. */
.disclosure{
  --disc-pad-x:24px; --disc-pad-y:22px;
  border:1px solid rgba(var(--accent),.35);
  background:rgba(255,255,255,.02);
}
.disclosure > summary{
  list-style:none; cursor:pointer; user-select:none;
  display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 14px;
  padding:var(--disc-pad-y) var(--disc-pad-x); position:relative;
  font-family:'JetBrains Mono', monospace;
  font-size:11px; font-weight:500;
  letter-spacing:.18em; text-transform:uppercase;
  color:rgb(var(--accent));
  transition: color .2s ease;
}
.disclosure > summary::-webkit-details-marker{ display:none; }
.disclosure > summary:hover{ color:rgb(var(--fg)); }
.disclosure > summary::after{
  content:'[ + ]'; margin-left:auto; opacity:.7; letter-spacing:.08em;
}
/* the whitespace after a CSS hex escape is swallowed as the escape's
   terminator, so the closing space needs to be an explicit \20 — otherwise
   this renders '[ -]' and the marker looks off-centre next to '[ + ]' */
.disclosure[open] > summary::after{ content:'[ \2212\20]'; }
/* script.js holds the panel open for the whole collapse so it can animate the
   height down, so flip the marker up front rather than 260ms late */
.disclosure.is-closing > summary::after{ content:'[ + ]'; }
.disclosure.is-animating{ overflow:hidden; }
/* inset the divider to the panel's own padding, like .skills-wrap h3's —
   a border-bottom on the summary itself would run edge to edge */
.disclosure[open] > summary::before{
  content:''; position:absolute; bottom:0; height:1px;
  left:var(--disc-pad-x); right:var(--disc-pad-x);
  background:rgba(var(--accent),.25);
}
.disc-label::before{ content:'// '; opacity:.55; }
.disc-note{ opacity:.45; letter-spacing:.12em; }

/* high school archive — same panel language as .skills-wrap */
.hs-archive{
  /* .skills-panel adds its own 8px on top of .log-grid's 22px, so match that
     here too — otherwise this panel sits tighter to the logs than to the skills */
  margin-top:8px; margin-bottom:22px;
}
.hs-body{ padding:22px 24px 24px; display:grid; gap:24px; }
.hs-group h4{
  font-family:'JetBrains Mono', monospace;
  font-size:10.5px; font-weight:500;
  letter-spacing:.16em; text-transform:uppercase;
  color:rgb(var(--accent)); opacity:.7;
  margin-bottom:12px;
}
.hs-list{ display:flex; flex-wrap:wrap; gap:8px; }
.hs-item{
  font-family:'JetBrains Mono', monospace;
  font-size:12px; letter-spacing:.02em;
  border:1px solid rgba(var(--accent),.4);
  padding:7px 12px;
  color:rgb(var(--fg));
  display:inline-flex; flex-wrap:wrap; align-items:baseline; gap:9px;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.hs-item:hover{
  border-color:rgb(var(--accent));
  color:rgb(var(--accent));
  background:rgba(var(--accent),.08);
}
.hs-item em{
  font-style:normal; opacity:.55; font-size:10px;
  text-transform:uppercase; letter-spacing:.06em; white-space:nowrap;
}

/* ---------- case detail overlay ---------- */
/* The markup sits at the end of <body>, outside every section: .log takes a
   transform on hover, and a transformed ancestor becomes the containing block
   for position:fixed, which would pin this to the card instead of the screen.
   z-index clears the sprocket rail (50) and the grain/scanline layers (39-42). */
.case-modal{
  position:fixed; inset:0; z-index:200;
  display:flex; align-items:center; justify-content:center;
  padding:5vh 5vw;
}
.case-modal[hidden]{ display:none; }
.case-backdrop{
  position:absolute; inset:0;
  background:rgba(0,0,0,.74); backdrop-filter:blur(3px);
  animation:case-fade .2s ease both;
}
.case-panel{
  position:relative;
  width:min(780px, 100%); max-height:88vh; overflow-y:auto;
  background:rgb(var(--bg));
  border:1px solid rgba(var(--accent),.5);
  box-shadow:0 24px 70px rgba(0,0,0,.6);
  padding:26px 28px 30px;
  animation:case-rise .26s cubic-bezier(.4,0,.2,1) both;
}
@keyframes case-fade{ from{ opacity:0; } to{ opacity:1; } }
@keyframes case-rise{
  from{ opacity:0; transform:translateY(14px) scale(.985); }
  to{ opacity:1; transform:none; }
}
@media (prefers-reduced-motion: reduce){
  .case-backdrop, .case-panel{ animation:none; }
}
.case-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:20px;
  padding-bottom:16px; margin-bottom:22px;
  border-bottom:1px solid rgba(var(--accent),.25);
}
.case-kicker{
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.18em;
  text-transform:uppercase; color:rgb(var(--accent)); opacity:.75; margin-bottom:8px;
}
.case-panel h3{
  font-family:'Inter',sans-serif; font-weight:600; font-size:1.35rem; color:rgb(var(--fg));
}
.case-sub{
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; opacity:.45; margin-top:6px;
}
.case-close{
  flex:none; width:34px; height:34px; border-radius:50%;
  background:transparent; border:1px solid rgba(var(--accent),.4);
  color:rgb(var(--accent)); font-size:19px; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition: border-color .2s ease, background .2s ease;
}
.case-close:hover{ border-color:rgb(var(--accent)); background:rgba(var(--accent),.1); }
.case-body{ display:grid; gap:22px; }
.course-description{
  font-family:'Inter',sans-serif; font-size:.96rem; line-height:1.7; opacity:.9;
}
.course-links{ display:flex; flex-wrap:wrap; gap:10px; }
.course-links a{
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.1em;
  text-transform:uppercase; color:rgb(var(--accent)); text-decoration:none;
  border:1px solid rgba(var(--accent),.4); padding:9px 11px;
  transition:background .2s ease, border-color .2s ease;
}
.course-links a:hover{ background:rgba(var(--accent),.1); border-color:rgb(var(--accent)); }
.case-intro{
  font-family:'Inter',sans-serif; font-size:.95rem; line-height:1.65; opacity:.9;
}
.case-stats{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(96px,1fr)); gap:12px;
  padding:16px 0;
  border-top:1px solid rgba(var(--accent),.2);
  border-bottom:1px solid rgba(var(--accent),.2);
}
.case-stats div{ text-align:center; }
.case-stats b{
  display:block; font-family:'JetBrains Mono',monospace; font-weight:700;
  font-size:1.3rem; color:rgb(var(--accent)); line-height:1;
}
.case-stats span{
  display:block; margin-top:6px;
  font-family:'JetBrains Mono',monospace; font-size:9px; letter-spacing:.12em;
  text-transform:uppercase; opacity:.55; line-height:1.35;
}
/* The eight pipeline stages. Scoped under .lm-group so these beat the generic
   .lm-group li rules below on specificity — the stage number is the marker
   here, so the shared dot is suppressed and the indent is wider to clear it. */
.case-stages{ list-style:none; display:grid; gap:10px; }
.lm-group .case-stages li{
  font-family:'Inter',sans-serif; font-size:.9rem; line-height:1.6;
  opacity:.88; padding-left:36px; position:relative;
}
.lm-group .case-stages li::before{ content:none; }
.case-stages b{
  position:absolute; left:0; top:.1em;
  font-family:'JetBrains Mono',monospace; font-size:11.5px; font-weight:500;
  letter-spacing:.06em; color:rgb(var(--accent)); opacity:.85;
}
/* the weekly ramp — label runs inline, since "Wk 3-4" is too wide to hang in
   the fixed gutter the numbered pipeline stages use */
.case-note{
  font-family:'Inter',sans-serif; font-size:.86rem; line-height:1.6;
  opacity:.72; margin-bottom:11px;
}
.case-arc{ list-style:none; display:grid; gap:10px; }
.lm-group .case-arc li{
  font-family:'Inter',sans-serif; font-size:.9rem; line-height:1.6;
  opacity:.88; padding-left:0;
}
.lm-group .case-arc li::before{ content:none; }
.case-arc b{
  font-family:'JetBrains Mono',monospace; font-size:11px; font-weight:500;
  letter-spacing:.06em; color:rgb(var(--accent)); opacity:.85; margin-right:9px;
}
.case-tags{ display:flex; flex-wrap:wrap; gap:7px; }
.case-tags span{
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.02em;
  border:1px solid rgba(var(--accent),.35); padding:5px 10px; opacity:.85;
}
.lm-group h4{
  font-family:'JetBrains Mono', monospace;
  font-size:10px; font-weight:500; letter-spacing:.16em; text-transform:uppercase;
  color:rgb(var(--accent)); opacity:.7; margin-bottom:9px;
}
.lm-group ul{ list-style:none; display:grid; gap:7px; }
.lm-group li{
  font-family:'Inter', sans-serif; font-size:.9rem; line-height:1.6;
  opacity:.88; padding-left:15px; position:relative;
}
.lm-group li::before{
  content:''; position:absolute; left:0; top:.62em;
  width:4px; height:4px; border-radius:50%; background:rgba(var(--accent),.7);
}
/* ---------- favorite things window ---------- */
.fav-open{ margin:4px 0 22px; }
.fav-open-row{ display:flex; flex-wrap:wrap; gap:0 12px; }
.fav-tabbar{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:8px 16px; margin-bottom:22px;
  border-bottom:1px solid rgba(var(--accent),.2);
}
.fav-tabs{ display:flex; flex-wrap:wrap; gap:6px; }
.fav-tools{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; padding-bottom:6px; }
.fav-count{
  margin-right:4px; font-family:'JetBrains Mono',monospace; font-size:10px;
  letter-spacing:.14em; text-transform:uppercase; opacity:.55; white-space:nowrap;
}
#favorites:not([data-tab="movies"]) .fav-all,
#favorites[data-tab="travel"] .fav-only,
#favorites[data-tab="interests"] .fav-only,
#favorites[data-tab="stats"] .fav-only,
#favorites[data-tab="travel"] .fav-filters,
#favorites[data-tab="interests"] .fav-filters,
#favorites[data-tab="stats"] .fav-filters{ display:none; }
/* search, genre and sort, under the tabs */
.fav-filters{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:-8px 0 22px; }
.fav-search, .fav-genre, .fav-sort{
  height:32px; padding:0 11px; background:rgba(var(--fg),.03); color:rgb(var(--fg));
  border:1px solid rgba(var(--accent),.35); border-radius:0;
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.06em;
  transition:border-color .2s ease;
}
.fav-search{ flex:1 1 220px; min-width:0; max-width:380px; }
.fav-search::placeholder{ color:rgba(var(--fg),.4); }
.fav-genre, .fav-sort{ flex:0 1 auto; max-width:100%; cursor:pointer; }
.fav-genre option, .fav-sort option{ background:#111; color:#eee; }
.fav-search:hover, .fav-genre:hover, .fav-sort:hover{ border-color:rgba(var(--accent),.7); }
.fav-search:focus-visible, .fav-genre:focus-visible, .fav-sort:focus-visible{ outline:none; border-color:rgb(var(--accent)); }
.fav-genre[hidden]{ display:none; }
.fav-item.is-filtered{ display:none; }
.fav-nomatch[hidden]{ display:none; }
.fav-tab{
  background:transparent; border:none; border-bottom:2px solid transparent;
  margin-bottom:-1px; padding:8px 12px; cursor:pointer;
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:rgb(var(--fg)); opacity:.55;
  transition: opacity .2s ease, border-color .2s ease, color .2s ease;
}
.fav-tab:hover{ opacity:.85; }
.fav-tab[aria-selected="true"]{ opacity:1; color:rgb(var(--accent)); border-bottom-color:rgb(var(--accent)); }
.fav-grid{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(118px,1fr)); gap:18px 14px;
}
.fav-grid[hidden]{ display:none; }
.fav-item{ margin:0; }
.fav-art{
  position:relative; aspect-ratio:2/3; overflow:hidden;
  border:1px solid rgba(var(--accent),.3);
  background:linear-gradient(160deg, rgba(var(--accent),.14), rgba(var(--accent2),.08));
}
.fav-grid--square .fav-art{ aspect-ratio:1/1; }
.fav-grid--round .fav-art{ aspect-ratio:1/1; border-radius:50%; }
/* the All tab mixes shapes in one grid, so each tile carries its own */
.fav-item.is-square .fav-art{ aspect-ratio:1/1; }
.fav-item.is-round .fav-art{ aspect-ratio:1/1; border-radius:50%; }
.fav-item.is-round{ text-align:center; }
.fav-grid--round .fav-item{ text-align:center; }
.fav-heading{
  font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:500;
  letter-spacing:.16em; text-transform:uppercase;
  color:rgb(var(--accent)); opacity:.7; margin:0 0 12px;
}
.fav-grid + .fav-heading{ margin-top:30px; }
/* all-time favorites: gold ring, glow and a corner star. Gold is fixed rather
   than era-tinted so it reads as a distinction, not just the accent colour */
/* the border itself is a conic gradient: a bright glint of gold that travels
   round the frame. The gradient sits in the border box and the usual card
   background is repainted over the padding box, so only the 2px edge shows */
@property --fav-ang{ syntax:'<angle>'; inherits:false; initial-value:0deg; }
.fav-item.is-fav .fav-art{
  border:2px solid transparent;
  background:
    linear-gradient(160deg, rgba(var(--accent),.14), rgba(var(--accent2),.08)) padding-box,
    conic-gradient(from var(--fav-ang), #8a6420, #e2b84c 18%, #fff3c4 25%, #e2b84c 32%, #8a6420 50%, #e2b84c 68%, #fff3c4 75%, #e2b84c 82%, #8a6420) border-box;
  box-shadow:0 0 22px rgba(226,184,76,.38);
  animation:fav-glow 3.6s ease-in-out infinite, fav-spin 4.5s linear infinite;
}
/* a slow sheen crosses the cover every few seconds */
.fav-item.is-fav .fav-art::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(115deg, transparent 38%, rgba(255,236,180,.28) 50%, transparent 62%);
  background-size:260% 100%; background-position:130% 0;
  animation:fav-sheen 5.5s ease-in-out infinite;
}
/* stagger so the favorites don't all shimmer in unison */
.fav-item.is-fav:nth-child(3n+1) .fav-art, .fav-item.is-fav:nth-child(3n+1) .fav-art::after{ animation-delay:-1.8s; }
.fav-item.is-fav:nth-child(3n+2) .fav-art, .fav-item.is-fav:nth-child(3n+2) .fav-art::after{ animation-delay:-3.4s; }
@keyframes fav-glow{
  0%,100%{ box-shadow:0 0 16px rgba(226,184,76,.26); }
  50%    { box-shadow:0 0 30px rgba(226,184,76,.55); }
}
@keyframes fav-spin{ to{ --fav-ang:360deg; } }
@keyframes fav-sheen{
  0%,55%{ background-position:130% 0; }
  100%  { background-position:-30% 0; }
}
@media (prefers-reduced-motion: reduce){
  .fav-item.is-fav .fav-art, .fav-item.is-fav .fav-art::after{ animation:none; }
}
.fav-item.is-fav figcaption b{ color:rgb(236,200,104); }
.fav-key{
  margin-left:10px; letter-spacing:.1em; color:rgb(236,200,104); opacity:.9;
}
.fav-key:first-child{ margin-left:0; }
.fav-toggle{
  padding:6px 11px; cursor:pointer; background:transparent;
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:rgb(var(--fg)); border:1px solid rgba(var(--accent),.35);
  transition:background .2s ease, border-color .2s ease, color .2s ease;
}
.fav-toggle:hover{ border-color:rgb(var(--accent)); }
.fav-toggle[aria-pressed="true"]{ color:rgb(var(--accent)); border-color:rgb(var(--accent)); background:rgba(var(--accent),.12); }
.fav-only{ color:rgb(236,200,104); border-color:rgba(226,184,76,.45); }
.fav-only:hover, .fav-only[aria-pressed="true"]{ border-color:rgb(226,184,76); }
.fav-only[aria-pressed="true"]{ color:rgb(236,200,104); background:rgba(226,184,76,.16); }
/* the gold-only filter hides everything else in every section */
.case-modal.is-only-fav .fav-item:not(.is-fav){ display:none; }
/* ---------- travel map ---------- */
.travel-bar{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:10px; margin-bottom:12px;
}
.travel-regions{ display:flex; flex-wrap:wrap; gap:6px; }
.travel-region, .travel-place{
  background:transparent; color:rgb(var(--fg)); cursor:pointer;
  border:1px solid rgba(var(--accent),.28);
  transition:border-color .2s ease, background .2s ease, color .2s ease;
}
.travel-region{
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; padding:6px 10px;
}
.travel-region:hover, .travel-place:hover{ border-color:rgb(var(--accent)); }
.travel-region[aria-pressed="true"]{
  color:rgb(var(--accent)); border-color:rgb(var(--accent)); background:rgba(var(--accent),.1);
}
.travel-map{
  position:relative; aspect-ratio:2/1; overflow:hidden;
  border:1px solid rgba(var(--accent),.2);
  background:radial-gradient(ellipse at 50% 40%, rgba(var(--accent),.07), transparent 70%);
}
.travel-svg{ display:block; width:100%; height:100%; }
.travel-fx{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; }
.travel-status{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  padding:20px; text-align:center;
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; opacity:.55;
}
.travel-status[hidden]{ display:none; }
.travel-land path{
  fill:rgba(var(--fg),.07); stroke:rgba(var(--fg),.16); stroke-width:.6;
  vector-effect:non-scaling-stroke; stroke-linejoin:round;
}
.travel-land path.is-been{ fill:rgba(var(--accent),.3); stroke:rgba(var(--accent),.6); fill-rule:evenodd; }
.travel-land path.is-been{ cursor:pointer; transition:fill .3s ease; }
.travel-land path.is-been:hover{ fill:rgba(var(--accent),.4); }
.travel-land path.is-been.is-active{ fill:rgba(var(--accent),.42); stroke:rgb(var(--accent)); }
/* internal borders (US states, provinces, the UK's nations...) fade in
   when their country is clicked */
.travel-borders path, .travel-states path{
  fill:none; stroke:rgba(var(--accent),.75); stroke-width:.6;
  vector-effect:non-scaling-stroke; stroke-linejoin:round; stroke-linecap:round; pointer-events:none;
}
.travel-borders path{ opacity:0; transition:opacity .6s ease; }
.travel-borders path.is-on{ opacity:1; }
.travel-states path{ stroke-opacity:0; transition:stroke-opacity .6s ease; }
.travel-states.is-on path{ stroke-opacity:1; }
.travel-states path.is-been{ fill:rgba(var(--accent),.5); }
.travel-arc{
  fill:none; stroke-width:2; stroke-opacity:.85;
  stroke-linecap:round; vector-effect:non-scaling-stroke; pointer-events:none;
}
.travel-arc.is-fading{ opacity:0; transition:opacity 3.5s ease; }
.travel-pin{ cursor:pointer; }
.travel-hit{ fill:transparent; }
.travel-dot{
  fill:rgb(var(--accent)); stroke:rgb(var(--bg)); stroke-width:1.5;
  transform-box:fill-box; transform-origin:center; transition:transform .25s ease;
}
.travel-ripple{
  fill:none; stroke:rgb(var(--accent)); stroke-width:1.2; opacity:0;
  transform-box:fill-box; transform-origin:center;
}
.travel-label{
  font-family:'Inter',sans-serif; font-size:11px; font-weight:500;
  fill:rgb(var(--fg)); paint-order:stroke; stroke:rgb(var(--bg)); stroke-width:3px; stroke-linejoin:round;
  opacity:0; transition:opacity .35s ease; pointer-events:none;
}
.travel-label.is-w{ text-anchor:end; }
.travel-label.is-s, .travel-label.is-n{ text-anchor:middle; }
.travel-svg.is-zoomed .travel-label{ opacity:.85; }
.travel-pin:hover .travel-label{ opacity:1; }
.travel-pin:hover .travel-dot{ transform:scale(1.3); }
.travel-pin.is-active .travel-label{ opacity:1; fill:rgb(var(--accent)); }
.travel-pin.is-active .travel-dot{ transform:scale(1.45); }
.travel-pin.is-active .travel-ripple{ animation:travel-ripple 1.8s ease-out infinite; }

/* countries warm up when the map first appears; each pin bounces and
   ripples as the plane lands on it */
.travel-svg.is-intro .travel-land .is-been{ animation:travel-been 1.4s ease .1s both; }
.travel-svg.is-intro .travel-states path.is-been{ animation:travel-fade 1s ease .2s both; }
.travel-pin.is-landed .travel-dot{ animation:travel-pop .5s cubic-bezier(.3,1.6,.5,1) both; }
.travel-pin.is-landed .travel-ripple{ animation:travel-ripple 1.1s ease-out .1s both; }
.travel-svg .travel-pin.is-active .travel-ripple{ animation:travel-ripple 1.8s ease-out infinite; }
/* home and school: bright diamonds */
.travel-pin.is-base .travel-dot{ fill:rgb(var(--fg)); stroke:rgb(var(--accent)); stroke-width:1.5; }
.travel-pin.is-base .travel-label{ font-weight:700; }
.travel-plane{ opacity:0; transition:opacity .3s ease; pointer-events:none; }
.travel-plane.is-flying{ opacity:1; }
.travel-plane path{ fill:rgb(var(--fg)); stroke:rgb(var(--bg)); stroke-width:1.2; stroke-linejoin:round; }
.travel-place.is-base{ font-weight:600; }
@keyframes travel-pop{ from{ transform:scale(0); } }
@keyframes travel-ripple{ from{ opacity:.9; transform:scale(1); } to{ opacity:0; transform:scale(3.4); } }
@keyframes travel-been{ from{ fill:rgba(var(--fg),.07); stroke:rgba(var(--fg),.16); } }
@keyframes travel-fade{ from{ opacity:0; } }
@keyframes travel-caption{ from{ opacity:0; transform:translateY(6px); } }
.travel-caption{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 12px;
  min-height:30px; margin:14px 0 16px;
}
.travel-caption.is-in{ animation:travel-caption .4s ease both; }
.travel-caption b{ font-size:19px; font-weight:600; color:rgb(var(--accent)); }
.travel-caption span{
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.1em; opacity:.6;
}
/* the picked place's photo, which opens its card */
.travel-caption .travel-more{
  display:inline-flex; align-items:center; gap:10px; margin-left:auto; align-self:center;
  padding:4px 12px 4px 4px; border:1px solid rgba(var(--accent),.28); border-radius:6px;
  background:rgba(var(--fg),.04); color:inherit; font:inherit; cursor:zoom-in;
  transition:border-color .2s, background .2s;
}
.travel-caption .travel-more:hover, .travel-caption .travel-more:focus-visible{
  border-color:rgba(var(--accent),.7); background:rgba(var(--accent),.08); outline:none;
}
.travel-caption .travel-thumb{
  position:relative; display:block; height:44px; width:auto; aspect-ratio:3 / 2;
  border-radius:4px; overflow:hidden; background:rgba(var(--fg),.08); opacity:1;
}
.travel-caption .travel-thumb img{ display:block; width:100%; height:100%; object-fit:cover; opacity:0; transition:opacity .3s; }
.travel-caption .travel-thumb.has-img img{ opacity:1; }
.travel-caption .travel-more-label{ opacity:.85; font-size:10px; letter-spacing:.14em; text-transform:uppercase; }
.travel-places{
  display:grid; grid-template-columns:repeat(5, minmax(0, 1fr)); gap:18px 14px; align-items:start;
}
.travel-group{ display:flex; flex-direction:column; gap:6px; }
.travel-group-name{
  margin-bottom:4px; padding-bottom:6px; border-bottom:1px solid rgba(var(--accent),.2);
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; opacity:.55; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.travel-place{ font-size:13px; padding:6px 10px; text-align:left; }
.travel-place.is-active{ color:rgb(var(--accent)); border-color:rgb(var(--accent)); background:rgba(var(--accent),.14); }
@media (max-width:760px){
  .travel-places{ grid-template-columns:repeat(3, minmax(0, 1fr)); }
}
@media (max-width:600px){
  .travel-map{ aspect-ratio:3/2; }
  .travel-places{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce){
  .travel-svg *, .travel-caption{ animation:none !important; }
}
/* ---------- other interests ---------- */
.int-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr)); gap:14px; margin-bottom:30px; }
.int-card{
  padding:18px 18px 16px; border:1px solid rgba(var(--accent),.28);
  background:linear-gradient(160deg, rgba(var(--accent),.07), transparent 70%);
  transition:border-color .25s ease, transform .25s ease;
}
.int-card:hover{ border-color:rgb(var(--accent)); transform:translateY(-2px); }
.int-icon{
  width:26px; height:26px; fill:none; stroke:rgb(var(--accent));
  stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round;
}
.int-card h5{ margin:12px 0 6px; font-size:16px; font-weight:600; }
.int-card p{ margin:0 0 12px; font-size:13.5px; line-height:1.5; opacity:.75; }
.int-tags{ display:flex; flex-wrap:wrap; gap:6px; margin:0; padding:0; list-style:none; }
.int-tags li{
  padding:3px 8px; border:1px solid rgba(var(--accent),.3);
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.1em; text-transform:uppercase; opacity:.8;
}
/* things I'm only starting on: dashed, a touch quieter */
.int-card.is-next{ border-style:dashed; background:none; }
.int-card.is-next .int-icon{ opacity:.75; }
@media (prefers-reduced-motion: reduce){ .int-card{ transition:none; } .int-card:hover{ transform:none; } }
/* link out to the full profile (Letterboxd, Last.fm, BGG) under a tab's grid */
.fav-profile{ margin-top:26px; }
.fav-art img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  opacity:0; transition:opacity .3s ease;
}
.fav-art.has-img img{ opacity:1; }
.fav-fallback{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  padding:10px; text-align:center;
  font-family:'Cinzel',serif; font-size:.85rem; line-height:1.3; color:rgb(var(--fg)); opacity:.8;
}
.fav-art.has-img .fav-fallback{ display:none; }
.fav-item figcaption{ margin-top:8px; }
.fav-item figcaption b{
  display:block; font-family:'Inter',sans-serif; font-weight:500; font-size:.85rem; line-height:1.35;
}
.fav-item figcaption span{
  display:block; margin-top:2px;
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.06em; opacity:.55;
}
.fav-empty{
  grid-column:1/-1; padding:28px 0; text-align:center;
  font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; opacity:.5;
}
@media (max-width:760px){
  .fav-grid{ grid-template-columns:repeat(auto-fill,minmax(96px,1fr)); }
  .fav-tab{ padding:8px 8px; font-size:10px; }
}

@media (max-width:760px){
  .case-modal{ padding:0; }
  .case-panel{ width:100%; max-height:100vh; height:100%; padding:22px 20px 26px; border:none; }
}

.cursor{ display:inline-block; width:8px; height:16px; background:rgb(var(--accent)); animation:blink 1s steps(1) infinite; vertical-align:-3px; }
.cursor.typing{ animation:none; opacity:1; }
@keyframes blink{ 50%{ opacity:0; } }
@media (prefers-reduced-motion: reduce){ .cursor{ animation:none; } }

.skills-panel{
  display:grid; grid-template-columns:1fr; gap:22px;
  margin-top:8px;
}
.skills-wrap{
  border:1px solid rgba(var(--accent),.35);
  background:rgba(255,255,255,.02);
  padding:22px 24px 24px;
}
.skills-wrap h3{
  font-family:'JetBrains Mono', monospace;
  font-size:11px; font-weight:500;
  letter-spacing:.18em; text-transform:uppercase;
  color:rgb(var(--accent));
  margin-bottom:16px; padding-bottom:12px;
  border-bottom:1px solid rgba(var(--accent),.25);
}
.skills-wrap h3::before{
  content:'// ';
  opacity:.55;
}
.pill-row{ display:flex; flex-wrap:wrap; gap:8px; }
/* each pill links out to that tool's own site, so these are anchors — the
   global `a{color:inherit}` keeps them looking like the plain tags they were */
.pill-row a{
  font-family:'JetBrains Mono', monospace;
  font-size:12px; letter-spacing:.02em;
  border:1px solid rgba(var(--accent),.4);
  padding:7px 12px;
  color:rgb(var(--fg));
  background:transparent;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.pill-row a:hover{
  border-color:rgb(var(--accent));
  color:rgb(var(--accent));
  background:rgba(var(--accent),.08);
}

/* ================= CONTACT — END CREDITS ================= */
/* shorter than the other full-viewport scenes — its content is short, so
   forcing min-height:100vh (like every other section) left a large dead
   gap below the credits before the footer */
#contact{ align-items:center; text-align:center; min-height:auto; padding-top:calc(14vh + 48px); padding-bottom:calc(6vh + 48px); }
#contact .eyebrow{ text-align:center; }
.credits-roll{ display:flex; flex-direction:column; gap:22px; margin-top:20px; }
.credit-row{
  display:flex; flex-direction:column; gap:4px;
  opacity:1; transform:none;
  transition:opacity .6s ease, transform .6s ease;
}
/* only hide for the fade-in once JS has marked the page as ready */
.js .credit-row:not(.in){
  opacity:0; transform:translateY(16px);
}
.credit-row.in{ opacity:1; transform:translateY(0); }
.credit-row .role{
  font-family:'JetBrains Mono', monospace; font-size:11px; letter-spacing:.2em;
  text-transform:uppercase; opacity:.6;
}
.credit-row a, .credit-row .val{
  font-family:'Inter', sans-serif; font-size:1.3rem; font-weight:500;
}
.credit-row a:hover{ color:rgb(var(--accent)); }
.fin{
  margin-top:64px; font-family:'Cinzel', serif; letter-spacing:.3em; font-size:13px; opacity:.55;
  margin-right:-.3em; /* letter-spacing pads a trailing gap after the last char, which throws off visual centering */
}
@media (max-width:760px){ .fin{ margin-top:48px; } }

.attribution{
  margin:14px auto 0; font-family:'JetBrains Mono', monospace; font-size:10px;
  line-height:1.7; letter-spacing:.06em; opacity:.38; max-width:520px;
}
footer.small{
  text-align:center;
  padding:30px 6vw 40px calc(var(--rail-w) + 6vw);
  font-family:'JetBrains Mono',monospace;
  font-size:10.5px; letter-spacing:.1em; opacity:.4;
}
@media (max-width:860px){
  footer.small{ padding:30px 6vw 40px calc(28px + 6vw); }
}

/* ---------- favorite things: the hall ----------
   A CSS-3D corridor built by script.js. Colours are fixed (not era-tinted)
   so it always reads as the same velvet-and-brass cinema hallway. The shell
   planes are single flat colours on purpose: the compositor draws those
   without rasterizing a texture, which is what keeps the walk smooth. */
.fav-head-actions{ display:flex; align-items:center; gap:12px; }
/* the title block can shrink so the header never pushes the panel wider */
.fav-panel{ width:min(1120px, 100%); max-height:90vh; }
.fav-panel .case-head > div:first-child{ min-width:0; }
@media (max-width:760px){
}

.hall{
  position:fixed; inset:0; z-index:220; overflow:hidden;
  background:#050405; color:#f3e7cc;
  font-family:'Inter', sans-serif;
  -webkit-user-select:none; user-select:none;
}
.hall[hidden]{ display:none; }
.hall-view{
  position:absolute; inset:0; overflow:hidden;
  touch-action:none;
  opacity:1; transition:opacity .9s ease;
}
.hall.is-loading .hall-view{ opacity:0; transition:none; }
/* long trips cut through black */
.hall.is-cut .hall-view{ opacity:0; transition:opacity .35s ease; }
.hall-canvas{ display:block; outline:none; cursor:grab; }
.hall.is-dragging .hall-canvas{ cursor:grabbing !important; }
/* a soft lens vignette over the scene */
.hall-view::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(ellipse at 50% 50%, transparent 55%, rgba(0,0,0,.55) 100%);
}
.hall-loading{
  position:absolute; left:0; right:0; top:50%; text-align:center; pointer-events:none;
  font-family:'JetBrains Mono', monospace; font-size:11px; letter-spacing:.3em;
  text-transform:uppercase; color:#e9c878; opacity:0; transition:opacity .4s ease .3s;
}
.hall.is-loading .hall-loading{ opacity:.75; animation:hall-breathe 1.8s ease-in-out infinite; }
@keyframes hall-breathe{ 50%{ opacity:.35; } }
/* title card for art that never loads (used by the focus view) */
.hall-fallback{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  padding:12px; font-family:'Cinzel', serif; font-size:15px; line-height:1.3; color:#f3e7cc; text-align:center;
}

/* focus view: the clicked frame grows off the wall into a card */
.hall-focus{ position:absolute; inset:0; z-index:5; }
.hall-focus[hidden]{ display:none; }
.hall-focus{ cursor:zoom-out; }
.hall-focus-panel{ outline:none; }
.hall-focus a{ cursor:pointer; }
.hall-focus-back{
  position:absolute; inset:0; cursor:zoom-out;
  background:rgba(4,3,4,.93); opacity:0; transition:opacity .45s ease;
}
.hall-focus.is-open .hall-focus-back{ opacity:1; }
.hall-focus-art{
  position:fixed; overflow:hidden; z-index:1;
  transform-origin:0 0; will-change:transform;
  transition:transform .6s cubic-bezier(.3,0,.15,1);
  background:linear-gradient(160deg, #3a2a22, #1c1411);
  border:6px solid #2b1d13;
  box-shadow:0 0 0 1px rgba(226,184,76,.6), 0 30px 60px rgba(0,0,0,.7);
}
.hall-focus-art.is-round{ border-radius:50%; }
.hall-focus-art img{ display:block; width:100%; height:100%; object-fit:cover; }
/* square app icons (mobile games) sit whole in the middle of a tall frame
   rather than being cropped to a sliver */
.fav-art.is-icon img, .hall-frame.is-icon img, .hall-focus-art.is-icon img{
  inset:auto; top:50%; left:50%; width:72%; height:auto; aspect-ratio:1/1;
  transform:translate(-50%,-50%); border-radius:22%; object-fit:cover;
  box-shadow:0 8px 22px rgba(0,0,0,.45);
}
.hall-focus-art.is-icon img{ position:absolute; }
.hall-focus-art .hall-fallback{ font-size:clamp(18px, 3vw, 34px); }
.hall-focus-panel{
  position:absolute; left:43vw; right:4vw; top:50%; max-width:940px; z-index:2;
  transform:translateY(calc(-50% + 16px)); opacity:0;
  transition:opacity .4s ease .3s, transform .4s ease .3s;
}
.hall-focus.is-open .hall-focus-panel{ opacity:1; transform:translateY(-50%); }
.hall-focus-kicker{
  font-family:'JetBrains Mono', monospace; font-size:11px; letter-spacing:.24em;
  text-transform:uppercase; color:#e9c878; opacity:.8; margin-bottom:12px;
}
.hall-focus-panel h3{
  font-family:'Bebas Neue', sans-serif; font-weight:400; font-size:clamp(34px, min(4.2vw, 7vh), 66px);
  line-height:.95; letter-spacing:.04em; color:#ffe6a6;
  text-shadow:0 0 22px rgba(255,196,90,.35);
}
.hall-focus-sub{
  margin-top:10px; font-family:'JetBrains Mono', monospace; font-size:13px;
  letter-spacing:.1em; opacity:.6;
}
.hall-focus-body{ margin-top:22px; font-size:1rem; line-height:1.65; color:#f3e7cc; }
.hall-focus-body p + p{ margin-top:12px; }
.hall-focus-body .log-link{ margin-top:16px; color:#e9c878; }
.hall-focus-soon{ opacity:.45; font-style:italic; }
/* the same card, opened from the favorites grid */
.media-card{
  position:fixed; z-index:240; color:#f3e7cc; font-family:'Inter', sans-serif;
}
.media-card .hall-focus-back{ background:rgba(4,3,4,.94); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px); }
.fav-item[role="button"]{ cursor:zoom-in; outline:none; }
.fav-item[role="button"]:focus-visible .fav-art{ box-shadow:0 0 0 2px #e2b84c; }
/* long cards (cast, credits) scroll inside the panel */
.hall-focus-panel{
  max-height:86vh; overflow-y:auto; overscroll-behavior:contain;
  padding-right:14px; scrollbar-width:thin; scrollbar-color:rgba(226,184,76,.4) transparent;
}
.media-tagline{
  font-family:'EB Garamond', serif; font-style:italic; font-size:1.2rem; color:#e9c878; margin-bottom:10px;
}
.media-overview{ font-size:1rem; line-height:1.65; }
.hall-focus-body .media-head{
  margin:20px 0 10px; font-family:'JetBrains Mono', monospace; font-weight:500; font-size:11px;
  letter-spacing:.24em; text-transform:uppercase; color:#e9c878; opacity:.8;
  padding-bottom:6px; border-bottom:1px solid rgba(226,184,76,.22);
}
.media-cast{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:10px 22px;
}
.media-cast--many{ grid-template-columns:repeat(4, minmax(0, 1fr)); gap:8px 18px; }
.media-cast li{ min-width:0; }
.media-cast b, .media-cast span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.media-cast b{ display:block; font-weight:500; font-size:.95rem; line-height:1.3; }
.media-cast span{
  display:block; margin-top:2px; font-family:'JetBrains Mono', monospace; font-size:11px;
  letter-spacing:.04em; opacity:.55;
}
.media-facts{
  display:grid; grid-template-columns:max-content minmax(0, 1fr) max-content minmax(0, 1fr); gap:8px 18px; margin:0;
}
.media-facts dt{
  font-family:'JetBrains Mono', monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; opacity:.55; padding-top:3px;
}
.media-facts dd{ margin:0; font-size:.95rem; line-height:1.45; }
.media-sources{
  margin-top:calc(16px * var(--fit, 1)) !important; font-family:'JetBrains Mono', monospace;
  font-size:calc(10.5px * var(--fit, 1)); letter-spacing:.06em; line-height:1.7; opacity:.5;
}
.media-sources a{ color:inherit; text-decoration:underline; text-underline-offset:2px; }
.media-sources a:hover{ color:#e9c878; opacity:1; }
@media (max-width:760px){
  .hall-focus-panel{ max-height:56vh; }
  .media-cast{ grid-template-columns:1fr; gap:8px; }
  .media-facts{ grid-template-columns:max-content 1fr; gap:6px 14px; }
}
/* the card scales its type by --fit (set by script.js) so it always fits
   the screen without scrolling on desktop */
.hall-focus-panel{ --fit:1; max-height:90vh; }
.hall-focus-kicker{ font-size:calc(11px * var(--fit)); margin-bottom:calc(10px * var(--fit)); }
.hall-focus-panel h3{ font-size:calc(clamp(34px, min(4.2vw, 7.5vh), 66px) * var(--fit)); }
.hall-focus-sub{ font-size:calc(13px * var(--fit)); margin-top:calc(8px * var(--fit)); }
.hall-focus-body{ font-size:calc(16px * var(--fit)); margin-top:calc(18px * var(--fit)); }
.media-tagline{ font-size:calc(19px * var(--fit)); margin-bottom:calc(8px * var(--fit)); }
.media-overview{ font-size:calc(16px * var(--fit)); line-height:1.6; }
.hall-focus-body .media-head{ font-size:calc(11px * var(--fit)); margin:calc(18px * var(--fit)) 0 calc(9px * var(--fit)); padding-bottom:calc(5px * var(--fit)); }
.media-cast{ gap:calc(9px * var(--fit)) 20px; }
.media-cast b{ font-size:calc(15px * var(--fit)); }
.media-cast span{ font-size:calc(11px * var(--fit)); }
.media-facts{ gap:calc(7px * var(--fit)) 18px; }
.media-facts dt{ font-size:calc(11px * var(--fit)); }
.media-facts dd{ font-size:calc(15px * var(--fit)); }
.hall.is-focus .hall-hud{ opacity:0; pointer-events:none; }
.hall-hud{ transition:opacity .3s ease; }
@media (max-width:760px){
  .hall-focus-panel{
    left:16px; right:16px; top:auto; bottom:0; width:auto; max-height:52vh; overflow-y:auto;
    padding-bottom:22px; transform:translateY(16px);
  }
  .hall-focus.is-open .hall-focus-panel{ transform:none; }
  .hall-focus-body{ margin-top:14px; font-size:.95rem; }
}
@media (prefers-reduced-motion: reduce){
  .hall-focus-art, .hall-focus-back, .hall-focus-panel{ transition:none; }
}

/* HUD: flat on top of the scene; only the controls take clicks */
.hall-hud{
  position:absolute; inset:0; pointer-events:none;
  display:flex; flex-direction:column; justify-content:space-between;
  padding:18px 20px 22px;
}
.hall-hud button{ pointer-events:auto; }
.hall-top{ display:flex; align-items:center; justify-content:space-between; gap:16px; }
.hall-hint{
  font-family:'JetBrains Mono', monospace; font-size:11px; letter-spacing:.14em;
  text-transform:uppercase; color:#f3e7cc; opacity:.55;
  transition:opacity 1.2s ease;
}
.hall.is-settled .hall-hint, .hall.is-loading .hall-hint{ opacity:0; }
.hall.is-loading .hall-bottom, .hall.is-loading .hall-tour{ opacity:0; pointer-events:none; }
.hall-bottom, .hall-tour{ transition:opacity .6s ease; }
.hall-actions{ display:flex; align-items:center; gap:10px; flex:none; }
.hall-tour{
  pointer-events:auto; cursor:pointer; height:38px; padding:0 16px; border-radius:19px;
  font-family:'JetBrains Mono', monospace; font-size:11px; letter-spacing:.18em; text-transform:uppercase;
  background:rgba(10,6,6,.55); color:#f0d48a; border:1px solid rgba(226,184,76,.5);
  transition:background .2s ease, border-color .2s ease;
}
.hall-tour:hover{ background:rgba(226,184,76,.16); border-color:#e2b84c; }
.hall-tour[aria-pressed="true"]{ background:rgba(226,184,76,.22); border-color:#e2b84c; }
.hall.is-touring .hall-hint{ opacity:0; }
.hall-close, .hall-step{
  flex:none; border-radius:50%; cursor:pointer;
  display:flex; align-items:center; justify-content:center; line-height:1;
  background:rgba(10,6,6,.55); color:#f0d48a;
  border:1px solid rgba(226,184,76,.5);
  transition:background .2s ease, border-color .2s ease;
}
.hall-close{ width:38px; height:38px; font-size:21px; }
.hall-step{ width:44px; height:44px; font-size:26px; padding-bottom:3px; }
.hall-close:hover, .hall-step:hover{ background:rgba(226,184,76,.16); border-color:#e2b84c; }
.hall-bottom{ display:flex; align-items:center; justify-content:center; gap:20px; }
.hall-rooms{ min-width:210px; text-align:center; }
.hall-label{
  display:block; font-family:'Bebas Neue', sans-serif; font-size:24px; letter-spacing:.14em;
  color:#ffe6a6; text-shadow:0 0 12px rgba(255,196,90,.5);
}
.hall-dots{ display:flex; justify-content:center; gap:9px; margin-top:7px; }
.hall-dot{
  width:9px; height:9px; padding:0; border-radius:50%; cursor:pointer;
  background:transparent; border:1px solid rgba(226,184,76,.7);
}
.hall-dot.is-on{ background:#e2b84c; box-shadow:0 0 8px rgba(226,184,76,.8); }
@media (max-width:760px){
  .hall-hint{ font-size:9.5px; letter-spacing:.1em; }
  .hall-rooms{ min-width:150px; }
}

/* ---------- timeline (its own window, beside the hall) ---------- */
.tl-count{ display:block; margin:0 0 18px; }
.tl-bar{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:10px 24px; margin:-6px 0 20px; }
.tl-kinds, .tl-jumps{ display:flex; flex-wrap:wrap; gap:6px; }
.tl-jumps{ gap:2px; }
.tl-kinds .fav-toggle[aria-pressed="false"]{ opacity:.4; text-decoration:line-through; background:transparent; border-color:rgba(var(--accent),.2); }
.tl-jump{
  padding:5px 7px; background:transparent; border:none; border-bottom:1px solid transparent; cursor:pointer;
  color:rgb(var(--fg)); opacity:.5; font-family:'JetBrains Mono',monospace; font-size:10.5px; letter-spacing:.08em;
  transition:opacity .2s ease, color .2s ease;
}
.tl-jump:hover{ opacity:.85; }
.tl-jump[aria-current="true"]{ opacity:1; color:rgb(236,200,104); border-bottom-color:rgba(226,184,76,.6); }
.tl-track{
  display:flex; overflow-x:auto; overflow-y:hidden; padding-bottom:16px; cursor:grab; outline:none;
  overscroll-behavior-x:contain; scrollbar-width:thin; scrollbar-color:rgba(226,184,76,.4) transparent;
}
.tl-track:focus-visible{ box-shadow:0 0 0 1px rgba(226,184,76,.5); }
.tl-track.is-dragging{ cursor:grabbing; user-select:none; }
.tl-track.is-dragging .fav-item{ pointer-events:none; }
.tl-year{ display:flex; flex:none; }
.tl-year[hidden], .tl-gap[hidden]{ display:none; }
/* the axis runs along the top: solid through years, dashed across a gap */
.tl-col{ padding:0 14px 0 12px; border-top:1px solid rgba(var(--accent),.45); border-left:1px solid rgba(var(--accent),.14); }
.tl-gap{
  flex:none; width:46px; display:flex; align-items:flex-start; justify-content:center; padding-top:14px;
  border-top:1px dashed rgba(var(--accent),.45);
}
.tl-gap span{
  writing-mode:vertical-rl; font-family:'JetBrains Mono',monospace; font-size:9.5px; letter-spacing:.1em; opacity:.45;
}
.tl-year-head{ display:flex; align-items:baseline; gap:8px; padding:10px 0 12px; }
.tl-year-head b{ font-family:'Playfair Display',serif; font-weight:700; font-size:1.35rem; color:rgb(236,200,104); line-height:1; }
.tl-year-head span{ font-family:'JetBrains Mono',monospace; font-size:10px; opacity:.45; }
.tl-items{
  display:grid; grid-auto-flow:column; grid-template-rows:repeat(3, auto); grid-auto-columns:88px;
  gap:14px 12px; align-items:start;
}
.tl-items .fav-item figcaption b{ font-size:.74rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.tl-items .fav-item figcaption span{ font-size:9px; }
.tl-items .fav-item.is-filtered{ display:none; }

/* ---------- favorite things: stats ---------- */
.fav-stats{ position:relative; }
.stats-tiles{
  display:grid; grid-template-columns:repeat(4, minmax(0, 1fr)); gap:1px;
  background:rgba(var(--accent),.2); border:1px solid rgba(var(--accent),.2); margin-bottom:34px;
}
.stats-tile{ background:rgb(var(--bg)); padding:16px 16px 14px; display:flex; flex-direction:column; gap:3px; }
.stats-tile b{ font-family:'Playfair Display',serif; font-weight:700; font-size:2rem; line-height:1.1; color:rgb(236,200,104); }
.stats-tile-label{ font-family:'JetBrains Mono',monospace; font-size:10.5px; letter-spacing:.16em; text-transform:uppercase; }
.stats-tile-sub{ font-family:'Inter',sans-serif; font-size:.78rem; opacity:.55; }
.stats-block{ position:relative; margin-bottom:34px; }
.stats-note{ margin:-4px 0 14px; font-family:'Inter',sans-serif; font-size:.8rem; opacity:.55; }

/* films by decade: thin columns on one baseline */
.stats-cols{ display:flex; align-items:stretch; gap:4px; height:190px; }
.stats-col{ flex:1 1 0; min-width:0; display:flex; flex-direction:column; outline:none; cursor:default; }
.stats-colplot{ flex:1; display:flex; align-items:flex-end; justify-content:center; border-bottom:1px solid rgba(var(--fg),.25); }
.stats-colbar{
  position:relative; width:min(26px, 70%); background:rgb(226,184,76); border-radius:4px 4px 0 0;
  transition:opacity .15s ease;
}
.stats-colval{
  position:absolute; bottom:100%; left:50%; transform:translateX(-50%); padding-bottom:4px;
  font-family:'JetBrains Mono',monospace; font-size:10px; color:rgb(var(--fg)); white-space:nowrap;
}
.stats-coltick{
  margin-top:6px; text-align:center; font-family:'JetBrains Mono',monospace; font-size:9.5px;
  letter-spacing:.04em; opacity:.55; white-space:nowrap;
}
.stats-cols.is-hovering .stats-col:not(.is-on) .stats-colbar{ opacity:.4; }
.stats-col:focus-visible .stats-coltick{ opacity:1; color:rgb(236,200,104); }
.stats-tip{
  position:absolute; z-index:2; transform:translate(-50%, -100%); pointer-events:none; white-space:nowrap;
  padding:5px 9px; background:#16130d; border:1px solid rgba(226,184,76,.45); color:#f3e7cc;
  font-family:'JetBrains Mono',monospace; font-size:10.5px; letter-spacing:.06em;
}
.stats-tip[hidden]{ display:none; }

/* ranked lists: label, bar, count; each row opens those films */
.stats-pair{ display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:0 44px; }
.stats-bars{ list-style:none; margin:0; padding:0; }
.stats-row{
  width:100%; display:grid; grid-template-columns:minmax(0, 11em) 1fr 2.6em; align-items:center; gap:12px;
  padding:5px 4px; background:transparent; border:none; color:rgb(var(--fg)); cursor:pointer; text-align:left;
  transition:background .15s ease;
}
.stats-row:hover, .stats-row:focus-visible{ background:rgba(226,184,76,.08); outline:none; }
.stats-label{ font-family:'Inter',sans-serif; font-size:.85rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.stats-track{ display:block; height:10px; }
.stats-bar{ display:block; height:100%; background:rgb(226,184,76); border-radius:0 4px 4px 0; }
.stats-val{ font-family:'JetBrains Mono',monospace; font-size:11px; text-align:right; opacity:.8; }

/* the card's footer: previous / next through its grid, and copy-link */
.media-actions{ display:flex; flex-wrap:wrap; align-items:center; gap:10px 14px; margin-top:18px; }
.media-nav{ display:flex; align-items:center; gap:8px; }
.media-nav[hidden]{ display:none; }
.media-step{
  width:30px; height:28px; padding:0; cursor:pointer; background:transparent; color:#e9c878;
  border:1px solid rgba(226,184,76,.4); font-size:18px; line-height:1;
  transition:border-color .2s ease, background .2s ease, opacity .2s ease;
}
.media-step:hover:not(:disabled), .media-step:focus-visible{ border-color:rgb(226,184,76); background:rgba(226,184,76,.1); outline:none; }
.media-step:disabled{ opacity:.3; cursor:default; }
.media-pos{
  min-width:5.5em; text-align:center; font-family:'JetBrains Mono',monospace; font-size:10px;
  letter-spacing:.12em; opacity:.6;
}
/* stepping swaps the card in place with a quick fade */
.media-card.is-stepped .hall-focus-art,
.media-card.is-stepped .hall-focus-kicker,
.media-card.is-stepped h3,
.media-card.is-stepped .hall-focus-sub,
.media-card.is-stepped .hall-focus-body{ animation:mediaStep .3s ease; }
@keyframes mediaStep{ from{ opacity:0; } }
@media (prefers-reduced-motion: reduce){
  .media-card.is-stepped *{ animation:none !important; }
}
.media-share{
  padding:6px 11px; cursor:pointer; background:transparent; color:#e9c878;
  border:1px solid rgba(226,184,76,.4);
  font-family:'JetBrains Mono',monospace; font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  transition:border-color .2s ease, background .2s ease;
}
.media-share:hover, .media-share:focus-visible{ border-color:rgb(226,184,76); background:rgba(226,184,76,.1); outline:none; }

@media (max-width:760px){
  .stats-tiles{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
  .tl-items{ grid-auto-columns:74px; gap:12px 10px; }
  .tl-bar{ margin-top:-10px; }
  .stats-tile b{ font-size:1.6rem; }
  .stats-pair{ grid-template-columns:1fr; }
  .stats-cols{ height:150px; gap:2px; }
  .stats-col:nth-child(even) .stats-coltick{ visibility:hidden; }
  .stats-row{ grid-template-columns:minmax(0, 8.5em) 1fr 2.4em; }
  .fav-filters{ margin-top:-10px; }
  .fav-search{ flex-basis:100%; max-width:none; }
}
