/* ==========================================================================
   Andreasen Media — stylesheet
   Cinematic, editorial, kinetic-typography flow (structure inspired by
   landonorris.com), skinned in the Andreasen Media brand.
   ========================================================================== */

:root{
  --charcoal:#1A1D23;
  --dark:#14161B;
  --white:#FFFFFF;
  --blue:#2D7DD2;
  --red:#E63946;
  --gold:#D4A843;
  --dim:rgba(255,255,255,.55);
  --faint:rgba(255,255,255,.30);
  --line:rgba(255,255,255,.10);
  --surface:#1F2229;
  --surface-2:#262930;
  --font-display:'Oswald',sans-serif;
  --font-body:'Inter',sans-serif;
  --font-mono:'Roboto Mono',monospace;
}

*{box-sizing:border-box;}
html{
  scroll-behavior:smooth;
  overflow-x:hidden; /* fallback for browsers without overflow:clip */
  /* Decorative elements (chapter-bg bleed, data-parallax-x drift, the
     kinetic band track) are deliberately sized/offset past the viewport
     edge. Clipping that on body alone still let it inflate the *layout*
     viewport (window.innerWidth grew past the real device width while
     document.documentElement.clientWidth stayed correct) — and every
     position:fixed element sized with left:0;right:0 (#nav, #mobile-menu)
     lays out against that inflated width, so on mobile the nav visibly
     overshot the right edge. Clipping it here on html too closes that gap;
     `clip` (unlike `hidden`) still doesn't create a scroll container, so
     it doesn't disable position:sticky either — same reasoning as body
     below. */
  overflow-x:clip;
}
/* Lenis drives scroll easing once it boots — hand off from the CSS
   fallback so the two smoothing systems don't fight each other. */
html.lenis{scroll-behavior:auto;}
body{
  margin:0;
  background:var(--charcoal);
  color:var(--white);
  font-family:var(--font-body);
  overflow-x:hidden; /* fallback for browsers without overflow:clip */
  /* `overflow-x:hidden` on an ancestor silently disables position:sticky
     on every descendant (incl. #hero's zoom-pin) because it turns body
     into a scroll container. `clip` clips the same horizontal overflow
     without creating one, so sticky keeps working. Unsupported browsers
     just ignore this line and fall back to the rule above. */
  overflow-x:clip;
  position:relative;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}
section{position:relative;}

::selection{background:var(--blue);color:#fff;}

[data-parallax-x]{will-change:transform;}
@media(prefers-reduced-motion:reduce){[data-parallax-x]{transform:none!important;}}

/* scroll progress bar */
#progress-bar{
  position:fixed;top:0;left:0;height:3px;width:0%;z-index:150;
  background:linear-gradient(90deg,var(--blue),var(--red),var(--gold));
  transition:width .12s linear;
}
@media(prefers-reduced-motion:reduce){#progress-bar{transition:none;}}

/* ==========================================================================
   SITE LOADER — shown until every initial page asset (images, stylesheets,
   fonts, the scripts above it) has actually finished loading, or a 6s
   safety timeout elapses, whichever comes first — see the "site loader"
   block in script.js, which also adds body.loaded at the same moment,
   gating the hero's own kinetic entrance so it plays out for real instead
   of finishing hidden behind this. The keyframe at the bottom is a
   pure-CSS fallback: if script.js never runs at all (blocked, erroring),
   this force-hides the loader on its own after 9s so a broken script
   can't trap a visitor behind a black screen forever.
   ========================================================================== */
#site-loader{
  position:fixed;inset:0;z-index:500;
  display:flex;align-items:center;justify-content:center;
  background:var(--charcoal);
  transition:opacity .6s ease,visibility 0s linear 0s;
  animation:siteLoaderForceHide .01s linear 9s forwards;
}
#site-loader.is-hidden{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .6s ease,visibility 0s linear .6s;}
body:has(#site-loader:not(.is-hidden)){overflow:hidden;}
@keyframes siteLoaderForceHide{to{opacity:0;visibility:hidden;pointer-events:none;}}
.site-loader-mark{position:relative;width:60px;height:60px;display:flex;align-items:center;justify-content:center;}
.site-loader-mark img{width:28px;height:auto;position:relative;z-index:1;}
.site-loader-mark::before,.site-loader-mark::after{content:'';position:absolute;inset:0;border-radius:50%;border:2px solid transparent;}
.site-loader-mark::before{border-color:var(--line);}
.site-loader-mark::after{border-top-color:var(--blue);border-right-color:var(--blue);animation:spin 1s linear infinite;}
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
@media(prefers-reduced-motion:reduce){
  #site-loader{transition:opacity .3s linear;}
  .site-loader-mark::after{animation-duration:2.4s;}
}

/* film grain — cinematic texture over the whole page, gently flickering
   instead of sitting static so the backdrop feels alive even at a standstill */
body::before{
  content:'';position:fixed;inset:-4%;z-index:300;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity:.035;mix-blend-mode:overlay;
  animation:grainShift 1.1s steps(8) infinite;
  transition:opacity .6s ease;
}
@keyframes grainShift{
  0%{transform:translate(0,0);}
  12%{transform:translate(-2%,2%);}
  24%{transform:translate(2%,-3%);}
  36%{transform:translate(-3%,4%);}
  48%{transform:translate(4%,1%);}
  60%{transform:translate(-1%,-4%);}
  72%{transform:translate(4%,3%);}
  84%{transform:translate(-4%,-1%);}
  100%{transform:translate(0,0);}
}

/* ambient glow field — soft, slow-drifting color bleeds used across the
   hero and chapters so the backdrop keeps moving on its own axis instead
   of sitting flat behind the scroll. */
@keyframes glowDrift{
  0%{transform:translate(0,0) scale(1);}
  50%{transform:translate(6%,-7%) scale(1.16);}
  100%{transform:translate(-7%,6%) scale(.94);}
}
@media(prefers-reduced-motion:reduce){body::before{animation:none;}}

/* vintage film overlay — scratches, dust and an edge vignette layered on
   top of the grain so the whole site reads as if it were shot on and
   projected from actual film stock, not just a flat digital page. */
body::after{
  content:'';position:fixed;inset:0;z-index:301;pointer-events:none;
  background-image:
    repeating-linear-gradient(90deg,
      rgba(255,255,255,0) 0 38px,
      rgba(255,255,255,.05) 38px 39px,
      rgba(255,255,255,0) 39px 91px,
      rgba(255,255,255,.035) 91px 92px,
      rgba(255,255,255,0) 92px 214px),
    radial-gradient(ellipse 130% 90% at 50% 50%,transparent 55%,rgba(0,0,0,.4) 100%);
  background-size:900px 100%,100% 100%;
  background-repeat:repeat,no-repeat;
  mix-blend-mode:overlay;
  opacity:.55;
  animation:filmScratchDrift 10s linear infinite,filmFlicker 5.3s steps(10) infinite;
}
@keyframes filmScratchDrift{
  0%{background-position:0 0,0 0;}
  100%{background-position:-900px 0,0 0;}
}
@keyframes filmFlicker{
  0%,100%{opacity:.5;}
  10%{opacity:.63;}
  22%{opacity:.44;}
  38%{opacity:.58;}
  50%{opacity:.38;}
  64%{opacity:.6;}
  78%{opacity:.46;}
  90%{opacity:.56;}
}
@media(prefers-reduced-motion:reduce){body::after{animation:none;opacity:.4;}}

/* ==========================================================================
   FILM STRIP BORDER — sprocket-hole edges framing the viewport on every
   page, like the perforated edge of real 35mm film stock. Fixed to the
   viewport (not the page), so the frame stays put while the site scrolls
   behind it. Built as a CSS mask (opaque strip, holes punched transparent)
   rather than an image, so it's crisp at any zoom and costs no request.
   ========================================================================== */
.filmstrip-edge{
  position:fixed;top:0;bottom:0;width:26px;z-index:120;pointer-events:none;
  background:linear-gradient(90deg,rgba(0,0,0,.92),rgba(0,0,0,.72));
  transition:box-shadow .6s ease;
  -webkit-mask-repeat:repeat-y;mask-repeat:repeat-y;
  -webkit-mask-size:26px 54px;mask-size:26px 54px;
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='54'%3E%3Crect width='26' height='54' fill='white'/%3E%3Crect x='7' y='18' width='12' height='18' rx='4' fill='black'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='54'%3E%3Crect width='26' height='54' fill='white'/%3E%3Crect x='7' y='18' width='12' height='18' rx='4' fill='black'/%3E%3C/svg%3E");
}
.filmstrip-edge--left{left:0;box-shadow:inset -1px 0 0 rgba(255,255,255,.1),inset -3px 0 0 rgba(45,125,210,.28);}
.filmstrip-edge--right{right:0;box-shadow:inset 1px 0 0 rgba(255,255,255,.1),inset 3px 0 0 rgba(45,125,210,.28);}
@media(max-width:700px){
  .filmstrip-edge{
    width:16px;-webkit-mask-size:16px 38px;mask-size:16px 38px;
    -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='38'%3E%3Crect width='16' height='38' fill='white'/%3E%3Crect x='4' y='12' width='8' height='13' rx='3' fill='black'/%3E%3C/svg%3E");
    mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='38'%3E%3Crect width='16' height='38' fill='white'/%3E%3Crect x='4' y='12' width='8' height='13' rx='3' fill='black'/%3E%3C/svg%3E");
  }
}

.wrap{max-width:1320px;margin:0 auto;padding:0 24px;}
@media(min-width:1024px){.wrap{padding:0 48px;}}

.eyebrow{
  font-family:var(--font-mono);font-size:12px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--dim);display:inline-flex;align-items:center;gap:10px;
}
.eyebrow::before{content:'';width:22px;height:1px;background:var(--gold);display:inline-block;}
.eyebrow.center{justify-content:center;}
.eyebrow.center::before{display:none;}

h1,h2,h3,h4{font-family:var(--font-display);font-weight:600;text-transform:uppercase;letter-spacing:-.01em;line-height:.95;margin:0;}

/* ---- kinetic display sizes ---- */
.h-hero{font-size:clamp(2.8rem,8.4vw,7.2rem);line-height:1.06;letter-spacing:-.02em;}
.h-huge{font-size:clamp(2.4rem,7vw,5.6rem);line-height:.94;}
.h-xl{font-size:clamp(2rem,4.6vw,3.6rem);}
.h-lg{font-size:clamp(1.6rem,3.2vw,2.4rem);}

.text-blue{color:var(--blue);}
.text-red{color:var(--red);}
.text-gold{color:var(--gold);}
.text-dim{color:var(--dim);font-weight:400;text-transform:none;}

.lede{font-family:var(--font-body);font-weight:300;color:var(--dim);font-size:clamp(1rem,1.6vw,1.25rem);line-height:1.6;}

.accent{height:3px;width:56px;border-radius:2px;}
.accent.blue{background:linear-gradient(90deg,var(--blue),transparent);}
.accent.red{background:linear-gradient(90deg,var(--red),transparent);}
.accent.gold{background:linear-gradient(90deg,var(--gold),transparent);}
.accent.center{margin-left:auto;margin-right:auto;}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--font-display);font-weight:600;text-transform:uppercase;letter-spacing:.05em;
  font-size:13.5px;padding:16px 30px;border-radius:6px;transition:all .25s cubic-bezier(.2,.8,.2,1);
  white-space:nowrap;border:1px solid transparent;cursor:pointer;
}
.btn-primary{background:var(--blue);color:#fff;box-shadow:0 14px 30px -10px rgba(45,125,210,.45);}
.btn-primary:hover{background:#3d8ce0;transform:translateY(-2px);box-shadow:0 18px 36px -8px rgba(45,125,210,.55);}
.btn-ghost{border-color:rgba(255,255,255,.22);color:#fff;}
.btn-ghost:hover{border-color:rgba(255,255,255,.5);background:rgba(255,255,255,.05);transform:translateY(-2px);}
.btn-sm{padding:12px 22px;font-size:12px;}

/* ---- reveal-on-scroll ----
   Base variant is a fade-up. The modifiers below give each section its own
   entrance so the page reads as a sequence of distinct arrivals — zooms,
   slides, fades — instead of one continuous scroll, per section. Applied
   via IntersectionObserver in script.js (unchanged: it just toggles
   is-visible on anything carrying .reveal, so no JS needed per variant). */
.reveal{opacity:0;transform:translateY(34px);transition:opacity .9s cubic-bezier(.16,1,.3,1),transform .9s cubic-bezier(.16,1,.3,1),filter .9s cubic-bezier(.16,1,.3,1);will-change:opacity,transform,filter;}
.reveal.is-visible{opacity:1;transform:translateY(0);}
.reveal.blur-in{filter:blur(10px);}
.reveal.blur-in.is-visible{filter:blur(0);}

/* zoom-in — section materializes out of a soft close-up, like a lens
   racking into focus */
.reveal.zoom-in{transform:scale(.78);filter:blur(9px);}
.reveal.zoom-in.is-visible{transform:scale(1);filter:blur(0);}

/* zoom-out — section starts oversized, as if the camera were pressed
   right up against it, then eases back to its normal size */
.reveal.zoom-out{transform:scale(1.24);filter:blur(9px);}
.reveal.zoom-out.is-visible{transform:scale(1);filter:blur(0);}

/* slide-left / slide-right — section arrives from off to one side rather
   than straight up, echoing the horizontal drift used elsewhere */
.reveal.slide-left{transform:translateX(64px);}
.reveal.slide-left.is-visible{transform:translateX(0);}
.reveal.slide-right{transform:translateX(-64px);}
.reveal.slide-right.is-visible{transform:translateX(0);}
@media(prefers-reduced-motion:reduce){.reveal,.marquee-track,.band-track,.clients-track{transition:none!important;animation:none!important;opacity:1!important;transform:none!important;filter:none!important;}}
@media(prefers-reduced-motion:reduce){#hero::before,.chapter::before,.podcast::before,.cta-banner::before{animation:none!important;}}

/* ==========================================================================
   NAV
   ========================================================================== */
#nav{
  position:fixed;top:0;left:0;right:0;z-index:100;
  padding:20px 0;transition:padding .35s ease,background-color .35s ease,border-color .35s ease,backdrop-filter .35s ease;
  border-bottom:1px solid transparent;
}
#nav.scrolled{
  padding:12px 0;background:rgba(20,22,27,.82);backdrop-filter:blur(16px);
  border-color:var(--line);
}
#nav .wrap{display:flex;align-items:center;justify-content:space-between;}
.nav-brand{display:flex;align-items:center;gap:12px;cursor:pointer;}
.nav-brand img{height:34px;width:auto;}
.nav-brand span{font-family:var(--font-display);font-weight:600;font-size:14px;letter-spacing:.16em;text-transform:uppercase;}
.nav-links{display:none;align-items:center;gap:2px;}
@media(min-width:900px){.nav-links{display:flex;}}
.nav-links a{
  position:relative;font-family:var(--font-body);font-weight:500;font-size:13px;letter-spacing:.03em;
  color:var(--dim);padding:10px 16px;border-radius:5px;transition:color .2s;
}
.nav-links a:hover{color:#fff;}
.nav-links a::after{
  content:'';position:absolute;left:16px;right:16px;bottom:6px;height:2px;
  background:linear-gradient(90deg,var(--blue),var(--gold));border-radius:1px;
  transform:scaleX(0);transform-origin:left;transition:transform .3s cubic-bezier(.2,.8,.2,1);
}
.nav-links a:hover::after{transform:scaleX(1);}
.nav-links a.active{color:#fff;}
.nav-links a.active::after{transform:scaleX(1);background:linear-gradient(90deg,var(--blue),var(--gold));}
#mobile-menu a.active{color:var(--blue);}
.nav-cta{display:none;}
@media(min-width:900px){.nav-cta{display:inline-flex;margin-left:8px;}}
.nav-burger{display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:none;border:0;color:#fff;cursor:pointer;}
@media(min-width:900px){.nav-burger{display:none;}}

#mobile-menu{
  position:fixed;inset:0;z-index:99;background:var(--dark);overflow-y:auto;
  display:flex;flex-direction:column;justify-content:center;padding:100px 32px 48px;
  transform:translateY(-100%);transition:transform .4s cubic-bezier(.16,1,.3,1);
}
#mobile-menu.open{transform:translateY(0);}
#mobile-menu a{
  font-family:var(--font-display);font-size:clamp(1.8rem,8vw,3rem);text-transform:uppercase;font-weight:600;
  padding:14px 0;border-bottom:1px solid var(--line);color:#fff;flex-shrink:0;
}
#mobile-menu .mm-cta{margin-top:28px;flex-shrink:0;}

/* ==========================================================================
   HERO — pinned inside .hero-stage below so it can zoom out from Mads's
   face and fade as you scroll, instead of just scrolling past like every
   other section. See the JS hero-zoom block for the scroll math.
   ========================================================================== */
.hero-stage{position:relative;height:170vh;}
@media(prefers-reduced-motion:reduce){.hero-stage{height:auto;}}
#hero{
  min-height:100svh;position:sticky;top:0;overflow:hidden;
  display:flex;align-items:flex-end;
  background:
    radial-gradient(ellipse 90% 60% at 78% 8%,rgba(45,125,210,.16),transparent 60%),
    radial-gradient(ellipse 70% 50% at 10% 100%,rgba(230,57,70,.10),transparent 60%),
    var(--charcoal);
  padding-top:120px;
  transform-origin:80% 24%;
  will-change:transform,opacity,filter;
}
@media(prefers-reduced-motion:reduce){#hero{position:relative;}}
#hero::before{
  content:'';position:absolute;inset:-20%;z-index:0;pointer-events:none;
  background:
    radial-gradient(32% 32% at 78% 8%,rgba(45,125,210,.22),transparent 70%),
    radial-gradient(28% 28% at 10% 100%,rgba(230,57,70,.15),transparent 70%);
  animation:glowDrift 24s ease-in-out infinite alternate;
}
/* photo is centered and sized up close to Mads's face (landonorris.com-style
   centered hero portrait) rather than tucked off to one side. Centering via
   left/right/margin — not transform — because the mouse-parallax JS below
   sets .style.transform directly on this element every mousemove, which
   would otherwise wipe out a transform-based centering trick. */
.hero-photo-wrap{
  /* full hero width now (was capped at min(70vw,880px)) so the showreel
     layer inside — which shares this box via inset:0 — covers the whole
     hero edge to edge; .hero-photo itself keeps its own width:auto
     intrinsic sizing below, so the portrait stays exactly as compact and
     centered as before, just inside a wider box. */
  position:absolute;left:0;right:0;bottom:0;top:0;
  display:flex;align-items:flex-end;justify-content:center;
  pointer-events:none;z-index:1;will-change:transform;
  transition:transform .5s cubic-bezier(.2,.8,.2,1);
}
/* ---- hero hover-reveal text ----
   What the cursor-tracked porthole in the video layer above uncovers —
   see .hero-video's mask-image. The video sits fully opaque over this, so
   it's invisible until you hover; there's no photo behind it any more
   (moved down to sit with the quote in chapter 1, where it reads better
   next to what Mads is actually saying). Set vertically along the right
   edge — like a spine label or a film edge-code — rather than centered,
   so it reads as a found detail rather than a second headline. */
.hero-reveal-text{
  position:absolute;inset:0;z-index:1;
  display:flex;align-items:center;justify-content:flex-end;
  padding:6% clamp(20px,6vw,88px) 6% 0;
}
.hero-reveal-text p{
  writing-mode:vertical-rl;text-orientation:mixed;
  font-family:var(--font-display);font-weight:500;text-transform:none;
  letter-spacing:-.01em;line-height:1.3;
  font-size:clamp(1.15rem,2.2vw,1.7rem);color:rgba(244,244,237,.94);
  max-height:72vh;margin:0;
}
@media(max-width:900px){
  .hero-reveal-text{padding:6% clamp(14px,5vw,32px) 6% 0;}
  .hero-reveal-text p{font-size:clamp(1rem,3.4vw,1.3rem);max-height:60vh;}
}

/* ---- hero showreel layer ----
   Sits over the photo at reduced opacity so the headline stays legible,
   filling the same centered column the photo lives in. Hovering (see the
   hero-mousemove JS below) opens a circular "porthole" through the video —
   masking it out rather than the photo, so the sharp portrait shows through
   right where the cursor is, landonorris.com-style — and eases shut again
   on mouseleave instead of just snapping away. */
.hero-video-layer{position:absolute;inset:0;z-index:2;overflow:hidden;pointer-events:none;}
.hero-video{
  width:100%;height:100%;object-fit:cover;object-position:center;display:block;
  /* darkened, not translucent — opacity would let the photo bleed through
     everywhere underneath it; a brightness filter keeps the video fully
     opaque so the photo is only ever visible through the hover-porthole */
  filter:brightness(.36) contrast(1.08);
  -webkit-mask-image:radial-gradient(circle var(--reveal-r,0px) at var(--mx,50%) var(--my,42%),transparent 0%,transparent 58%,black 82%);
  mask-image:radial-gradient(circle var(--reveal-r,0px) at var(--mx,50%) var(--my,42%),transparent 0%,transparent 58%,black 82%);
}
@media(prefers-reduced-motion:reduce){.hero-video-layer{display:none;}}
/* touch devices never get a cursor to open the porthole with, so skip the
   video layer entirely rather than just showing it permanently dimmed —
   script.js also never injects a <source> here on such devices, so this
   is belt-and-braces against the layer rendering (poster included) at all */
@media(pointer:coarse){.hero-video-layer{display:none;}}

/* ---- hero static-photo fallback ----
   Stands in for the video layer wherever that's hidden (reduced motion,
   coarse pointer) — same footprint/z-index, so the two are a straight
   swap and never both show at once. */
.hero-photo-fallback{
  display:none;position:absolute;inset:0;z-index:2;
  width:100%;height:100%;object-fit:cover;object-position:top center;
}
@media(prefers-reduced-motion:reduce){.hero-photo-fallback{display:block;}}
@media(pointer:coarse){.hero-photo-fallback{display:block;}}

.hero-photo-fade{
  position:absolute;left:0;right:0;bottom:0;height:52%;z-index:3;
  background:linear-gradient(180deg,transparent,var(--charcoal) 88%);
}
.hero-photo-fade-side{
  position:absolute;inset:0;z-index:3;
  background:linear-gradient(90deg,var(--charcoal),transparent 22%,transparent 78%,var(--charcoal));
}
@media(max-width:900px){
  .hero-photo-wrap{position:relative;width:100%;top:auto;height:52vh;order:-1;margin-bottom:8px;}
  #hero{flex-direction:column;padding-top:100px;}
  #hero .wrap{width:100%;}
}

.hero-inner{
  position:relative;z-index:2;width:100%;padding-bottom:56px;
  display:flex;flex-direction:column;align-items:center;text-align:center;
}
/* hero-kicker/cta-row/title-lines/status-chip below all sit at their
   pre-animation resting state (opacity:0 / off-screen) by default, and
   only actually PLAY their entrance animation once body.loaded is set —
   see the "site loader" block in script.js. Without that gate they'd run
   to completion hidden behind the loader and the visitor would only ever
   see the settled end state; this way the kinetic reveal actually plays
   out once the loader clears instead of being wasted underneath it. */
.hero-kicker{display:flex;align-items:center;justify-content:center;gap:12px;margin-bottom:22px;
  opacity:0;transform:translateY(14px);}
body.loaded .hero-kicker{animation:fadeUp .7s cubic-bezier(.16,1,.3,1) .15s forwards;}
.hero-kicker img{height:30px;width:auto;}
.hero-cta-row{display:flex;flex-direction:column;align-items:center;gap:24px;margin-top:32px;
  opacity:0;transform:translateY(14px);}
body.loaded .hero-cta-row{animation:fadeUp .7s cubic-bezier(.16,1,.3,1) 1.05s forwards;}
.hero-buttons{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;}
@keyframes fadeUp{to{opacity:1;transform:translateY(0);}}

/* hero headline — line-by-line kinetic reveal */
.hero-title .line{overflow:hidden;display:block;}
.hero-title .line span{display:block;transform:translateY(112%);}
body.loaded .hero-title .line span{animation:lineUp .85s cubic-bezier(.16,1,.3,1) forwards;}
.hero-title .line:nth-child(1) span{animation-delay:.42s;}
.hero-title .line:nth-child(2) span{animation-delay:.55s;}
.hero-title .line:nth-child(3) span{animation-delay:.68s;}
@keyframes lineUp{to{transform:translateY(0);}}
@media(prefers-reduced-motion:reduce){
  .hero-kicker,.hero-cta-row{opacity:1;transform:none;animation:none;}
  .hero-title .line span{transform:none;animation:none;}
}

.scroll-cue{
  position:absolute;bottom:22px;left:50%;transform:translateX(-50%);z-index:5;
  display:flex;flex-direction:column;align-items:center;gap:8px;color:var(--faint);
}
.scroll-cue .line{width:1px;height:34px;background:linear-gradient(180deg,var(--gold),transparent);animation:scrollcue 1.8s ease-in-out infinite;}
@keyframes scrollcue{0%{transform:scaleY(0);transform-origin:top;}50%{transform:scaleY(1);transform-origin:top;}51%{transform:scaleY(1);transform-origin:bottom;}100%{transform:scaleY(0);transform-origin:bottom;}}

/* ==========================================================================
   KINETIC BAND ("message from Mads" style)
   Pinned directly under the hero, like landonorris.com's own act two: the
   hero zooms out (see hero-zoom above), then this band pins to the
   viewport and its text sweeps leftward as you keep scrolling — a second,
   distinct beat of motion instead of a passive marquee that loops on its
   own timer. See the "kinetic band scroll-sweep" block in script.js.
   ========================================================================== */
.band-stage{position:relative;height:260vh;}
@media(max-width:700px){.band-stage{height:190vh;}}
@media(prefers-reduced-motion:reduce){.band-stage{height:auto;}}
.band{
  /* full 100vh (not a partial min-height) — this pins over the *entire*
     viewport, so there's no gap of bare page background left showing
     below it while it's pinned, the way a shorter box left one before. */
  position:sticky;top:0;overflow:hidden;min-height:100vh;display:flex;align-items:center;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--dark);
}
@media(max-width:700px){.band{min-height:100vh;}}
@media(prefers-reduced-motion:reduce){.band{position:relative;min-height:auto;padding:26px 0;}}
.band-track{display:flex;width:max-content;gap:3.5rem;will-change:transform;position:relative;z-index:1;}
.band-track span{
  font-family:var(--font-display);font-weight:600;text-transform:uppercase;
  font-size:clamp(1.6rem,4.4vw,3.2rem);letter-spacing:-.01em;color:transparent;
  -webkit-text-stroke:1.5px rgba(255,255,255,.28);white-space:nowrap;
  display:flex;align-items:center;gap:3.5rem;
}
.band-track span b{color:var(--gold);-webkit-text-stroke:0;font-weight:600;}

/* ---- photo-drop stack ----
   Nine shots drop in one at a time as you scroll through the band (see the
   "photo-drop stack" block in script.js, driven by the same band-progress
   math as the text sweep above), like prints being tossed onto a light
   table — with a multi-shutter camera sound firing once the first photo
   lands. Each photo links straight out to Instagram. */
.photo-drop-stack{
  position:absolute;inset:0;z-index:4;pointer-events:none;
  --scatter:1;
}
@media(max-width:700px){.photo-drop-stack{--scatter:.5;}}
.photo-drop-item{
  position:absolute;left:50%;top:50%;pointer-events:auto;
  width:clamp(96px,14vw,176px);aspect-ratio:4/5;
  padding:7px 7px 20px;background:#F4F4F0;border-radius:3px;
  box-shadow:0 18px 34px -12px rgba(0,0,0,.65),0 2px 6px rgba(0,0,0,.3);
  transform:translate(-50%,-50%) translate(calc(var(--dx) * var(--scatter)),calc((var(--dy) - 320px) * var(--scatter))) rotate(0deg);
  opacity:0;
  transition:transform .85s cubic-bezier(.22,1.4,.36,1),opacity .5s ease-out;
  will-change:transform,opacity;
}
.photo-drop-item.is-dropped{
  opacity:1;
  transform:translate(-50%,-50%) translate(calc(var(--dx) * var(--scatter)),calc(var(--dy) * var(--scatter))) rotate(var(--rot));
}
.photo-drop-item:hover,.photo-drop-item:focus-visible{
  transform:translate(-50%,-50%) translate(calc(var(--dx) * var(--scatter)),calc(var(--dy) * var(--scatter))) rotate(0deg) scale(1.08);
  z-index:5;transition-duration:.3s;
}
.photo-drop-item img{width:100%;height:100%;object-fit:cover;display:block;border-radius:1px;}
@media(prefers-reduced-motion:reduce){
  .photo-drop-item{transition:opacity .4s ease-out;transform:translate(-50%,-50%) translate(calc(var(--dx) * var(--scatter)),calc(var(--dy) * var(--scatter))) rotate(var(--rot));}
}

.photo-drop-hint{
  position:absolute;left:50%;bottom:28px;transform:translateX(-50%);z-index:6;
  display:flex;align-items:center;gap:8px;padding:10px 18px;border-radius:30px;
  background:rgba(20,22,27,.72);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.14);
  font-family:var(--font-display);font-size:12.5px;font-weight:600;letter-spacing:.04em;
  color:var(--dim);transition:color .25s,border-color .25s,transform .25s;
}
.photo-drop-hint svg{width:16px;height:16px;flex-shrink:0;}
.photo-drop-hint:hover{color:#fff;border-color:rgba(45,125,210,.5);transform:translateX(-50%) translateY(-2px);}
@media(max-width:700px){.photo-drop-hint{bottom:14px;padding:8px 14px;font-size:11px;}}

/* ==========================================================================
   QUOTE / MANIFESTO
   ========================================================================== */
.quote-section{padding:110px 0;text-align:center;position:relative;border-bottom:1px solid var(--line);}
.quote-mark{font-family:var(--font-display);font-size:5rem;color:var(--blue);opacity:.35;line-height:1;margin-bottom:10px;}
.quote-huge{
  font-family:var(--font-display);font-weight:500;text-transform:none;letter-spacing:-.01em;
  line-height:1.18;font-size:clamp(1.5rem,3.2vw,2.6rem);max-width:920px;margin:0 auto;
}
/* portrait accompanying the quote — sits below the statement it belongs
   to (rather than the old hero treatment, dimmed behind a video off at
   the top of the page) so it's clear at a glance whose words these are */
.quote-portrait{
  margin:32px auto 14px;width:118px;height:118px;border-radius:50%;overflow:hidden;
  border:2px solid rgba(45,125,210,.45);box-shadow:0 16px 34px -12px rgba(0,0,0,.65);
}
.quote-portrait img{width:100%;height:100%;object-fit:cover;object-position:top center;}
.quote-attr{margin-top:0;}

.manifesto{padding:100px 0;border-bottom:1px solid var(--line);}
.manifesto-row{display:grid;grid-template-columns:1fr;gap:14px;}
.manifesto-item{
  display:grid;grid-template-columns:1fr;gap:10px;padding:26px 0;border-top:1px solid var(--line);
}
@media(min-width:800px){
  .manifesto-item{grid-template-columns:1.4fr 1fr;align-items:center;gap:40px;}
}
.manifesto-item:last-child{border-bottom:1px solid var(--line);}
.manifesto-num{font-family:var(--font-mono);color:var(--faint);font-size:13px;}
.manifesto-item h3{font-size:clamp(1.8rem,4.2vw,3.2rem);}
.manifesto-item--emphasis{padding:44px 0;}
.manifesto-item--emphasis h3{font-size:clamp(2.4rem,6vw,4.6rem);}
.manifesto-item--emphasis .lede{font-size:clamp(1.05rem,1.9vw,1.4rem);}

/* ==========================================================================
   STATS
   ========================================================================== */
.stats{padding:64px 0;border-bottom:1px solid var(--line);background:var(--dark);}
.stats-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:32px;text-align:center;align-items:end;}
@media(min-width:800px){.stats-grid{grid-template-columns:repeat(4,1fr);}}
.stat-num{font-family:var(--font-display);font-weight:700;font-size:clamp(2.2rem,5vw,3.4rem);font-variant-numeric:tabular-nums;line-height:1;margin-bottom:8px;}
.stat-num--xl{font-size:clamp(3.2rem,8vw,5.6rem);}

/* ==========================================================================
   SHOWREEL
   ========================================================================== */
.section-head{margin-bottom:52px;}
.section-head.center{text-align:center;}
.section-head h2{margin-top:14px;}
.section-head p{margin-top:16px;}

#showreel{padding:110px 0;border-bottom:1px solid var(--line);}
.reel-frame{
  position:relative;border-radius:14px;overflow:hidden;border:1px solid var(--line);
  background:#000;aspect-ratio:16/9;box-shadow:0 40px 90px -30px rgba(0,0,0,.7);
}
.reel-frame img{width:100%;height:100%;object-fit:cover;opacity:.75;transition:opacity .4s;
  animation:kenburns 22s ease-in-out infinite alternate;}
.reel-frame:hover img{opacity:.55;}
@keyframes kenburns{0%{transform:scale(1.0);}100%{transform:scale(1.09);}}
@media(prefers-reduced-motion:reduce){.reel-frame img{animation:none;}}
.reel-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0;}
.play-btn{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:84px;height:84px;border-radius:50%;background:rgba(45,125,210,.92);
  display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px);
  transition:all .25s;cursor:pointer;z-index:2;
}
.play-btn:hover{background:var(--blue);transform:translate(-50%,-50%) scale(1.1);}
.play-tri{width:0;height:0;border-top:14px solid transparent;border-bottom:14px solid transparent;border-left:22px solid #fff;margin-left:4px;}
.reel-caption{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:16px;margin-top:24px;}

.filmstrip{display:flex;gap:16px;overflow-x:auto;padding:32px 0 8px;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;}
.filmstrip::-webkit-scrollbar{height:6px;}
.filmstrip::-webkit-scrollbar-thumb{background:var(--line);border-radius:3px;}
.film-card{
  flex:0 0 auto;width:260px;scroll-snap-align:start;cursor:pointer;
  border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--surface);
  transition:transform .3s cubic-bezier(.2,.8,.2,1),border-color .3s;
}
.film-card:hover{transform:translateY(-6px);border-color:rgba(45,125,210,.45);}
.film-thumb{position:relative;aspect-ratio:16/9;background:#000;overflow:hidden;}
.film-thumb img{width:100%;height:100%;object-fit:cover;transition:transform .5s;}
.film-card:hover .film-thumb img{transform:scale(1.06);}
.film-thumb .mini-play{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(20,22,27,.25);}
.film-thumb .mini-play svg{width:34px;height:34px;filter:drop-shadow(0 2px 6px rgba(0,0,0,.5));}
.film-dur{position:absolute;bottom:6px;right:8px;font-family:var(--font-mono);font-size:11px;background:rgba(0,0,0,.7);padding:2px 6px;border-radius:4px;}
.film-info{padding:14px 16px;}
.film-info h4{font-size:14px;font-weight:700;letter-spacing:0;text-transform:none;line-height:1.3;font-family:var(--font-body);}
.film-info span{display:block;margin-top:6px;}

/* ==========================================================================
   SPLIT TILES  (På skærmen / Bag kameraet)
   ========================================================================== */
.split{padding:110px 0;border-bottom:1px solid var(--line);}
.split-grid{display:grid;grid-template-columns:1fr;gap:22px;}
@media(min-width:820px){.split-grid{grid-template-columns:1fr 1fr;}}
.split-tile{
  position:relative;overflow:hidden;border-radius:12px;aspect-ratio:4/5;
  border:1px solid var(--line);background:var(--surface);cursor:pointer;
}
@media(min-width:820px){.split-tile{aspect-ratio:3/4;}}
.split-tile img{width:100%;height:100%;object-fit:cover;opacity:.55;transition:transform .8s cubic-bezier(.2,.8,.2,1),opacity .4s;}
.split-tile:hover img{transform:scale(1.08);opacity:.72;}
.split-tile .tile-overlay{position:absolute;inset:0;background:linear-gradient(180deg,rgba(20,22,27,.1) 15%,rgba(20,22,27,.97) 90%);}
.split-tile .tile-content{position:absolute;left:0;right:0;bottom:0;padding:34px;}
.split-tile h3{font-size:clamp(1.8rem,3.4vw,2.6rem);margin-bottom:12px;}
.split-tile p{max-width:360px;margin-bottom:16px;}

/* ==========================================================================
   SERVICES (Ydelser)
   ========================================================================== */
.services{padding:110px 0;border-bottom:1px solid var(--line);background:var(--dark);}
.services-grid{display:grid;grid-template-columns:1fr;gap:1px;background:var(--line);border:1px solid var(--line);border-radius:14px;overflow:hidden;}
@media(min-width:860px){.services-grid{grid-template-columns:1.35fr 1fr 1fr;}}
.service-card{background:var(--charcoal);padding:40px 32px;transition:background .3s;position:relative;overflow:hidden;}
.service-card--featured{padding:48px 36px;}
.service-card--featured h3{font-size:2.1rem;}
.service-card--featured .service-icon{width:56px;height:56px;}
.service-card--featured .service-icon svg{width:26px;height:26px;}
.service-card:hover{background:var(--surface);}
.service-card::before{
  content:'';position:absolute;left:var(--mx,50%);top:var(--my,30%);width:340px;height:340px;
  transform:translate(-50%,-50%);border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(45,125,210,.16),transparent 70%);
  opacity:0;transition:opacity .4s;
}
.service-card:hover::before{opacity:1;}
.service-icon{width:46px;height:46px;border-radius:10px;display:flex;align-items:center;justify-content:center;margin-bottom:24px;}
.service-icon svg{width:22px;height:22px;}
.service-card h3{font-size:1.6rem;margin-bottom:14px;}
.service-list{margin:20px 0 0;padding:0;list-style:none;display:flex;flex-direction:column;gap:10px;}
.service-list li{display:flex;gap:10px;font-size:13.5px;color:var(--dim);font-weight:400;line-height:1.4;}
.service-list li::before{content:'';width:5px;height:5px;border-radius:50%;background:currentColor;margin-top:7px;flex-shrink:0;opacity:.6;}

/* ==========================================================================
   PORTFOLIO GRID
   ========================================================================== */
#portfolio{padding:110px 0;border-bottom:1px solid var(--line);}
/* one pile per category, each its own little scattered stack of polaroids
   rather than one flat undifferentiated grid */
.case-pile{margin-top:56px;}
.case-pile:first-of-type{margin-top:0;}
.case-pile-title{
  display:flex;align-items:center;gap:10px;
  font-family:var(--font-display);font-size:clamp(1.1rem,2vw,1.5rem);font-weight:700;
  text-transform:uppercase;letter-spacing:.02em;color:var(--dim);
  margin:0 0 24px;padding-bottom:14px;border-bottom:1px solid var(--line);
}
.case-pile-title::before{content:'';width:8px;height:8px;border-radius:50%;background:var(--blue);flex-shrink:0;}
/* ---- real overlapping pile, not a grid ----
   Same idea as the homepage photo-drop stack: flex-wrap with a negative
   right margin on every card so each one overlaps the next, instead of
   sitting in its own clean grid cell. DOM order gives the base stacking
   (later cards naturally paint over earlier ones); hover pulls a card to
   the very front with z-index so it can be read clearly out of the pile. */
.case-grid{display:flex;flex-wrap:wrap;align-items:flex-start;padding:24px 8px 8px;}
/* ---- polaroid treatment ----
   Same white-bordered, printed-photo card as the homepage's photo-drop
   stack, so the portfolio grid reads as a stack of instant prints rather
   than a generic thumbnail grid. The client/case name only shows up once
   you hover — like flipping over a print to read the label on the back —
   instead of being printed on the card permanently. */
.case-card{
  --rot:0deg;--ty:0px;
  position:relative;z-index:1;
  flex:0 0 auto;width:clamp(150px,19vw,216px);
  margin:0 -34px 26px 0;
  display:flex;flex-direction:column;cursor:pointer;
  background:#F4F4F0;border-radius:3px;padding:8px 8px 6px;
  box-shadow:0 18px 34px -16px rgba(0,0,0,.6),0 2px 8px rgba(0,0,0,.25);
  /* replaces .reveal's own transition list wholesale (equal specificity,
     later in the cascade) — so it has to restate the opacity fade too,
     not just the bouncier transform, or the fade-in silently stops */
  transition:opacity .9s cubic-bezier(.16,1,.3,1),transform .5s cubic-bezier(.22,1.4,.36,1),box-shadow .35s;
}
.case-card.is-wide{width:clamp(300px,38vw,432px);}
/* a little scattered instead of perfectly grid-locked, the same idea as
   the homepage photo-drop stack — each card sits at a small resting tilt
   and vertical stagger (skipped on the wide feature cards, where it reads
   as messy rather than casual) and straightens out on hover, echoing the
   same bounce that settles the dropped photos into place. Combined
   explicitly with the .reveal entrance transform below so the two don't
   clobber each other — same fix as the trust-wall's permanent tilt
   earlier in this file. */
.case-card:nth-child(6n+1){--rot:-2.4deg;--ty:6px;}
.case-card:nth-child(6n+2){--rot:1.8deg;--ty:-10px;}
.case-card:nth-child(6n+3){--rot:-1.2deg;--ty:2px;}
.case-card:nth-child(6n+4){--rot:2.6deg;--ty:-6px;}
.case-card:nth-child(6n+5){--rot:-2deg;--ty:8px;}
.case-card:nth-child(6n+6){--rot:1.4deg;--ty:-4px;}
.case-card.is-wide{--rot:0deg;--ty:0px;}
.case-card.reveal{transform:translateY(calc(var(--ty) + 34px)) rotate(var(--rot)) scale(.96);}
.case-card.reveal.is-visible{transform:translateY(var(--ty)) rotate(var(--rot)) scale(1);}
/* .reveal.is-visible above is 3 classes deep — plain .case-card:hover
   (2 selectors) loses that specificity fight and silently never applies
   once a card has settled in, so this has to match it class-for-class */
.case-card.reveal.is-visible:hover{
  transform:translateY(calc(var(--ty) - 10px)) rotate(0deg) scale(1.08);
  box-shadow:0 30px 50px -18px rgba(0,0,0,.75),0 4px 10px rgba(0,0,0,.3);
  transition:transform .4s cubic-bezier(.22,1.4,.36,1),box-shadow .35s;
  z-index:10;
}
@media(prefers-reduced-motion:reduce){.case-card{--rot:0deg;--ty:0px;}}
@media(max-width:700px){.case-card{margin-right:-22px;}}
.case-photo{position:relative;aspect-ratio:4/5;border-radius:1px;overflow:hidden;background:#000;}
.case-card.is-wide .case-photo{aspect-ratio:16/9;}
.case-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.88;transition:transform .6s,opacity .3s;}
.case-card:hover .case-photo img{transform:scale(1.08);opacity:.7;}
/* title + category stay hidden — printed on the back of the print, so to
   speak — until the card is drawn out of the pile on hover */
.case-info{padding:12px 6px 8px;opacity:0;transform:translateY(-4px);transition:opacity .25s ease,transform .25s ease;}
.case-card:hover .case-info{opacity:1;transform:translateY(0);}
.case-card h4{font-family:var(--font-display);font-size:14px;font-weight:700;line-height:1.25;text-transform:uppercase;color:var(--charcoal);}
.case-card .case-tag{margin-top:5px;color:rgba(26,29,35,.62);}
.case-card .case-tag::before{background:var(--red);}
.case-photo .mini-play{position:absolute;top:10px;right:10px;width:34px;height:34px;border-radius:50%;background:rgba(20,22,27,.55);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px);}
.case-photo .mini-play svg{width:14px;height:14px;}

/* ==========================================================================
   CHAPTER 06 — TRUST WALL
   Replaces the old white/light chapter (it clashed with the rest of the
   dark cinematic palette). Stays dark like every other chapter but gets
   its own identity: two rows of names tilted off the horizontal and
   drifting in opposite directions, so "trusted by" reads as a slab of
   motion on a diagonal rather than a plain static logo strip.
   ========================================================================== */
.chapter--trust{background:var(--dark);min-height:auto;padding:120px 0 140px;}
.chapter--trust::before{--glow:rgba(212,168,67,.16);}
.trust-wall{margin-top:60px;display:flex;flex-direction:column;gap:20px;transform:rotate(-2deg) scale(1.05);}
/* .trust-wall's permanent tilt has to survive the .reveal fade — combine
   both transforms explicitly so the entrance motion doesn't just clobber
   the tilt (equal-specificity single-class rules would otherwise fight
   on source order) */
.trust-wall.reveal.zoom-in{transform:rotate(-2deg) scale(.8);filter:blur(6px);}
.trust-wall.reveal.zoom-in.is-visible{transform:rotate(-2deg) scale(1.05);filter:blur(0);}
.clients-wrap{overflow:hidden;-webkit-mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent);mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent);}
.clients-track{display:flex;width:max-content;gap:1.1rem;align-items:center;animation:marquee 34s linear infinite;}
.clients-track--reverse{animation-name:marqueeReverse;animation-duration:40s;}
.clients-wrap:hover .clients-track{animation-play-state:paused;}
.clients-track span{
  font-family:var(--font-display);font-size:clamp(.95rem,1.7vw,1.3rem);font-weight:600;
  text-transform:uppercase;letter-spacing:.02em;color:var(--dim);white-space:nowrap;
  padding:14px 26px;border:1px solid var(--line);border-radius:8px;background:var(--surface);
  transition:color .3s,border-color .3s,background-color .3s,transform .3s;
}
.clients-track span:hover{color:#fff;border-color:rgba(212,168,67,.55);background:rgba(212,168,67,.1);transform:translateY(-3px);}
@keyframes marqueeReverse{from{transform:translateX(-50%);}to{transform:translateX(0);}}
@media(prefers-reduced-motion:reduce){.trust-wall{transform:none;}}

/* ==========================================================================
   PODCAST
   ========================================================================== */
.podcast{padding:110px 0;border-bottom:1px solid var(--line);position:relative;overflow:hidden;}
.podcast::before{
  content:'';position:absolute;inset:-20%;
  background:radial-gradient(ellipse 40% 40% at 85% 30%,rgba(230,57,70,.13),transparent 65%);
  pointer-events:none;animation:glowDrift 28s ease-in-out infinite alternate;
}
.podcast-grid{display:grid;grid-template-columns:1fr;gap:48px;align-items:center;position:relative;}
@media(min-width:900px){.podcast-grid{grid-template-columns:1fr 1fr;}}
.podcast-meta{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;margin-top:32px;}
.podcast-meta div{border-top:1px solid var(--line);padding-top:12px;}
.podcast-meta strong{display:block;font-family:var(--font-display);font-size:1.4rem;margin-bottom:2px;}
.podcast-art{
  aspect-ratio:1;border-radius:16px;border:1px solid var(--line);
  background:linear-gradient(155deg,var(--surface),var(--dark));
  display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden;
}
.podcast-art .ring{position:absolute;border-radius:50%;border:1px solid rgba(255,255,255,.08);}
.podcast-art .r1{width:70%;height:70%;border-top-color:rgba(230,57,70,.35);animation:spin 34s linear infinite;}
.podcast-art .r2{width:46%;height:46%;border-bottom-color:rgba(45,125,210,.35);animation:spin 22s linear infinite reverse;}
.podcast-art .mark{font-family:var(--font-display);font-size:clamp(1.6rem,3vw,2.2rem);text-align:center;line-height:1.1;}
@keyframes spin{to{transform:rotate(360deg);}}
@media(prefers-reduced-motion:reduce){.podcast-art .ring{animation:none;}}

/* ---- embedded social posts (Instagram guests, TikTok clips), piled ----
   Shared by both the Instagram guest-post section and the TikTok
   viral-clips section below — each card is the platform's own official
   oEmbed <blockquote> (their embed.js turns it into a live iframe on
   load), same "printed card on a dark page" feeling as the site's other
   polaroid treatments, just leaning on the platform's own white embed
   card instead of building a custom one, since its internal layout/
   branding isn't ours to restyle. Same real overlapping-pile technique
   as .case-grid: negative right margin so cards overlap, DOM order gives
   the base stacking, hover pulls one to the front. 330px is deliberate,
   not arbitrary — both Instagram's and TikTok's embeds enforce a hard
   ~326px minimum width internally, so this is as small as either
   platform allows it to render; the pile's tilt/overlap is what makes it
   read as compact rather than the card size itself. */
.embed-pile-grid{display:flex;flex-wrap:wrap;align-items:flex-start;padding:24px 8px 8px;}
.embed-pile-card{
  --rot:0deg;--ty:0px;
  position:relative;z-index:1;
  width:330px;margin:0 -70px 40px 0;
  transition:opacity .9s cubic-bezier(.16,1,.3,1),transform .5s cubic-bezier(.22,1.4,.36,1);
}
.embed-pile-card:nth-child(6n+1){--rot:-2.2deg;--ty:8px;}
.embed-pile-card:nth-child(6n+2){--rot:1.6deg;--ty:-10px;}
.embed-pile-card:nth-child(6n+3){--rot:-1.4deg;--ty:4px;}
.embed-pile-card:nth-child(6n+4){--rot:2deg;--ty:-6px;}
.embed-pile-card:nth-child(6n+5){--rot:-1.8deg;--ty:10px;}
.embed-pile-card:nth-child(6n+6){--rot:1.2deg;--ty:-4px;}
.embed-pile-card.reveal{transform:translateY(calc(var(--ty) + 34px)) rotate(var(--rot)) scale(.96);}
.embed-pile-card.reveal.is-visible{transform:translateY(var(--ty)) rotate(var(--rot)) scale(1);}
/* same specificity fix as the portfolio cards — .reveal.is-visible is 3
   classes deep, so plain :hover needs matching specificity to ever win */
.embed-pile-card.reveal.is-visible:hover{
  z-index:10;
  transform:translateY(calc(var(--ty) - 10px)) rotate(0deg) scale(1.05);
  transition:transform .4s cubic-bezier(.22,1.4,.36,1);
}
@media(prefers-reduced-motion:reduce){.embed-pile-card{--rot:0deg;--ty:0px;}}
@media(max-width:700px){.embed-pile-card{margin-right:-46px;}}

/* ==========================================================================
   CTA BANNER
   ========================================================================== */
.cta-banner{padding:130px 0;text-align:center;position:relative;overflow:hidden;border-bottom:1px solid var(--line);}
.cta-banner::before{
  content:'';position:absolute;inset:-20%;
  background:radial-gradient(ellipse 46% 46% at 50% 30%,rgba(45,125,210,.17),transparent 65%);
  animation:glowDrift 30s ease-in-out infinite alternate;
}
.cta-banner .inner{position:relative;max-width:760px;margin:0 auto;}
.cta-buttons{display:flex;flex-wrap:wrap;gap:16px;justify-content:center;margin-top:36px;}

/* ==========================================================================
   SOCIALS
   ========================================================================== */
.socials{padding:90px 0;border-bottom:1px solid var(--line);text-align:center;background:var(--dark);}
.social-row{display:flex;flex-wrap:wrap;justify-content:center;gap:14px;margin-top:36px;}
.social-btn{
  display:flex;align-items:center;gap:10px;padding:14px 24px;border-radius:8px;
  border:1px solid var(--line);font-family:var(--font-display);font-size:13px;font-weight:600;
  text-transform:uppercase;letter-spacing:.04em;transition:all .25s;
}
.social-btn svg{width:18px;height:18px;}
.social-btn:hover{transform:translateY(-3px);border-color:rgba(255,255,255,.35);background:rgba(255,255,255,.05);}

/* ==========================================================================
   FOOTER
   ========================================================================== */
footer{background:var(--dark);padding:80px 0 32px;}
.footer-top{display:grid;grid-template-columns:1fr;gap:48px;padding-bottom:56px;border-bottom:1px solid var(--line);}
@media(min-width:900px){.footer-top{grid-template-columns:1.4fr 1fr 1fr 1fr;}}
.footer-brand img{height:34px;margin-bottom:18px;}
.footer-tag{font-family:var(--font-display);font-size:1.4rem;text-transform:uppercase;line-height:1.15;max-width:280px;}
.footer-col h5{font-family:var(--font-mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--faint);margin-bottom:18px;}
.footer-col a,.footer-col p{display:block;color:var(--dim);font-size:14px;margin-bottom:12px;font-weight:400;transition:color .2s;}
.footer-col a:hover{color:#fff;}
.footer-bottom{display:flex;flex-wrap:wrap;justify-content:space-between;gap:16px;padding-top:28px;font-size:12.5px;color:var(--faint);font-family:var(--font-mono);}
.footer-bottom a:hover{color:#fff;}

/* ==========================================================================
   FILM REEL — chapters 01–07, pinned inside .reel-stage and dragged
   sideways as you scroll down (same sticky+transform pin trick as
   .hero-stage/.band-stage above), so the story advances like frames of
   film running through a projector gate instead of stacking vertically.
   See the "reel horizontal takeover" block in script.js for the scroll math.
   ========================================================================== */
.reel-stage{position:relative;height:900vh;}
@media(max-width:900px){.reel-stage{height:700vh;}}
@media(prefers-reduced-motion:reduce){.reel-stage{height:auto;}}
.reel-pin{position:sticky;top:0;height:100vh;overflow:hidden;}
@media(prefers-reduced-motion:reduce){.reel-pin{position:static;height:auto;overflow:visible;}}
.reel-track{display:flex;height:100%;width:max-content;will-change:transform;}
@media(prefers-reduced-motion:reduce){.reel-track{display:block;width:auto;transform:none!important;}}
.reel-track>.chapter{width:100vw;height:100%;flex:0 0 100vw;border-bottom:0;}
@media(prefers-reduced-motion:reduce){.reel-track>.chapter{width:auto;height:auto;border-bottom:1px solid var(--line);}}

/* horizontal sprocket rails along the top/bottom of the pinned frame — like
   the guide rails a film strip runs through on a projector, fixed to the
   gate rather than the film, so they stay put while frames pan behind them */
.reel-pin::before,.reel-pin::after{
  content:'';position:absolute;left:0;right:0;height:14px;z-index:3;pointer-events:none;
  background:var(--dark);
  transition:filter .6s ease;
  -webkit-mask-repeat:repeat-x;mask-repeat:repeat-x;
  -webkit-mask-size:46px 14px;mask-size:46px 14px;
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='14'%3E%3Crect width='46' height='14' fill='white'/%3E%3Crect x='16' y='3' width='14' height='8' rx='3' fill='black'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='46' height='14'%3E%3Crect width='46' height='14' fill='white'/%3E%3Crect x='16' y='3' width='14' height='8' rx='3' fill='black'/%3E%3C/svg%3E");
}
.reel-pin::before{top:0;box-shadow:0 1px 0 rgba(45,125,210,.18);}
.reel-pin::after{bottom:0;box-shadow:0 -1px 0 rgba(45,125,210,.18);}
@media(prefers-reduced-motion:reduce){.reel-pin::before,.reel-pin::after{content:none;}}
@media(max-width:700px){
  .reel-pin::before,.reel-pin::after{
    height:10px;-webkit-mask-size:32px 10px;mask-size:32px 10px;
    -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='10'%3E%3Crect width='32' height='10' fill='white'/%3E%3Crect x='11' y='2' width='10' height='6' rx='2' fill='black'/%3E%3C/svg%3E");
    mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='10'%3E%3Crect width='32' height='10' fill='white'/%3E%3Crect x='11' y='2' width='10' height='6' rx='2' fill='black'/%3E%3C/svg%3E");
  }
}

/* ---- reel entry effect: film strips + grain intensify, and stay ----
   Not a one-shot transition that plays and disappears — script.js toggles
   body.reel-active for as long as the reel-pin stays engaged (on the same
   pinned/scroll-driven condition as the projector sound cue), so the
   effect fades in on entry and holds for the whole time you're scrolling
   through the reel, fading back out only once you leave it. Two things
   intensify: the site-wide grain (body::before) gets noticeably heavier,
   and the sprocket-hole film-strip edges glow brighter. */
body.reel-active::before{opacity:.11;}
body.reel-active .filmstrip-edge--left{box-shadow:inset -1px 0 0 rgba(255,255,255,.16),inset -4px 0 0 rgba(45,125,210,.4);}
body.reel-active .filmstrip-edge--right{box-shadow:inset 1px 0 0 rgba(255,255,255,.16),inset 4px 0 0 rgba(45,125,210,.4);}
.reel-pin.is-active::before,.reel-pin.is-active::after{filter:brightness(1.5);}
@media(prefers-reduced-motion:reduce){
  body.reel-active::before{opacity:.035;}
  body.reel-active .filmstrip-edge--left,body.reel-active .filmstrip-edge--right{box-shadow:none;}
  .reel-pin.is-active::before,.reel-pin.is-active::after{filter:none;}
}

/* ==========================================================================
   CHAPTERS — full-viewport, alternating-mood sections used to make the
   homepage (and page-heroes) feel like distinct places rather than one
   continuous scroll.
   ========================================================================== */
.chapter{
  position:relative;overflow:hidden;min-height:100vh;
  display:flex;flex-direction:column;justify-content:center;padding:140px 0;
  border-bottom:1px solid var(--line);
}
.chapter-num{
  position:absolute;top:36px;right:28px;z-index:1;
  font-family:var(--font-mono);font-size:13px;letter-spacing:.2em;color:var(--faint);
}
.chapter-num b{color:var(--dim);font-weight:500;}
/* inset beyond the section edge (not flush 0) so the scroll-linked vertical
   drift in script.js never uncovers an empty edge as it glides */
.chapter-bg{position:absolute;inset:-60px;z-index:0;}
.chapter-bg img{width:100%;height:100%;object-fit:cover;opacity:.22;
  animation:kenburns 26s ease-in-out infinite alternate;}
.chapter-bg.dim img{opacity:.14;}
@media(prefers-reduced-motion:reduce){.chapter-bg img{animation:none;}}
.chapter-bg::after{content:'';position:absolute;inset:0;}
.chapter--blue .chapter-bg::after{background:linear-gradient(180deg,rgba(20,22,27,.55),var(--charcoal) 88%),radial-gradient(ellipse 70% 60% at 20% 15%,rgba(45,125,210,.20),transparent 60%);}
.chapter--red .chapter-bg::after{background:linear-gradient(180deg,rgba(20,22,27,.55),var(--charcoal) 88%),radial-gradient(ellipse 70% 60% at 80% 15%,rgba(230,57,70,.18),transparent 60%);}
.chapter--gold .chapter-bg::after{background:linear-gradient(180deg,rgba(20,22,27,.55),var(--charcoal) 88%),radial-gradient(ellipse 70% 60% at 20% 85%,rgba(212,168,67,.16),transparent 60%);}
.chapter--blue:not(:has(.chapter-bg)){background:radial-gradient(ellipse 80% 60% at 15% 10%,rgba(45,125,210,.13),transparent 60%),var(--charcoal);}
.chapter--red:not(:has(.chapter-bg)){background:radial-gradient(ellipse 80% 60% at 85% 10%,rgba(230,57,70,.12),transparent 60%),var(--dark);}
.chapter--gold:not(:has(.chapter-bg)){background:radial-gradient(ellipse 80% 60% at 15% 90%,rgba(212,168,67,.12),transparent 60%),var(--charcoal);}
/* ambient glow layer — sits between the background image (z0) and the
   copy (z2), drifting slowly on its own so chapters feel like they have
   depth rather than a single flat backdrop */
.chapter::before{
  content:'';position:absolute;inset:-15%;z-index:1;pointer-events:none;
  background:radial-gradient(38% 38% at 25% 30%,var(--glow,transparent),transparent 70%);
  animation:glowDrift 24s ease-in-out infinite alternate;
}
.chapter--blue::before{--glow:rgba(45,125,210,.22);}
.chapter--red::before{--glow:rgba(230,57,70,.20);}
.chapter--gold::before{--glow:rgba(212,168,67,.20);}
.chapter-content{position:relative;z-index:2;}

/* full-bleed teaser tile — an entire chapter that acts as one big link */
a.chapter-teaser{display:flex;text-decoration:none;color:inherit;cursor:pointer;}
.chapter-teaser .chapter-bg img{transition:transform 1.4s cubic-bezier(.2,.8,.2,1),opacity .5s;}
.chapter-teaser:hover .chapter-bg img{transform:scale(1.1);opacity:.34;}
.teaser-row{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:24px;}
.teaser-arrow{
  width:64px;height:64px;border-radius:50%;border:1px solid rgba(255,255,255,.25);
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
  transition:all .35s cubic-bezier(.2,.8,.2,1);
}
.chapter-teaser:hover .teaser-arrow{background:var(--blue);border-color:var(--blue);transform:rotate(45deg);}
.teaser-arrow svg{width:24px;height:24px;}

.founder-grid{grid-template-columns:1fr;}
@media(min-width:900px){.founder-grid{grid-template-columns:.85fr 1.4fr;}}

/* ==========================================================================
   PAGE HERO — smaller header banner used on subpages
   ========================================================================== */
.page-hero{
  position:relative;padding:170px 0 90px;overflow:hidden;border-bottom:1px solid var(--line);
}
.page-hero .chapter-bg img{opacity:.18;}
.page-hero .eyebrow{margin-bottom:18px;}
.page-hero p{margin-top:22px;max-width:620px;}

/* ==========================================================================
   VIDEO MODAL
   ========================================================================== */
.modal-overlay{
  position:fixed;inset:0;z-index:200;background:rgba(10,11,14,.94);backdrop-filter:blur(8px);
  display:none;align-items:center;justify-content:center;padding:20px;
}
.modal-overlay.open{display:flex;animation:fadeIn .25s ease-out;}
@keyframes fadeIn{from{opacity:0;}to{opacity:1;}}
.modal-content{width:100%;max-width:960px;}
.modal-close{
  display:flex;justify-content:flex-end;margin-bottom:12px;
}
.modal-close button{background:none;border:0;color:#fff;opacity:.6;cursor:pointer;padding:8px;}
.modal-close button:hover{opacity:1;}
.modal-video{position:relative;aspect-ratio:16/9;background:#000;border-radius:10px;overflow:hidden;border:1px solid var(--line);}
.modal-video iframe{position:absolute;inset:0;width:100%;height:100%;border:0;}
.modal-title{margin-top:18px;text-align:center;}
