/* ==========================================================================
   KAHNZ — hero stylesheet
   Palette: charcoal + orange. Orange is structural/accent only — never a
   background wash. Photography sits untouched on near-black.
   ========================================================================== */

:root {
  --charcoal-0: #0b0b0b;   /* near-black stage background, never pure #000 */
  --charcoal-1: #141414;   /* panel / scrim base */
  --charcoal-2: #1e1e1e;   /* borders, hairlines */
  --white: #ECE9E3;        /* warm off-white, matches warm photography tones */
  --white-dim: rgba(236, 233, 227, 0.62);
  --orange: #E85C21;       /* single accent — structure, lines, active states */
  --orange-dim: rgba(232, 92, 33, 0.55);

  --font-display: "Archivo Black", "Arial Black", "Helvetica Neue", sans-serif;
  --font-mono: "Space Mono", "IBM Plex Mono", ui-monospace, monospace;

  --container-max: 1440px;
  --edge: clamp(20px, 4vw, 56px);

  /* Pinned logo size. Declared here because the hero social row has to sit
     beside the logo and needs to know how wide it is; 3.1111 is the logo
     file's real aspect (1400 x 450). */
  --logo-h: clamp(30px, 4.9vw, 59px);
  --logo-w: calc(var(--logo-h) * 3.1111);
}

/* Sprite host — holds the <symbol> defs and must never take up space. */
.icon-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Every icon is monoline on currentColor, so it inherits the colour of
   whatever it sits in and matches the 1px hairlines used elsewhere. */
.icon {
  width: 1em;
  height: 1em;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

* { box-sizing: border-box; }

html { color-scheme: dark; }

body {
  margin: 0;
  background: var(--charcoal-0);
  color: var(--white);
  font-family: var(--font-mono);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { display: block; max-width: 100%; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--orange);
  color: var(--charcoal-0);
  padding: 12px 20px;
  z-index: 1000;
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
}
.skip-link:focus {
  left: var(--edge);
  top: var(--edge);
}

/* ==========================================================================
   HERO — scroll runway + sticky stage
   ========================================================================== */

.hero-scroll {
  position: relative;
  /* Scroll runway: total distance the sequence scrubs across.
     Was 400vh when the hero carried a single preview rail. Five disciplines
     now share the same 90 frames, so the runway is stretched to give each
     one roughly a screen of dwell instead of a third of one. The frame count
     is unchanged — the drone pass just reads slower. */
  height: 800vh;
  background: var(--charcoal-0);
}

.hero-stage {
  position: sticky;
  top: 0;
  height: 100dvh;
  width: 100%;
  overflow: hidden;
  background: var(--charcoal-0);
}

#hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  /* Photography sits untouched — no filters on the canvas itself.
     Contrast/darkening for text legibility happens via .hero-scrim only. */
}

/* Fixed gradient scrim so overlay type stays legible regardless of frame
   content. Kept subtle — this is contrast management, not a color wash. */
.hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      180deg,
      rgba(11, 11, 11, 0.55) 0%,
      rgba(11, 11, 11, 0.10) 30%,
      rgba(11, 11, 11, 0.10) 60%,
      rgba(11, 11, 11, 0.75) 100%
    );
  pointer-events: none;
}

/* ==========================================================================
   HERO CONTENT
   ========================================================================== */

.hero-content {
  position: relative;
  z-index: 2;
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--edge);
}

.hero-brand {
  /* This IS the pinned resting position — left/top are never touched by JS.
     js/hero.js only translates the logo away from here (centred and scaled
     up) at the top of the runway and interpolates back to an identity
     transform, so the animation cannot end anywhere other than exactly
     here. Aligns with .hero-clients, which is inset by the same --edge. */
  position: absolute;
  left: var(--edge);
  top: var(--edge);
  transform-origin: top left;
  will-change: transform;
}

.hero-logo {
  /* Resting (pinned) size. The hero-sized logo is this multiplied by
     LOGO_START_SCALE in js/hero.js — keep the two in step if either moves. */
  height: var(--logo-h);
  width: auto;
  filter: drop-shadow(0 2px 24px rgba(0, 0, 0, 0.5));
}

/* --- Social row, pinned beside the logo --------------------------------- */

.hero-social {
  position: absolute;
  left: calc(var(--edge) + var(--logo-w) + clamp(14px, 2vw, 28px));
  top: var(--edge);
  height: var(--logo-h);
  z-index: 4;

  display: flex;
  align-items: center;
  gap: clamp(10px, 1.3vw, 18px);

  /* Opacity driven by js/hero.js so the row resolves as the logo lands.
     pointer-events gated on .is-active — same reasoning as the rails. */
  opacity: 0;
  pointer-events: none;
  will-change: opacity, transform;
}

.hero-social.is-active {
  pointer-events: auto;
}

.hero-social-link {
  color: var(--white);
  opacity: 0.75;
  font-size: clamp(16px, 1.5vw, 20px); /* .icon is sized in em */
  transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
  filter: drop-shadow(0 1px 6px rgba(0, 0, 0, 0.6));
}

.hero-social-link:hover,
.hero-social-link:focus-visible {
  color: var(--orange);
  opacity: 1;
  transform: translateY(-2px);
}

.hero-social-link:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 4px;
}

/* --- Tagline ------------------------------------------------------------ */

.hero-tagline {
  position: absolute;
  left: 50%;
  top: calc(42% + clamp(64px, 10vw, 108px));
  transform: translateX(-50%);
  margin: 0;
  width: min(90vw, 760px);
  text-align: center;
  font-family: var(--font-mono);
  color: var(--white);
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vw, 14px);
  will-change: opacity, transform;

  /* The scrim only darkens the top and bottom of the frame; the tagline sits
     in the bright middle, where a pale sky or sand would swallow it. Shadow
     goes on the TYPE, not the photograph — same approach as .hero-logo. */
  text-shadow:
    0 1px 3px rgba(11, 11, 11, 0.65),
    0 2px 16px rgba(11, 11, 11, 0.85);
}

.hero-tagline-lead {
  font-size: clamp(0.95rem, 1.9vw, 1.4rem);
  letter-spacing: 0.01em;
  line-height: 1.25;
}

.hero-tagline-sub {
  font-style: italic;
  font-size: clamp(0.74rem, 1.15vw, 0.95rem);
  letter-spacing: 0.02em;
  line-height: 1.5;
  color: var(--white-dim);
}

/* Client marks — resolve (blur + fade) into view during the back half of
   the scroll runway, staggered per mark. */
.hero-clients {
  position: relative;
  z-index: 2;
  align-self: stretch;
  /* Pushed to the bottom of the stage. .hero-content is a space-between
     column, but .hero-brand and .hero-tagline are both absolutely
     positioned, which left this as the only in-flow child — so it collapsed
     to the TOP and collided with the logo once the logo pinned to the
     top-left corner. margin-top:auto pins it down regardless of how many
     in-flow siblings there are. */
  margin-top: auto;
  border-top: 1px solid var(--charcoal-2);
  padding-top: 18px;
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
  flex-wrap: wrap;
}

.hero-clients-label {
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--white-dim);
  flex-shrink: 0;
}

.hero-clients-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: clamp(20px, 4vw, 48px);
  flex-wrap: wrap;
}

.client-mark {
  opacity: 0;
  filter: blur(6px);
  transform: translateY(6px);
  will-change: opacity, filter, transform;
}

.client-mark img {
  /* Doubled from 22px. */
  height: 44px;
  width: auto;
  /* Placeholder marks are full-color; production marks should be
     single-color (white) transparent PNGs — see asset spec. */
  filter: grayscale(1) brightness(0) invert(1);
  opacity: 0.85;
}

/* ==========================================================================
   DISCIPLINE PREVIEW RAILS (overlaid on the hero)
   Five horizontally scrollable rails riding on top of the drone footage, one
   per discipline, sequenced across the runway by js/hero.js. They share one
   position and only one is ever visible. Sit above .hero-content (z-index 2)
   so they receive the pointer first.
   ========================================================================== */

.hero-preview {
  /* Card geometry. One shared thumbnail HEIGHT keeps the rail band from
     jumping as one discipline hands over to the next; each rail then only
     declares its aspect ratio as a plain number (--card-k = width ÷ height)
     and the width follows. Equal heights are structural here rather than
     three sets of hand-matched clamps that have to be recalculated whenever
     a ratio changes. */
  --thumb-h: clamp(127px, 14vw, 200px);
  --card-k: 1.5;                              /* 3:2 landscape */
  --card-w: calc(var(--thumb-h) * var(--card-k));

  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  /* --clients-clearance is set by js/hero.js from the CLIENT STRIP'S OWN
     measured height, recomputed on resize. The client marks used to fade
     out before this band appeared, so a static clamp() was safe; now they
     hold visible for the whole runway (frame 10 onward) and sit directly
     underneath, so the band has to react to however tall that strip
     actually renders — 5 logos wrapped one way, 7 will wrap another, and no
     fixed guess covers both. */
  bottom: calc(var(--clients-clearance, 90px) + var(--edge) + clamp(14px, 2.2vw, 26px) + 36px);

  /* Bottom-anchoring against the client strip's height (above) guarantees
     clearance from BELOW, but says nothing about the TOP — on a real device
     shorter than whatever it was tuned against, a tall enough panel still
     pushes up into the pinned logo. --panel-max-h is set by js/hero.js from
     the actual measured gap between the logo and the client strip, so this
     is a hard guarantee rather than a hope; overflow-y is the fallback for
     the rare case content still doesn't fit even at that size. */
  max-height: var(--panel-max-h, none);
  overflow-y: auto;

  /* Opacity and transform are driven per-frame by js/hero.js. pointer-events
     is gated on .is-active so a faded-out rail isn't an invisible click
     target sitting across the hero. */
  opacity: 0;
  pointer-events: none;
  will-change: opacity, transform;
}

.hero-preview.is-active {
  pointer-events: auto;
}

/* Each discipline is shot in its own orientation, so each gets its own
   ratio. Architecture, corporate and BTS are all landscape and use the 1.5
   default; only the portrait ones need declaring. */
.hero-preview[data-discipline="food"]    { --card-k: 0.8; }     /* 4:5 */
.hero-preview[data-discipline="wedding"] { --card-k: 0.6667; }  /* 2:3 */

/* Soft band behind the rail. The hero scrim handles the top and bottom of
   the frame, but the rail floats in the middle where a bright sky or pale
   sand would swallow a 1px border. */
.hero-preview::before {
  content: "";
  position: absolute;
  inset: -28px 0 -22px;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(11, 11, 11, 0) 0%,
    rgba(11, 11, 11, 0.58) 16%,
    rgba(11, 11, 11, 0.58) 84%,
    rgba(11, 11, 11, 0) 100%
  );
}

.hero-preview-head {
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 20px);
  padding: 0 var(--edge);
  margin-bottom: 14px;

  /* At the enlarged title size the head can't hold everything on one line on
     a phone. Wrapping is the graceful failure; the row-gap keeps the two
     lines from touching. */
  flex-wrap: wrap;
  row-gap: 6px;
}

/* Which discipline of five you're currently in — same telemetry register as
   the frame counter, so the two read as one instrument. */
.hero-preview-step {
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  color: var(--orange);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.hero-preview-label {
  /* Doubled from 0.66rem — this is the section title, so it now carries the
     head rather than sitting as a caption next to the counters. */
  font-size: 1.32rem;
  letter-spacing: 0.1em; /* eased off: 0.16em is loose at this size */
  text-transform: uppercase;
  color: var(--white);
  flex-shrink: 0;
  line-height: 1.1;
}

.hero-preview-rule {
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, var(--orange), rgba(232, 92, 33, 0));
}

.hero-preview-count {
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  color: var(--orange);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* Each discipline links to its own hosted gallery. Lives in the head rather
   than only on the cards, so a rail whose photos haven't been supplied yet
   still reaches its gallery. */
.hero-preview-gallery {
  flex-shrink: 0;
  color: var(--white);
  text-decoration: none;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--charcoal-2);
  transition: color 0.25s ease, border-color 0.25s ease;
}

.hero-preview-gallery:hover,
.hero-preview-gallery:focus-visible {
  color: var(--orange);
  border-bottom-color: var(--orange);
}

.hero-preview-gallery:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}

.hero-preview-rail {
  display: flex;
  gap: clamp(10px, 1.2vw, 16px);
  padding: 0 var(--edge);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  /* Snapping aligns to the SNAPPORT, which is inset by scroll-padding — not
     by padding. Without this the rail snaps the first card flush to the
     window edge, breaking its alignment with the label above it. */
  scroll-padding-inline: var(--edge);
  overscroll-behavior-x: contain;
  cursor: grab;

  /* No touch-action override on purpose: the browser's native gesture
     disambiguation for nested scrollers already routes a horizontal swipe to
     the rail and a vertical swipe to the page (which keeps scrubbing frames).
     Pinning touch-action would break one of the two. */

  scrollbar-width: none;
  -ms-overflow-style: none;
}

.hero-preview-rail::-webkit-scrollbar {
  display: none;
}

.hero-preview-rail.is-grabbing {
  cursor: grabbing;
}

/* A rail whose cards already fit centres them instead of hugging the left
   edge, so the leftover space reads as composition rather than as a rail
   that ran out. Set by js/hero-preview.js and applied ONLY when there's no
   overflow — centring an overflowing flex scroller makes its first item
   unreachable, because the overflow spills off both ends. */
.hero-preview-rail.is-fitted {
  justify-content: center;
}

.hero-preview-card {
  flex: 0 0 auto;
  width: var(--card-w);
  scroll-snap-align: start;
  text-decoration: none;
  color: var(--white);
  border: 1px solid var(--charcoal-2);
  background: rgba(11, 11, 11, 0.55);
  transition:
    border-color 0.25s ease,
    transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

.hero-preview-card:hover,
.hero-preview-card:focus-visible {
  border-color: var(--orange);
  transform: translateY(-4px);
}

.hero-preview-card:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
}

.hero-preview-thumb {
  display: block;
  position: relative;
  aspect-ratio: var(--card-k);
  overflow: hidden;
  background: var(--charcoal-1);
}

.hero-preview-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Untouched, same as everywhere else the photography appears. */
  -webkit-user-drag: none;
  user-select: none;
}

/* Empty slot — shown only when the discipline's photos haven't been supplied
   yet. Names the file it's waiting for rather than rendering a broken image,
   so an unfinished rail still reads as deliberate. */
.hero-preview-slot {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 12px;
  text-align: center;
  background: var(--charcoal-1);
  border: 1px dashed var(--charcoal-2);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  color: var(--white-dim);
  word-break: break-all;
}

.hero-preview-thumb.is-missing .hero-preview-slot { display: flex; }
.hero-preview-thumb.is-missing img { display: none; }

/* A card with no photo behind it shouldn't advertise itself as a link. */
.hero-preview-card.is-empty {
  pointer-events: none;
}

.hero-preview-card.is-empty .hero-preview-name {
  color: var(--white-dim);
}

.hero-preview-meta {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 10px 12px;
}

.hero-preview-num {
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  color: var(--orange);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.hero-preview-name {
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--white);

  /* Always reserve two lines, never allow a third. Narrow (portrait) cards
     wrap their captions where wide ones don't, which otherwise made the
     whole rail band jump vertically as one discipline handed to the next. */
  line-height: 1.35;
  min-height: 2.7em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.hero-preview-hint {
  display: block;
  padding: 12px var(--edge) 0;
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--white-dim);
  transition: opacity 0.4s ease;
}

.hero-preview-hint.is-gone {
  opacity: 0;
}

@media (max-width: 640px) {
  /* The client marks wrap on narrow screens, so the rail has to clear a
     taller footer block. Cards shrink to keep two of them in view — one
     card filling the width reads as a banner, not as a rail. */
  /* bottom is no longer overridden here — --clients-clearance (set in
     js/hero.js) already accounts for however tall the strip wraps on a
     narrow screen, so a second fixed guess on top of it would either fight
     the measurement or double up the clearance. */
  .hero-preview { --thumb-h: clamp(99px, 37vw, 140px); }
  .hero-preview-hint { display: none; }
  /* Halved from 44px. At 44px on a real phone (as opposed to the simulated
     375-wide viewport this was tuned against) the client strip ran tall
     enough, combined with the "More of Kahnz" panel above it, to push that
     panel up into the pinned logo at the top of the screen. Shrinking the
     logos shrinks --clients-clearance too, since js/hero.js measures the
     strip's real rendered height rather than assuming a fixed number. */
  .client-mark img { height: 22px; }
  /* Doubled from 0.6rem, in step with the desktop title. At this size it no
     longer shares a line with the counters, so it takes the full width and
     goes first — otherwise each discipline's head wrapped to a different
     height depending on how long its name is, and the title block jumped by
     up to 47px between sections. */
  .hero-preview-label {
    font-size: 1.2rem;
    letter-spacing: 0.06em;
    flex-basis: 100%;
    order: -1;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* The reduced-motion hero is a single static frame with no runway to
     reveal against, and the rail duplicates the N.03 grid sitting directly
     below it — so nothing is lost by dropping it here. */
  .hero-preview { display: none; }
}

/* ==========================================================================
   SCROLL CUE + FRAME INDEX (telemetry-style micro UI)
   ========================================================================== */

.hero-scrollcue {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: var(--edge);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  color: var(--white-dim);
  will-change: opacity;
}

.hero-scrollcue-line {
  width: 1px;
  height: 28px;
  background: linear-gradient(180deg, var(--orange), transparent);
  animation: scrollcue-pulse 1.8s ease-in-out infinite;
}

@keyframes scrollcue-pulse {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}

.hero-frame-index {
  position: absolute;
  z-index: 2;
  right: var(--edge);
  /* Top-right, opposite the pinned logo. It used to sit bottom-right, which
     is now where the client marks land. */
  top: var(--edge);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  color: var(--white-dim);
  font-variant-numeric: tabular-nums;
}

#hero-frame-counter {
  color: var(--orange);
}

/* --- SFX mute toggle -----------------------------------------------------
   Bottom-left, mirroring the frame index's top-right corner. Unlike the
   frame index and scroll cue it is NOT driven by js/hero.js's per-frame
   opacity math — it has to stay put and clickable at every scroll position,
   since muting only matters once the whooshes have already started. */

.hero-sfx-toggle {
  position: absolute;
  z-index: 5;
  left: var(--edge);
  bottom: var(--edge);

  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  background: rgba(11, 11, 11, 0.4);
  border: 1px solid var(--charcoal-2);
  color: var(--white-dim);
  font-size: 15px; /* .icon is sized in em */
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}

.hero-sfx-toggle:hover,
.hero-sfx-toggle:focus-visible {
  color: var(--orange);
  border-color: var(--orange);
}

.hero-sfx-toggle:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}

.hero-sfx-toggle[aria-pressed="false"] {
  color: var(--white-dim);
  opacity: 0.55;
}

@media (max-width: 640px) {
  .hero-sfx-toggle {
    width: 30px;
    height: 30px;
    font-size: 13px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-sfx-toggle {
    transition: none;
  }
}

/* ==========================================================================
   REDUCED MOTION — static hero, no scrub
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .hero-scroll { height: 100dvh; }
  .hero-scrollcue { display: none; }
  .client-mark {
    opacity: 1;
    filter: none;
    transform: none;
  }
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

@media (max-width: 640px) {
  .hero-tagline {
    white-space: normal;
    max-width: 86vw;
  }
  .hero-clients {
    justify-content: flex-start;
  }
  .hero-frame-index { display: none; }
}

/* ==========================================================================
   ENQUIRY
   The closing section and the page's only conversion point. No photography
   here on purpose — the hero rail already showed the work and links out to
   the gallery, so this section's whole job is to be easy to fill in.
   Orange stays structural: the index mark, the focus ring, the submit fill.
   ========================================================================== */

.enquiry {
  position: relative;
  background: var(--charcoal-0);
  border-top: 1px solid var(--charcoal-2);
  /* Halved from clamp(72px, 12vw, 160px) — the form is the whole section
     now that the pitch column and the "elsewhere" links have both moved
     out, so the old spacing read as dead air around a single element. */
  padding: clamp(36px, 6vw, 80px) var(--edge);
}

/* Was a two-column grid with the pitch on the left. That column is gone, so
   the form stands alone and is capped rather than stretched across the full
   container — a 1440px-wide text input is unusable. */
.enquiry-inner {
  max-width: 720px;
  margin: 0 auto;
}

/* ==========================================================================
   MORE OF KAHNZ
   Lives inside the hero, overlaid on the drone footage as the sixth and last
   beat, after the Behind the Scenes rail. Shares the rails' band position so
   it reads as part of the same sequence. Only the enquiry form below sits on
   flat black.
   ========================================================================== */

.hero-contact {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  /* Same measured clearance as .hero-preview — see the comment there. */
  bottom: calc(var(--clients-clearance, 90px) + var(--edge) + clamp(14px, 2.2vw, 26px) + 36px);
  padding: 0 var(--edge);

  /* Same top-guarantee as .hero-preview — see the comment there. This panel
     in particular has 7 rows of text, the tallest thing sitting in this
     band, so it's the one most likely to actually need the overflow
     fallback on a short viewport. */
  max-height: var(--panel-max-h, none);
  overflow-y: auto;

  opacity: 0;
  pointer-events: none;
  will-change: opacity, transform;
}

.hero-contact.is-active {
  pointer-events: auto;
}

/* Same soft band the rails use — the block floats in the middle of the frame
   where a bright sky would swallow hairlines and small type. */
.hero-contact::before {
  content: "";
  position: absolute;
  inset: -28px 0 -22px;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(11, 11, 11, 0) 0%,
    rgba(11, 11, 11, 0.68) 14%,
    rgba(11, 11, 11, 0.68) 86%,
    rgba(11, 11, 11, 0) 100%
  );
}

/* Denser than the on-black version: this one has to fit inside the hero
   stage alongside the logo above it and the client marks below. */
.hero-contact .contact-title {
  margin-bottom: clamp(14px, 2vw, 20px);
}

.hero-contact .contact-list {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0 clamp(16px, 3vw, 32px);
}

.hero-contact .contact-link {
  padding: 6px 0;
}

.hero-contact .contact-icon {
  width: 32px;
  height: 32px;
  font-size: 16px;
  background: rgba(20, 20, 20, 0.72);
}

/* --- Contact rows (shared) ---------------------------------------------- */

.contact {
  margin-bottom: clamp(48px, 7vw, 72px);
  padding-bottom: clamp(40px, 6vw, 56px);
  border-bottom: 1px solid var(--charcoal-2);
}

.contact-title {
  margin: 0 0 clamp(20px, 3vw, 28px);
  font-family: var(--font-mono);
  font-weight: 700;
  /* Doubled from 0.7rem to match the rail section titles. */
  font-size: 1.4rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--orange);
}

.contact-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: clamp(4px, 1vw, 10px) clamp(16px, 3vw, 32px);
}

.contact-link {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
  text-decoration: none;
  color: var(--white);
}

.contact-icon {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  font-size: 18px; /* .icon is sized in em */
  background: var(--charcoal-1);
  border: 1px solid var(--charcoal-2);
  color: var(--white-dim);
  transition: color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}

.contact-link:hover .contact-icon,
.contact-link:focus-visible .contact-icon {
  color: var(--charcoal-0);
  background: var(--orange);
  border-color: var(--orange);
}

.contact-text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.contact-line {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.02em;
  color: var(--white);
  /* Handles are long and must not knock the grid out of alignment. */
  overflow-wrap: anywhere;
}

.contact-line b {
  font-weight: 700;
  color: var(--orange);
}

.contact-sub {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: var(--white-dim);
}

.contact-link:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .contact-icon,
  .hero-social-link {
    transition: none;
  }
  .hero-social-link:hover {
    transform: none;
  }
}

/* --- Right: the form ---------------------------------------------------- */

.enquiry-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 24px);
}

.enquiry-honeypot {
  position: absolute;
  left: -9999px;
  margin: 0;
}

.enquiry-field {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.enquiry-field--wide,
.enquiry-submit {
  grid-column: 1 / -1;
}

.enquiry-label {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--white-dim);
}

.enquiry-optional {
  color: var(--charcoal-2);
  letter-spacing: 0.12em;
}

.enquiry-input {
  width: 100%;
  padding: 14px 16px;
  background: var(--charcoal-1);
  border: 1px solid var(--charcoal-2);
  border-radius: 0; /* hard geometry — no rounded corners anywhere on the page */
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.enquiry-input::placeholder {
  color: rgba(236, 233, 227, 0.3);
}

.enquiry-input:hover {
  border-color: rgba(236, 233, 227, 0.2);
}

.enquiry-input:focus {
  outline: none;
  border-color: var(--orange);
  background: var(--charcoal-0);
}

/* Only flag a field once the browser has something invalid to report, so
   empty untouched fields aren't painted red on arrival. */
.enquiry-input:user-invalid {
  border-color: #C2410C;
}

.enquiry-textarea {
  resize: vertical;
  min-height: 120px;
  line-height: 1.6;
}

.enquiry-select {
  appearance: none;
  cursor: pointer;
  /* Chevron drawn inline so the control stays self-contained — no asset,
     no external request. */
  background-image: linear-gradient(45deg, transparent 50%, var(--white-dim) 50%),
                    linear-gradient(135deg, var(--white-dim) 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 44px;
}

.enquiry-select option {
  background: var(--charcoal-1);
  color: var(--white);
}

.enquiry-submit {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: clamp(8px, 1.5vw, 16px);
  padding: clamp(18px, 2.2vw, 22px) clamp(24px, 3vw, 32px);
  background: transparent;
  border: 1px solid var(--orange);
  border-radius: 0;
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease;
}

.enquiry-submit:hover,
.enquiry-submit:focus-visible {
  background-color: var(--orange);
  color: var(--charcoal-0);
}

.enquiry-submit:focus-visible {
  outline: 2px solid var(--white);
  outline-offset: 3px;
}

.enquiry-submit-arrow {
  transition: transform 0.25s ease;
}

.enquiry-submit:hover .enquiry-submit-arrow {
  transform: translateX(6px);
}

@media (prefers-reduced-motion: reduce) {
  .enquiry-submit-arrow {
    transition: none;
  }
}

@media (max-width: 560px) {
  .enquiry-form {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==========================================================================
   OUTRO
   Closing lockup — the same logo and tagline the page opened with, so it
   ends where it started. No links, no CTA: the form directly above is the
   action, and anything else here would compete with it.
   ========================================================================== */

.outro {
  border-top: 1px solid var(--charcoal-2);
  background: var(--charcoal-0);
  /* Both halved from clamp(64px,10vw,128px) / clamp(24px,4vw,40px) — same
     over-spaced problem as .enquiry above. */
  padding: clamp(32px, 5vw, 64px) var(--edge);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 2vw, 20px);
  text-align: center;
}

.outro-logo {
  height: clamp(44px, 6.5vw, 84px);
  width: auto;
  opacity: 0.92;
}

.outro-tagline {
  margin: 0;
  max-width: 60ch;
  font-family: var(--font-mono);
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.2vw, 14px);
}

.outro-tagline-lead {
  font-size: clamp(0.9rem, 1.6vw, 1.2rem);
  letter-spacing: 0.01em;
  line-height: 1.3;
  color: var(--white);
}

.outro-tagline-sub {
  font-style: italic;
  font-size: clamp(0.72rem, 1.1vw, 0.9rem);
  letter-spacing: 0.02em;
  line-height: 1.6;
  color: var(--white-dim);
}

/* --- Outro social row + credit ------------------------------------------ */

.outro-social {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(18px, 3vw, 34px);
}

.outro-social a {
  display: block;
  color: var(--white);
  opacity: 0.72;
  font-size: clamp(18px, 1.7vw, 22px); /* .icon is sized in em */
  transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
}

.outro-social a:hover,
.outro-social a:focus-visible {
  color: var(--orange);
  opacity: 1;
  transform: translateY(-2px);
}

.outro-social a:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 4px;
}

.outro-credit {
  margin: 0;
  padding-top: clamp(8px, 1.5vw, 16px);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--white-dim);
  line-height: 1.8;
}

.outro-credit-name {
  color: var(--white);
}

@media (prefers-reduced-motion: reduce) {
  .outro-social a {
    transition: none;
  }
  .outro-social a:hover {
    transform: none;
  }
}
