/* ══ TOKENS ═══════════════════════════════════════════ */
/* --ink is the foreground, --paper the background, --white the colour that
   sits on top of --ink (chips, badges). All three invert together in dark
   mode so the whole page can cross-fade as you scroll. */
/* Hemi Media brand: the deck alternates deep-red spreads with black ones, so
   the template's light/dark pair becomes red/black and keeps cross-fading. */
:root {
  --ink:        #fff1ee;
  --ink-2:      rgba(255,241,238,.78);
  --grey:       rgba(255,232,228,.62);
  --grey-light: rgba(255,232,228,.24);
  --black:      #0a0a0a;
  --white:      #a31418;
  --paper:      #a31418;
  --red:        #ee1616;
  --scanline:   rgba(0,0,0,.05);

  --gutter: 64px;
  --maxw:   1297px;

  --sans: "Geist", sans-serif;
  --mono: "Geist Mono", monospace;
  --script: "Inspiration", cursive;

  --ease: cubic-bezier(.22, 1, .36, 1);
}

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

html { scroll-behavior: smooth; }

/* Mobile browsers flash a translucent block over whatever you tap — blue on
   Android, grey on iOS. It is drawn on the element's own box, so on this site
   it lands as a rectangle behind the nav links, the burger, the works toggles
   and every anchor, which reads as a rendering fault rather than a response.
   The property inherits, so setting it once here covers the page. Focus rings
   are untouched: they are how a keyboard finds its place. */
html { -webkit-tap-highlight-color: transparent; }

/* No scrollbar in any engine. The standard property covers Firefox and
   Chrome 121+, the pseudo-element the older WebKit/Blink builds, and
   -ms-overflow-style legacy Edge. Only the bar goes: wheel, trackpad, touch,
   keyboard and the scroll-driven theme all behave exactly as before. */
html, body {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
html::-webkit-scrollbar,
body::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* Scroll-driven dark mode. JS toggles .dark on <body> when a section marked
   data-theme="dark" reaches the reference line; everything cross-fades. */
body.dark {
  --ink:        #fff;
  --ink-2:      rgba(255,255,255,.78);
  --paper:      #0a0a0a;
  --white:      #0a0a0a;
  --grey:       rgba(255,255,255,.52);
  --grey-light: rgba(255,255,255,.18);
  --scanline:   rgba(255,255,255,.035);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 500;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color .6s ease, color .6s ease;
}

/* Anything that names a flipping token needs its own transition, or it snaps
   while the inherited colours fade. */
.card, .sq, .clients__label, .viewlive,
.works__toggle button, .works__index li::after,
.services__title, .services__tag, .services__name, .services__list,
.services__list li, .contact__tag, .field__label,
.field input, .field textarea,
.footer, .footer__screen, .footer__social, .footer__copy,
.cta__link, .menu__label,
.stats, .stats li, .stats__figure, .stats__label,
.overview__list a, .team__grid, .team__name, .team__role,
.cases__group, .cases__tags,
.contact__details, .contact__details li, .contact__key, .contact__details a {
  transition: background-color .6s ease, color .6s ease, border-color .6s ease;
}

img, video, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ol, ul { margin: 0; padding: 0; list-style: none; }
p  { margin: 0; }
h1, h2 { margin: 0; font-weight: 400; }

.mono {
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.3;
  letter-spacing: .03em;
  font-weight: 400;
}

/* Script accent letters. Inspiration has tall, loose glyphs — they sit as
   inline-blocks with line-height 1 so they align to the top of the Geist
   letters rather than pushing the line box around. */
.script {
  font-family: var(--script);
  font-weight: 400;
  letter-spacing: 0;
  display: inline-block;
  line-height: 1;
  vertical-align: top;
}

/* MEDIA → MED·AI. Laid out inline by default, so a visitor with no JS or with
   reduced motion gets the wordmark exactly as it was; main.js measures the two
   letters and only then takes over their placement. --swap-w is that
   measurement: the run is the same width in both orders, so nothing on the
   line moves while they trade places. */
.swap__l { display: inline-block; }
.swap.is-live {
  position: relative;
  width: var(--swap-w);
  height: 1em;
  perspective: 900px;
}
.swap.is-live .swap__l {
  position: absolute;
  left: 0;
  top: 0;
  line-height: 1;
  letter-spacing: 0;
  will-change: transform;
}
/* Straightened into the title's own face. Inspiration's swash capitals do not
   read as "AI" in that order — an I is a curl and an A is a flourish, so the
   reorder on its own loses the joke it exists to make. */
.swap.is-live .swap__l.is-sans { font-family: var(--sans); }

.arrow { display: inline-block; font-size: .7em; vertical-align: .35em; }
.plus  { display: inline-block; margin-right: .35em; }

/* Fine vertical pinstripe over the whole page */
.grain {
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg,
      var(--scanline) 0 1px,
      transparent 1px 4px);
}
/* The moving plate under the pinstripe, at the template's tenth of opacity.
   Stretched rather than cropped, as Framer had it: the source is 400×225, so
   covering a desktop viewport would only crop noise that has no composition to
   protect. The plate is a light grey, which is why a tenth is all it takes. */
.grain__film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  opacity: .1;
}

/* ══ INTRO ════════════════════════════════════════════
   Counts up over black on every load, then opens like an eye: a soft ellipse
   is masked out of the overlay, widening into a slit first and lifting after.
   JS sets --ew / --eh per frame, because a gradient can't be transitioned. */
.preload {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  background: var(--black);
  --ew: 0%;
  --eh: 0%;
}
.preload.is-open {
  -webkit-mask-image:
    radial-gradient(ellipse var(--ew) var(--eh) at 50% 50%,
      transparent 0 74%, #000 100%);
  mask-image:
    radial-gradient(ellipse var(--ew) var(--eh) at 50% 50%,
      transparent 0 74%, #000 100%);
}
.preload.is-done { display: none; }

.preload__count {
  margin: 0;
  color: var(--grey);
  font-size: 15px;
  letter-spacing: .06em;
  transition: opacity .25s ease;
}
.preload.is-open .preload__count { opacity: 0; }

/* ══ NAV ══════════════════════════════════════════════ */
.nav {
  position: fixed;
  inset: 16px var(--gutter) auto;
  z-index: 20;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  /* The template used difference blending for automatic contrast; over the
     brand red that inverts to cyan, so the nav follows the theme token instead. */
  color: var(--ink);
  transition: transform .45s var(--ease), opacity .35s var(--ease), color .6s ease;
}
/* hidden while scrolling down, back on the first scroll up */
.nav.is-hidden {
  transform: translateY(calc(-100% - 24px));
  opacity: 0;
}

.nav__logo { display: block; }
/* The lockup is white on transparent, and both themes' --ink is near-white,
   so one file works over the red and the black. */
.nav__logo img { display: block; width: 112px; height: auto; }

.nav__links {
  display: flex;
  gap: 28px;
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: .03em;
  padding-top: 6px;
}
.nav__links a { transition: opacity .3s var(--ease); }
.nav__links a:hover { opacity: .5; }

.nav__contact {
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: .03em;
  padding-top: 6px;
  transition: opacity .3s var(--ease);
}
.nav__contact:hover { opacity: .5; }

.nav__burger { display: none; }

.menu { display: none; }

/* ══ HERO ═════════════════════════════════════════════ */
/* Hero sizing is capped by viewport height as well as width, so the whole
   composition — title, TV and clock — fits above the fold on short screens
   instead of pushing the TV below it. */
.hero {
  position: relative;
  min-height: 100svh;
  padding: min(176px, 18vh) var(--gutter) 64px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hero__title {
  font-size: clamp(72px, min(11.5vw, 18vh), 164px);
  line-height: .8;
  letter-spacing: -.02em;
  text-align: center;
  display: grid;
  justify-items: center;
  gap: 9px;
}
.hero__line { display: block; }
.hero__title .script { font-size: 1em; }

/* The TV sits left of the page centre; the tagline hangs off its right edge.
   The vh cap is what protects short laptop screens — the hero is a column of
   title + TV inside 100svh, so the set has to shrink as the viewport does. */
.hero__tv {
  position: relative;
  width: min(520px, 74vw, 52vh);
  margin-top: min(37px, 4vh);
  transform: translateX(-18.1%);
}
/* The frame is exactly the photo's box, so the video inset stays correct even
   when the tagline drops below the TV on small screens. */
.hero__tv-frame { position: relative; }
/* The photo sits on top of the screen layers. In-flow boxes paint under
   positioned siblings whatever the source order, so it needs positioning of
   its own to win — and winning is the point: the transparent aperture becomes
   the mask and the bezel crops whatever the screen overshoots. */
.hero__tv-img { width: 100%; position: relative; z-index: 2; }
/* Inset into the CRT screen area of the TV photo. These numbers are the
   measured bounding box of the transparent hole in tv-hero.png, not the
   template's estimate — the old values overhung the bezel on the left. */
.hero__tv-video {
  position: absolute;
  left: 8.2%;
  top: 9.89%;
  width: 64.65%;
  height: 68.98%;
  object-fit: cover;
  z-index: 1;
}
/* Deliberately larger than the aperture: the canvas carries no mask of its
   own, so it overshoots and lets the bezel do the cropping. */
.hero__tv-canvas {
  position: absolute;
  left: 7.5%;
  top: 9.2%;
  width: 66.1%;
  height: 70.4%;
  z-index: 1;
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.hero__tv-canvas.is-on { opacity: 1; }
/* The reel is only a texture source for the canvas above and is never seen —
   but it has to stay in the document, since iOS will not autoplay a detached
   video. Hidden by size and opacity rather than display:none, which stops the
   decoder in some browsers and would freeze the texture on its first frame. */
.hero__tv-source {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.hero__tagline {
  position: absolute;
  left: calc(100% + 8px);
  top: 75.3%;
  width: 200px;
  color: var(--ink);
  line-height: 1.3;
}

.clock {
  position: absolute;
  left: var(--gutter);
  bottom: min(56px, 6vh);
  color: var(--ink);
  line-height: 1.6;
}
.clock__row { display: flex; align-items: center; gap: 6px; }
.clock__globe {
  width: 11px; height: 11px;
  border: 1px solid currentColor;
  border-radius: 50%;
  position: relative;
  flex: none;
}
.clock__globe::before,
.clock__globe::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid currentColor;
}
.clock__globe::before { border-radius: 50%; border-width: 0 1px; inset: -1px 2px; }
.clock__globe::after  { border-width: 1px 0 0; top: 50%; left: -1px; right: -1px; }

/* ══ INTRO ════════════════════════════════════════════ */
.intro {
  padding: 176px var(--gutter) 0;
}
.intro__text {
  max-width: var(--maxw);
  margin: 0 auto;
  font-size: clamp(28px, 3.7vw, 48px);
  line-height: 1;
  letter-spacing: -.02em;
  font-weight: 500;
}
.intro__indent { display: inline-block; width: 5.2em; }

.intro__loc {
  max-width: var(--maxw);
  margin: 40px auto 0;
  display: flex;
  align-items: center;
  gap: 12px;
}
.sq {
  width: 11px; height: 11px;
  background: var(--ink);
  display: inline-block;
  flex: none;
}

/* Company-profile figures, straight off the profile spread. */
.stats {
  max-width: var(--maxw);
  margin: 88px auto 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
  border-top: 1px solid var(--grey-light);
}
.stats li {
  padding: 28px 0 0;
  border-right: 1px solid var(--grey-light);
  padding-right: 32px;
}
.stats li:last-child { border-right: 0; }
.stats__figure {
  display: block;
  font-family: var(--sans);
  font-size: clamp(44px, 5.2vw, 76px);
  line-height: .9;
  letter-spacing: -.03em;
  font-weight: 500;
  color: var(--ink);
}
/* the middle figure is a phrase, not a number — it needs a smaller size */
.stats__figure--text { font-size: clamp(22px, 2.3vw, 32px); line-height: 1.05; }
.stats__label { display: block; margin-top: 16px; color: var(--grey); }

/* ══ PORTFOLIO OVERVIEW ═══════════════════════════════ */
/* No heading here: the section opens straight onto the index, so it carries
   less top padding than the titled sections — 200px of air reads as a void
   above 16px type when there is no display line to fill it. */
.overview { padding: 140px var(--gutter) 0; }

.overview__list {
  max-width: var(--maxw);
  margin: 0 auto;
  display: grid;
  gap: 2px;
  font-size: 16px;
}
.overview__list a {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 14px 0;
  color: var(--grey);
  transition: color .35s var(--ease);
}
/* the deck draws a rule with an arrowhead leading into each entry */
.overview__rule {
  flex: none;
  width: 180px;
  height: 1px;
  background: currentColor;
  position: relative;
  transition: width .45s var(--ease);
}
.overview__rule::after {
  content: "";
  position: absolute;
  right: 0; top: -3px;
  border: 3.5px solid transparent;
  border-left-color: currentColor;
}
.overview__list a:hover { color: var(--ink); }
.overview__list a:hover .overview__rule { width: 232px; }

/* ══ TEAM ═════════════════════════════════════════════ */
.team { padding: 220px var(--gutter) 0; }
.team__title {
  max-width: var(--maxw);
  margin: 0 auto;
  font-size: clamp(52px, 6.7vw, 96px);
  line-height: .8;
  letter-spacing: -.03em;
}
.team__title .script { font-size: 1em; }

.team__grid {
  max-width: var(--maxw);
  margin: 96px auto 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 64px 40px;
  border-top: 1px solid var(--grey-light);
  padding-top: 56px;
}
.team__name {
  font-size: 20px;
  line-height: 1.2;
  letter-spacing: -.02em;
  font-weight: 500;
  color: var(--ink);
}
.team__role { margin-top: 10px; color: var(--grey); }

/* ══ SELECTED WORKS ═══════════════════════════════════ */
.works { padding: 140px var(--gutter) 0; }

/* The grid mark hangs above the heading in the left column; the heading is
   right-aligned and its top lines up with the mark's caption. */
.works__head {
  max-width: var(--maxw);
  margin: 0 auto;
  position: relative;
  padding-top: 265px;
}
.works__title {
  font-size: clamp(52px, 6.7vw, 96px);
  line-height: .8;
  letter-spacing: -.03em;
  text-align: right;
}
.works__title .script { font-size: 1em; }

.works__mark {
  position: absolute;
  left: 0;
  top: 0;
}
.works__mark img { width: 180px; opacity: .55; }
.works__mark p { margin-top: 82px; }

.works__toggle {
  max-width: var(--maxw);
  margin: 128px auto 0;
  display: flex;
  gap: 16px;
}
.works__toggle button { transition: .3s var(--ease); color: var(--grey); }
.works__toggle button.is-active {
  background: var(--ink);
  color: var(--white);
  padding: 2px 6px;
  margin: -2px -6px;
}

.works__body {
  max-width: var(--maxw);
  margin: 86px auto 0;
  display: grid;
  grid-template-columns: 206px 1fr;
  gap: 0 200px;
  align-items: start;
}

/* Nineteen projects need far more scroll travel than the template's six, or
   the preview flicks through the whole set in a couple of hundred pixels.
   The extra height is the runway; both columns pin while it plays out. */
.works__body:not(.is-list) { min-height: 210vh; }

/* Sticks just below the nav so it starts level with the top of the preview. */
.works__index { position: sticky; top: 120px; }
.works__index li {
  position: relative;
  display: grid;
  grid-template-columns: 58px 1fr;
  padding: 12px 0;
  color: var(--grey);
  cursor: pointer;
  transition: color .4s var(--ease);
}
/* the active row's rule extends past the column, as in the template */
.works__index li::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  height: 1px;
  width: 100%;
  background: var(--grey-light);
  transition: width .5s var(--ease);
}
.works__index li.is-active { color: var(--ink); }
.works__index li.is-active::after { width: 182%; }

.works__stage {
  position: sticky;
  top: 120px;
  aspect-ratio: 875 / 650;
}
.works__stage img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .55s var(--ease);
}
.works__stage img.is-active { opacity: 1; }

/* ── list view ───────────────────────────────────────
   One centred preview above a wrapping run of large project names. */
.works__list { display: none; }

.works__body.is-list { grid-template-columns: 1fr; }
.works__body.is-list .works__index { display: none; }
.works__body.is-list .works__stage {
  position: relative;
  top: auto;
  width: 552px;
  max-width: 100%;
  margin: 0 auto;
}
.works__body.is-list .works__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-content: flex-start;
  column-gap: 40px;
  margin-top: 88px;
  /* one full-width rule per 70px row */
  background-image: repeating-linear-gradient(180deg,
    transparent 0 69px, var(--grey-light) 69px 70px);
}

.wl {
  display: flex;
  align-items: baseline;
  gap: 20px;
  height: 70px;
  color: var(--grey-light);
  transition: color .35s var(--ease);
}
.wl__num  { flex: none; }
.wl__name {
  font-family: var(--sans);
  font-size: 48px;
  line-height: 1;
  letter-spacing: -.02em;
  font-weight: 400;
}
.wl:hover, .wl.is-active { color: var(--ink); }

/* cursor-following label shown while hovering the list */
.viewlive {
  position: fixed;
  z-index: 30;
  top: 0; left: 0;
  padding: 3px 8px;
  background: var(--ink);
  color: var(--white);
  pointer-events: none;
  opacity: 0;
  transition: opacity .25s var(--ease);
}
.viewlive.on { opacity: 1; }

/* ── case notes ──────────────────────────────────────
   The deck follows each service with its projects; these reuse the services
   list rows so the two runs read as one system. */
.cases { margin-top: 180px; }
.cases__group {
  max-width: var(--maxw);
  margin: 96px auto 0;
  color: var(--ink);
  letter-spacing: .06em;
}
.cases__group:first-child { margin-top: 0; }
.cases .services__list { margin-top: 28px; }
.cases .services__list li { align-items: start; }
/* grid items default to min-width:auto, which lets the long tag runs spill
   past their column instead of wrapping inside it */
.cases .services__list li > * { min-width: 0; }
.cases .services__name { display: block; line-height: 1.35; }
.cases__tags {
  display: block;
  margin-top: 8px;
  color: var(--grey);
  font-size: 12px;
  letter-spacing: .02em;
}

/* ══ CTA ══════════════════════════════════════════════ */
.cta {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 120px var(--gutter) 0;
  text-align: center;
}
.cta__label { color: var(--ink); margin-bottom: 10px; }
.cta__link {
  font-family: var(--sans);
  font-size: 32px;
  line-height: 1.3;
  letter-spacing: -.02em;
  font-weight: 500;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
  display: inline-block;
  transition: opacity .3s var(--ease);
}
/* The arrow rests pointing up-right and swings to horizontal while the link is
   held — the glyph is already at 45°, so a 45° clockwise turn levels it. Touch
   has no hover, so there .is-aimed does it as the link comes into view. */
.cta__link .arrow {
  border: 0;
  margin-left: 8px;
  transition: transform .45s var(--ease);
}
.cta__link:hover .arrow,
.cta__link:focus-visible .arrow,
.cta__link.is-aimed .arrow { transform: rotate(45deg); }
.cta__link:hover { opacity: .55; }

/* ══ APPROACH ═════════════════════════════════════════ */
/* Core values carry a name but no description, so the cards are shorter than
   the template's and the section needs less room beneath them. */
.approach {
  position: relative;
  padding: 260px var(--gutter) 120px;
}
.approach__title {
  position: sticky;
  top: 14vh;
  font-size: clamp(52px, 6.7vw, 96px);
  line-height: .8;
  letter-spacing: -.03em;
  width: max-content;
}
.approach__title .script { font-size: 1em; }

.approach__cards {
  position: relative;
  z-index: 2;
  margin: -80px auto 0;
  width: 288px;
  display: grid;
  gap: 90px;
}

/* Opaque so the cards occlude the statement scrolling behind them. */
.card {
  border: 1px solid var(--grey-light);
  background: var(--paper);
}
.card__bar {
  display: flex;
  gap: 4px;
  align-items: center;
  padding: 7px 10px;
  border-bottom: 1px solid var(--grey-light);
}
.card__bar i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--grey);
}
.card__body { padding: 18px 12px 22px; }
.card__num  { color: var(--ink); }
.card__name { color: var(--ink); margin-top: 28px; }
.card__desc { color: var(--grey); margin-top: 8px; }

/* Pinned to the bottom of the viewport for as long as the section is on
   screen — sticky-bottom is bounded by .approach, so it never rides up over
   the section above. */
.approach__statement {
  position: sticky;
  bottom: 96px;
  margin: 0 0 0 auto;
  width: 812px;
  max-width: 100%;
  text-align: right;
  font-size: clamp(28px, 3.7vw, 48px);
  line-height: 1.05;
  letter-spacing: -.02em;
  font-weight: 500;
  color: var(--grey);
}

/* ══ SERVICES ═════════════════════════════════════════ */
/* No background of its own — the page itself goes dark around this section. */
.services {
  position: relative;
  padding: 120px var(--gutter) 140px;
  margin-top: 200px;
}

.services__diagram {
  width: 304px;
  margin: 0 auto;
  opacity: .85;
}
.services__ruler {
  width: 100%;
  max-width: var(--maxw);
  margin: 44px auto 0;
  opacity: .75;
}

.services__head {
  max-width: var(--maxw);
  margin: 76px auto 0;
  display: flex;
  align-items: flex-start;
  gap: 28px;
}
.services__title {
  font-size: clamp(52px, 6.7vw, 96px);
  line-height: .8;
  letter-spacing: -.03em;
}
.services__title .script { font-size: 1em; }
.services__tag { color: var(--ink); padding-top: 8px; }

.services__statement {
  max-width: var(--maxw);
  margin: 88px auto 0;
  padding-left: 30%;
  font-size: clamp(28px, 3.7vw, 48px);
  line-height: 1.05;
  letter-spacing: -.02em;
  font-weight: 500;
  color: var(--grey);
}
.services__statement--sub { margin-top: 72px; }

.services__list {
  max-width: var(--maxw);
  margin: 120px auto 0;
  border-top: 1px solid var(--grey-light);
}
.services__list li {
  display: grid;
  grid-template-columns: 324px 366px 1fr;
  align-items: center;
  padding: 22px 0;
  border-bottom: 1px solid var(--grey-light);
}
.services__num  { color: var(--grey); }
.services__name { color: var(--ink); font-weight: 500; }
.services__desc { color: var(--grey); line-height: 1.35; }

/* Why Us lists advantages, not services — no description column. */
.whyus { margin-top: 220px; }
.whyus .services__list li { grid-template-columns: 324px 1fr; }
.whyus .services__name { line-height: 1.35; }

.cta--dark { padding-top: 140px; }

/* ══ ABOUT ════════════════════════════════════════════ */
.about { padding: 200px var(--gutter) 0; }

.about__title {
  max-width: var(--maxw);
  margin: 0 auto;
  font-size: clamp(52px, 6.7vw, 96px);
  line-height: .8;
  letter-spacing: -.03em;
  text-align: center;
}
.about__title .script { font-size: 1em; }

/* Portrait sits on the page centre line; the name block hangs off its left. */
.about__intro {
  position: relative;
  max-width: var(--maxw);
  margin: 150px auto 0;
  display: flex;
  justify-content: center;
}
.about__text {
  position: absolute;
  right: 50%;
  margin-right: 169px;
  bottom: 4px;
  text-align: right;
}
.about__hello { color: var(--ink); }
.about__name {
  font-size: 32px;
  line-height: 1.3;
  letter-spacing: -.02em;
  font-weight: 500;
  margin-top: 8px;
}
.about__name em { font-style: normal; color: var(--grey); }
/* The dither and the 3D mark share one box, stacked. */
.about__mark { position: relative; width: 304px; height: 352px; flex: none; }
.about__portrait { display: block; width: 100%; height: 100%; }
.about__model {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity .6s var(--ease);
  background: transparent;
  --poster-color: transparent;
  /* model-viewer draws a loading bar across the top of its own box, which on
     the red reads as a stray rule above the mark. Nothing else marks the
     load, and the dither underneath already covers that. */
  --progress-bar-color: transparent;
  --progress-bar-height: 0px;
  cursor: grab;
}
.about__model.is-on { opacity: 1; }
.about__model:active { cursor: grabbing; }
/* Once the 3D mark is up the dither behind it is clutter, so it crossfades
   away. Two classes and an element beat [data-fade].on, which holds the
   canvas at opacity 1 after its entrance. */
.about__mark.is-3d .about__portrait { opacity: 0; }

.about__statement {
  max-width: var(--maxw);
  margin: 120px auto 0;
  font-size: clamp(28px, 3.7vw, 48px);
  line-height: 1.05;
  letter-spacing: -.02em;
  font-weight: 500;
}
.about__statement--left  { text-align: left;  max-width: 900px; margin-left: 0; }
.about__statement--right { text-align: right; }

.about__tag {
  max-width: var(--maxw);
  margin: 96px auto 0;
  color: var(--ink);
}

.clients-sec { padding-top: 220px; }
.clients-sec .clients { margin-top: 110px; }

.clients {
  max-width: var(--maxw);
  margin: 180px auto 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  flex-wrap: wrap;
}
.clients__label {
  background: var(--ink);
  color: var(--white);
  padding: 3px 7px;
  align-self: flex-end;
}
/* Twenty marks, ten to a row, two clean rows. A wrapping flex row could never
   line these up: they are trimmed to their artwork and run from 0.8:1 to 7:1,
   so any shared height made the wide marks seven times the width of the tall
   ones and every row ragged. The grid fixes the cell instead and each mark is
   contained inside it, bounded on both axes and centred. */
.clients__row {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 34px 20px;
  place-items: center;
}
.clients__row img {
  width: 100%;
  height: 34px;
  object-fit: contain;
  opacity: .8;
}

/* ══ CONTACT ══════════════════════════════════════════ */
.contact {
  position: relative;
  margin-top: 220px;
  padding: 120px var(--gutter) 160px;
}

.contact__tag { color: var(--ink); }

.contact__title {
  font-size: clamp(52px, 6.7vw, 96px);
  line-height: 1;
  letter-spacing: -.03em;
  text-align: center;
  margin-top: 150px;
  display: grid;
  justify-items: center;
}

/* Direct contact details, as listed on the deck's closing spread. */
.contact__details {
  width: 548px;
  max-width: 100%;
  margin: 96px auto 0;
  display: grid;
  border-top: 1px solid var(--grey-light);
}
.contact__details li {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 20px;
  padding: 16px 0;
  border-bottom: 1px solid var(--grey-light);
}
.contact__key { color: var(--grey); }
.contact__details a {
  color: var(--ink);
  border-bottom: 1px solid transparent;
  justify-self: start;
  transition: border-color .3s var(--ease);
}
.contact__details a:hover { border-bottom-color: currentColor; }

/* ── form ── */
.form {
  width: 548px;
  max-width: 100%;
  margin: 130px auto 0;
}
.field { display: block; margin-bottom: 44px; border: 0; padding: 0; }
.field__label {
  display: block;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 26px;
}
.field input[type=text],
.field input[type=email],
.field textarea {
  width: 100%;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--grey-light);
  color: var(--ink);
  font: inherit;
  padding: 0 0 14px;
  outline: none;
}
.field textarea { resize: vertical; }
.field input::placeholder,
.field textarea::placeholder { color: var(--grey); }
.field input:focus,
.field textarea:focus { border-bottom-color: var(--ink); }

.form__submit {
  display: block;
  margin: 80px auto 0;
}
.form__status { text-align: center; margin-top: 20px; color: var(--grey); min-height: 18px; }

/* ══ FOOTER ═══════════════════════════════════════════ */
.footer {
  position: relative;
  background: var(--paper);
  overflow: hidden;
}
.footer__tv {
  width: 100%;
  height: auto;
  display: block;
}
.footer__screen {
  position: absolute;
  /* aligned to the CRT screen area of the footer photo */
  left: 0;
  top: 8%;
  width: 67.5%;
  height: 84%;
  padding: 0 4.4%;
  color: var(--ink);
  display: flex;
  flex-direction: column;
}
.footer__heading {
  text-align: center;
  font-size: 24px;
  letter-spacing: -.02em;
  font-weight: 500;
  padding-top: 8%;
}

.marquee {
  flex: 1;
  overflow: hidden;
  margin-top: 4%;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
          mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
}
.marquee__track {
  display: grid;
  gap: 42px;
  width: 52%;
  margin: 0 auto;
  animation: marquee 26s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee { to { transform: translateY(-50%); } }

.quote {
  margin: 0;
  display: grid;
  grid-template-columns: 30% 1fr;
  gap: 5.5%;
  color: var(--grey);
  font-size: clamp(7px, .78vw, 13px);
}
.quote figcaption { text-align: right; }
.quote figcaption b { font-weight: 400; color: #cfcfcf; }
.quote blockquote { margin: 0; line-height: 1.4; }

.footer__social {
  display: flex;
  justify-content: space-between;
  border-top: 1px solid var(--grey-light);
  border-bottom: 1px solid var(--grey-light);
  padding: 14px 0;
  margin-top: 3%;
}
.footer__social a { transition: opacity .3s var(--ease); }
.footer__social a:hover { opacity: .55; }

.footer__bottom {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  padding: 3% 0 4%;
}
.footer__bottom .clock { position: static; color: var(--ink); }
.footer__copy {
  font-family: var(--mono);
  font-size: 56px;
  line-height: .8;
  letter-spacing: -.02em;
  color: var(--ink);
}

/* ══ SCROLL-REVEAL WORDS ══════════════════════════════ */
[data-reveal-words] .w { color: var(--grey-light); transition: color .25s linear; }
.services [data-reveal-words] .w,
.approach__statement .w { color: rgba(255,255,255,.16); }
[data-reveal-words] .w.on { color: var(--ink); }
.services [data-reveal-words] .w.on { color: var(--grey); }
/* This one stays a watermark: it lifts as it is read, but only far enough to
   register behind the cards, never far enough to compete with them. */
.approach__statement .w.on { color: rgba(255,255,255,.30); }

/* fade-up entrances */
[data-fade] { opacity: 0; transform: translateY(18px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
[data-fade].on { opacity: 1; transform: none; }

/* ══ PER-LETTER HEADING REVEAL ════════════════════════
   Headings are split into .ch spans and staggered in, matching the
   template's letter-by-letter build. */
/* keeps a word's letters on one line — see the note in main.js */
.split .wd { display: inline-block; white-space: nowrap; }

.split .ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(.32em);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
  transition-delay: var(--d, 0ms);
}
.split.on .ch { opacity: 1; transform: none; }

/* hero fades and drifts up as it scrolls away */
.hero__title { will-change: opacity, transform; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  [data-fade] { opacity: 1; transform: none; }
  /* the pinstripe stays; only the moving plate goes */
  .grain__film { display: none; }
}

/* ══ RESPONSIVE ═══════════════════════════════════════ */
@media (max-width: 1100px) {
  :root { --gutter: 40px; }
  .services__list li { grid-template-columns: 120px 240px 1fr; gap: 20px; }
  .whyus .services__list li { grid-template-columns: 120px 1fr; }
  .services__statement { padding-left: 12%; }
  .approach__statement { width: min(812px, 70vw); }
  .team__grid { grid-template-columns: repeat(2, 1fr); }
  /* Ten cells would be ~56px wide here, which shrinks the wide marks to
     nothing — half as many, twice the room, still even. */
  .clients__row { grid-template-columns: repeat(5, 1fr); }
  .overview__rule { width: 110px; }
  .overview__list a:hover .overview__rule { width: 150px; }
}

@media (max-width: 820px) {
  :root { --gutter: 24px; }

  .nav { inset: 14px var(--gutter) auto; align-items: center; }
  .nav__links, .nav__contact { display: none; }
  .nav__burger {
    display: grid;
    gap: 5px;
    width: 26px;
    padding: 6px 0;
  }
  .nav__burger span {
    display: block;
    height: 1.5px;
    background: currentColor;
    transition: transform .35s var(--ease), opacity .2s;
  }
  .nav__burger[aria-expanded=true] span:first-child { transform: translateY(3.2px) rotate(45deg); }
  .nav__burger[aria-expanded=true] span:last-child  { transform: translateY(-3.2px) rotate(-45deg); }

  .menu {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 19;
    /* fixed colours — the overlay must not follow the scroll theme */
    background: #000;
    color: #fff;
    padding: 18px var(--gutter) 40px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .4s var(--ease);
  }
  .menu.is-open { opacity: 1; pointer-events: auto; }

  .menu__label {
    font-size: 26px;
    line-height: 1.05;
    letter-spacing: -.02em;
    color: var(--grey);
  }
  .menu__label .script { font-size: 26px; }

  .menu__links {
    display: grid;
    margin-top: 96px;
    font-size: 28px;
    line-height: 1.8;
    letter-spacing: .01em;
  }
  .menu__links a { display: flex; justify-content: space-between; align-items: center; }
  .menu__links .arrow { font-size: .6em; }

  .menu .clock { position: absolute; left: var(--gutter); bottom: 40px; color: #fff; }

  /* the burger doubles as the close button, so hide the logo behind the overlay */
  body.menu-open .nav__logo { opacity: 0; }

  /* hero */
  .hero { padding-top: 120px; }
  /* template mobile sizes: 80px hero, 48px section headings */
  .hero__title { margin-top: 8vh; font-size: 80px; }
  /* The longest headings ("SELECTED CLIENTS", "AND OPPORTUNITIES") run past a
     narrow viewport at a flat 48px, so they scale with it and settle at the
     template's 48px once there is room. */
  .works__title, .approach__title, .services__title,
  .about__title, .contact__title,
  .team__title { font-size: clamp(26px, 7.6vw, 48px); }
  .hero__tv { width: 100%; margin-top: 28px; transform: none; }
  .hero__tagline {
    position: static;
    width: auto;
    text-align: center;
    margin-top: 28px;
  }
  .clock { bottom: 32px; }

  /* intro */
  .intro { padding-top: 110px; }
  .intro__indent { width: 0; }
  .stats { grid-template-columns: 1fr; gap: 0; margin-top: 56px; }
  .stats li {
    border-right: 0;
    border-bottom: 1px solid var(--grey-light);
    padding: 24px 0;
  }
  .stats li:last-child { border-bottom: 0; }
  .stats__label { margin-top: 10px; }

  /* overview */
  .overview { padding-top: 90px; }
  .overview__list { font-size: 15px; }
  .overview__rule { width: 40px; }
  .overview__list a:hover .overview__rule { width: 56px; }

  /* team */
  .team { padding-top: 130px; }
  .team__grid { grid-template-columns: 1fr; gap: 34px; margin-top: 56px; padding-top: 34px; }

  .clients-sec { padding-top: 130px; }
  .clients-sec .clients { margin-top: 64px; }

  /* why us */
  .whyus { margin-top: 130px; }
  .whyus .services__list li { grid-template-columns: 1fr; }

  /* case notes */
  .cases { margin-top: 110px; }
  .cases__group { margin-top: 64px; }

  /* works */
  .works { padding-top: 140px; }
  /* the 265px reserve is only needed for the desktop absolute-positioned mark */
  .works__head { padding-top: 0; display: grid; gap: 56px; }
  .works__title { text-align: left; order: 2; }
  .works__mark { position: static; order: 1; }
  .works__mark p { margin-top: 28px; }
  .works__toggle { display: none; }

  .works__body { grid-template-columns: 1fr; margin-top: 40px; }
  .works__body:not(.is-list) { min-height: 0; }
  .works__index { display: none; }
  /* mobile stacks every image, so the stage scrolls normally */
  .works__stage { position: static; aspect-ratio: auto; display: grid; }
  .works__stage img {
    position: static;
    opacity: 1;
    aspect-ratio: 875 / 650;
  }
  /* label under each image, generated in JS */
  .works__item { display: grid; gap: 0; }
  .works__caption {
    display: grid;
    grid-template-columns: 58px 1fr;
    padding: 14px 0 16px;
    border-bottom: 1px solid var(--grey-light);
    margin-bottom: 44px;
  }

  /* approach */
  .approach { padding: 160px var(--gutter) 120px; }
  .approach__title { position: static; }
  .approach__cards { margin: 60px auto 0; width: 100%; max-width: 320px; gap: 80px; }
  .approach__statement {
    position: static;
    margin: 100px 0 0;
    width: auto;
    text-align: left;
  }

  /* services */
  .services { margin-top: 120px; padding: 90px var(--gutter) 100px; }
  .services__diagram { width: 210px; }
  .services__head { flex-direction: column; gap: 14px; margin-top: 56px; }
  .services__statement { padding-left: 0; margin-top: 64px; }
  .services__list { margin-top: 80px; }
  .services__list li { grid-template-columns: 1fr; gap: 10px; padding: 20px 0; }
  .cta--dark { padding-top: 90px; }

  /* about */
  .about { padding-top: 130px; }
  .about__intro { flex-direction: column; align-items: center; gap: 28px; margin-top: 80px; }
  .about__text { position: static; margin: 0; text-align: center; order: 2; }
  .about__mark { width: 240px; height: 278px; }
  .about__statement, .about__statement--left { text-align: left; margin-top: 80px; max-width: none; }
  .about__statement--right { text-align: left; }
  .clients { margin-top: 110px; flex-direction: column; align-items: flex-start; gap: 28px; }
  /* four to a row on a phone, so five clean rows */
  .clients__row { grid-template-columns: repeat(4, 1fr); gap: 26px 14px; }
  .clients__row img { height: 32px; }

  /* contact */
  .contact { margin-top: 130px; padding: 90px var(--gutter) 110px; }
  .contact__title { margin-top: 80px; text-align: left; justify-items: start; }
  .contact__details { margin-top: 56px; }
  .contact__details li { grid-template-columns: 1fr; gap: 6px; }
  .form { margin-top: 80px; }
  .form__submit { margin-top: 56px; }

  /* Footer: the TV photo is blown up so only its top bezel shows; the screen
     becomes the full width of the viewport, as in the template. */
  .footer__tv {
    position: absolute;
    top: 0;
    left: -8%;
    width: 260%;
    max-width: none;
  }
  .footer__screen {
    position: relative;
    top: 0;
    left: 0;
    width: 100%;
    height: auto;
    padding: 132px 22px 34px;
    z-index: 2;
  }
  .footer__heading { font-size: 17px; padding-top: 0; }

  .marquee { flex: none; height: 350px; margin-top: 26px; }
  .marquee__track { gap: 26px; width: 100%; }
  .quote { grid-template-columns: 33% 1fr; gap: 6%; font-size: 11px; }
  .quote figcaption { text-align: left; }

  .footer__social {
    flex-direction: column;
    gap: 18px;
    font-size: 13px;
    margin-top: 28px;
    padding: 20px 0;
  }
  .footer__bottom { padding: 26px 0 8px; }
  .footer__copy { font-size: 40px; }
}

@media (max-width: 480px) {
  .cta__link { font-size: 24px; }
  .about__name { font-size: 24px; }
  .footer__heading { font-size: 16px; }
  .footer__copy { font-size: 36px; }
}
