@import url("tokens.css");

/* ===========================================================================
   Veronika Novikova — portfolio
   Site-local styles. Tokens come from tokens.css (design system).
   =========================================================================== */

:root {
  /* chosen digital accent — acid lime (tweakable) */
  --vn-accent: var(--accent-acid);
  --vn-accent-soft: var(--accent-acid-soft);
  --hero-scale: 1;           /* driven by type-play tweak */
  --rail-h: 60px;
}

* { box-sizing: border-box; }
html { scroll-behavior: auto; }
html, body {
  margin: 0; padding: 0;
  background: var(--paper);
  color: var(--ink);
}
body { -webkit-font-smoothing: antialiased; }
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

/* ───────────────────────── chrome: top rail ───────────────────────── */
.top-rail {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  height: var(--rail-h);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 22px;
  pointer-events: none;
}
.top-rail > * { pointer-events: auto; }
/* glassmorphism panel — fades in with the wordmark so it stays legible over dark sections */
.top-rail::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: rgba(241,236,227,0.6);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow: inset 0 -1px 0 var(--rule);
  opacity: 0; transition: opacity var(--dur-slow) var(--ease-out);
}
.top-rail.show::before { opacity: 1; }

/* burger */
.burger {
  all: unset; cursor: pointer; pointer-events: auto;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink);
  background: rgba(241,236,227,0.66);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  box-shadow: inset 0 0 0 1px var(--rule);
  padding: 13px; border-radius: var(--radius-pill);
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.burger .bars { display: inline-flex; flex-direction: column; gap: 4px; width: 18px; }
.burger .bars i { display: block; height: 2px; width: 18px; background: currentColor; transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-fast); }
.burger:hover { background: var(--ink); color: var(--paper); }

/* brand wordmark center */
.wordmark {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
  font-family: var(--font-display); font-style: italic; font-size: 19px;
  letter-spacing: -0.01em; color: var(--ink);
  cursor: pointer; opacity: 0; transition: opacity var(--dur-slow) var(--ease-out);
  white-space: nowrap;
}
.wordmark.show { opacity: 1; }

/* contacts trigger + dropdown */
.contacts { position: relative; }
.contacts-btn {
  all: unset; cursor: pointer;
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink);
  background: rgba(241,236,227,0.66);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  box-shadow: inset 0 0 0 1px var(--rule);
  padding: 10px 16px 10px 22px; border-radius: var(--radius-pill);
  position: relative; isolation: isolate;
  transition: color var(--dur-base) var(--ease-out);
}
.contacts-btn::before {
  content: ""; position: absolute; inset: 0; z-index: 0; border-radius: inherit;
  background: var(--ink);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 480ms var(--ease-cinematic);
}
.contacts:hover .contacts-btn::before, .contacts.open .contacts-btn::before { transform: scaleX(1); transform-origin: right center; }
.contacts-btn > * { position: relative; z-index: 1; }
.contacts-btn .dot { width: 6px; height: 6px; border-radius: 999px; background: var(--signal); box-shadow: 0 0 0 3px rgba(217,66,26,.16); }
.contacts:hover .contacts-btn, .contacts.open .contacts-btn { color: var(--paper); }
.contacts:hover .contacts-btn .dot, .contacts.open .contacts-btn .dot { background: var(--success); box-shadow: 0 0 0 3px color-mix(in oklch, var(--success) 34%, transparent); }

.contacts-menu {
  position: absolute; top: calc(100% + 10px); right: 0;
  display: flex; flex-direction: column; gap: 2px; min-width: 230px;
  background: var(--surface-card);
  box-shadow: var(--shadow-lift), inset 0 0 0 1px var(--rule);
  border-radius: var(--radius-md); padding: 8px;
  opacity: 0; transform: translateY(-8px) scale(0.98); transform-origin: top right;
  pointer-events: none; transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-cinematic);
}
.contacts:hover .contacts-menu, .contacts.open .contacts-menu { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }
/* invisible bridge across the gap so the hover doesn't drop while moving to the menu */
.contacts-menu::before { content: ""; position: absolute; left: 0; right: 0; top: -14px; height: 14px; }
.contacts-menu a {
  display: flex; align-items: center; gap: 13px;
  padding: 11px 12px; border-radius: var(--radius-sm);
  font-family: var(--font-sans); font-size: 14px; font-weight: 500; color: var(--ink);
  transition: background var(--dur-fast) var(--ease-out);
}
.contacts-menu a:hover { background: var(--paper-deep); }
.contacts-menu a .ico { width: 20px; height: 20px; flex: none; color: var(--ink-2); }
.contacts-menu a .sub { margin-left: auto; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }

/* ───────────────────────── menu drawer ───────────────────────── */
.scrim {
  position: fixed; inset: 0; z-index: 70; background: rgba(11,9,7,0.32);
  backdrop-filter: blur(2px); opacity: 0; pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out);
}
.scrim.open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 80; width: min(440px, 86vw);
  background: var(--paper-soft);
  box-shadow: var(--shadow-lift);
  transform: translateX(-102%); transition: transform var(--dur-slow) var(--ease-cinematic);
  display: flex; flex-direction: column; padding: 26px 30px 34px;
  overflow-y: auto;
}
.drawer.open { transform: translateX(0); }
.drawer .d-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 40px; }
.drawer .d-head .mark { font-family: var(--font-display); font-style: italic; font-size: 22px; }
.drawer .close { all: unset; cursor: pointer; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-3); }
.drawer .close:hover { color: var(--ink); }
.drawer .d-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 14px; }
.drawer nav { display: flex; flex-direction: column; }
.drawer nav a {
  display: flex; align-items: baseline; gap: 16px; padding: 12px 0;
  border-bottom: 1px solid var(--rule-soft);
  font-family: var(--font-display); font-size: clamp(28px, 5vw, 40px); line-height: 1;
  color: var(--ink); transition: color var(--dur-fast), padding-left var(--dur-base) var(--ease-out);
}
.drawer nav a .n { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; color: var(--ink-3); width: 30px; flex: none; }
.drawer nav a:hover { padding-left: 10px; }
.drawer nav a:hover .n { color: var(--vn-accent); }
.drawer .d-foot { margin-top: auto; padding-top: 30px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.05em; color: var(--ink-3); line-height: 1.7; }

/* ───────────────────────── cinema pin ───────────────────────── */
.cinema { position: relative; height: 380vh; }
.cinema-sticky { position: sticky; top: 0; height: 100vh; overflow: hidden; background: var(--paper); isolation: isolate; z-index: 1; }
/* same faint turbulent grid as the work area, riding over the hero gradient (under the text) */
.cinema-sticky::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(21,17,13,0.06) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(21,17,13,0.06) 1px, transparent 1px);
  background-size: 18px 18px;
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='560' height='560'><filter id='t' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.018' numOctaves='3' seed='7' stitchTiles='stitch'/><feComponentTransfer><feFuncA type='gamma' amplitude='1' exponent='1.7' offset='0'/></feComponentTransfer></filter><rect width='560' height='560' filter='url(%23t)'/></svg>");
          mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='560' height='560'><filter id='t' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.018' numOctaves='3' seed='7' stitchTiles='stitch'/><feComponentTransfer><feFuncA type='gamma' amplitude='1' exponent='1.7' offset='0'/></feComponentTransfer></filter><rect width='560' height='560' filter='url(%23t)'/></svg>");
  -webkit-mask-size: 560px 560px; mask-size: 560px 560px;
  -webkit-mask-repeat: repeat; mask-repeat: repeat;
  /* noise animation removed for perf — static mask */
}

/* shuffle the turbulence holes across the grid so the noise feels alive */
@keyframes gridNoise {
  0%   { -webkit-mask-position: 0 0;          mask-position: 0 0; }
  20%  { -webkit-mask-position: -224px 112px; mask-position: -224px 112px; }
  40%  { -webkit-mask-position: 168px -196px; mask-position: 168px -196px; }
  60%  { -webkit-mask-position: -112px -84px; mask-position: -112px -84px; }
  80%  { -webkit-mask-position: 252px 196px;  mask-position: 252px 196px; }
  100% { -webkit-mask-position: 0 0;          mask-position: 0 0; }
}

/* hero background — clean mesh gradient: large luminous colour fields that blend
   through the light paper base (NOT multiply → no muddy overlaps). Warm left,
   cool right, like the reference loop. */
.hero-bg { position: absolute; inset: 0; overflow: hidden; background: var(--paper); }
.hero-liquid { position: absolute; inset: -16%; filter: blur(2px) saturate(120%); }
.mesh {
  position: absolute; width: 66%; height: 76%; border-radius: 50%;
  filter: blur(58px); mix-blend-mode: normal; opacity: 0.5; will-change: transform;
}
/* warm cluster on the left, cool on the right — soft-edged so they cross-fade
   through paper and stay clean; gentle continuous drift, no reversing */
.mesh.m1 { left: -8%;  bottom: -14%; background: radial-gradient(circle at 50% 50%, var(--accent-magenta), color-mix(in oklch, var(--accent-magenta) 30%, transparent) 40%, transparent 66%); animation: mesh1 20s linear infinite; }
.mesh.m2 { left: -4%;  top: 12%;     background: radial-gradient(circle at 50% 50%, var(--signal),        color-mix(in oklch, var(--signal) 28%, transparent) 40%, transparent 66%);        animation: mesh2 23s linear infinite; }
.mesh.m3 { left: 22%;  top: -16%;    background: radial-gradient(circle at 50% 50%, var(--accent-amber),   color-mix(in oklch, var(--accent-amber) 26%, transparent) 42%, transparent 66%);   animation: mesh3 26s linear infinite; }
.mesh.m4 { right: -10%; top: 2%;     background: radial-gradient(circle at 50% 50%, var(--accent-cyan),    color-mix(in oklch, var(--accent-cyan) 28%, transparent) 42%, transparent 66%);    animation: mesh4 21s linear infinite; }
.mesh.m5 { right: -6%; bottom: -10%; background: radial-gradient(circle at 50% 50%, var(--accent-electric),color-mix(in oklch, var(--accent-electric) 24%, transparent) 40%, transparent 64%); animation: mesh5 24s linear infinite; }
@keyframes mesh1 {
  0%   { transform: translate(0%,0%)     scale(1);    }
  33%  { transform: translate(16%,-12%)  scale(1.22); }
  66%  { transform: translate(-11%,9%)   scale(1.06); }
  100% { transform: translate(0%,0%)     scale(1);    }
}
@keyframes mesh2 {
  0%   { transform: translate(0%,0%)     scale(1.1);  }
  33%  { transform: translate(-13%,16%)  scale(1);    }
  66%  { transform: translate(13%,7%)    scale(1.22); }
  100% { transform: translate(0%,0%)     scale(1.1);  }
}
@keyframes mesh3 {
  0%   { transform: translate(0%,0%)     scale(1);    }
  33%  { transform: translate(19%,14%)   scale(1.2);  }
  66%  { transform: translate(6%,-11%)   scale(1.04); }
  100% { transform: translate(0%,0%)     scale(1);    }
}
@keyframes mesh4 {
  0%   { transform: translate(0%,0%)     scale(1.18); }
  33%  { transform: translate(-17%,10%)  scale(1);    }
  66%  { transform: translate(-6%,-14%)  scale(1.22); }
  100% { transform: translate(0%,0%)     scale(1.18); }
}
@keyframes mesh5 {
  0%   { transform: translate(0%,0%)     scale(1);    }
  33%  { transform: translate(-14%,-12%) scale(1.22); }
  66%  { transform: translate(10%,8%)    scale(1.05); }
  100% { transform: translate(0%,0%)     scale(1);    }
}
/* faint film grain over the mesh */
.hero-grain {
  position: absolute; inset: 0; pointer-events: none; opacity: 0.22;
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='180' height='180' filter='url(%23g)'/></svg>");
  background-size: 180px 180px;
}
/* paper veil — keeps the left lighter so the ink headline stays readable */
.hero-veil { position: absolute; inset: 0; background:
    linear-gradient(100deg, rgba(241,236,227,0.82) 0%, rgba(241,236,227,0.56) 32%, rgba(241,236,227,0.30) 58%, rgba(241,236,227,0.14) 84%, rgba(241,236,227,0.08) 100%); }

/* glassmorphic cursor lens — page-wide fixed grid of frosted tiles riding above content */
.lens-grid { position: fixed; inset: 0; z-index: 45; pointer-events: none; }
.lens-tile {
  position: absolute; box-sizing: border-box; border-radius: 5px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.34);
  -webkit-backdrop-filter: blur(5px) saturate(140%);
  backdrop-filter: blur(5px) saturate(140%);
  /* outer ink ring defines the tile on light/cream sections; inner light highlight on dark */
  box-shadow: 0 2px 9px rgba(11,9,7,0.13), 0 0 0 1px rgba(11,9,7,0.06), inset 0 1px 0 rgba(255,255,255,0.6), inset 0 -1px 0 rgba(255,255,255,0.18);
  opacity: 0; transition: opacity 600ms var(--ease-out); will-change: opacity;
}

/* hero content */
.hero-content {
  position: absolute; inset: 0; z-index: 20;
  display: flex; flex-direction: column; justify-content: center;
  padding: 0 clamp(22px, 6vw, 96px);
  will-change: opacity, transform;
}
.hero-top { display: flex; flex-direction: column; }
.hero-sub {
  display: none; align-items: center; justify-content: center; gap: 16px;
  margin-top: clamp(18px, 2.6vh, 30px);
  font-family: var(--font-sans); font-weight: 400; font-size: clamp(14px, 1.4vw, 18px);
  color: var(--ink-2); text-align: center;
}
.hero-sub .fl { width: 38px; height: 11px; color: var(--signal); flex: none; }
.hero-cta { display: none; }
.hero-lower { display: none; }
.hero-lower .hl-text { font-family: var(--font-display); font-size: clamp(22px, 2.5vw, 36px); line-height: 1.12; letter-spacing: -0.01em; color: var(--ink); margin: 0 0 18px; max-width: 22ch; }
.hero-lower .hl-text em { font-style: italic; }
.hero-lower .hl-link { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); padding: 11px 18px; border-radius: var(--radius-pill); cursor: pointer; transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out); }
.hero-lower .hl-link:hover { background: var(--ink); color: var(--paper); }
.hero-lower .hl-link .arr { transition: transform var(--dur-base) var(--ease-out); }
.hero-lower .hl-link:hover .arr { transform: translate(2px,2px); }
.hero-eyebrow { display: flex; align-items: center; gap: 12px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-3); margin-bottom: clamp(14px, 2vh, 26px); }
.hero-eyebrow .rec { display: inline-flex; align-items: center; gap: 7px; color: var(--ink); }
.hero-eyebrow .rec b { width: 7px; height: 7px; border-radius: 999px; background: var(--signal); box-shadow: 0 0 0 4px rgba(217,66,26,.14); animation: rec 1.6s ease-in-out infinite; }
@keyframes rec { 50% { opacity: 0.25; } }

.hero-name {
  font-family: var(--font-display); font-weight: 400; color: var(--ink);
  font-size: calc(clamp(58px, 13.5vw, 230px) * var(--hero-scale));
  line-height: 0.84; letter-spacing: -0.03em; margin: 0;
}
.hero-name .line { display: block; width: max-content; max-width: 100%; }
.hero-name .ital { font-style: italic; }
.hero-role {
  font-family: var(--font-display); font-style: italic; font-weight: 400;
  font-size: calc(clamp(26px, 5vw, 72px) * var(--hero-scale));
  line-height: 1; color: var(--ink); margin: clamp(14px,2.4vh,30px) 0 0;
}
.hero-role .accent { font-style: normal; position: relative; }
.hero-role .accent::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0.08em; height: 0.30em; background: var(--vn-accent); z-index: -1; opacity: 0.9; transition: transform 320ms var(--ease-out), height 320ms var(--ease-out); }
.hero-role .accent:hover::after { transform: translateY(-0.22em); }
.hero-intro {
  margin-top: clamp(20px, 3vh, 36px); max-width: 40ch;
  font-family: var(--font-sans); font-weight: 400; font-size: clamp(15px, 1.5vw, 19px);
  line-height: 1.55; color: var(--ink-2);
}
/* ── griflan-style hero intro: characters flicker in from transparency while the
      headline sits centered, then it settles into its left-aligned resting spot ── */
@keyframes heroRise { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
@keyframes charFlick { 0% { opacity: 0; } 38% { opacity: 0.9; } 52% { opacity: 0.16; } 100% { opacity: 1; } }

/* a single split character */
.flick { display: inline-block; opacity: 0; will-change: opacity; }

/* lines stay hidden until JS arms the intro (avoids a flash of un-split text) */
.hero-name .line { opacity: 0; transform: translateX(0); will-change: transform; }
.hero-intro-ready .hero-name .line { opacity: 1; }
/* centered start → settle home */
.hero-name.intro-centered .line { transform: translateX(var(--tx, 0)); }
.hero-name.intro-centered.settling .line { transform: translateX(0); transition: transform 980ms var(--ease-cinematic), letter-spacing 520ms var(--ease-cinematic); }
.hero-name.intro-centered.settling .line.ital { transition-delay: 50ms; transition-duration: 930ms; }

/* hover a word → its letters spread apart (each line is independent) */
.hero-settled .hero-name .line:hover { letter-spacing: 0.08em; }

/* role + intro fade up once the headline has settled */
.hero-role, .hero-intro { opacity: 0; transform: translateY(16px); transition: opacity 760ms var(--ease-cinematic), transform 760ms var(--ease-cinematic); }
.hero-settled .hero-role { opacity: 1; transform: translateY(0); transition-delay: 60ms; }
.hero-settled .hero-intro { opacity: 1; transform: translateY(0); transition-delay: 200ms; }

/* hover highlighter — a lime marker sweeps in behind the text, retracts on leave */
.hero-intro { position: relative; isolation: isolate; width: max-content; }
.hero-intro::before {
  content: ""; position: absolute; z-index: -1;
  left: -0.14em; right: -0.14em; top: 0.06em; bottom: 0.04em;
  background: var(--vn-accent); border-radius: 2px;
  transform: scaleX(0); transform-origin: left center;
  transition: transform 460ms cubic-bezier(0.2, 0.65, 0.25, 1);
}
.hero-intro:hover::before { transform: scaleX(1); transform-origin: left center; }

/* eyebrow keeps a soft fade-rise (its rec dot glow can't be clipped) */
.hero-eyebrow { animation: heroRise 820ms var(--ease-cinematic) 120ms both; }
.hero-sub { animation: heroRise 900ms var(--ease-cinematic) 600ms both; }
.hero-cta { animation: heroRise 900ms var(--ease-cinematic) 720ms both; }
.hero-lower { animation: heroRise 900ms var(--ease-cinematic) 840ms both; }
.hero-scrollcue {
  position: absolute; left: clamp(22px,6vw,96px); right: auto; bottom: clamp(22px,4vh,40px); z-index: 30;
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-3);
}
.hero-scrollcue .cue-mobile { display: none; }
.hero-scrollcue .ar { animation: bobv 1.8s ease-in-out infinite; }
@keyframes bobv { 50% { transform: translateY(4px); } }

/* hero layout variants */
[data-hero="left"] .hero-content { align-items: flex-start; text-align: left; }
[data-hero="center"] .hero-content { align-items: center; text-align: center; justify-content: flex-start; padding-top: clamp(84px, 13vh, 168px); }
[data-hero="center"] .hero-top { align-items: center; }
[data-hero="center"] .hero-role .accent::after { left: 6%; right: 6%; }
[data-hero="center"] .hero-sub { display: flex; }
[data-hero="center"] .hero-cta { display: inline-flex; margin: clamp(22px,3.2vh,40px) auto 0; }
[data-hero="center"] .hero-lower { display: block; position: absolute; left: clamp(22px,6vw,96px); bottom: clamp(120px, 17vh, 200px); max-width: 34ch; text-align: left; }
[data-hero="center"] .hero-name { font-size: calc(clamp(58px, 14.5vw, 250px) * var(--hero-scale)); }
[data-hero="center"] .hero-role { font-size: calc(clamp(24px, 4.4vw, 64px) * var(--hero-scale)); }
[data-hero="split"] .hero-content { align-items: stretch; }
[data-hero="split"] .hero-role { align-self: flex-end; text-align: right; margin-top: -0.4em; }
[data-hero="split"] .hero-intro { align-self: flex-end; text-align: right; }

/* track that holds reel-stage + about, slides horizontally in phase B */
/* pointer-events pass through the empty areas so the hero text underneath stays hoverable;
   the reel itself re-enables them in its corner */
.cine-track { position: absolute; inset: 0; display: flex; width: 200vw; z-index: 24; will-change: transform; pointer-events: none; }
.cine-pane { position: relative; width: 100vw; height: 100%; flex: none; }
.reel { pointer-events: auto; }
/* about pane sits off-screen during the hero, so its interactive bits stay clickable/hoverable */
.about-pane { pointer-events: auto; }

/* showreel */
.reel {
  position: absolute; overflow: hidden; background: transparent;
  right: clamp(16px, 3vw, 28px); left: auto; bottom: clamp(78px, 12vh, 104px);
  width: min(40vw, 380px); height: min(22.5vw, 214px); border-radius: 4px;
  box-shadow: 0 2px 10px rgba(11,9,7,0.10), 0 18px 50px -12px rgba(11,9,7,0.42); will-change: left, top, width, height, border-radius;
}
@keyframes reelRise { from { opacity: 0; transform: translateY(42px) scale(0.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
.reel .rvid { position: absolute; inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px); object-fit: cover; }
.reel iframe.rvid { border: 0; z-index: 1; background: var(--film-black); }
.reel-fallback { position: absolute; inset: 0; }
.reel-fallback .l1 { position: absolute; inset: -10%; background: conic-gradient(from 200deg at 50% 50%, var(--vn-accent), var(--accent-electric), var(--accent-magenta), var(--accent-cyan), var(--vn-accent)); filter: blur(40px) saturate(120%); opacity: 0.85; animation: spin 30s linear infinite; }
.reel-fallback .l2 { position: absolute; inset: 0; background: radial-gradient(ellipse at 50% 60%, transparent 30%, rgba(11,9,7,0.7) 100%); }
.reel-fallback .grain { position: absolute; inset: -10%; opacity: 0.08; mix-blend-mode: overlay; background-image: radial-gradient(rgba(255,255,255,0.7) 1px, transparent 1px); background-size: 3px 3px; animation: grain 1.4s steps(8) infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes grain { 0%{transform:translate(0,0)} 25%{transform:translate(-2%,1%)} 50%{transform:translate(1%,-2%)} 75%{transform:translate(-1%,2%)} 100%{transform:translate(0,0)} }
.reel .r-overlay { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; justify-content: space-between; padding: clamp(16px,2.4vw,30px); pointer-events: none; }
/* "Better with sound" hint — positioned by JS just below the reel's bottom-right corner */
.reel-hint {
  position: absolute; top: 0; left: 0; z-index: 6;
  pointer-events: none; opacity: 0; will-change: opacity, transform;
}
.reel-hint-in {
  font-family: var(--font-mono); font-size: clamp(12px, 1.15vw, 15px); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink); white-space: nowrap;
  display: inline-flex; flex-direction: row; align-items: center;
}
.reel-hint .ar { font-size: 14px; }
/* label is always visible but breathes with the icon cycle: bright + solid when the icon is
   in the sound-ON state, dim + semi-transparent when it flips back to muted — long eases so
   the brightness change is gradual, not a hard blink */
.reel-hint .rh-label {
  display: flex; justify-content: flex-end; flex: none;
  animation: rhPulse 2.8s var(--ease-in-out) infinite;
}
.reel-hint .rh-tx { white-space: nowrap; padding-right: 11px; }
@keyframes rhPulse {
  0%       { opacity: 0.34; }
  40%      { opacity: 0.34; }
  54%      { opacity: 1; }
  86%      { opacity: 1; }
  100%     { opacity: 0.34; }
}
/* the icon toggles MUTED (×) ↔ SOUND (waves) on a loop — the label rides the same cycle */
.reel-hint .snd-ico { width: 1.15em; height: 1.15em; flex: none; overflow: visible; }
.reel-hint .snd-spk { fill: currentColor; stroke: none; }
.reel-hint .snd-w1, .reel-hint .snd-w2 { transform-origin: 14px 12px; }
.reel-hint .snd-mute { transform-origin: 19px 12px; }
.reel-hint .snd-mute { animation: sndMute 2.8s var(--ease-in-out) infinite; }
.reel-hint .snd-w1 { animation: sndOn 2.8s var(--ease-in-out) infinite; }
.reel-hint .snd-w2 { animation: sndOn 2.8s var(--ease-in-out) infinite 0.1s; }
@keyframes sndMute {
  0%, 36%  { opacity: 1; transform: scale(1); }
  48%, 90% { opacity: 0; transform: scale(0.6); }
  100%     { opacity: 1; transform: scale(1); }
}
@keyframes sndOn {
  0%, 40%  { opacity: 0; transform: scale(0.55); }
  54%, 86% { opacity: 1; transform: scale(1); }
  100%     { opacity: 0; transform: scale(0.55); }
}
@media (prefers-reduced-motion: reduce) {
  .reel-hint .rh-label, .reel-hint .snd-mute, .reel-hint .snd-w1, .reel-hint .snd-w2 { animation: none; }
  .reel-hint .rh-label { opacity: 1; }
  .reel-hint .snd-mute { opacity: 0; }
  .reel-hint .snd-w1, .reel-hint .snd-w2 { opacity: 1; transform: none; }
}
/* sound toggle + hint anchored to the reel's bottom-right corner */
.reel-sound-wrap {
  position: absolute; bottom: clamp(12px, 1.8vw, 22px); right: clamp(12px, 1.8vw, 22px); z-index: 5;
  display: inline-flex; align-items: center; gap: 12px;
  opacity: 0; /* revealed by JS (applyCinema) — ramped with reel growth, no class-toggle jitter */
}
.reel:hover .reel-sound-wrap { opacity: 1; }
.reel-sound-hint {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--on-film); white-space: nowrap; pointer-events: none;
  display: inline-flex; align-items: center; gap: 8px;
  text-shadow: 0 1px 6px rgba(11,9,7,0.55);
  animation: soundHintBlink 2.4s var(--ease-in-out) infinite;
}
.reel-sound-hint .ar { font-size: 14px; transform: translateY(0.5px); }
@keyframes soundHintBlink { 0%, 100% { opacity: 1; } 50% { opacity: 0.28; } }
.reel-sound[aria-pressed="true"] ~ .reel-sound-hint, .reel-sound-wrap.muted-off .reel-sound-hint { display: none; }
.reel-sound {
  all: unset; box-sizing: border-box; cursor: pointer; pointer-events: auto;
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  color: var(--on-film); border-radius: var(--radius-pill);
  background: rgba(11,9,7,0.42); backdrop-filter: blur(8px) saturate(140%); -webkit-backdrop-filter: blur(8px) saturate(140%);
  box-shadow: inset 0 0 0 1px rgba(241,236,227,0.22);
  transition: background var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.reel-sound:hover { background: rgba(11,9,7,0.62); box-shadow: inset 0 0 0 1px rgba(241,236,227,0.4); }
.reel-sound:active { transform: scale(0.94); }
.reel-sound svg { width: 21px; height: 21px; display: block; }
.reel-sound .ic-on { display: none; }
.reel-sound[aria-pressed="true"] { background: var(--signal); box-shadow: none; color: var(--on-film); }
.reel-sound[aria-pressed="true"] .ic-muted { display: none; }
.reel-sound[aria-pressed="true"] .ic-on { display: block; }
/* hide the hint once sound is on */
.reel-sound-wrap:has(.reel-sound[aria-pressed="true"]) .reel-sound-hint { display: none; }
@media (prefers-reduced-motion: reduce) { .reel-sound { transition: none; } .reel-sound-hint { animation: none; } }
.reel .r-row { display: flex; justify-content: space-between; align-items: flex-end; gap: 14px; font-family: var(--font-mono); font-size: clamp(9px,0.85vw,11px); letter-spacing: 0.16em; text-transform: uppercase; color: rgba(241,236,227,0.82); }
.reel .r-row .live { display: inline-flex; align-items: center; gap: 7px; color: var(--on-film); }
.reel .r-row .live b { width: 7px; height: 7px; border-radius: 999px; background: var(--signal); animation: rec 1.6s ease-in-out infinite; }
.reel .r-title { font-family: var(--font-display); font-style: italic; color: var(--on-film); font-size: clamp(16px, 3vw, 46px); line-height: 1; opacity: 0; transition: opacity var(--dur-slow) var(--ease-out); }
.reel.full .r-title { opacity: 1; }
/* scrub bar */
.reel .r-scrub { position: relative; height: 2px; background: rgba(241,236,227,0.22); margin-top: 12px; }
.reel .r-scrub i { position: absolute; left: 0; top: 0; height: 100%; width: 38%; background: var(--signal); animation: scrub 14s linear infinite; }
@keyframes scrub { from { width: 2%; } to { width: 100%; } }

/* corner hint on small reel */
.reel .r-cornerhint { position: absolute; left: 0; top: 0; }

/* about panel (black) */
.about-pane { background: var(--film-black); color: var(--on-film); }
.about-inner {
  position: absolute; inset: 0; display: grid; align-content: center;
  grid-template-columns: minmax(160px, 0.5fr) minmax(0, 1.5fr);
  gap: clamp(28px, 5vw, 80px); padding: 0 clamp(22px, 6vw, 110px);
  max-width: 1440px; margin: 0 auto; left: 0; right: 0;
}
.about-photo {
  position: relative; aspect-ratio: 1/1; width: 100%; max-width: 170px;
  align-self: center; justify-self: end; border-radius: 50%;
  background: var(--film-black-2); overflow: visible;
  box-shadow: inset 0 0 0 1px rgba(241,236,227,0.14);
}
/* clip the visual layers to the circle so the container can let the burst overflow */
.about-photo .ph, .about-photo .ph-img { border-radius: 50%; }
.about-photo .photo-grid { border-radius: 50%; overflow: hidden; }
/* 3D shapes spill out of the portrait on hover (griflan-style dropping objects) */
.shape-drop { position: absolute; inset: 0; z-index: 6; pointer-events: none; }
.shape-obj {
  position: absolute; left: 50%; top: 50%;
  width: 52px; height: 52px;
  will-change: transform, opacity;
  filter: drop-shadow(0 10px 18px rgba(11,9,7,0.28));
}
.shape-obj img { width: 100%; height: 100%; object-fit: contain; display: block; }
.about-photo:hover { animation: photoBounce 560ms var(--ease-out); }
@keyframes photoBounce {
  0%   { transform: scale(1)    rotate(0deg); }
  38%  { transform: scale(1.08) rotate(-4deg); }
  100% { transform: scale(1)    rotate(0deg); }
}
@media (prefers-reduced-motion: reduce) { .shape-drop { display: none; } }
.about-photo .ph { position: absolute; inset: 0; background: linear-gradient(150deg, color-mix(in oklch, var(--vn-accent) 30%, var(--film-black-2)), var(--film-black-2) 70%); display: flex; align-items: flex-end; padding: 16px; }
.about-photo .ph span { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--on-film-soft); }
.about-photo .ph-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 22%; }
.about-photo .frametag { display: none; }
.about-copy .a-label { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--on-film-soft); margin-bottom: 20px; }
.about-copy .a-lede { font-family: var(--font-display); font-size: clamp(28px, 3.6vw, 56px); line-height: 1.05; letter-spacing: -0.015em; color: var(--on-film); margin: 0 0 24px; max-width: 18ch; }
.about-copy .a-lede em { font-style: italic; }
/* "Hi!" enlarges and a waving hand pops in beside it on hover */
.about-copy .a-lede { display: inline-flex; align-items: center; gap: 0.16em; transform-origin: left center; transition: transform var(--dur-base) var(--ease-out); cursor: default; }
.about-copy .a-lede:hover { transform: scale(1.14); }
.about-copy .a-lede .wave {
  display: inline-block; transform-origin: 72% 82%;
  opacity: 0; transform: scale(0.4) translateX(-0.25em);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-cinematic);
}
.about-copy .a-lede:hover .wave { opacity: 1; transform: scale(1) translateX(0); animation: handwave 1.1s var(--ease-in-out) 0.1s infinite; }
@keyframes handwave { 0%,100% { rotate: 0deg; } 18% { rotate: 16deg; } 38% { rotate: -10deg; } 58% { rotate: 14deg; } 78% { rotate: -6deg; } }
@media (prefers-reduced-motion: reduce) { .about-copy .a-lede:hover .wave { animation: none; } }
.about-copy .a-body {
  font-family: var(--font-sans); font-size: clamp(15px, 1.4vw, 18px); line-height: 1.62; color: rgba(241,236,227,0.74); max-width: 74ch;
  transform-origin: left top;
  transition: transform var(--dur-base) var(--ease-out);
}
.about-copy .a-body:hover {
  transform: scale(1.05);
}
.about-copy .a-body em { font-family: var(--font-display); font-style: italic; color: var(--on-film); font-size: 1.06em; -webkit-text-fill-color: var(--on-film); }
@keyframes bodyGlint {
  from { background-position: 100% 0; }
  to   { background-position: 0% 0; }
}
@media (prefers-reduced-motion: reduce) { .about-copy .a-body:hover .ln-i { animation: none; } }
.about-copy .a-meta { margin-top: 28px; display: flex; flex-wrap: wrap; gap: 8px; }
.about-copy .a-meta span { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(241,236,227,0.66); padding: 6px 11px; box-shadow: inset 0 0 0 1px rgba(241,236,227,0.18); border-radius: 2px; }

/* About — running tools marquee */
.a-marquee {
  margin-top: 32px; overflow: hidden; width: 100%;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.about-inner > .a-marquee { grid-column: 1 / -1; margin-top: clamp(40px, 7vh, 80px); }
.a-track { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; animation: marquee 46s linear infinite; will-change: transform; }
.a-marquee:hover .a-track { animation-play-state: paused; }
.a-track span {
  flex: none; font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(241,236,227,0.78); padding: 8px 14px; border-radius: 2px;
  box-shadow: inset 0 0 0 1px rgba(241,236,227,0.18);
  transition: color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.a-track span:hover, .a-track span.hot:hover {
  color: var(--ink); background: var(--vn-accent); transform: scale(1.18);
  box-shadow:
    inset 0 0 0 1px transparent,
    0 10px 30px -4px color-mix(in oklch, var(--vn-accent) 70%, transparent),
    0 0 22px -2px color-mix(in oklch, var(--vn-accent) 60%, transparent);
}
.a-track span.hot { color: var(--vn-accent); box-shadow: inset 0 0 0 1px color-mix(in oklch, var(--vn-accent) 60%, transparent); }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ───────────────────────── portfolio blocks ───────────────────────── */
.work {
  background-color: var(--paper);
  position: relative; z-index: 6;
  /* the ONE stacking moment: Work slides up over the still-pinned About panel */
  margin-top: -84vh;
  box-shadow: 0 -46px 90px -52px rgba(11,9,7,0.42), 0 52px 100px -56px rgba(11,9,7,0.55);
}
/* fine grid sits behind the content and is eaten away in patches by a turbulent-noise mask */
.work::before {
  content: "";
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(21,17,13,0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(21,17,13,0.05) 1px, transparent 1px);
  background-size: 18px 18px;
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='560' height='560'><filter id='t' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.018' numOctaves='3' seed='7' stitchTiles='stitch'/><feComponentTransfer><feFuncA type='gamma' amplitude='1' exponent='1.7' offset='0'/></feComponentTransfer></filter><rect width='560' height='560' filter='url(%23t)'/></svg>");
          mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='560' height='560'><filter id='t' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.018' numOctaves='3' seed='7' stitchTiles='stitch'/><feComponentTransfer><feFuncA type='gamma' amplitude='1' exponent='1.7' offset='0'/></feComponentTransfer></filter><rect width='560' height='560' filter='url(%23t)'/></svg>");
  -webkit-mask-size: 560px 560px; mask-size: 560px 560px;
  -webkit-mask-repeat: repeat; mask-repeat: repeat;
  /* noise animation removed for perf — static mask */
}
.block { padding: clamp(120px, 19vh, 248px) 0 clamp(20px, 4vh, 40px); position: relative; z-index: 1; }
/* first work block gets extra breathing room after the dark About section */
.work > .block:first-of-type { padding-top: clamp(120px, 19vh, 248px); }
.block:last-of-type { padding-bottom: clamp(60px, 9vh, 110px); }
.block-head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;
  padding: 0 clamp(22px, 6vw, 96px) clamp(22px, 3vh, 34px);
  width: 100%; max-width: 1680px; margin: 0 auto;
}
.block-head .bh-left { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; }
.block-head .bh-idx { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.14em; color: var(--ink-3); }
.block-head h2 { font-family: var(--font-display); font-weight: 400; font-size: clamp(34px, 5.4vw, 80px); line-height: 0.96; letter-spacing: -0.02em; color: var(--ink); }
.block-head h2 .ital { font-style: italic; }
.block-head .bh-note { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--ink-3); max-width: 40ch; text-align: right; line-height: 1.5; }
#explainers .block-head .bh-note { max-width: 76ch; }
#hero-images .block-head .bh-note { max-width: 62ch; }
.block-head .bh-count { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); white-space: nowrap; }

/* horizontal rail */
.rail-wrap { position: relative; }
.h-rail {
  display: flex; gap: clamp(16px, 2vw, 28px);
  overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 22px clamp(22px, 6vw, 96px) 34px;
  scrollbar-width: none;
}
.h-rail::-webkit-scrollbar { display: none; }
.h-rail .card { scroll-snap-align: center; flex: none; }

/* horizontal-scroll controls under each work rail: ← · dots · → */
.rail-nav {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(16px, 2.2vw, 28px);
  margin-top: clamp(20px, 2.6vw, 34px);
  padding: 0 clamp(22px, 6vw, 96px);
}
.rail-arrow {
  all: unset; box-sizing: border-box;
  flex: none; width: 46px; height: 46px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--ink);
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--rule);
  font-family: var(--font-mono); font-size: 16px; line-height: 1;
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.rail-arrow:hover { background: var(--accent-acid); color: var(--ink); box-shadow: inset 0 0 0 1px var(--accent-acid); }
.rail-arrow:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.rail-arrow[disabled] { opacity: 0.28; pointer-events: none; }
.rail-dots { display: flex; align-items: center; gap: 11px; }
.rail-dot {
  all: unset; box-sizing: border-box; cursor: pointer;
  width: 7px; height: 7px; border-radius: 999px;
  background: var(--ink-4);
  transition: background var(--dur-base) var(--ease-out), width var(--dur-base) var(--ease-out);
}
.rail-dot:hover { background: var(--ink-3); }
.rail-dot.active { background: var(--ink); width: 20px; }
.rail-dot:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .rail-arrow, .rail-dot { transition: none; } }

/* ── animated icon tiles (Logos & icons) ── */
.icon-rail { padding-top: 10px; padding-bottom: 22px; }
.icon-card { width: clamp(184px, 20vw, 240px); }
.icon-card .iconframe {
  position: relative; width: 100%; aspect-ratio: 1 / 1;
  display: grid; place-items: center;
  background: var(--paper-soft);
  box-shadow: inset 0 0 0 1px var(--rule);
  overflow: hidden;
  transition: box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
/* faint baseline-rule texture behind the mark */
.icon-card .iconframe::before {
  content: ""; position: absolute; inset: 0;
  background-image: radial-gradient(60% 60% at 50% 46%, rgba(11,9,7,0.05), transparent 70%);
}
.icon-card .ic-num {
  position: absolute; left: 11px; top: 10px; z-index: 2;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; color: var(--ink-3);
}
.icon-card .iconsvg {
  position: relative; z-index: 1; width: 56%; height: 56%; display: block;
  pointer-events: none;
  filter: drop-shadow(0 7px 12px rgba(11,9,7,0.16));
  transition: transform var(--dur-base) var(--ease-out);
}
/* hover reacts exactly like the video frames in other blocks: scale up, accent border,
   and one quick ~1.5° "touch" tilt — applied to the frame so it doesn't fight the GIF's
   own looping micro-motion */
.icon-card:hover .iconframe {
  transform: scale(1.05);
  box-shadow: inset 0 0 0 1px var(--vn-accent), var(--shadow-lift);
  animation: cardNudge 620ms var(--ease-out);
}
@media (prefers-reduced-motion: reduce) { .icon-card:hover .iconframe { animation: none; } }

/* tasteful looping micro-motion — one curve per mark, no overshoot */
@keyframes ic-float  { 0%,100% { transform: translateY(0); }            50% { transform: translateY(-7px); } }
@keyframes ic-bob    { 0%,100% { transform: translateY(0) rotate(0); }  50% { transform: translateY(-5px) rotate(-2.5deg); } }
@keyframes ic-spin   { from { transform: rotate(0); }                    to  { transform: rotate(360deg); } }
@keyframes ic-pulse  { 0%,100% { transform: scale(1); }                 50% { transform: scale(1.09); } }
@keyframes ic-wobble { 0%,100% { transform: rotate(0); } 25% { transform: rotate(-7deg); } 75% { transform: rotate(7deg); } }
@keyframes ic-swing  { 0%,100% { transform: rotate(-5deg); }            50% { transform: rotate(5deg); } }
@keyframes ic-tilt   { 0%,100% { transform: perspective(420px) rotateY(-13deg); } 50% { transform: perspective(420px) rotateY(13deg); } }
.anim-float  { animation: ic-float  3.4s var(--ease-in-out) infinite; }
.anim-bob    { animation: ic-bob    3.0s var(--ease-in-out) infinite; }
.anim-spin   { animation: ic-spin   6.5s linear infinite; }
.anim-pulse  { animation: ic-pulse  2.6s var(--ease-in-out) infinite; }
.anim-wobble { animation: ic-wobble 3.2s var(--ease-in-out) infinite; }
.anim-swing  { animation: ic-swing  3.2s var(--ease-in-out) infinite; transform-origin: 50% 14%; }
.anim-tilt   { animation: ic-tilt   4.0s var(--ease-in-out) infinite; }
.icon-card:hover .iconsvg.anim-spin { transform: none; }

/* dashed video frame */
.vframe {
  position: relative; padding: 10px; border: 1.5px dashed var(--rule-strong);
  background: var(--paper-soft); border-radius: var(--radius-sm);
  transition: border-color var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

/* ── click-to-expand affordance on gif (icon) frames ── */
.icon-card .iconframe { cursor: zoom-in; }

/* ── fullscreen lightbox ── */
.lightbox {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; padding: clamp(20px, 4vw, 56px);
  background: rgba(11,9,7,0.90);
  -webkit-backdrop-filter: blur(14px) saturate(120%); backdrop-filter: blur(14px) saturate(120%);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out), visibility 0s linear var(--dur-base);
}
.lightbox.open { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity var(--dur-base) var(--ease-out); }
.lb-stage {
  display: flex; align-items: center; justify-content: center;
  max-width: min(94vw, 1400px); max-height: 82vh;
  transform: scale(0.965); transition: transform var(--dur-slow) var(--ease-cinematic);
}
.lightbox.open .lb-stage { transform: scale(1); }
.lb-stage > video, .lb-stage > img {
  display: block; max-width: min(94vw, 1400px); max-height: 82vh;
  width: auto; height: auto; object-fit: contain;
  border-radius: 4px; background: var(--film-black);
  box-shadow: 0 30px 90px -20px rgba(0,0,0,0.7);
}
/* gifs keep the same light paper background + inset rule they had in the small card, with a
   little breathing room around the mark */
.lb-stage > img.lb-gif {
  background: var(--paper-soft);
  box-shadow: inset 0 0 0 1px var(--rule), 0 30px 90px -20px rgba(0,0,0,0.5);
  padding: clamp(20px, 4vw, 56px);
  max-width: min(80vw, 760px); max-height: 80vh;
}
.lb-cap {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--on-film-soft); text-align: center; max-width: 80vw;
}
.lb-close {
  all: unset; position: absolute; top: clamp(16px, 3vw, 30px); right: clamp(16px, 3vw, 30px); z-index: 2;
  width: 44px; height: 44px; display: grid; place-items: center; cursor: pointer;
  font-family: var(--font-sans); font-size: 26px; line-height: 1; color: var(--on-film);
  border-radius: 999px; background: rgba(241,236,227,0.08);
  box-shadow: inset 0 0 0 1px rgba(241,236,227,0.22);
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.lb-close:hover { background: var(--vn-accent); transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) {
  .lb-stage, .lightbox { transition: opacity var(--dur-fast) linear; }
  .lb-stage { transform: none; }
  .lb-close:hover { transform: none; }
}
.vframe.live { border-color: var(--vn-accent); background: color-mix(in oklch, var(--vn-accent) 7%, var(--paper-soft)); }
/* hover a video card → it lifts/enlarges with a deep glow */
.card { transition: transform var(--dur-base) var(--ease-out); }
.card .vframe { will-change: transform; }
.h-rail .card:hover, .feed .card:hover { z-index: 4; }
.h-rail .card:hover .vframe, .feed .card:hover .vframe {
  transform: scale(1.05);
  border-color: var(--vn-accent);
  animation: cardNudge 620ms var(--ease-out);
}
/* touch devices have no hover — a single tap replays the same scale + "touch" tilt */
.card.tap-react .vframe {
  transform: scale(1.05);
  border-color: var(--vn-accent);
  animation: cardNudge 620ms var(--ease-out);
}
/* one quick "touch" tilt on hover — leans ~1.5° fast, then settles back to zero on a long,
   gentle ease so the return doesn't snap */
@keyframes cardNudge {
  0%   { transform: scale(1.05) rotate(0deg); animation-timing-function: cubic-bezier(0.3,0,0.2,1); }
  28%  { transform: scale(1.05) rotate(-1.5deg); animation-timing-function: cubic-bezier(0.33,0,0.15,1); }
  100% { transform: scale(1.05) rotate(0deg); }
}
@media (prefers-reduced-motion: reduce) { .h-rail .card:hover .vframe, .feed .card:hover .vframe { animation: none; } }
.h-rail .card:hover .vid, .feed .card:hover .vid {
  box-shadow: inset 0 0 0 1px color-mix(in oklch, var(--vn-accent) 40%, transparent);
}
.vid {
  position: relative; overflow: hidden; background: var(--film-black);
  border-radius: 2px;
}
.vid video, .vid .vfill { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.vid iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
/* real-video frames read as finished, not placeholder slots */
.vframe.has-video { border-style: solid; border-color: var(--rule); }
.vframe.has-video.live { border-color: var(--vn-accent); }
.has-video .vmono { pointer-events: none; }
.vid .vfill { background: linear-gradient(135deg, var(--g1, var(--accent-electric)), var(--g2, var(--accent-magenta))); filter: saturate(115%); }
.vid .vfill::after { content: ""; position: absolute; inset: 0; background: radial-gradient(ellipse at 50% 120%, transparent 40%, rgba(11,9,7,0.5)); }
.vid .vmono { position: absolute; left: 10px; top: 9px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(241,236,227,0.82); z-index: 2; }
.vid .vdur { position: absolute; right: 10px; bottom: 9px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; color: rgba(241,236,227,0.82); z-index: 2; }
.vid .vstate { position: absolute; left: 10px; bottom: 9px; display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(241,236,227,0.9); z-index: 2; }
.vid .vstate b { width: 6px; height: 6px; border-radius: 999px; background: var(--ink-4); }
.vframe.live .vid .vstate b { background: var(--signal); animation: rec 1.6s ease-in-out infinite; }
.card .c-cap { margin-top: 12px; display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
/* caption aligns to the VIDEO's own left edge, not the frame box — indent by the frame's
   border (1.5px) + padding (10px) so the text sits under the video content, not the dashed rule */
.card:has(.vframe) .c-cap { padding-left: 11.5px; }
.card .c-cap .t { font-family: var(--font-sans); font-size: 13px; color: var(--ink-2); }
.card .c-cap .y { display: none; }

/* card size variants */
.size-wide .vid { width: clamp(280px, 64vw, 760px); aspect-ratio: 16/9; }
.size-square .vid { width: clamp(140px, 30vw, 230px); aspect-ratio: 1/1; }
.size-rect  .vid { width: clamp(170px, 36vw, 300px); aspect-ratio: 4/3; }
/* every explainer is a landscape promo — pin EVERY frame to a single uniform 16:9 size so no
   frame is bigger than another and none balloons to a giant letterbox while metadata loads.
   the video fills it via object-fit:cover, so any source ratio crops in cleanly */
#explainers .card .vid { width: clamp(360px, 40vw, 540px); height: auto; aspect-ratio: 16 / 9; }

/* performance marketing — horizontal loop rail of vertical 9:16 reels */
.size-perf { width: clamp(232px, 25vw, 320px); }
.perf-rail .vid { width: 100%; aspect-ratio: 9/16; }
.perf-rail .pvid { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: var(--film-black); }
.perf-rail .pvid.fit-contain { object-fit: contain; }

/* native fullscreen: a video is normally object-fit:cover inside a fixed-ratio frame, which
   crops it (badly on mobile, where a 9:16 reel meets a landscape screen). When the element
   itself is fullscreen, show the whole frame — contain, centered, on black */
.vid video:fullscreen, .perf-rail .pvid:fullscreen, video:fullscreen {
  position: fixed; inset: 0; width: 100vw; height: 100vh;
  object-fit: contain; background: var(--film-black);
}
.vid video:-webkit-full-screen, .perf-rail .pvid:-webkit-full-screen, video:-webkit-full-screen {
  width: 100vw; height: 100vh; object-fit: contain; background: var(--film-black);
}

/* ───────────────────────── footer ───────────────────────── */
.footer { background: var(--film-black); color: var(--on-film); padding: clamp(70px,12vh,150px) clamp(22px,6vw,96px) 40px; position: fixed; left: 0; right: 0; bottom: 0; z-index: 0; overflow: hidden; }
/* spacer holds open the scroll length the fixed footer needs to be revealed from under .work */
.footer-spacer { width: 100%; }
/* drifting gradients behind the sign-off, echoing the hero */
.footer-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.fblob { position: absolute; border-radius: 50%; filter: blur(52px); will-change: transform; }
.fb1 { width: 46vw; height: 46vw; left: -8vw; top: -14vw; opacity: 0.34; background: radial-gradient(circle at 40% 40%, var(--accent-electric), transparent 66%); animation: drift1 28s ease-in-out infinite alternate; }
.fb2 { width: 40vw; height: 40vw; right: -6vw; bottom: -16vw; opacity: 0.28; background: radial-gradient(circle at 50% 50%, var(--accent-magenta), transparent 64%); animation: drift2 34s ease-in-out infinite alternate; }
.fb3 { width: 34vw; height: 34vw; left: 32vw; bottom: -12vw; opacity: 0.22; background: radial-gradient(circle at 50% 50%, var(--vn-accent), transparent 66%); animation: drift3 30s ease-in-out infinite alternate; }
.footer-inner { max-width: 1440px; margin: 0 auto; position: relative; z-index: 1; }
.footer .thanks { font-family: var(--font-display); font-size: clamp(44px, 9vw, 160px); line-height: 0.9; letter-spacing: -0.03em; color: var(--on-film); }
.footer .thanks em { font-style: italic; }
.footer .f-grid { margin-top: clamp(40px,7vh,90px); display: grid; grid-template-columns: 1fr auto; gap: 40px; align-items: end; }
.footer .f-contacts { display: flex; flex-wrap: wrap; gap: 10px; }
.f-link {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-sans); font-size: 15px; font-weight: 500; color: var(--on-film);
  position: relative; overflow: hidden; isolation: isolate;
  padding: 12px 18px; border-radius: var(--radius-pill);
  box-shadow: inset 0 0 0 1px rgba(241,236,227,0.22);
  transition: color var(--dur-base) var(--ease-out), box-shadow var(--dur-base);
}
.f-link::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: var(--vn-accent);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 480ms var(--ease-cinematic);
}
.f-link:hover::before { transform: scaleX(1); transform-origin: right center; }
.f-link > * { position: relative; z-index: 1; }
.f-link .ico { width: 18px; height: 18px; }
.f-link:hover { color: var(--ink); box-shadow: inset 0 0 0 1px transparent; }
.footer .f-slate { display: flex; justify-content: flex-end; text-align: right; gap: 20px; margin-top: clamp(40px,7vh,80px); padding-top: 22px; border-top: 1px solid rgba(241,236,227,0.16); font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--on-film-soft); flex-wrap: wrap; }

/* ───────────────────────── buttons (wabi-style) ───────────────────────── */
.btn {
  all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-sans); font-weight: 500; font-size: 15px; letter-spacing: -0.005em;
  padding: 13px 22px; border-radius: var(--radius-pill);
  background: var(--ink); color: var(--paper);
  position: relative; overflow: hidden; isolation: isolate;
  --btn-fill: var(--vn-accent); --btn-fill-text: var(--ink);
  transition: color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
/* griflan-style right-to-left colour wipe on hover */
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: var(--btn-fill);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 480ms var(--ease-cinematic);
}
.btn:hover::before { transform: scaleX(1); transform-origin: right center; }
.btn > * { position: relative; z-index: 1; }
.btn .arr { display: inline-flex; transition: transform var(--dur-base) var(--ease-out); }
.btn:hover { color: var(--btn-fill-text); }
.btn:hover .arr { transform: translate(3px,-3px); }
.btn:active { transform: translateY(1px); }
/* button style variants */
[data-btn="accent"] .btn { background: var(--vn-accent); color: var(--ink); --btn-fill: var(--ink); --btn-fill-text: var(--paper); }
[data-btn="outline"] .btn { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); --btn-fill: var(--ink); --btn-fill-text: var(--paper); }

/* griflan-style hover: the label rolls up while an identical copy rolls in from below */
.btn-roll { position: relative; display: inline-flex; align-items: center; overflow: hidden; vertical-align: middle; padding-inline: 5px; margin-inline: -5px; }
.br-a, .br-b { display: inline-flex; align-items: center; white-space: nowrap; transition: transform 520ms var(--ease-cinematic); }
.br-b { position: absolute; left: 0; top: 0; transform: translateY(115%); }
.btn:hover .br-a,
.f-link:hover .br-a,
.contacts-btn:hover .br-a { transform: translateY(-115%); }
.btn:hover .br-b,
.f-link:hover .br-b,
.contacts-btn:hover .br-b { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) { .br-a, .br-b { transition: none; } }

/* ───────────────────────── work blocks: unroll from a scroll ───────────────────────── */
/* headings render normally now — the whole block unfurls top-down when scrolled to */
.block-head h2.reveal-mask { overflow: visible; padding: 0; margin: 0; }
.block-head .reveal-rise { display: inline; transform: none; }

.block .rail-wrap,
.block .feed {
  opacity: 0;
  clip-path: inset(0 0 100% 0);
  transform-origin: top center;
  transition: clip-path 1000ms var(--ease-cinematic), opacity 640ms ease, transform 1000ms var(--ease-cinematic);
}
/* the card row also curls down as it releases, like a scroll unrolling */
.block .rail-wrap, .block .feed { transform: perspective(1500px) rotateX(-22deg); }

.block.in .rail-wrap,
.block.in .feed { opacity: 1; clip-path: inset(0 0 0 0); transform: none; transition-delay: 150ms; }

/* block title flickers in character-by-character (JS-driven); note fades up after */
.block-head .reveal-rise .flick { opacity: 0; }
.block-head .bh-note { opacity: 0; transform: translateY(10px); transition: opacity 700ms var(--ease-cinematic) 380ms, transform 700ms var(--ease-cinematic) 380ms; }
.block.in .bh-note { opacity: 1; transform: translateY(0); }

/* about block, on arrival:
   • label  — soft fade-up
   • “Hi!”   — fade-by-character (same flicker as the hero)
   • body   — reveals line by line, each line rising from a clip mask
   • tags   — slide in from the right */
.about-copy .a-label { opacity: 0; transform: translateY(18px); transition: opacity 700ms var(--ease-cinematic), transform 700ms var(--ease-cinematic); }
.about-pane.reveal-in .a-label { opacity: 1; transform: translateY(0); }

.about-copy .a-body .ln { display: block; overflow: hidden; }
.about-copy .a-body .ln.para { margin-top: 1.15em; }
.about-copy .a-body .ln-i {
  display: block; transform: translateY(115%); transition: transform 840ms var(--ease-cinematic); will-change: transform;
  /* sheen lives on the line spans (they carry the text); base colour fully covers, white band sweeps on hover */
  background-image: linear-gradient(100deg,
    rgba(241,236,227,0.74) 0%, rgba(241,236,227,0.74) 44%,
    #fffdf7 50%,
    rgba(241,236,227,0.74) 56%, rgba(241,236,227,0.74) 100%);
  background-size: 300% 100%; background-position: 100% 0; background-repeat: no-repeat;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.about-copy .a-body:hover .ln-i { animation: bodyGlint 5.7s var(--ease-out) forwards; }
.about-pane.reveal-in .a-body .ln-i { transform: translateY(0); }

.a-marquee .a-track span.tag-enter {
  opacity: 0; transform: translateX(64px);
  transition: opacity 600ms var(--ease-out), transform 760ms var(--ease-cinematic),
              color var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.about-pane.reveal-in .a-marquee .a-track span.tag-enter { opacity: 1; transform: translateX(0); }
/* keep the hover scale winning over the reveal rule's transform */
.about-pane.reveal-in .a-marquee .a-track span:hover { transform: scale(1.18); }

/* about photo: develops square-by-square through the same frosted glass tiles
   that ride behind the cursor — they sit over the photo and clear away in a
   diagonal sweep, uncovering the portrait beneath. */
.about-photo .photo-grid { position: absolute; inset: 0; z-index: 5; display: grid; pointer-events: none; }
.about-photo .pg-tile {
  background: rgba(255,255,255,0.12);
  border: 0.5px solid rgba(255,255,255,0.42);
  -webkit-backdrop-filter: blur(7px) saturate(135%);
  backdrop-filter: blur(7px) saturate(135%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), inset 0 -1px 0 rgba(255,255,255,0.18);
  opacity: 1; transition: opacity 560ms var(--ease-out);
  will-change: opacity;
}
.about-pane.reveal-in .pg-tile { opacity: 0; }

/* ───────────────────────── reduced motion ───────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
}

/* ───────────────────────── mobile (portrait phones only) ───────────────────────── */
/* gated to portrait so a phone turned landscape gets the full desktop layout instead of the
   stacked mobile one (the user asked for desktop in landscape) */
@media (max-width: 860px) and (orientation: portrait) {
  :root { --rail-h: 56px; }
  .lens { display: none; }
  /* ── performance: freeze the GPU-heavy decorative effects on phones ── */
  /* the nested parent filter (blur over five already-blurred meshes) is the single biggest
     scroll cost on phones — drop it and thin the mesh count so the hero composites as a few
     cheap cached layers instead of re-rasterising a filter stack every frame */
  .hero-liquid { filter: none !important; }
  .mesh { animation: none !important; filter: blur(40px); opacity: 0.46; }
  .mesh.m3, .mesh.m5 { display: none; }
  .cinema-sticky { transform: translateZ(0); will-change: transform; }
  .hero-grain { display: none; }
  .fblob { animation: none !important; filter: blur(44px); }
  /* the footer gradients drift on-screen via their keyframes on desktop; with animation frozen
     for mobile perf they'd sit parked off the bottom edge, so re-anchor them inside the footer */
  .fb1 { left: -14vw; top: -10vw; width: 62vw; height: 62vw; opacity: 0.5; }
  .fb2 { right: -14vw; bottom: 2vw; width: 58vw; height: 58vw; opacity: 0.44; }
  .fb3 { left: 18vw; bottom: 12vw; width: 50vw; height: 50vw; opacity: 0.4; }
  /* backdrop-filter (live blur) is very expensive on mobile GPUs — use flat translucency */
  .top-rail::before { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; background: rgba(241,236,227,0.9) !important; }
  .burger, .contacts-btn { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
  .reel-sound { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
  /* pinned cinema, mobile-tuned (the linear experiment was reverted) */
  .cinema { height: 340vh; }
  /* first screen: centered headline sits a bit lower in the upper area with the showreel
     thumbnail just below it (kept close together), and the bottom cue stays clear of chrome */
  [data-hero] .hero-content { align-items: center; text-align: center; justify-content: flex-start; padding-top: 25vh; }
  .hero-name .line { width: max-content; max-width: 92vw; margin-inline: auto; }
  .hero-role { text-align: center; }
  .hero-intro { display: none; }
  .hero-scrollcue { left: 0; right: 0; bottom: clamp(34px, 7vh, 66px); padding-inline: 20px; justify-content: center; text-align: center; }
  .hero-scrollcue .ar { display: none; }
  .hero-scrollcue .cue-desktop { display: none; }
  .hero-scrollcue .cue-mobile { display: inline; max-width: 30ch; line-height: 1.45; animation: cueBlink 1.8s var(--ease-in-out) infinite; }
  @keyframes cueBlink { 0%, 100% { opacity: 1; } 50% { opacity: 0.32; } }
  .about-inner { grid-template-columns: 1fr; gap: 22px; align-content: center; padding: 0 22px; }
  .about-photo { max-width: 180px; }

  /* tighter rhythm between work blocks on phones */
  .block { padding: clamp(52px,8vh,84px) 0 clamp(12px,2.5vh,22px); }
  .work > .block:first-of-type { padding-top: clamp(40px,6vh,64px); }
  .feed { grid-template-columns: repeat(2, 1fr); }
  .size-wide .vid { width: 78vw; }
  .size-square .vid { width: 40vw; }
  .size-rect .vid { width: 56vw; }
  /* explainers: drive frames by a capped WIDTH (not a uniform height) on mobile, so landscape
     videos can't blow past the viewport and break the rail. height follows the real aspect
     ratio, capped so portrait reels stay reasonable */
  /* every explainer is a 16:9 promo, so pin the frame to 16:9 at a uniform width — no
     letterboxed "huge frame" while metadata loads, and every card is the exact same size */
  #explainers .card .vid {
    width: min(86vw, 360px); height: auto;
    aspect-ratio: 16 / 9;
  }
  .block-head { flex-direction: column; align-items: flex-start; gap: 12px; }
  .block-head .bh-note { text-align: left; }
  [data-hero="split"] .hero-role, [data-hero="split"] .hero-intro { align-self: flex-start; text-align: left; }
  .footer .f-grid { grid-template-columns: 1fr; }
}
@media (max-width: 520px) and (orientation: portrait) {
  .feed { grid-template-columns: 1fr; }
  /* keep the wordmark visible and dead-centred on the viewport — no horizontal shift.
     fixed to the rail's full width so it centres on the screen regardless of the
     burger (left) / contacts (right) flex items */
  .wordmark {
    display: block; position: absolute; left: 50%; right: auto; top: 50%;
    transform: translate(-50%, -50%); font-size: 16px;
    max-width: calc(100vw - 132px); overflow: hidden; text-overflow: ellipsis;
  }
}
