/* ============================================================
   MOR SEDERO — Cinematic / Game-HUD Portfolio
   ============================================================ */

:root{
  --bg: #121219;
  --bg-alt: #18181f;
  --panel: #1e1e28;
  --line: #34343f;
  --ink: #f5f1e8;
  --ink-dim: #a3a1af;
  --accent: #ff7a52;
  --accent-text: #ff9b7a; /* brighter tint of --accent, used only for text (not borders/glows) */
  --accent-dim: #8a4530;
  --gold: #f6c667;
  --accent-blue: #6fa3e0;
  --font-display: 'Fredoka', 'Space Grotesk', sans-serif;
  --font-body: 'Space Grotesk', sans-serif;
  --night-blue: #16224a;
}

*{ margin:0; padding:0; box-sizing:border-box; }

html{ scroll-behavior:smooth; }

body{
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font-body);
  overflow-x:hidden;
}

a{ color:inherit; text-decoration:none; }
ul{ list-style:none; }

::selection{ background:var(--accent); color:#0a0a0a; }

/* ---------- CRT / grain overlay ---------- */
.crt-overlay{
  position:fixed; inset:0; z-index:70; pointer-events:none; mix-blend-mode:overlay; opacity:.5;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,.035) 0px, rgba(255,255,255,.035) 1px, transparent 1px, transparent 3px);
}
.crt-overlay::after{
  content:""; position:absolute; inset:0;
  background:radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,.55) 100%);
}


/* ---------- home zone: logo + about get a quiet, distinct backdrop, set apart from projects onward ---------- */
.home-zone{
  position:relative; overflow:hidden;
  isolation:isolate;
  background:var(--bg-alt);
  box-shadow:
    inset 0 70px 90px -70px rgba(0,0,0,.55),
    inset 0 -70px 90px -70px rgba(0,0,0,.55);
}
.home-glow{ position:absolute; inset:0; z-index:-2; overflow:hidden; pointer-events:none; }
/* Real studio photo as the hero backdrop — kept mostly sharp (the site has
   had zero literal photography in the hero until now) but faded low enough
   to stay backdrop, not foreground. Replaced the old pair of blurred
   game-cover glow blobs entirely; they were unrelated crops standing in for
   ambient color before there was a real photo to provide it. */
.home-bg-photo{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  object-position:center 35%; opacity:.4; filter:saturate(1.05) brightness(1.3);
  /* scale(1.4) leaves slack around the edges so homeParallax() in main.js
     can translateY it on scroll without ever exposing an edge — checked
     against the tightest real breakpoint (~760px tall, just above the
     700px layout reflow) so MAX in main.js always stays covered. */
  transform:scale(1.4) translateY(var(--parallax-y, 0px)); will-change:transform;
}
/* One flat opacity behind the logo bar, one flat (lighter) opacity for the
   rest of the hero — a hard cut between the two, no blended transition.
   --banner-h is set by homeParallax() in main.js from the logo bar's own
   measured height, so this line always lands exactly on the bar's bottom
   edge instead of an approximated px guess. */
.home-glow::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(180deg,
    rgba(24,24,31,.9) 0, rgba(24,24,31,.9) var(--banner-h, 110px),
    rgba(24,24,31,.42) var(--banner-h, 110px), rgba(24,24,31,.42) 100%);
}
.home-zone::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  background:rgba(255,255,255,.09);
}

/* ---------- logo / name mark (regular flow, scrolls with the page) ---------- */
.site-logo-bar{
  position:relative; z-index:5; display:flex; align-items:flex-start; justify-content:space-between;
  flex-wrap:wrap; gap:18px 32px; padding:34px 8vw 18px; max-width:1400px; margin:0 auto;
  border-bottom:1px solid rgba(255,255,255,.09);
}
.site-logo-block{ display:flex; flex-direction:column; gap:12px; }
.site-logo{
  display:inline-flex; align-items:center; font-family:var(--font-display); font-weight:700;
  font-size:clamp(2.1rem,4.6vw,3.1rem); letter-spacing:.02em; line-height:1;
}
.site-logo-mark{
  position:relative; display:inline-block; box-sizing:border-box;
  width:1.5em; height:1.5em; margin-right:.16em; flex-shrink:0; cursor:pointer;
  animation:logoBob 4.2s ease-in-out infinite;
}
@keyframes logoBob{
  0%, 100%{ transform:translateY(0); }
  50%{ transform:translateY(-3px); }
}
/* Click reaction — see eyesFollowCursor()'s click handler in main.js, which
   drives --shake-x/--shake-rot through a decaying oscillation at a fixed
   cadence and fires a matching burst of pupil jitter. A stronger shake gets
   MORE oscillation steps at that same fixed speed, not the same steps played
   back slower — stretching a fixed animation's duration made a longer shake
   read as slow-motion wobble instead of a harder hit that rings out longer.
   translate/rotate are standalone properties (not `transform`), so they
   compose with logoBob's own transform:translateY instead of fighting it. */
.site-logo-mark.shaking{
  transition:translate 65ms ease, rotate 65ms ease;
  translate:var(--shake-x, 0px) 0;
  rotate:var(--shake-rot, 0deg);
}
/* --combo-saturate ramps up with the click-combo's intensity (see
   eyesFollowCursor() in main.js) — colors get hotter the closer a break is —
   then drops to 0 (grey) the instant it breaks, and returns to 1 once the
   shatter fully reassembles. Applied to the shards too so the pieces stay
   grey through the whole break, not just the intact image. */
.site-logo-mark-img{
  display:block; width:100%; height:100%; object-fit:contain;
  transition:filter .18s ease;
  filter:
    drop-shadow(0 2px 0 rgba(0,0,0,.35))
    drop-shadow(0 6px 10px rgba(0,0,0,.45))
    drop-shadow(0 0 14px rgba(255,122,82,.25))
    saturate(var(--combo-saturate, 1));
}
/* Pupils sit inside the mark's naturally-transparent eye sockets (real alpha
   cutouts in the PNG, not a painted white fill) and drift a couple px toward
   the cursor — see eyesFollowCursor() in main.js. Positioned from the eye
   centers traced during the 3D experiment (data-cx/cy, normalized 0-1 image
   space), independent of that experiment's now-removed WebGL mesh. */
.site-logo-pupil{
  position:absolute; width:5%; height:5%; border-radius:50%;
  background:var(--accent-text); box-shadow:0 0 4px rgba(255,155,122,.85);
  transform:translate(calc(-50% + var(--pupil-x, 0px)), calc(-50% + var(--pupil-y, 0px)));
  pointer-events:none;
}
/* Applied only while the post-click jitter eases back to the cursor-tracked
   position, so normal frame-by-frame tracking stays instant the rest of the time. */
.site-logo-pupil.settling{ transition:transform var(--pupil-settle-duration, .6s) cubic-bezier(.22,1,.36,1); }

/* Rage-click easter egg — see eyesFollowCursor()'s combo counter in main.js.
   Enough rapid clicks in a row fires .flash, which briefly reveals these crack
   lines over the skull before healing back to invisible. Masked to the logo's
   own silhouette (same trick as the grain layer above) so cracks never spill
   past the actual artwork. */
.site-logo-crack{
  position:absolute; inset:0; width:100%; height:100%; pointer-events:none;
  opacity:0; z-index:2;
  -webkit-mask-image:url('../assets/logos/mor-logo-mark.png');
  -webkit-mask-size:contain; -webkit-mask-repeat:no-repeat; -webkit-mask-position:center;
  mask-image:url('../assets/logos/mor-logo-mark.png');
  mask-size:contain; mask-repeat:no-repeat; mask-position:center;
}
.site-logo-crack g{
  fill:none; stroke:#fff; stroke-width:7; stroke-linecap:round; stroke-linejoin:round;
  filter:drop-shadow(0 0 6px rgba(255,255,255,.8));
}
.site-logo-crack.flash{ animation:crackFlash .85s ease-out; }
@keyframes crackFlash{
  0%{ opacity:0; }
  8%{ opacity:1; }
  22%{ opacity:.7; }
  38%{ opacity:1; }
  70%{ opacity:.4; }
  100%{ opacity:0; }
}
/* Same rage-click break: 8 wedges of the logo, each a full copy of the
   artwork clipped to one slice, tiled from the center out to the box edges
   so at rest (identity transform) they reconstruct the image exactly — see
   runShatter() in main.js. The break hides the real img/pupils and swaps in
   these shards, flings each to a random offset, holds a beat scattered, then
   eases them back to identity before swapping back to the plain image. */
.site-logo-shards{ position:absolute; inset:0; pointer-events:none; }
.site-logo-shard{
  position:absolute; inset:0; opacity:0;
  background-image:url('../assets/logos/mor-logo-mark.png');
  background-size:contain; background-position:center; background-repeat:no-repeat;
  transform:translate(var(--shard-dx, 0px), var(--shard-dy, 0px)) rotate(var(--shard-rot, 0deg));
  filter:saturate(var(--combo-saturate, 1));
  transition:filter .18s ease;
}
.site-logo-mark.shattering .site-logo-shard{ opacity:var(--shard-op, 1); }
.site-logo-mark.shattering .site-logo-mark-img,
.site-logo-mark.shattering .site-logo-pupil{ opacity:0; }
.site-logo-shard.flying{ transition:transform .24s ease-out, opacity .24s ease-out, filter .18s ease; }
.site-logo-shard.returning{ transition:transform .42s cubic-bezier(.22,1,.36,1), opacity .42s ease, filter .18s ease; }
.site-logo-shards > .site-logo-shard:nth-child(1){ clip-path:polygon(50% 50%, 50% 0%, 100% 0%); }
.site-logo-shards > .site-logo-shard:nth-child(2){ clip-path:polygon(50% 50%, 100% 0%, 100% 50%); }
.site-logo-shards > .site-logo-shard:nth-child(3){ clip-path:polygon(50% 50%, 100% 50%, 100% 100%); }
.site-logo-shards > .site-logo-shard:nth-child(4){ clip-path:polygon(50% 50%, 100% 100%, 50% 100%); }
.site-logo-shards > .site-logo-shard:nth-child(5){ clip-path:polygon(50% 50%, 50% 100%, 0% 100%); }
.site-logo-shards > .site-logo-shard:nth-child(6){ clip-path:polygon(50% 50%, 0% 100%, 0% 50%); }
.site-logo-shards > .site-logo-shard:nth-child(7){ clip-path:polygon(50% 50%, 0% 50%, 0% 0%); }
.site-logo-shards > .site-logo-shard:nth-child(8){ clip-path:polygon(50% 50%, 0% 0%, 50% 0%); }
.site-logo-mark::after{
  /* faint etched grain, clipped to the mark's own silhouette for a textured, tactile surface */
  content:""; position:absolute; inset:0; pointer-events:none; opacity:.55; mix-blend-mode:overlay;
  background-image:repeating-linear-gradient(0deg, rgba(255,255,255,.08) 0px, rgba(255,255,255,.08) 1px, transparent 1px, transparent 3px);
  -webkit-mask-image:url('../assets/logos/mor-logo-mark.png');
  -webkit-mask-size:contain; -webkit-mask-repeat:no-repeat; -webkit-mask-position:center;
  mask-image:url('../assets/logos/mor-logo-mark.png');
  mask-size:contain; mask-repeat:no-repeat; mask-position:center;
}
.site-logo-mor{ color:var(--ink); }
.site-logo-sedero{
  color:var(--accent); display:inline-block; margin-left:.2em; transition:transform .25s ease;
}
.site-logo-sedero:hover{ transform:rotate(-3deg); }
.rec-dot{
  width:8px; height:8px; border-radius:50%; background:var(--accent);
  box-shadow:0 0 8px var(--accent); animation:blink 1.4s infinite;
}
@keyframes blink{ 0%,100%{opacity:1;} 50%{opacity:.25;} }
.site-role{
  display:flex; align-items:center; gap:10px;
  font-family:var(--font-body); font-size:11px; letter-spacing:.12em;
  color:var(--ink-dim); text-transform:uppercase;
}
.site-socials{ display:flex; align-items:center; gap:12px; padding-top:4px; }
.site-socials a{
  display:inline-flex; align-items:center; justify-content:center; width:44px; height:44px;
  border-radius:50%; border:1px solid var(--line); color:var(--ink-dim);
  transition:color .2s ease, border-color .2s ease, transform .2s ease;
}
.site-socials a svg{ width:21px; height:21px; }
.site-socials a:hover{ color:var(--accent-text); border-color:var(--accent); transform:translateY(-2px); }

/* ---------- HUD side nav: dock-style magnify + proximity label reveal ---------- */
.hud-nav{
  /* Sits just below the logo bar (using the same measured --banner-h as the
     hero's opacity cut) rather than dead-center down the right edge, so it
     reads as a top-corner nav rather than a mid-page HUD element. */
  position:fixed; right:18px; top:calc(var(--banner-h, 110px) + 22px); z-index:65;
  display:flex; flex-direction:column; gap:24px; align-items:flex-end;
}
.hud-node{
  background:none; border:none; cursor:pointer; display:flex; align-items:center; gap:10px;
  justify-content:flex-end; padding:9px 6px; margin:-9px -6px; opacity:.6; transition:opacity .25s;
}
.hud-node:hover, .hud-node.active{ opacity:1; }
.hud-node .hud-label{
  order:1;
  font-family:var(--font-body); font-size:11px; font-weight:600; letter-spacing:.06em; color:var(--ink);
  white-space:nowrap;
  opacity:var(--dock-label-opacity, 0);
  transform:translateX(calc((1 - var(--dock-label-opacity, 0)) * 6px));
  transition:opacity .15s ease, transform .15s ease;
}
/* Current section's label stays readable all the time — a permanent "you are
   here" instead of relying entirely on cursor proximity to ever be seen. */
.hud-node.active .hud-label{ opacity:1; transform:none; }
.hud-node::before{
  order:2; content:""; width:9px; height:9px; border-radius:50%; background:var(--ink-dim); flex-shrink:0;
  transform:scale(var(--dock-scale, 1)); transition:transform .12s ease, background .2s ease, box-shadow .2s ease;
}
.hud-node.active::before{ background:var(--accent); box-shadow:0 0 8px var(--accent); }
@media (max-width:640px){ .hud-nav{ display:none; } }

/* ---------- layout ---------- */
.section{ position:relative; padding:70px 8vw 50px; max-width:1400px; margin:0 auto; }
.chapter-head{ margin-bottom:36px; }
.chapter-title{
  font-family:var(--font-display); font-weight:600; font-size:clamp(2.3rem,5.6vw,4.2rem); line-height:1;
  letter-spacing:-.01em; margin-top:6px;
}
.chapter-sub{ color:var(--ink-dim); margin-top:10px; font-size:1.05rem; }

.badge-award{
  margin-top:26px; display:inline-flex; align-items:center; gap:8px;
  border:1px solid var(--line); padding:8px 14px; border-radius:999px;
  font-size:12px; font-family:var(--font-body); color:var(--gold);
  background:rgba(246,198,103,.08);
}
.badge-icon{ font-size:13px; }
.badge-award--small{ margin-top:14px; font-size:11px; padding:6px 12px; }

/* ============ PROJECTS ============ */
.project-group{ margin-bottom:64px; }
.project-group:last-child{ margin-bottom:0; }
.project-group-title{
  font-family:var(--font-body); font-weight:700; font-size:13px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--accent-text); margin-bottom:20px; padding-bottom:10px; border-bottom:1px solid var(--line);
}
/* ============ LEVEL SELECT (games / film): a list of wide info rows, not a tile grid ============ */
.level-select{ display:flex; flex-direction:column; gap:22px; }
.level-card{
  position:relative; background:var(--panel); border:1px solid var(--line); border-radius:4px;
  overflow:hidden; width:100%; scroll-margin-top:90px;
  transition:border-color .2s ease, box-shadow .2s ease;
}
.level-card:hover:not(.expanded){ border-color:var(--accent); box-shadow:0 12px 30px rgba(0,0,0,.4); }

.level-toggle{
  all:unset; box-sizing:border-box; width:100%; cursor:pointer;
  display:flex; align-items:center;
}
@media (max-width:640px){ .level-toggle{ flex-direction:column; } }
.level-cover{
  position:relative; flex:0 0 320px; width:320px; aspect-ratio:16/9; background:var(--bg-alt); overflow:hidden;
}
@media (max-width:640px){ .level-cover{ flex:none; width:100%; } }
/* Film & Video: an always-looping poster strip (same physics as the brand marquee) —
   closed cards never leave this strip. Opening a card physically moves just that
   one card into .film-expanded-slot below, where it falls back to plain .level-card
   styling (i.e. looks like Games) since these narrow overrides no longer match it. */
.level-select--film{
  overflow:hidden; padding:2px 2px 12px; cursor:grab;
  -webkit-mask-image:linear-gradient(90deg, transparent, black 1.5%, black 98.5%, transparent);
  mask-image:linear-gradient(90deg, transparent, black 1.5%, black 98.5%, transparent);
}
.level-select--film.dragging{ cursor:grabbing; }
.film-track{
  display:flex; flex-direction:row; gap:18px; width:max-content;
  touch-action:pan-y; user-select:none; will-change:transform;
}
.film-track img{ -webkit-user-drag:none; user-select:none; pointer-events:none; }
.level-select--film .level-card{ flex:0 0 260px; width:260px; }
.level-select--film .level-toggle{ flex-direction:column; }
.level-select--film .level-cover{ flex:none; width:100%; aspect-ratio:2/3; }
.level-select--film .level-quick{ padding:14px 16px; gap:7px; }
.level-select--film .level-quick-title{ font-size:1rem; }
.level-select--film .level-quick-fields{ gap:4px; }
.level-select--film .level-quick-fields p{ font-size:.78rem; }

.film-expanded-slot:empty{ display:none; }
/* Layout once a film is open: identical left/videos/soundtrack split to an
   open Games card (see .level-card.expanded further below) — title+meta in
   a left column, screenshots+trailer beside it, soundtrack (when there is
   one) further right, all top-aligned. The whole card is physically
   relocated into this slot rather than expanding in place, so unlike Games
   there's no accordion animation to keep separate for .level-details — the
   jump to this slot is already an instant cut, so .level-info can just show
   immediately too instead of needing its own display toggle. */
/* .level-info now lives outside .level-details (see .level-left above), so
   its visibility isn't covered by the accordion's 0-height collapse anymore
   — needs an explicit hide while still in the marquee, matching Games'
   collapsed default. */
.level-select--film .level-info{ display:none; }
.film-expanded-slot .level-cover{ display:none; }
.film-expanded-slot .level-left{ display:flex; flex-direction:column; }
.film-expanded-slot .level-info{ display:flex; }
.film-expanded-slot .level-card{ padding:16px; }
@media (min-width:900px){
  /* Same full-width breakout as an open Games card (see .level-card.expanded
     further below) — applied to the card itself, not the slot around it, so
     the card's own background/border reaches the true viewport edge and only
     its content is inset. Padding the slot instead left a gap of bare page
     background down the left edge where the card's panel should have been. */
  .film-expanded-slot .level-card{
    width:100vw; margin-left:calc(50% - 50vw); margin-right:calc(50% - 50vw);
    padding-left:max(24px, 4vw); padding-right:max(24px, 4vw);
    display:grid; grid-template-columns: minmax(200px,260px) 1fr; column-gap:28px; align-items:start;
  }
  .film-expanded-slot .level-card > .level-left{ grid-column:1; }
  .film-expanded-slot .level-card > .level-details{ grid-column:2; }
}
.level-cover img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .4s ease;
}
.level-toggle:hover .level-cover img{ transform:scale(1.06); }
.coming-soon-badge{
  position:absolute; bottom:14px; right:-8px; z-index:2;
  font-family:var(--font-display); font-size:1.05rem; letter-spacing:.1em;
  color:#0a0906; background:var(--gold); padding:4px 16px;
  transform:rotate(-8deg); box-shadow:0 3px 10px rgba(0,0,0,.45);
}
.level-cover--empty{ background:linear-gradient(135deg, #1a1c24, #0c0d11); }

.level-quick{
  flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center;
  padding:24px 28px; text-align:left; gap:13px;
}
.level-quick-title{
  font-family:var(--font-body); font-weight:700; font-size:1.3rem; letter-spacing:-.005em; color:var(--ink);
}
.level-quick-fields{ display:flex; flex-direction:column; align-items:flex-start; gap:9px; }
.level-quick-fields p{ font-size:.88rem; color:var(--ink-dim); }
.level-quick-meta{ font-size:.85rem; color:var(--ink-dim); }
.level-quick-hint{
  margin-top:auto; padding-top:6px;
  font-family:var(--font-body); font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-dim);
  display:inline-flex; align-items:center; gap:6px; transition:color .2s ease;
}
.level-quick-arrow{ display:inline-block; transition:transform .3s ease; }
.level-card.expanded .level-quick-arrow{ transform:rotate(180deg); }
.level-toggle:hover .level-quick-hint{ color:var(--accent-text); }
/* Swap the hint's own label to make it obvious the same control closes the
   card again, instead of just flipping the arrow (easy to miss on its own). */
.level-quick-hint-open{ display:none; }
.level-card.expanded .level-quick-hint-closed{ display:none; }
.level-card.expanded .level-quick-hint-open{ display:inline; }

/* accordion reveal, animated via grid-rows so height needs no guessing */
.level-details{
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .4s ease;
}
.level-card.expanded .level-details{ grid-template-rows:1fr; }
.level-details-inner{ overflow:hidden; }
.level-details-inner{
  display:grid; grid-template-columns:1fr; gap:4px 28px; padding:0 20px;
}
.level-card.expanded .level-details-inner{ padding:20px; }
.level-details-inner .photo-roller{ grid-column:1 / -1; margin-bottom:12px; }
@media (min-width:640px){
  /* Direct-child :has() only — Games' own media lives beside the toggle now
     (see .level-left below), not inside here. */
  .level-details-inner:has(> .video-embed, > .music-embed){ grid-template-columns:1fr 1fr; }
}

.level-info{ display:flex; flex-direction:column; align-items:flex-start; gap:8px; padding:0 28px 16px; }
.level-field-label{ font-family:var(--font-body); color:var(--ink); font-weight:600; }
.level-field-sep{ color:var(--ink-dim); margin:0 8px; }
.level-role{ display:inline-flex; align-items:flex-start; gap:6px; color:var(--ink); }
.level-desc{ color:var(--ink-dim); font-size:.92rem; line-height:1.6; margin:6px 0 4px; }

.level-media{ display:flex; flex-direction:column; gap:24px; padding-bottom:16px; }
.level-media-group{ display:flex; flex-direction:column; gap:12px; }
/* Behind-the-scenes clips are vertical (9:16) and would otherwise stack in a
   tall single-file column — lay a group of them out side by side instead. */
.level-media-group:has(.video-embed--vertical){ flex-direction:row; flex-wrap:wrap; }
.level-media-group:has(.video-embed--vertical) .video-embed--vertical{ flex:1 1 200px; max-width:280px; margin:0; }

/* Games: description | screenshots+videos | soundtrack as three parallel
   columns once there's room, instead of one long stacked feed — modeled on
   Mick Gordon's site, which lays out credits, media, and the album embed
   side by side.

   .level-left wraps the toggle (title/role/fields — always visible, open or
   closed) together with .level-info (description+link, hidden until open)
   as ONE grid item, so it and .level-details (screenshots/videos/soundtrack)
   both start at the exact same top. Putting .level-info inside .level-details
   instead — so it could keep animating open with the accordion — was tried
   first, but then it and .level-details were two separately-sized rows, and
   a tall videos column spanning both to reach the toggle's height inflates
   BOTH rows' auto-height (not just the last one), leaving a dead gap before
   the description. Folding description into .level-left avoids that
   entirely; the trade-off is it now pops in with the toggle row's own
   reflow instead of sliding open — only the videos/soundtrack columns still
   animate via the existing accordion on .level-details. */
.level-select:not(.level-select--film):not(.film-expanded-slot) .level-left{ display:flex; flex-direction:column; }
.level-select:not(.level-select--film):not(.film-expanded-slot) .level-card.expanded .level-cover{ display:none; }
.level-select:not(.level-select--film):not(.film-expanded-slot) .level-left .level-info{ display:none; }
.level-select:not(.level-select--film):not(.film-expanded-slot) .level-card.expanded .level-left .level-info{ display:flex; }
.level-videos-col, .level-side-col{ display:flex; flex-direction:column; gap:20px; padding-bottom:16px; min-width:0; }
@media (min-width:900px){
  /* Break the expanded card out of .section's 1400px reading-width column so
     it spreads across the browser window instead of staying boxed in — with
     its own smaller side padding standing in for the section's 8vw gutter,
     not literally edge-to-edge. Standard 100vw/negative-margin breakout;
     safe because body already has overflow-x:hidden for exactly this. */
  .level-select:not(.level-select--film):not(.film-expanded-slot) .level-card.expanded{
    width:100vw; margin-left:calc(50% - 50vw); margin-right:calc(50% - 50vw);
    padding-left:max(24px, 4vw); padding-right:max(24px, 4vw);
    display:grid; grid-template-columns: minmax(200px,260px) 1fr; column-gap:28px; align-items:start;
  }
  .level-select:not(.level-select--film):not(.film-expanded-slot) .level-card.expanded > .level-left{ grid-column:1; }
  .level-select:not(.level-select--film):not(.film-expanded-slot) .level-card.expanded > .level-details{ grid-column:2; }
  /* minmax(0, …) on the flexible tracks, not bare fr units — otherwise the
     photo-roller's track (deliberately width:max-content, and doubled for
     the seamless drag loop) reports its full unrolled width as this column's
     content-based minimum, and blows the grid column out to thousands of px
     instead of sharing the row like every other column. */
  /* .level-side-col is the right-hand column: normally a soundtrack embed,
     but if a game has no soundtrack, drop its next video in here instead —
     keeps the trailer at the same width as every other card rather than
     stretching to fill the row alone. */
  .level-details-inner:has(.level-videos-col):not(:has(.level-side-col)){
    grid-template-columns: minmax(0,1fr);
  }
  .level-details-inner:has(.level-videos-col):has(.level-side-col){
    grid-template-columns: minmax(0,1.3fr) minmax(0,1fr);
  }
  .level-details-inner:has(.level-videos-col){ align-items:start; }
}

.photo-roller{
  overflow:hidden; border-radius:4px;
  -webkit-mask-image:linear-gradient(90deg, transparent, black 6%, black 94%, transparent);
  mask-image:linear-gradient(90deg, transparent, black 6%, black 94%, transparent);
}
/* Games: roller gets relocated to sit directly before the toggle (main photo)
   when expanded — a plain DOM sibling, not inside a gapped grid/flex, so it
   needs its own separation from the toggle below it. */
.level-card > .photo-roller{ margin-bottom:16px; }
.photo-roller-track{
  display:flex; gap:10px; width:max-content; touch-action:pan-y;
  cursor:grab; will-change:transform; user-select:none; -webkit-user-drag:none;
}
.photo-roller.dragging .photo-roller-track{ cursor:grabbing; }
.photo-roller-track img{
  height:140px; width:auto; max-width:240px; object-fit:cover; border-radius:4px; flex:none;
  -webkit-user-drag:none; user-select:none; pointer-events:none; display:block;
}
.video-embed{
  position:relative; width:100%; aspect-ratio:16/9; border-radius:4px; overflow:hidden; background:#000;
}
.video-embed iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; }
/* YouTube Shorts / BTS clips are vertical, not 16:9 — keep them from being squeezed */
.video-embed--vertical{ aspect-ratio:9/16; max-width:320px; margin:0 auto; }

.music-embed{ width:100%; border-radius:4px; overflow:hidden; }
.music-embed iframe{ width:100%; height:152px; display:block; border:0; }
.music-embed--album iframe{ height:480px; }
.level-side-col .music-embed--album iframe{ height:560px; }

.level-link{
  font-family:var(--font-body); font-size:12px; color:var(--gold); border-bottom:1px solid transparent;
}
.level-link:hover{ border-color:var(--gold); }

/* ============ SKILL TREE (closed/open accordion cards) ============
   Closed: four cards share the row via flex-basis, same as a 4-col grid.
   Opening one sets flex-basis:100% on just that card, which — with no JS
   reflow needed — pushes the rest down onto a row of their own beneath it.
   Nothing is ever hidden or covered; the other three are just displaced
   downward for as long as one card stays open. The open card splits into a
   teaser column on the left and the full text on the right. The text
   reveal reuses the same grid-template-rows:0fr→1fr trick as the
   Games/Film level-details accordion so its height never needs guessing. */
.skill-tree{ display:flex; flex-wrap:wrap; gap:20px; }
.skill-card{
  flex:0 1 calc(25% - 15px); min-width:230px; position:relative;
  background:var(--panel); border:1px solid var(--line); border-radius:4px;
  overflow:hidden; scroll-margin-top:90px;
  transition:border-color .2s ease, box-shadow .2s ease;
}
.skill-card:hover:not(.expanded){ border-color:var(--accent); box-shadow:0 12px 30px rgba(0,0,0,.4); }
@media (max-width:1000px){ .skill-card{ flex-basis:calc(50% - 10px); } }
@media (max-width:560px){ .skill-card{ flex-basis:100%; } }

/* Muted looping screen-capture footage, sat behind everything else in the
   card. Blurred + desaturated on the video itself (not backdrop-filter —
   better support, and it needs to affect the video regardless of what's
   layered on top) plus a solid scrim so text stays legible over any frame,
   bright or dark. Lazy-loaded: stays srcless until skillBgVideos() in
   main.js sees the section scroll into view. */
.skill-bg-video{
  position:absolute; inset:0; z-index:0; width:100%; height:100%; object-fit:cover;
  transform:scale(1.4); transform-origin:center;
  filter:blur(1.5px) saturate(.9) brightness(.95); opacity:0; transition:opacity .6s ease;
}
.skill-bg-video.is-active{ opacity:1; }
.skill-card::before{
  content:""; position:absolute; inset:0; z-index:1; background:rgba(30,30,40,.55); pointer-events:none;
}
.skill-card > .skill-toggle, .skill-card > .skill-details{ position:relative; z-index:2; }

.skill-toggle{ all:unset; box-sizing:border-box; display:flex; width:100%; height:100%; cursor:pointer; }
.skill-quick{ flex:1; display:flex; flex-direction:column; align-items:center; text-align:center; gap:10px; padding:28px 24px; }
/* Reserves 2 lines' worth of height even for one-line titles (e.g. "Music"),
   so every card's teaser starts at the same y regardless of title length. */
.skill-quick-title{ font-size:1.4rem; line-height:1.15; min-height:2.3em; text-shadow:0 1px 4px rgba(0,0,0,.7); }
.skill-teaser{ color:#d6d4de; font-size:.92rem; line-height:1.6; text-shadow:0 1px 4px rgba(0,0,0,.7); }
.skill-quick-hint{
  margin-top:auto; font-family:var(--font-body); font-size:11px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-dim); display:inline-flex; align-items:center; gap:6px; transition:color .2s ease;
}
.skill-quick-arrow{ display:inline-block; transition:transform .3s ease; }
.skill-card.expanded .skill-quick-arrow{ transform:rotate(180deg); }
.skill-toggle:hover .skill-quick-hint{ color:var(--accent-text); }
.skill-quick-hint-open{ display:none; }
.skill-card.expanded .skill-quick-hint-closed{ display:none; }
.skill-card.expanded .skill-quick-hint-open{ display:inline; }

.skill-details{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .4s ease; }
.skill-card.expanded .skill-details{ grid-template-rows:1fr; }
.skill-details-inner{ overflow:hidden; padding:0 24px; }
.skill-card.expanded .skill-details-inner{ padding:0 24px 24px; }
.skill-details-inner p{ color:#d6d4de; font-size:.92rem; line-height:1.6; text-shadow:0 1px 4px rgba(0,0,0,.7); }

/* order:-1 forces whichever card is opened to the front of the flex flow —
   otherwise flex-wrap packs greedily in DOM order and any closed card that
   comes before the one you opened gets stranded alone on its own line
   instead of packing with the other closed cards, making the layout look
   different depending on which of the four you clicked. */
.skill-card.expanded{ flex-basis:100%; order:-1; }
@media (min-width:640px){
  .skill-card.expanded{
    display:grid; grid-template-columns:minmax(200px,260px) 1fr;
    column-gap:28px; align-items:start;
  }
  .skill-card.expanded .skill-toggle{ grid-column:1; }
  .skill-card.expanded .skill-quick{ align-items:flex-start; text-align:left; }
  .skill-card.expanded .skill-details{ grid-column:2; }
  .skill-card.expanded .skill-details-inner{ padding:24px 24px 24px 0; }
}

/* ============ SOUND REDESIGN (simple video-presentation cards) ============ */
.redesign-grid{ display:grid; grid-template-columns:repeat(3, 1fr); gap:22px; }
@media (max-width:900px){ .redesign-grid{ grid-template-columns:repeat(2, 1fr); } }
@media (max-width:600px){ .redesign-grid{ grid-template-columns:1fr; } }
.redesign-grid--single{ grid-template-columns:1fr; width:100%; max-width:900px; margin:0 auto; }
.redesign-grid--duo{ grid-template-columns:repeat(2, 1fr); width:100%; max-width:1120px; margin:0 auto; position:relative; }
@media (max-width:600px){ .redesign-grid--duo{ grid-template-columns:1fr; } }

/* Showreel side labels: pop up beside each video on hover, on the outward side
   (left label to the left of the left video, right label to the right of the
   right video). Needs room in the gutter, so only shown once the layout has
   space for it. Each spans the video's full height (top:0/bottom:0, matching
   the grid row) with its text centered inside via flex, so the shimmer glow
   behind it — anchored to the edge nearest its video — lines up with the
   video's height instead of just the text line. */
.showreel-hint{
  position:absolute; top:0; bottom:0; width:180px;
  align-items:center;
  font-family:var(--font-body); font-size:1.05rem; letter-spacing:.01em;
  color:var(--ink); line-height:1.4; opacity:0; pointer-events:none;
  text-shadow:0 1px 4px rgba(0,0,0,.7);
  transition:opacity .25s ease, transform .25s ease;
  display:none;
}
.showreel-hint--music{ right:calc(100% + 26px); justify-content:flex-end; text-align:right; transform:translateX(10px); }
.showreel-hint--sound{ left:calc(100% + 26px); justify-content:flex-start; text-align:left; transform:translateX(-10px); }
.redesign-grid--duo:has(.redesign-card--music:hover) .showreel-hint--music,
.redesign-grid--duo:has(.redesign-card--sound:hover) .showreel-hint--sound{
  opacity:1; transform:translateX(0);
}
.showreel-hint::before{
  content:""; position:absolute; top:0; bottom:0; z-index:-2; width:280px;
  filter:blur(30px);
}
.showreel-hint--music::before{ right:-10px; background:linear-gradient(to left, rgba(111,163,224,.55), transparent 75%); }
.showreel-hint--sound::before{ left:-10px; background:linear-gradient(to right, rgba(111,163,224,.55), transparent 75%); }
.showreel-hint-label{ position:relative; z-index:1; }
/* A soft, blurred, mirrored reflection of the video's own thumbnail — sits
   between the color glow and the text, fading out away from the video edge
   it's mirrored off of. */
.showreel-hint-reflection{
  /* height:75% + top:12.5% (not top:0/bottom:0) — as a replaced element, an
     <img> doesn't stretch to fill absolute top+bottom offsets the way a normal
     box does, so without an explicit height it was rendering at its own
     thumbnail aspect ratio (about half the video's height) pinned to the top. */
  position:absolute; top:12.5%; height:75%; z-index:-1; width:280px;
  object-fit:cover; pointer-events:none;
  filter:blur(4px) saturate(1.15); opacity:.5;
}
.showreel-hint--music .showreel-hint-reflection{
  right:-10px; transform:scaleX(-1);
  -webkit-mask-image:linear-gradient(to left, black, transparent 80%);
  mask-image:linear-gradient(to left, black, transparent 80%);
}
.showreel-hint--sound .showreel-hint-reflection{
  left:-10px; transform:scaleX(-1);
  -webkit-mask-image:linear-gradient(to right, black, transparent 80%);
  mask-image:linear-gradient(to right, black, transparent 80%);
}
@media (min-width:1100px){ .showreel-hint{ display:flex; } }
.redesign-card{
  display:flex; flex-direction:column;
  border-radius:4px; overflow:hidden; background:var(--panel); border:1px solid var(--line);
  transition:border-color .2s ease, box-shadow .2s ease;
}
.redesign-card:hover{ border-color:var(--accent); box-shadow:0 12px 30px rgba(0,0,0,.4); }
.redesign-thumb{ position:relative; width:100%; aspect-ratio:16/9; overflow:hidden; cursor:pointer; }
.redesign-thumb img{ width:100%; height:100%; object-fit:cover; display:block; transition:transform .4s ease; }
.redesign-card:hover .redesign-thumb img{ transform:scale(1.06); }
.redesign-play{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  background:rgba(8,9,12,.3); transition:background .2s ease;
}
/* Showreel thumbnails specifically: no dark scrim, shown at full original
   brightness — the play button's own backdrop-blur + border stays legible
   without needing the whole thumbnail dimmed underneath it. */
.redesign-grid--duo .redesign-play{ background:transparent; }
.redesign-play span{
  width:56px; height:56px; border-radius:50%; border:1px solid rgba(255,255,255,.5);
  display:flex; align-items:center; justify-content:center; color:#fff; font-size:18px;
  backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
  transition:border-color .2s ease, color .2s ease;
}
.redesign-card:hover .redesign-play span{ border-color:var(--accent); color:var(--accent-text); }
.redesign-video{ position:relative; width:100%; aspect-ratio:16/9; background:#000; transition:aspect-ratio .35s ease, width .35s ease; }
.redesign-video iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; }
.redesign-close{
  position:absolute; top:10px; right:10px; z-index:2;
  width:32px; height:32px; padding:0; border-radius:50%;
  background:rgba(8,9,12,.65); border:1px solid rgba(255,255,255,.4); color:#fff;
  font-size:20px; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition:border-color .2s ease, color .2s ease, background .2s ease;
}
.redesign-close:hover{ border-color:var(--accent); color:var(--accent-text); background:rgba(8,9,12,.85); }

.redesign-grid--list{ grid-template-columns:1fr; gap:18px; }
.redesign-grid--list .redesign-card{ flex-direction:row; }
.redesign-grid--list .redesign-thumb{ width:320px; flex:0 0 320px; }
.redesign-grid--list .redesign-video{ width:320px; flex:0 0 320px; }
.redesign-grid--list .redesign-info{
  display:flex; flex-direction:column; justify-content:center; gap:8px; padding:18px 24px;
}
.redesign-grid--list .redesign-card.is-playing .redesign-video{
  width:520px; flex:0 0 520px; aspect-ratio:16/9;
}
.redesign-grid--list .redesign-title{ font-family:var(--font-body); font-weight:700; font-size:1.05rem; color:var(--ink); margin:0; }
.redesign-grid--list .redesign-desc{ color:var(--ink-dim); font-size:.92rem; line-height:1.6; margin:0; }
@media (max-width:700px){
  .redesign-grid--list .redesign-card{ flex-direction:column; }
  .redesign-grid--list .redesign-thumb,
  .redesign-grid--list .redesign-video{ width:100%; flex:none; }
}

/* ============ BRAND MARQUEE (worked with) ============ */
.brand-marquee{
  overflow:hidden; border-top:1px solid var(--line); border-bottom:1px solid var(--line); padding:14px 0;
  -webkit-mask-image:linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
  mask-image:linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
}
.brand-track{
  display:flex; gap:14px; width:max-content; touch-action:pan-y;
  cursor:grab; will-change:transform; user-select:none; -webkit-user-drag:none;
}
.brand-marquee.dragging .brand-track{ cursor:grabbing; }
.brand-track img{ -webkit-user-drag:none; user-select:none; pointer-events:none; }
.brand-card{ display:flex; flex-direction:column; align-items:center; gap:8px; flex:none; width:140px; }
.brand-logo{
  flex:none; width:68px; height:68px;
  display:flex; align-items:center; justify-content:center; overflow:hidden;
}
.brand-logo img{ max-width:100%; max-height:100%; object-fit:contain; }
.brand-logo--empty{ position:relative; }
.brand-logo--empty img{ display:none; }
.brand-logo--empty::after{
  content:attr(data-brand); font-family:var(--font-body); font-size:9px; letter-spacing:.05em;
  color:var(--ink-dim); text-align:center; text-transform:uppercase; padding:0 6px;
}
.brand-name{
  text-align:center; font-size:.75rem; color:var(--ink-dim); font-weight:500; line-height:1.4;
}

/* ============ multi-link rows on cards ============ */
.link-row{ display:flex; gap:18px; flex-wrap:wrap; margin-top:12px; }
.link-row .level-link{ margin-top:0; }

/* ============ HOME: PUNCH LINE + SHOWREEL ============ */
.home-punch{ position:relative; z-index:1; max-width:1400px; margin:0 auto; padding:8px 8vw 0; }
.home-punch-title{
  font-family:var(--font-display); font-weight:600; font-size:clamp(2.2rem,5.4vw,3.8rem);
  letter-spacing:-.01em; line-height:1; color:var(--ink);
}
.home-punch-sub{
  font-family:var(--font-body); color:#d6d4de; font-size:1.05rem;
  margin-top:14px; letter-spacing:.01em; text-shadow:0 1px 4px rgba(0,0,0,.7);
}
.home-showreel{ position:relative; z-index:1; max-width:1400px; margin:0 auto; padding:64px 8vw 0; }

/* ============ ABOUT: portrait fixed on the left, all text in one column on
   the right, and the text itself splits into two columns rather than
   one long one. ============ */
#about{ padding-top:110px; }
.about-row{ display:grid; grid-template-columns:260px 1fr; gap:48px; align-items:start; }
@media (max-width:700px){ .about-row{ grid-template-columns:1fr; } }
.about-photo{
  width:100%; aspect-ratio:3/4; border:1px solid var(--accent); border-radius:4px; overflow:hidden;
  background:radial-gradient(circle at 30% 20%, rgba(255,122,82,.15), transparent 60%);
}
.about-photo img{ width:100%; height:100%; object-fit:cover; display:block; }
/* Two collapse mechanisms working together: grid-template-columns handles
   the second column's width on desktop (0fr closed, 1fr open), and
   grid-template-rows on .about-col--extra handles its height (needed for
   when the layout stacks to one column on narrow screens, where the width
   trick alone wouldn't hide anything). Both driven by the same .expanded
   class from the "Read more" toggle. */
.about-text{
  padding-top:4px; display:grid; grid-template-columns:1fr 0fr; gap:0;
  transition:grid-template-columns .4s ease, gap .4s ease;
}
.about-text.expanded{ grid-template-columns:1fr 1fr; gap:0 40px; }
@media (max-width:560px){
  .about-text, .about-text.expanded{ grid-template-columns:1fr; gap:0; }
}
.about-col p{ color:#d6d4de; line-height:1.75; font-size:1.05rem; text-shadow:0 1px 4px rgba(0,0,0,.7); }
.about-col p + p{ margin-top:16px; }
.about-col--extra{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .4s ease; min-width:0; }
.about-text.expanded .about-col--extra{ grid-template-rows:1fr; }
.about-col--extra-inner{ overflow:hidden; }
.about-more-toggle{
  margin-top:18px; font-family:var(--font-body); font-weight:600; font-size:13px; letter-spacing:.02em;
  color:var(--accent-text); background:none; border:none; cursor:pointer;
  display:inline-flex; align-items:center; gap:6px;
}
.about-more-toggle span{ transition:transform .3s ease; display:inline-block; }
.about-more-toggle:hover{ color:var(--gold); }
.about-text.expanded .about-more-toggle span{ transform:rotate(180deg); }

/* ============ CONTACT ============ */
.contact-layout{ display:grid; grid-template-columns:1fr 1.15fr; gap:48px; align-items:center; }
@media (max-width:900px){ .contact-layout{ grid-template-columns:1fr; } }
.contact-layout--no-photo{ grid-template-columns:1fr; max-width:720px; margin:0 auto; text-align:center; }
.contact-layout--no-photo .contact-main{ text-align:center; }
.contact-layout--no-photo .contact-chips{ justify-content:center; }
.contact-layout--no-photo .contact-socials{ justify-content:center; }
.contact-photo{
  width:100%; aspect-ratio:3/2; border:1px solid var(--accent); border-radius:4px;
  overflow:hidden; background:radial-gradient(circle at 30% 20%, rgba(255,122,82,.15), transparent 60%);
}
.contact-photo img{ width:100%; height:100%; object-fit:cover; display:block; }
.contact-main{ text-align:left; }
.contact-eyebrow{
  font-family:var(--font-body); font-size:12px; font-weight:700; letter-spacing:.18em;
  text-transform:uppercase; color:var(--accent-blue); margin-bottom:14px;
}
.contact-cta{
  position:relative; z-index:1;
  font-family:var(--font-display); font-weight:600; font-size:clamp(2.8rem,6.5vw,4.7rem); line-height:.95; letter-spacing:-.01em;
}
/* Fixed (non-animated) glow sat behind the CTA line, light-blue toned. Sized
   and saturated well past "subtle" so it reads clearly even against the
   busy hero photo/scrim behind the section. */
.contact-cta::before{
  content:""; position:absolute; z-index:-1; inset:-55% -35%;
  background:radial-gradient(ellipse at center, rgba(111,163,224,.65), rgba(184,212,245,.4) 40%, transparent 70%);
  filter:blur(55px); pointer-events:none;
}
.contact-chips{ display:flex; gap:14px; flex-wrap:wrap; margin-top:30px; }
.chip{
  border:1px solid var(--line); background:var(--bg-alt); padding:13px 22px; border-radius:999px;
  font-family:var(--font-body); font-weight:600; font-size:13.5px;
  transition:border-color .2s ease, color .2s ease, transform .2s ease;
}
.chip:hover{ border-color:var(--accent); color:var(--accent-text); transform:translateY(-2px); }
.contact-socials{ margin-top:26px; padding-top:22px; border-top:1px solid var(--line); }

/* ============ FOOTER ============ */
.site-footer{
  text-align:center; padding:60px 8vw 90px; color:var(--ink-dim); font-family:var(--font-body); font-size:12px;
}

/* ---------- reveal on scroll ---------- */
.chapter{ opacity:0; transform:translateY(30px); transition:opacity .7s ease, transform .7s ease; }
.chapter.in-view{ opacity:1; transform:translateY(0); }
