/* ============================================================
   OAA Media — design system
   Dark, warm, cinematic. One accent only.
   ============================================================ */

:root{
  /* Palette */
  --ink:          #141414;
  --ink-raised:   #1E1E1E;
  --ink-line:     #2A2A28;
  --ember:        #F47B20;
  --ember-deep:   #C25715;
  --bone:         #F2EFEA;
  --sand:         #DED4C9;
  --muted:        #8A8479;

  /* Type */
  --display: 'Archivo', system-ui, sans-serif;
  --body:    'Epilogue', system-ui, sans-serif;

  /* Fluid scale */
  --t-hero:  clamp(2.75rem, 7.5vw, 7.5rem);
  --t-xl:    clamp(2rem, 4.6vw, 4rem);
  --t-lg:    clamp(1.5rem, 2.6vw, 2.25rem);
  --t-md:    clamp(1.125rem, 1.5vw, 1.375rem);
  --t-body:  1.0625rem;
  --t-meta:  0.75rem;

  /* Rhythm */
  --gut:     clamp(1.25rem, 4vw, 3.5rem);
  --section: clamp(5rem, 11vw, 10rem);
  --maxw:    1560px;

  /* Motion */
  --ease:    cubic-bezier(0.16, 1, 0.3, 1);
  --dur:     600ms;
}

*,*::before,*::after{ box-sizing:border-box; }

html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }

body{
  margin:0;
  background:var(--ink);
  color:var(--bone);
  font-family:var(--body);
  font-size:var(--t-body);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

img,video{ display:block; max-width:100%; }
a{ color:inherit; text-decoration:none; }
h1,h2,h3,h4{ margin:0; font-weight:400; }
p{ margin:0; }

/* Film grain. Very subtle, sells the cinematic register. */
body::after{
  content:'';
  position:fixed; inset:0; z-index:9999;
  pointer-events:none; opacity:.035;
  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='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- Shared primitives ---------- */

.wrap{ width:100%; max-width:var(--maxw); margin-inline:auto; padding-inline:var(--gut); }

.display{
  font-family:var(--display);
  font-stretch:112%;
  font-weight:500;
  line-height:0.95;
  letter-spacing:-0.02em;
  text-transform:uppercase;
}

.meta{
  font-size:var(--t-meta);
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
  font-weight:500;
}

.eyebrow{
  display:flex; align-items:center; gap:.7rem;
  font-size:var(--t-meta); letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted); font-weight:500;
  margin-bottom:2.5rem;
}
.eyebrow::before{
  content:''; width:2rem; height:1px; background:var(--ember); flex:none;
}

.section{ padding-block:var(--section); }

/* Scroll reveal */
.js .rv{ opacity:0; transform:translate3d(0,24px,0); }
.js .rv.in{
  opacity:1; transform:none;
  transition:opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

/* ============================================================
   Motion layer
   Everything here is transform and opacity only, so it stays on the
   compositor and never triggers layout. All of it is switched off by
   prefers-reduced-motion at the bottom of this file.
   ============================================================ */

/* Line reveal. Headings are split into lines at runtime, each line sitting in
   its own overflow-hidden box so the text rises out from behind a mask rather
   than fading in. This is the difference between "a website" and a title
   sequence, which is the point for a film company.

   The padding and negative margin are a pair: overflow:hidden would otherwise
   clip descenders and the tail of a Q, and this gives them room without
   changing the layout. */
.js .lines .ln{
  display:block; overflow:hidden;
  padding-bottom:.09em; margin-bottom:-.09em;
}
.js .lines .ln-i{
  display:block;
  transform:translate3d(0,110%,0);
}
.js .lines.lines-in .ln-i{
  transform:none;
  transition:transform 1000ms var(--ease);
  transition-delay:calc(var(--ln) * 85ms);
}
/* A split heading does its own entrance, so the wrapper must not also slide,
   or the two movements fight each other. */
.js .rv.has-lines{ transform:none; }

/* Hero loader. The mark floats over the poster while the showreel buffers.

   It sits above the hero gradient but inside .hero-media, so it stays behind
   the headline rather than covering it. Held at opacity 0 until JS decides the
   film is genuinely slow, so a fast connection never sees a flash of it. */
.hero-loader{
  position:absolute; inset:0; z-index:3;
  display:grid; place-items:center;
  opacity:0; pointer-events:none;
  transition:opacity 460ms var(--ease);
}
.hero-loader.on{ opacity:1; }
/* Scoped through .hero-media on purpose. A bare .hero-loader img loses to the
   later .hero-media img rule on equal specificity, and the mark comes out
   stretched to cover the entire hero. */
.hero-media .hero-loader img{
  width:clamp(52px,6vw,84px);
  height:auto;
  object-fit:contain;
  animation:heroFloat 1700ms var(--ease) infinite;
}
@keyframes heroFloat{
  0%, 100%{ transform:translate3d(0,0,0) scale(1);       opacity:.7; }
  50%     { transform:translate3d(0,-14px,0) scale(1.04); opacity:1; }
}

@media (prefers-reduced-motion:reduce){
  /* The showreel is switched off entirely under reduced motion, so there is
     nothing to wait for and nothing to announce. */
  .hero-loader{ display:none; }
}

/* Cycling word in the hero headline.

   Width is animated rather than left to reflow, because the words are
   different lengths and the full stop after them would otherwise jump on
   every swap. The padding and negative margin pair does the same job as on
   .ln: overflow:hidden would clip the descender on "story" otherwise. */
.cyc{
  display:inline-block; overflow:hidden; vertical-align:bottom;
  padding-bottom:.09em; margin-bottom:-.09em;
  transition:width 620ms var(--ease);
  will-change:width;
}
.cyc-i{
  display:inline-block; color:var(--ember);
  transition:transform 480ms var(--ease), opacity 480ms var(--ease);
}
/* Current word leaves upward. */
.cyc.cyc-out .cyc-i{ transform:translateY(-105%); opacity:0; }
/* Next word is parked below with no transition, then released. */
.cyc.cyc-park .cyc-i{ transform:translateY(105%); opacity:0; transition:none; }

@media (prefers-reduced-motion:reduce){
  .cyc{ transition:none; width:auto !important; }
  .cyc-i{ transition:none; transform:none !important; opacity:1 !important; }
}

/* Parallax. The scale is not decoration: shifting a cover image vertically
   exposes an edge unless it is oversized first. 1.14 covers the ±6% drift.

   Deliberately scoped to .hero-media rather than any [data-parallax]. The
   statement backdrops carry a hand-tuned translateX and scale to place the
   figures clear of the copy, and a blanket rule would silently overwrite it
   and put a hard edge back down the left side. */
.js .hero-media[data-parallax] img{
  transform:scale(1.14) translate3d(0,var(--par,0),0);
  will-change:transform;
}

/* Marquee reacts to scroll speed. Skew only, so the type stays on the
   compositor. Ratcheting the animation duration instead would jump. */
.marquee a{ transform:skewX(var(--mq-skew,0deg)); transition:transform 600ms var(--ease); }

/* Work tiles: the photo settles out of a slow push in, the way a locked-off
   shot settles. Deliberately a one-shot animation with no fill rather than a
   transition on .in, because a transition would hold transform at scale(1)
   at higher specificity than .tile:hover and quietly kill the hover zoom. */
.js .tile.rv.in .tile-media img{ animation:tileSettle 1400ms var(--ease); }
@keyframes tileSettle{ from{ transform:scale(1.09); } to{ transform:scale(1); } }

/* Buttons */
.btn{
  display:inline-flex; align-items:center; gap:.75rem;
  font-family:var(--display); font-stretch:105%; font-weight:600;
  font-size:.8125rem; letter-spacing:.12em; text-transform:uppercase;
  padding:1.05rem 2.1rem; border:1px solid var(--ember);
  background:var(--ember); color:var(--ink);
  transition:background 320ms var(--ease), border-color 320ms var(--ease), color 320ms var(--ease);
}
.btn:hover{ background:var(--ember-deep); border-color:var(--ember-deep); color:var(--bone); }

.btn-ghost{ background:transparent; color:var(--bone); border-color:var(--ink-line); }
.btn-ghost:hover{ background:transparent; border-color:var(--ember); color:var(--ember); }

/* Arrow that nudges on hover */
.btn .arw{ transition:transform 320ms var(--ease); }
.btn:hover .arw{ transform:translateX(4px); }

/* ============================================================
   Nav
   ============================================================ */

#nav{
  position:fixed; inset:0 0 auto 0; z-index:100;
  padding-block:1.5rem;
  transition:background 400ms var(--ease), padding 400ms var(--ease), border-color 400ms var(--ease);
  border-bottom:1px solid transparent;
}
#nav.stuck{
  background:rgba(20,20,20,.88);
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  padding-block:1rem; border-bottom-color:var(--ink-line);
}
.nav-in{ display:flex; align-items:center; justify-content:space-between; gap:2rem; }
.nav-logo img{ height:34px; width:auto; }

.nav-links{ display:flex; align-items:center; gap:2.5rem; }
.nav-links a{
  font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase;
  font-weight:500; color:var(--bone); position:relative; padding-block:.35rem;
}
.nav-links a:not(.btn)::after{
  content:''; position:absolute; left:0; bottom:0; height:1px; width:100%;
  background:var(--ember); transform:scaleX(0); transform-origin:right;
  transition:transform 380ms var(--ease);
}
.nav-links a:not(.btn):hover::after,
.nav-links a[aria-current="page"]::after{ transform:scaleX(1); transform-origin:left; }
.nav-links .btn{ padding:.8rem 1.5rem; }

.nav-toggle{
  display:none; background:none; border:0; padding:.5rem; cursor:pointer;
  color:var(--bone);
}
.nav-toggle span{ display:block; width:26px; height:2px; background:currentColor; margin:5px 0; transition:transform 320ms var(--ease), opacity 320ms var(--ease); }
#nav.open .nav-toggle span:nth-child(1){ transform:translateY(7px) rotate(45deg); }
#nav.open .nav-toggle span:nth-child(2){ opacity:0; }
#nav.open .nav-toggle span:nth-child(3){ transform:translateY(-7px) rotate(-45deg); }

/* ============================================================
   Hero
   ============================================================ */

.hero{
  position:relative; min-height:100svh;
  display:flex; flex-direction:column; justify-content:flex-end;
  padding-bottom:clamp(2rem,5vh,4rem); overflow:hidden;
}
.hero-media{ position:absolute; inset:0; z-index:0; }
.hero-media img,
.hero-media video{ width:100%; height:100%; object-fit:cover; }
.hero-media::after{
  content:''; position:absolute; inset:0;
  background:
    linear-gradient(to top, rgba(20,20,20,.92) 0%, rgba(20,20,20,.25) 45%, rgba(20,20,20,.55) 100%);
}
.hero-in{ position:relative; z-index:1; }

.hero h1{
  font-size:var(--t-hero);
  max-width:16ch;
  margin-bottom:2.25rem;
}
.hero h1 em{ font-style:normal; color:var(--ember); }

.hero-foot{
  display:flex; flex-wrap:wrap; align-items:flex-end;
  justify-content:space-between; gap:2rem;
  border-top:1px solid rgba(242,239,234,.16); padding-top:1.5rem;
}
.hero-coords{ display:flex; flex-direction:column; gap:.35rem; color:var(--muted); }
.hero-coords strong{ color:var(--bone); font-weight:500; letter-spacing:.14em; font-size:var(--t-meta); text-transform:uppercase; }

.scroll-cue{ display:flex; align-items:center; gap:.75rem; color:var(--muted); font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; }
.scroll-cue i{
  display:block; width:1px; height:2.5rem; background:linear-gradient(var(--ember), transparent);
  animation:cue 2.2s var(--ease) infinite;
}
@keyframes cue{ 0%,100%{ transform:scaleY(.4); transform-origin:top; } 50%{ transform:scaleY(1); transform-origin:top; } }

/* ============================================================
   Statement
   ============================================================ */

.statement{ position:relative; overflow:hidden; }
.statement > .wrap{ position:relative; z-index:1; }

/* Faded backdrop. The image is dropped right down and a scrim sits over it,
   weighted heaviest on the left where the text sits, so contrast never
   depends on which frame gets swapped in. */
.statement-bg{ position:absolute; inset:0; z-index:0; pointer-events:none; }
/* The frame is near square and the band is wide, so cover scales by width and
   object-position X does nothing. Scale and shift instead, to bring the two
   figures into the centre of the visible band. */
.statement-bg img{
  width:100%; height:100%; object-fit:cover; object-position:center 54%;
  /* Shift right to place the figures clear of the copy, but scale enough that
     the left edge still covers. With translateX(d) scale(s) the left edge sits
     at 50 - 50s + d, so s must exceed 1 + d/50 or a hard edge shows. */
  transform:translateX(14%) scale(1.35); transform-origin:center;
  opacity:.5; filter:grayscale(.15) brightness(.92);
}
.statement-bg::after{
  content:''; position:absolute; inset:0;
  background:
    linear-gradient(95deg, rgba(20,20,20,.94) 0%, rgba(20,20,20,.74) 34%, rgba(20,20,20,.2) 100%),
    linear-gradient(to bottom, var(--ink) 0%, transparent 20%, transparent 82%, var(--ink) 100%);
}

.statement p{
  font-family:var(--display); font-stretch:104%; font-weight:400;
  font-size:var(--t-xl); line-height:1.12; letter-spacing:-0.015em;
  max-width:30ch;
}
/* Lighter than --muted because this now sits over a photo, not flat dark. */
.statement .sub{
  font-family:var(--body); font-size:var(--t-md); line-height:1.65;
  color:rgba(242,239,234,.82); max-width:54ch; margin-top:2.5rem; letter-spacing:0;
}

/* Closing turn from what we do to what we'll do for you. */
.statement-cta{
  display:inline-flex; align-items:center; gap:.9rem; margin-top:2.75rem;
  font-family:var(--display); font-stretch:108%; font-weight:600;
  font-size:var(--t-lg); line-height:1; letter-spacing:-0.01em;
  text-transform:uppercase; color:var(--ember);
  transition:color 320ms var(--ease);
}
.statement-cta:hover{ color:var(--bone); }
.statement-cta .arw{ transition:transform 320ms var(--ease); }
.statement-cta:hover .arw{ transform:translateX(5px); }

/* ============================================================
   Work grid
   ============================================================ */

.work-head{
  display:flex; flex-wrap:wrap; align-items:flex-end; justify-content:space-between;
  gap:2rem; margin-bottom:3.5rem;
}
.work-head h2{ font-size:var(--t-xl); }

.work-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:clamp(1rem,2.2vw,2rem); }
.work-grid.stagger .tile:nth-child(even){ transform:translateY(3.5rem); }
.js .work-grid.stagger .tile.rv:nth-child(even).in{ transform:translateY(3.5rem); }

.tile{ position:relative; display:block; overflow:hidden; background:var(--ink-raised); }
.tile-media{ position:relative; aspect-ratio:4/3; overflow:hidden; }
.tile-media img{
  width:100%; height:100%; object-fit:cover;
  transition:transform 900ms var(--ease), filter 900ms var(--ease);
  filter:saturate(.88) brightness(.92);
}
.tile:hover .tile-media img{ transform:scale(1.055); filter:saturate(1) brightness(1); }
/* The scrim has to hold a two-line title over a bright sky, not just over a
   dark frame. The old two-stop ramp hit transparent at 55%, which put the
   second line of a title like Suzuki Marine in the weak part of the gradient
   and left it sitting on white water. This ramps longer and harder at the
   bottom while still leaving the top of the photo clear. */
.tile-media::after{
  content:''; position:absolute; inset:0;
  background:linear-gradient(to top,
    rgba(16,16,16,.95) 0%,
    rgba(16,16,16,.86) 22%,
    rgba(16,16,16,.55) 45%,
    rgba(16,16,16,.16) 68%,
    transparent 88%);
}

.tile-body{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  padding:clamp(1.25rem,2.4vw,2.25rem);
  display:flex; align-items:flex-end; justify-content:space-between; gap:1.5rem;
}
/* line-height stays above 1 so the uppercase ascenders cannot bleed up
   into the category label on two-line titles */
.tile-body h3{ font-family:var(--display); font-stretch:108%; font-weight:500; font-size:var(--t-lg); text-transform:uppercase; letter-spacing:-0.01em; line-height:1.08; }
/* Sits over a photo gradient, not a flat panel, so --muted is too weak here.
   Needs more contrast than the eyebrows used elsewhere on the page. */
.tile-cat{ display:block; font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:rgba(242,239,234,.74); margin-bottom:1.1rem; }

.tile-go{
  flex:none; display:flex; align-items:center; gap:.5rem;
  font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:var(--ember);
  opacity:0; transform:translateY(8px);
  transition:opacity 380ms var(--ease), transform 380ms var(--ease);
}
.tile:hover .tile-go{ opacity:1; transform:none; }

/* ============================================================
   Client band
   ============================================================ */

.clients{ border-block:1px solid var(--ink-line); padding-block:clamp(2.5rem,5vw,4rem); }

/* Seamless scrolling logo wall. The track holds the set twice and slides
   exactly one set width, so the loop has no visible seam. */
.logo-marquee{
  position:relative; overflow:hidden; margin-top:2.5rem;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent);
}
.logo-track{ display:flex; width:max-content; animation:logoslide 52s linear infinite; }
.logo-marquee:hover .logo-track{ animation-play-state:paused; }
@keyframes logoslide{ from{ transform:translateX(0); } to{ transform:translateX(-50%); } }

.logo-set{ display:flex; }

.logo-item{
  flex:none; display:flex; align-items:center; justify-content:center;
  height:clamp(64px,6.5vw,96px);
  padding-inline:clamp(1.75rem,3.6vw,3.75rem);
  font-family:var(--display); font-stretch:100%; font-weight:500;
  font-size:clamp(.8125rem,1vw,1rem); letter-spacing:.1em; text-transform:uppercase;
  color:var(--muted); white-space:nowrap;
  transition:color 380ms var(--ease);
}
.logo-item:hover{ color:var(--bone); }

/* Logos are forced to uniform white silhouettes at rest, so a wall of mixed
   brand colours still reads as one system. Hover restores the real colours.
   --lh tunes each logo's height by eye, because bounding boxes lie: a wide
   wordmark and a stacked mark at the same height look nothing alike. */
.logo-item img{
  height:var(--lh,62%); width:auto; max-width:200px; object-fit:contain;
  opacity:.55; filter:brightness(0) invert(1);
  transition:opacity 380ms var(--ease), filter 380ms var(--ease);
}
.logo-item:hover img{ opacity:1; filter:none; }

/* ============================================================
   Two-up (team / about)
   ============================================================ */

.twoup{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(2rem,6vw,6rem); align-items:center; }
.twoup h2{ font-size:var(--t-xl); margin-bottom:1.75rem; }
.twoup p + p{ margin-top:1.25rem; }
.twoup .lede{ color:var(--bone); font-size:var(--t-md); }
.twoup p{ color:var(--muted); max-width:46ch; }

.duo{ display:grid; grid-template-columns:1fr 1fr; gap:1rem; }
.duo figure{ margin:0; }
/* Portraits are already black and white, so desaturating does nothing.
   Just a touch down in brightness so they sit in the dark page.
   height:auto is required: the width/height attributes on the img are
   presentational hints, and aspect-ratio is ignored unless height is auto. */
.duo img{ width:100%; height:auto; aspect-ratio:4/5; object-fit:cover; filter:brightness(.95); }
.duo figcaption{ margin-top:.9rem; }
.duo figcaption strong{ display:block; font-family:var(--display); font-stretch:106%; font-weight:500; text-transform:uppercase; letter-spacing:.02em; font-size:1rem; }
.duo figcaption span{ font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }

/* ============================================================
   Services
   ============================================================ */

.svc-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:1px; background:var(--ink-line); border-block:1px solid var(--ink-line); }
.svc{ background:var(--ink); padding:clamp(2rem,3.2vw,3rem) clamp(1.5rem,2.4vw,2.25rem); position:relative; transition:background 420ms var(--ease); }
.svc:hover{ background:var(--ink-raised); }
.svc-num{ font-size:var(--t-meta); letter-spacing:.14em; color:var(--ember); display:block; margin-bottom:3.5rem; }
.svc h3{ font-family:var(--display); font-stretch:108%; font-weight:500; font-size:var(--t-lg); text-transform:uppercase; line-height:1.08; letter-spacing:-0.01em; margin-bottom:1rem; }
.svc p{ color:var(--muted); font-size:.9375rem; }

/* ============================================================
   Testimonials
   ============================================================ */

.quotes-head{
  display:flex; align-items:center; justify-content:space-between;
  gap:2rem; margin-bottom:3rem;
}
.quotes-head .eyebrow{ margin-bottom:0; }

.slider-nav{ display:flex; gap:.75rem; flex:none; }
.sld-btn{
  width:54px; height:54px; flex:none;
  display:grid; place-items:center; cursor:pointer;
  background:transparent; border:1px solid var(--ink-line); color:var(--bone);
  font-size:1.05rem; font-family:var(--body);
  transition:border-color 320ms var(--ease), color 320ms var(--ease), opacity 320ms var(--ease);
}
.sld-btn:hover:not(:disabled){ border-color:var(--ember); color:var(--ember); }
.sld-btn:disabled{ opacity:.28; cursor:default; }
.sld-btn:focus-visible{ outline:2px solid var(--ember); outline-offset:3px; }

/* Two per view on desktop, one on mobile. Native scrolling does the work,
   so this still functions with the script disabled. */
.quotes-track{
  display:grid; grid-auto-flow:column; grid-auto-columns:calc(50% - 2.5rem);
  gap:5rem; overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory; scroll-behavior:smooth;
  scrollbar-width:none; -ms-overflow-style:none;
}
.quotes-track::-webkit-scrollbar{ display:none; }
.quotes-track:focus-visible{ outline:2px solid var(--ember); outline-offset:8px; }
.quotes-track > blockquote{ scroll-snap-align:start; }

blockquote{ margin:0; }
blockquote p{
  font-family:var(--display); font-stretch:102%; font-weight:400;
  font-size:var(--t-lg); line-height:1.24; letter-spacing:-0.01em; margin-bottom:1.75rem;
}
blockquote footer{ display:flex; align-items:center; gap:.75rem; }
blockquote footer::before{ content:''; width:1.75rem; height:1px; background:var(--ember); flex:none; }
blockquote cite{ font-style:normal; font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
blockquote cite b{ color:var(--bone); font-weight:500; }

/* ============================================================
   Marquee CTA
   ============================================================ */

.marquee{
  border-block:1px solid var(--ink-line);
  padding-block:clamp(1.75rem,3vw,2.75rem);
  overflow:hidden; white-space:nowrap; display:flex;
}
.marquee a{ display:flex; flex:none; align-items:center; animation:slide 26s linear infinite; }
.marquee:hover a{ animation-play-state:paused; }
.marquee span{
  font-family:var(--display); font-stretch:114%; font-weight:600;
  font-size:clamp(2rem,5.4vw,4.75rem); line-height:1; text-transform:uppercase;
  letter-spacing:-0.02em; padding-inline:1.5rem;
  transition:color 420ms var(--ease);
}
.marquee i{ color:var(--ember); font-style:normal; font-size:clamp(1rem,2vw,1.75rem); }
.marquee:hover span{ color:var(--ember); }
@keyframes slide{ to{ transform:translateX(-50%); } }

/* ============================================================
   Footer
   ============================================================ */

.footer{ background:var(--sand); color:var(--ink); padding-block:clamp(3.5rem,6vw,5.5rem) 2rem; }
.footer a{ transition:color 300ms var(--ease); }
.footer a:hover{ color:var(--ember-deep); }
/* Booking prompt. Same native <dialog> mechanics as the person cards, so
   Escape, focus trapping and the backdrop come from the browser. */
.book-modal{
  border:0; padding:0; background:var(--ink-raised); color:var(--bone);
  width:min(460px, calc(100vw - 2rem));
  border:1px solid var(--ink-line);
  position:relative;
  /* The embedded calendar step is roughly 511px on its own, and the modal has
     to hold that plus the heading and chips without running off a short laptop
     screen. svh rather than vh so a mobile URL bar cannot push the bottom of
     the dialog out of reach. */
  max-height:min(88svh, 860px);
}
.book-in{ overflow-y:auto; max-height:inherit; overscroll-behavior:contain; }
.book-in::-webkit-scrollbar{ width:0; height:0; display:none; }
.book-modal::backdrop{ background:rgba(10,10,10,.82); backdrop-filter:blur(6px); }
.book-modal[open]{ animation:dlg 420ms var(--ease); }
.book-in{ padding:clamp(1.75rem,4vw,2.5rem); }
.book-in h2{
  font-family:var(--display); font-stretch:110%; font-weight:600;
  font-size:var(--t-md); text-transform:uppercase; line-height:1.1;
  letter-spacing:-0.01em; margin-top:1rem;
}
.book-in p{ color:var(--muted); font-size:.9375rem; margin-top:1rem; }
.book-in .booking-meta{ margin-top:1.25rem; }
.book-in .btn{ margin-top:1.75rem; }
.book-dismiss{
  display:block; margin-top:1.1rem; cursor:pointer;
  background:none; border:0; padding:0; font:inherit;
  font-size:var(--t-meta); letter-spacing:.1em; text-transform:uppercase;
  color:var(--muted); transition:color 300ms var(--ease);
}
.book-dismiss:hover{ color:var(--bone); }

@media (prefers-reduced-motion:reduce){
  .book-modal[open]{ animation:none; }
}

/* Booking card on the contact page. Sits on the dark body, so it borrows the
   raised-panel treatment used by the testimonial cards. */
.booking{
  margin-top:3rem; padding:clamp(1.5rem,3vw,2rem);
  background:var(--ink-raised); border:1px solid var(--ink-line);
  transition:border-color 420ms var(--ease);
}
.booking:hover{ border-color:var(--ember); }
.booking h3{
  font-family:var(--display); font-stretch:110%; font-weight:600;
  font-size:var(--t-md); text-transform:uppercase; line-height:1.1;
  letter-spacing:-0.01em; margin-top:1rem;
}
.booking-sub{ color:var(--muted); font-size:.9375rem; margin-top:1rem; max-width:34ch; }
.booking-meta{
  list-style:none; margin:1.25rem 0 0; padding:0;
  display:flex; flex-wrap:wrap; gap:.5rem;
}
.booking-meta li{
  font-size:var(--t-meta); letter-spacing:.1em; text-transform:uppercase;
  color:var(--bone); border:1px solid var(--ink-line); padding:.35rem .7rem;
}
.booking .btn{ margin-top:1.75rem; }

/* The embedded scheduler. min-height holds the space before the booking page
   reports its real height, so the rest of the page does not jump when it
   lands. The frame paints its own near black, close enough to the panel that
   the seam does not read. */
.booking-embed{
  margin-top:1.75rem;
  border:1px solid var(--ink-line);
  background:var(--ink);
  overflow:hidden;
}
/* Starting height only. The booking page now reports its real height over
   postMessage and site.js takes over within a moment of load, so this just
   holds the space before the first message lands. Kept close to the real
   first step (202px measured) so the page barely moves when it arrives. */
.booking-embed iframe{
  display:block; width:100%; border:0;
  height:320px;
  transition:height 320ms var(--ease);
}
.booking-alt{
  margin-top:1rem;
  font-size:var(--t-meta); letter-spacing:.04em;
  color:var(--muted);
}
.booking-alt a{ color:var(--bone); text-decoration:underline; text-underline-offset:3px; }
.booking-alt a:hover{ color:var(--ember); }

@media (prefers-reduced-motion:reduce){
  .booking-embed iframe{ transition:none; }
}

/* Newsletter signup. Lives in the footer, which is sand, so this is dark on
   light and does not inherit the dark form styling used elsewhere. */
.signup{ margin-top:2.5rem; max-width:26rem; }
.signup label{
  display:block; font-size:var(--t-meta); letter-spacing:.06em;
  color:rgba(20,20,20,.62); margin-bottom:.75rem;
}
.signup-row{ display:flex; gap:.5rem; }
.signup input{
  flex:1 1 auto; min-width:0;
  background:transparent; color:var(--ink);
  border:1px solid rgba(20,20,20,.28);
  padding:.7rem .85rem; font:inherit; font-size:.9375rem;
  transition:border-color 300ms var(--ease);
}
.signup input::placeholder{ color:rgba(20,20,20,.38); }
.signup input:focus{ outline:none; border-color:var(--ember); }
.signup button{
  flex:0 0 auto; cursor:pointer;
  background:var(--ink); color:var(--bone);
  border:1px solid var(--ink); padding:.7rem 1.1rem;
  font:inherit; font-size:var(--t-meta); letter-spacing:.1em; text-transform:uppercase;
  transition:background 300ms var(--ease), border-color 300ms var(--ease);
}
.signup button:hover{ background:var(--ember-deep); border-color:var(--ember-deep); }
.signup[aria-disabled="true"]{ opacity:.5; }
.signup[aria-disabled="true"] button{ cursor:not-allowed; }
.signup-note{ font-size:var(--t-meta); color:rgba(20,20,20,.55); margin-top:.6rem; min-height:1em; }
.signup-note:empty{ display:none; }

@media (max-width:560px){
  .signup-row{ flex-direction:column; }
}

.foot-grid{ display:grid; grid-template-columns:2fr 1fr 1fr 1fr; gap:clamp(2rem,4vw,3rem); }
.foot-grid h2{ font-family:var(--display); font-stretch:110%; font-weight:600; font-size:var(--t-lg); text-transform:uppercase; line-height:1.05; letter-spacing:-0.015em; max-width:14ch; }
.foot-col h3{ font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:rgba(20,20,20,.55); margin-bottom:1.25rem; font-weight:500; }
.foot-col ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.6rem; }
.foot-col a{ font-size:.9375rem; }
.foot-base{
  margin-top:clamp(3rem,5vw,4.5rem); padding-top:1.5rem;
  border-top:1px solid rgba(20,20,20,.16);
  display:flex; flex-wrap:wrap; gap:1rem; justify-content:space-between;
  font-size:var(--t-meta); letter-spacing:.1em; text-transform:uppercase; color:rgba(20,20,20,.55);
}

/* ============================================================
   Responsive
   ============================================================ */

@media (max-width:1100px){
  .svc-grid{ grid-template-columns:repeat(2,1fr); }
  .foot-grid{ grid-template-columns:1fr 1fr; }
}

@media (max-width:860px){
  .nav-toggle{ display:block; }
  .nav-links{
    position:fixed; inset:0; z-index:-1;
    flex-direction:column; justify-content:center; gap:2rem;
    background:var(--ink);
    opacity:0; visibility:hidden;
    transition:opacity 420ms var(--ease), visibility 420ms var(--ease);
  }
  #nav.open .nav-links{ opacity:1; visibility:visible; }
  .nav-links a{ font-size:1.125rem; }

  .work-grid{ grid-template-columns:1fr; }
  .work-grid.stagger .tile:nth-child(even),
  .js .work-grid.stagger .tile.rv:nth-child(even).in{ transform:none; }
  .twoup{ grid-template-columns:1fr; }
  .quotes-track{ grid-auto-columns:100%; gap:2.5rem; }
  .hero-foot{ flex-direction:column; align-items:flex-start; }
  .scroll-cue{ display:none; }
}

@media (max-width:560px){
  .svc-grid{ grid-template-columns:1fr; }
  .foot-grid{ grid-template-columns:1fr; }
  .duo{ gap:.75rem; }
}

/* ============================================================
   Reduced motion
   ============================================================ */

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .js .rv{ opacity:1 !important; transform:none !important; }
  .js .work-grid.stagger .tile:nth-child(even){ transform:none !important; }
  .marquee a{ animation:none; }
  .tile-go{ opacity:1; transform:none; }

  /* Motion layer off. Headings show as plain text, images sit still. */
  .js .lines .ln{ overflow:visible; padding-bottom:0; margin-bottom:0; }
  .js .lines .ln-i{ transform:none !important; transition:none !important; }
  .js .hero-media[data-parallax] img{ transform:none !important; }
  .marquee a{ transform:none !important; }
  .js .tile.rv.in .tile-media img{ animation:none; }

  /* Logo wall stops sliding and becomes a static wrapped row,
     so every logo is still reachable. */
  .logo-marquee{ -webkit-mask-image:none; mask-image:none; }
  .logo-track{ animation:none; width:100%; }
  .logo-track > [aria-hidden="true"]{ display:none; }
  .logo-set{ flex-wrap:wrap; justify-content:center; width:100%; }
}

/* ============================================================
   Interior pages
   ============================================================ */

.page-head{ padding-block:calc(var(--section) + 5rem) var(--section); }
.page-head h1{ font-size:var(--t-xl); max-width:18ch; }
.page-sub{ color:var(--muted); font-size:var(--t-md); max-width:56ch; margin-top:2rem; }

.prose{ max-width:74ch; }
.prose .display{ font-size:var(--t-lg); line-height:1.18; letter-spacing:-0.015em; margin-bottom:2.5rem; }
.prose p{ color:var(--muted); margin-bottom:1.25rem; }
.prose h3{
  font-family:var(--display); font-stretch:106%; font-weight:500;
  font-size:1.375rem; text-transform:uppercase; letter-spacing:-0.01em;
  color:var(--bone); margin:3rem 0 1rem;
}

/* ---------- Services rows ---------- */

.svc-row{ border-top:1px solid var(--ink-line); padding-block:clamp(2.5rem,5vw,4.5rem); }
.svc-row:last-of-type{ border-bottom:1px solid var(--ink-line); }
.svc-row-in{ display:grid; grid-template-columns:1fr 1.4fr; gap:clamp(2rem,5vw,5rem); align-items:start; }
.svc-row-head .svc-num{ margin-bottom:1.25rem; }
.svc-row-head h2{ font-size:var(--t-lg); }
.svc-row-body .lede{ color:var(--bone); font-size:var(--t-md); margin-bottom:1.75rem; }

.ticks{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.9rem; }
.ticks li{ position:relative; padding-left:1.75rem; color:var(--muted); }
.ticks li::before{
  content:''; position:absolute; left:0; top:.7em;
  width:.6rem; height:1px; background:var(--ember);
}

.steps{ list-style:none; margin:0; padding:0; counter-reset:s; display:flex; flex-direction:column; gap:1.5rem; }
.steps li{ position:relative; padding-left:3.25rem; color:var(--muted); counter-increment:s; }
.steps li::before{
  content:counter(s,decimal-leading-zero);
  position:absolute; left:0; top:.1em;
  font-family:var(--display); font-size:var(--t-meta); letter-spacing:.14em; color:var(--ember);
}
.steps b{ color:var(--bone); font-weight:500; }

/* ---------- About ---------- */

.duo-wide{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(1rem,2.5vw,2rem); max-width:900px; }
.duo-wide figure{ margin:0; }
.duo-wide img{ width:100%; height:auto; aspect-ratio:4/5; object-fit:cover; filter:brightness(.95); }
.duo-wide figcaption{ margin-top:.9rem; }
.duo-wide figcaption strong{ display:block; font-family:var(--display); font-stretch:106%; font-weight:500; text-transform:uppercase; font-size:1rem; }
.duo-wide figcaption span{ font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }

/* ---------- Case study ---------- */

.cs-hero{
  position:relative; min-height:74svh; overflow:hidden;
  display:flex; flex-direction:column; justify-content:flex-end;
  padding-bottom:clamp(2rem,5vh,4rem);
}
.cs-hero h1{ font-size:var(--t-xl); max-width:16ch; }

.cs-meta{ display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:2rem; border-block:1px solid var(--ink-line); padding-block:2rem; }
.cs-meta .meta{ display:block; margin-bottom:.6rem; }
.cs-meta p{ color:var(--bone); }

.embed{ position:relative; aspect-ratio:16/9; background:var(--ink-raised); }
.embed iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; }
.embed-placeholder{
  display:grid; place-items:center; text-align:center;
  border:1px dashed var(--ink-line); background:transparent;
}
.embed-placeholder p{ font-family:var(--display); font-stretch:106%; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); line-height:1.9; }
.embed-placeholder span{ font-family:var(--body); font-size:var(--t-meta); letter-spacing:.14em; }

.stills{ display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(.75rem,1.5vw,1.25rem); margin-top:2rem; }
.stills img{ width:100%; aspect-ratio:3/2; object-fit:cover; }
.still-placeholder{
  aspect-ratio:3/2; display:grid; place-items:center;
  border:1px dashed var(--ink-line);
}
.still-placeholder span{ font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }

.cs-quote{ max-width:60ch; }
.next-tile{ display:block; max-width:760px; }

/* ---------- Contact ---------- */

.contact-grid{ display:grid; grid-template-columns:1.3fr 1fr; gap:clamp(2.5rem,6vw,6rem); align-items:start; }

.field{ margin:0 0 1.5rem; display:flex; flex-direction:column; gap:.6rem; }
.field-row{ display:grid; grid-template-columns:1fr 1fr; gap:1.5rem; }
.field label{ font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
.field input,
.field select,
.field textarea{
  font-family:var(--body); font-size:1rem; color:var(--bone);
  background:var(--ink-raised); border:1px solid var(--ink-line);
  padding:.95rem 1.1rem; width:100%; border-radius:0;
  transition:border-color 300ms var(--ease);
}
.field textarea{ resize:vertical; min-height:9rem; }
.field input:focus,
.field select:focus,
.field textarea:focus{ outline:none; border-color:var(--ember); }
.field select{ appearance:none; cursor:pointer; }

.contact-list{ list-style:none; margin:2rem 0 0; padding:0; display:flex; flex-direction:column; gap:1.5rem; }
.contact-list li{ display:flex; flex-direction:column; gap:.4rem; }
.contact-list a{ transition:color 300ms var(--ease); }
.contact-list a:hover{ color:var(--ember); }
.note{ color:var(--muted); font-size:.9375rem; margin-top:2.5rem; max-width:38ch; }

@media (max-width:1100px){
  .svc-row-in{ grid-template-columns:1fr; gap:1.75rem; }
  .contact-grid{ grid-template-columns:1fr; }
}
@media (max-width:860px){
  .stills{ grid-template-columns:repeat(2,1fr); }
  .page-head{ padding-block:calc(var(--section) + 3rem) var(--section); }
}
@media (max-width:560px){
  .field-row{ grid-template-columns:1fr; gap:0; }
  .duo-wide{ gap:.75rem; }
}

/* Hero eyebrows sit over photography that varies from night-dark to pale sky,
   so they need more contrast than the muted grey used on flat sections. */
.hero .eyebrow,
.cs-hero .eyebrow{ color:rgba(242,239,234,.8); }

/* Overlay band. Reuses .statement but with its own framing: the image is a
   wide landscape that needs no repositioning, so the transform tuned for the
   homepage frame is reset here. */
.statement.band{ padding-block:clamp(6rem,13vw,11rem); }
.statement.band .statement-bg img{
  transform:none; object-position:center 46%;
  opacity:.72; filter:grayscale(.08) brightness(.94);
}
/* This band is shorter than the homepage statement, so the top and bottom
   fades have to be much tighter or they swallow the whole frame. */
.statement.band .statement-bg::after{
  background:
    linear-gradient(95deg, rgba(20,20,20,.88) 0%, rgba(20,20,20,.5) 46%, rgba(20,20,20,.08) 100%),
    linear-gradient(to bottom, var(--ink) 0%, transparent 11%, transparent 89%, var(--ink) 100%);
}
.statement.band .display{ max-width:20ch; }

/* Contact overlay hero. The source is a tall portrait, so the crop is pulled
   up to keep both the shooter and the bloke on the jetty in a wide band. */
.contact-hero{ min-height:72svh; }
.contact-hero .hero-media img{ object-position:center 36%; }
.contact-hero .hero-media::after{
  background:linear-gradient(to top, rgba(20,20,20,.94) 0%, rgba(20,20,20,.4) 55%, rgba(20,20,20,.6) 100%);
}
.contact-hero .eyebrow{ color:rgba(242,239,234,.8); }
.contact-hero .page-sub{ color:rgba(242,239,234,.84); margin-top:1.5rem; }

/* Films on a case study. A single film runs wide because it is the hero.
   Two or more drop to a two-up grid so a page with four does not become
   four full-width players stacked down the screen. */
.embed-stack{ display:grid; gap:clamp(1rem,2vw,1.75rem); margin-top:2rem; }
.embed-stack:has(> .embed:nth-child(2)){ grid-template-columns:repeat(2,1fr); }
.embed-stack .embed{ width:100%; }
/* An odd last film spans both columns rather than sitting half-width alone. */
.embed-stack:has(> .embed:nth-child(2)) > .embed:last-child:nth-child(odd){ grid-column:1 / -1; }
/* Single film: capped so it does not dominate, and centred rather than
   left-aligned against a wide empty right side. */
.embed-stack:not(:has(> .embed:nth-child(2))){ max-width:900px; margin-inline:auto; }

@media (max-width:760px){
  .embed-stack:has(> .embed:nth-child(2)){ grid-template-columns:1fr; }
  .embed-stack:has(> .embed:nth-child(2)) > .embed:last-child:nth-child(odd){ grid-column:auto; }
}

/* Enquiry block at the foot of each case study. */
.enquiry{ border-top:1px solid var(--ink-line); }
.enquiry-in{ display:grid; grid-template-columns:1fr 1.2fr; gap:clamp(2.5rem,6vw,6rem); align-items:start; }
.enquiry h2{ font-size:var(--t-lg); margin-bottom:1.25rem; }
@media (max-width:1100px){ .enquiry-in{ grid-template-columns:1fr; } }

/* ============================================================
   About: person cards + dialogs
   ============================================================ */

.person{
  display:block; width:100%; padding:0; border:0; background:none;
  color:inherit; font:inherit; text-align:left; cursor:pointer;
}
.person-media{ position:relative; display:block; overflow:hidden; }
.person-media img{
  width:100%; height:auto; aspect-ratio:4/5; object-fit:cover;
  filter:brightness(.95);
  transition:transform 800ms var(--ease), filter 800ms var(--ease);
}
.person:hover .person-media img,
.person:focus-visible .person-media img{ transform:scale(1.05); filter:brightness(1.04); }
.person-media::after{
  content:''; position:absolute; inset:0;
  background:linear-gradient(to top, rgba(20,20,20,.8), transparent 45%);
  opacity:0; transition:opacity 420ms var(--ease);
}
.person:hover .person-media::after,
.person:focus-visible .person-media::after{ opacity:1; }

.person-cue{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  padding:clamp(1rem,2vw,1.5rem);
  display:flex; align-items:center; gap:.5rem;
  font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ember);
  opacity:0; transform:translateY(10px);
  transition:opacity 420ms var(--ease), transform 420ms var(--ease);
}
.person:hover .person-cue,
.person:focus-visible .person-cue{ opacity:1; transform:none; }
.person:focus-visible{ outline:2px solid var(--ember); outline-offset:4px; }

.person-name{ display:block; margin-top:.9rem; }
.person-name strong{
  display:block; font-family:var(--display); font-stretch:106%; font-weight:500;
  text-transform:uppercase; letter-spacing:.02em; font-size:1rem;
  transition:color 320ms var(--ease);
}
.person:hover .person-name strong{ color:var(--ember); }
.person-name span{ font-size:var(--t-meta); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }

/* ---- Dialog ---- */

.person-dialog{
  border:0; padding:0; background:var(--ink-raised); color:var(--bone);
  width:min(920px, calc(100vw - 2rem));
  max-height:min(88svh, 900px);
  border:1px solid var(--ink-line);
}
.person-dialog::backdrop{ background:rgba(10,10,10,.82); backdrop-filter:blur(6px); }
.person-dialog[open]{ animation:dlg 420ms var(--ease); }
@keyframes dlg{ from{ opacity:0; transform:translateY(18px); } to{ opacity:1; transform:none; } }

.dlg-in{ padding:clamp(1.5rem,3.5vw,3rem); overflow-y:auto; max-height:inherit; }

.dlg-close{
  position:absolute; top:.75rem; right:.75rem; z-index:3;
  width:44px; height:44px; display:grid; place-items:center; cursor:pointer;
  background:rgba(20,20,20,.7); border:1px solid var(--ink-line); color:var(--bone);
  font-size:1.5rem; line-height:1;
  transition:border-color 300ms var(--ease), color 300ms var(--ease);
}
.dlg-close:hover{ border-color:var(--ember); color:var(--ember); }

.dlg-head{ display:grid; grid-template-columns:150px 1fr; gap:clamp(1.25rem,3vw,2.25rem); align-items:center; }
.dlg-head img{ width:100%; aspect-ratio:4/5; object-fit:cover; }
.dlg-head h2{ font-size:var(--t-lg); }
.dlg-head .eyebrow{ margin-bottom:1rem; }
.dlg-head .note{ margin-top:.9rem; }

.dlg-body{ margin-top:clamp(1.5rem,3vw,2.25rem); max-width:66ch; }
.dlg-body p{ color:var(--muted); }
.dlg-body p + p{ margin-top:1rem; }
.dlg-body b{ color:var(--bone); font-weight:500; }

.dlg-strip{ display:grid; grid-template-columns:repeat(3,1fr); gap:.75rem; margin-top:clamp(1.5rem,3vw,2.25rem); }
.dlg-strip img{ width:100%; aspect-ratio:3/2; object-fit:cover; filter:brightness(.95); }

@media (max-width:640px){
  .dlg-head{ grid-template-columns:1fr; }
  .dlg-head img{ max-width:160px; aspect-ratio:1/1; }
  .dlg-strip{ grid-template-columns:1fr 1fr; }
  .dlg-strip img:last-child{ display:none; }
}

@media (prefers-reduced-motion:reduce){
  .person-dialog[open]{ animation:none; }
  .person:hover .person-media img{ transform:none; }
  .person-cue{ opacity:1; transform:none; }
}

/* Services header overlay. Shorter than a case study hero because the four
   service rows need to start pulling into view. */
.services-hero{ min-height:64svh; }
.services-hero .hero-media img{ object-position:center 45%; }
.services-hero .hero-media::after{
  background:linear-gradient(to top, rgba(20,20,20,.95) 0%, rgba(20,20,20,.45) 58%, rgba(20,20,20,.6) 100%);
}
.services-hero .eyebrow{ color:rgba(242,239,234,.8); }
.services-hero .page-sub{ color:rgba(242,239,234,.84); margin-top:1.5rem; max-width:52ch; }

/* Dialog scrolling: only the inner pane scrolls, and its scrollbar is hidden.
   Without the outer overflow:hidden you get two visible bars side by side. */
.person-dialog{ overflow:hidden; }
.dlg-in{ scrollbar-width:none; -ms-overflow-style:none; overscroll-behavior:contain; }
.dlg-in::-webkit-scrollbar{ width:0; height:0; display:none; }

/* Hero showreel. A 16:9 iframe made to cover any viewport: size it by the
   larger of 100vw or 177.78vh, then centre it. Sits above the poster. */
.hero-video{
  position:absolute; top:50%; left:50%;
  width:100vw; height:56.25vw;
  min-height:100%; min-width:177.78vh;
  transform:translate(-50%,-50%);
  z-index:1; pointer-events:none;
  opacity:0; transition:opacity 900ms var(--ease);
}
.hero-video.ready{ opacity:1; }
.hero-video iframe{ width:100%; height:100%; border:0; display:block; }
/* Gradient must sit above the film, not just the poster. */
.hero-media::after{ z-index:2; }

@media (prefers-reduced-motion:reduce){
  .hero-video{ display:none; }
}

/* Testimonials as cards. The quotes vary a lot in length, so without a box
   they read as ragged. Equal height comes from stretching the grid row and
   pushing the attribution to the bottom with margin-top:auto. */
.quotes-track > blockquote{
  display:flex; flex-direction:column;
  background:var(--ink-raised); border:1px solid var(--ink-line);
  padding:clamp(1.75rem,3vw,2.5rem);
  transition:border-color 420ms var(--ease);
}
.quotes-track > blockquote:hover{ border-color:var(--ember); }
.quotes-track > blockquote p{
  font-size:var(--t-md); line-height:1.45; letter-spacing:0;
  font-family:var(--display); font-stretch:100%;
}
.quotes-track > blockquote footer{ margin-top:auto; padding-top:1.75rem; }
/* Gap now sits between cards rather than between floating columns. */
.quotes-track{ gap:clamp(1rem,2vw,1.75rem); grid-auto-columns:calc(50% - 0.875rem); }
@media (max-width:860px){ .quotes-track{ grid-auto-columns:100%; } }

/* ============================================================
   Process (home)
   Deliberately not a bordered grid: the services block above already
   uses cells, so this uses a hairline rule and a large number instead.
   ============================================================ */

.process-head{
  display:grid; grid-template-columns:1fr 1fr; gap:clamp(2rem,5vw,5rem);
  align-items:end; margin-bottom:clamp(3rem,6vw,5rem);
}
/* The hard <br> that used to be in this heading forced "to work with us" onto
   its own line, and "What it looks like" then wrapped on its own, stranding
   "LIKE" alone in the middle. Balance lets the browser even the lines out at
   whatever width it is given, which is the only thing that holds up from a
   390px phone to a 1560px desktop. */
.process-head h2{ font-size:var(--t-xl); text-wrap:balance; }
.process-head .note{ max-width:40ch; margin:0; }

.process-grid{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(4,1fr); gap:clamp(1.5rem,3vw,3rem);
}
.process-grid li{
  position:relative; padding-top:2.25rem;
  border-top:1px solid var(--ink-line);
}
/* The tick that marks each step on the rule. */
.process-grid li::before{
  content:''; position:absolute; top:-1px; left:0;
  width:2.5rem; height:1px; background:var(--ember);
}
.step-num{
  display:block; font-family:var(--display); font-stretch:110%; font-weight:600;
  font-size:clamp(1.75rem,3vw,2.5rem); line-height:1; letter-spacing:-0.02em;
  color:var(--ink-line); margin-bottom:1.5rem;
  transition:color 420ms var(--ease);
}
.process-grid li:hover .step-num{ color:var(--ember); }
.process-grid h3{
  font-family:var(--display); font-stretch:106%; font-weight:500;
  font-size:1.125rem; text-transform:uppercase; letter-spacing:.01em;
  margin-bottom:.9rem;
}
.process-grid p{ color:var(--muted); font-size:.9375rem; }

.process-cta{ margin-top:clamp(3rem,5vw,4.5rem); }

@media (max-width:1100px){
  .process-grid{ grid-template-columns:repeat(2,1fr); gap:2.5rem; }
  .process-head{ grid-template-columns:1fr; gap:1.5rem; align-items:start; }
}
@media (max-width:560px){
  .process-grid{ grid-template-columns:1fr; }
}

/* Light variant of the process band. Uses --sand, the same surface as the
   footer, so the page alternates rather than introducing a third tone.
   Every colour that assumed a dark background has to be inverted here. */
.process.light{ background:var(--sand); color:var(--ink); }
.process.light .eyebrow{ color:rgba(20,20,20,.55); }
.process.light h2,
.process.light h3{ color:var(--ink); }
.process.light .note,
.process.light .process-grid p{ color:rgba(20,20,20,.66); }
.process.light .process-grid li{ border-top-color:rgba(20,20,20,.18); }
.process.light .step-num{ color:rgba(20,20,20,.2); }
.process.light .process-grid li:hover .step-num{ color:var(--ember-deep); }
.process.light .btn{ background:var(--ink); border-color:var(--ink); color:var(--bone); }
.process.light .btn:hover{ background:var(--ember-deep); border-color:var(--ember-deep); color:var(--bone); }

/* Belt and braces: soften both vertical edges of the statement backdrop so a
   hard line can never appear if the frame is ever swapped for a different one. */
.statement-bg{
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
}
.statement.band .statement-bg{ -webkit-mask-image:none; mask-image:none; }

/* ============================================================
   Storytelling (home)
   Image left, copy right, so it reads opposite to the About block below it.
   ============================================================ */

/* Image column stretches to whatever height the copy needs, so there is no
   floating rectangle with dead space around it. A minimum stops it going
   letterbox-thin if the copy is ever shortened. */
.story-in{
  display:grid; grid-template-columns:0.9fr 1.1fr;
  gap:clamp(2rem,5vw,4.5rem); align-items:stretch;
}
.story-media{ margin:0; position:relative; min-height:clamp(340px,42vw,560px); }
.story-media img{
  position:absolute; inset:0;
  width:100%; height:100%; object-fit:cover; object-position:center 55%;
  filter:brightness(.95);
}
.story-copy{ display:flex; flex-direction:column; justify-content:center; }
.story-copy h2{ font-size:var(--t-xl); margin-bottom:1.25rem; }
.story-copy .lede{ color:var(--bone); font-size:var(--t-md); margin-bottom:1.75rem; }
.story-copy p{ color:var(--muted); max-width:52ch; }
.story-copy p + p{ margin-top:1.1rem; }
.story-close{
  color:var(--bone) !important; font-family:var(--display); font-stretch:104%;
  font-size:var(--t-lg); line-height:1.2; letter-spacing:-0.01em;
  text-transform:uppercase; margin-top:2.25rem !important; max-width:22ch;
}

@media (max-width:900px){
  .story-in{ grid-template-columns:1fr; }
  .story-media{ min-height:0; aspect-ratio:16/10; }
}

/* The story block and the About block both carry full section padding, which
   stacks into roughly 280px of dead space between them. Halve the join. */
.story{ padding-bottom:clamp(2rem,4vw,3.5rem); }
.story + section{ padding-top:clamp(2.5rem,5vw,4.5rem); }

/* Poster is the instant paint, then steps aside once the film is running. */
.hero-media img{ transition:opacity 700ms var(--ease); }
.hero-media img.handed-over{ opacity:0; }

/* A project with no photography yet: the tile and hero fall back to a flat
   panel rather than a broken image box. */
.tile-media:empty{ background:var(--ink-raised); }
.cs-hero .hero-media:empty{ background:linear-gradient(160deg,var(--ink-raised),var(--ink)); }
