/* The Apex AI - Through Time. Black/gold/silver only. No em dashes in copy. */

:root {
  color-scheme: dark;
  --black: #030507;
  --gold: #c8a84b;
  --gold-light: #e8c96a;
  --gold-dark: #a88430;
  --silver: #c4cdd8;
  --silver-light: #dde5ee;
  --off-white: #eef3f8;
  --hairline: rgba(200, 168, 75, 0.28);
  --font: "Trebuchet MS", "Segoe UI", system-ui, -apple-system, sans-serif;
  --ease: cubic-bezier(0.33, 0, 0.2, 1);
  --fast: 220ms;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* cutting-edge details: every touchpoint on-palette */
::selection { background: rgba(200, 168, 75, 0.4); color: var(--off-white); }
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: #060608; }
::-webkit-scrollbar-thumb {
  background: linear-gradient(var(--gold-dark), #6d5620);
  border-radius: 5px;
  border: 2px solid #060608;
}
::-webkit-scrollbar-thumb:hover { background: var(--gold); }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font);
  background: var(--black);
  color: var(--silver-light);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  line-height: 1.5;
}

/* ---- fixed background stack: poster (instant) then canvas (fades over) ---- */
#poster {
  position: fixed;
  inset: 0;
  z-index: 0;
  /* COLOUR ONLY on the element itself. main.js interpolates this per scroll tick
     between the two nearest era poster colours, and writes it as
     style.backgroundColor - NEVER the `background` shorthand, which would blow
     away the hero still layered on ::after below. The colour is not decoration:
     two clips crossfading leave #poster ~25% visible at the midpoint (top layer
     alpha 1-t over bottom layer alpha t), and this is what fills that window. */
  background-color: #060608;
  /* no transition: scroll-driven colour writes already interpolate per-tick, and
     a transition on a fixed full-viewport layer kept the compositor busy */
}
/* THE REAL HERO FRAME, painted straight from CSS with no JS at all.
   It used to be attached only as a <video poster> inside VideoBackdrop.mount(),
   which cannot run until main.js finishes awaiting three.js from unpkg: on a cold
   phone visit that was 1-4s of flat #060608 while /public/posters/cosmos.jpg sat
   preloaded in <head> and unused by anything.
   It rides its OWN layer rather than the `background` shorthand on #poster so the
   per-tick colour writes and the still cannot wipe each other.
   It then RETIRES the moment something better owns the frame: any mounted clip
   (body.clip-scene / body.clip-hero - and the hero <video> carries this exact
   frame as its poster attribute, so the handover is invisible), or static mode
   (main.js paints its own per-era poster essay). Retiring is not optional: an
   opaque nebula left here would ghost through the middle of every later era
   crossfade, which is precisely the gap the era colour above exists to fill. */
#poster::after {
  content: '';
  position: absolute;
  inset: 0;
  background: #060608 url('/public/posters/cosmos.jpg') center / cover no-repeat;
  opacity: 1; /* stated, not inherited from the initial value: it is one end of the transition */
  transition: opacity 600ms ease;
}
body.clip-scene #poster::after,
body.clip-hero #poster::after,
body.static-mode #poster::after { opacity: 0; }

/* ---- photoreal clip layer: sits above the poster, below the canvas -------- */
#video-layer {
  position: fixed;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}
#video-layer video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  will-change: opacity;
  /* THE UNIFIED FILM GRADE. Every generated clip is forced through this so seven
     separately-generated videos read as one film: deepen the blacks, lift contrast,
     push warm. Tune here, once, and every era follows. */
  filter: contrast(1.14) saturate(1.05) brightness(0.95) sepia(0.07) hue-rotate(-6deg);
}
.video-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 42%, rgba(0, 0, 0, 0) 42%, rgba(3, 5, 7, 0.6) 100%);
}
/* TWO stacked scrims, each driven purely by opacity from its own body class, so
   overlapping eras (rail clip + hero/finale through a crossfade) crossfade their
   gradients instead of hard-swapping one shared element's background. */
.video-scrim-rail,
.video-scrim-hero {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 500ms ease;
}
/* Directional rail scrim: copy legible on one side, footage + gold anchor clear
   on the other. */
.video-scrim-rail {
  background: linear-gradient(
    100deg,
    rgba(3, 5, 7, 0.93) 0%,
    rgba(3, 5, 7, 0.8) 26%,
    rgba(3, 5, 7, 0.3) 52%,
    rgba(3, 5, 7, 0) 70%
  );
}
body.clip-scene .video-scrim-rail { opacity: 1; }
/* flipped rail (the lion): copy right, scrim darkens the right instead */
body.rail-right .video-scrim-rail {
  background: linear-gradient(
    260deg,
    rgba(3, 5, 7, 0.93) 0%,
    rgba(3, 5, 7, 0.8) 26%,
    rgba(3, 5, 7, 0.3) 52%,
    rgba(3, 5, 7, 0) 70%
  );
}
body.rail-right .scene:not(.scene-hero):not(.scene-finale) .scene-copy { margin-left: auto; }
/* Centred elliptical scrim: the hero wordmark reads against a busy nebula
   without flattening the footage. */
.video-scrim-hero {
  background: radial-gradient(
    ellipse 60% 24% at 50% 44%,
    rgba(3, 5, 7, 0.66) 0%,
    rgba(3, 5, 7, 0.4) 55%,
    rgba(3, 5, 7, 0) 100%
  );
}
body.clip-hero .video-scrim-hero { opacity: 1; }
/* The FINALE's deep variant: taller and darker, because a centred near-white
   form headline sits over a bright wall-to-wall gold lattice. The outer stop is
   a FLOOR, not zero: the assessment funnel made the finale copy taller than the
   viewport, so text now scrolls through the ellipse's edge zones - unbacked
   text over the bright lattice was unreadable there. */
body.clip-deep .video-scrim-hero {
  background: radial-gradient(
    ellipse 74% 50% at 50% 50%,
    rgba(3, 5, 7, 0.82) 0%,
    rgba(3, 5, 7, 0.6) 55%,
    rgba(3, 5, 7, 0.4) 100%
  );
}

/* The canvas carries ONLY the additive gold spark now (the particle wordmark is
   gone), so screen-blend it over footage EVERYWHERE a clip is up - otherwise the
   spark glow composites source-over and reads as a flat translucent blob. */
body.clip-scene #gl,
body.clip-hero #gl { mix-blend-mode: screen; }
body.static-mode #video-layer { display: none; }

/* ---- static mode (reduced-motion / no-WebGL): real imagery, not flat colour ----
   main.js injects a sticky viewport-height poster underlay into each era section
   (a dark legibility gradient over the clip's poster frame). Sticky, because
   background-size: cover on the SECTION zooms the frame 2-3x once a section
   outgrows the viewport (the finale's assessment form), and iOS ignores
   background-attachment: fixed - the sticky child gives every section a correct
   viewport-sized crop on all platforms. */
body.static-mode .scene.static-poster { position: relative; }
body.static-mode .static-poster-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: -1;
}
body.static-mode .spb-img {
  position: sticky;
  top: 0;
  height: 100vh;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* outside static mode the underlay must never paint (belt and braces) */
.static-poster-bg { display: none; }
body.static-mode .static-poster-bg { display: block; }
/* static mode can never hide the lockup: target the elements js-anim hides */
body.static-mode .hero-logo .hl,
body.static-mode .hero-tag,
body.static-mode .hero-sub,
body.static-mode .hero-cta { opacity: 1 !important; visibility: visible !important; }

/* ---- copy behaves differently over a photoreal clip ---------------------- */
/* Move it into a side rail and lighten the cards so the film reads through.
   The hero AND the finale are excluded: both are centred compositions (the
   wordmark lockup; the assessment form) and must never be railed. */
body.clip-scene .scene:not(.scene-hero):not(.scene-finale) .scene-copy { max-width: min(46vw, 640px); }
body.clip-scene .services-grid,
body.clip-scene .problem-grid { grid-template-columns: repeat(2, 1fr); }
body.clip-scene .process-list { grid-template-columns: 1fr; }
body.clip-scene .service-card,
body.clip-scene .problem-item {
  background: rgba(6, 9, 14, 0.5);
  border-color: rgba(200, 168, 75, 0.22);
}
/* the signature gold accent survives the clip-scene border override */
body.clip-scene .problem-item { border-left-color: var(--gold); }

@media (max-width: 768px) {
  /* Mobile keeps the FULL unified grade (dropping it permanently left clips
     unmatched and the Earth ungraded). Only while two videos actually composite -
     a scene crossfade or the moon's internal segment blend - drop to the cheap
     two-stage filter for that window. */
  body.scene-xfade #video-layer video,
  body.seg-xfade #video-layer video { filter: contrast(1.12) brightness(0.96); }
  /* (the "lockup must never crop" clamp USED to live here and was dead code: this
     block sits ABOVE the base .hero-logo rule, and at equal specificity the later
     source wins, so the lockup kept the base 2.9rem/0.12em and overflowed. Same
     trap as the iOS 16px form floor below. It now lives in the LAST mobile block.) */
  /* (the iOS 16px form floor lives in the LAST mobile block: here it was dead
     code - the later equal-specificity base .contact rules overrode it) */
  /* no room for a rail on a phone: copy goes full width over a bottom-up scrim */
  body.clip-scene .scene:not(.scene-hero):not(.scene-finale) .scene-copy { max-width: 100%; }
  body.clip-scene .services-grid,
  body.clip-scene .problem-grid { grid-template-columns: 1fr; }
  .video-scrim-rail,
  body.rail-right .video-scrim-rail {
    background: linear-gradient(
      180deg,
      rgba(3, 5, 7, 0.3) 0%,
      rgba(3, 5, 7, 0.55) 38%,
      rgba(3, 5, 7, 0.9) 100%
    );
  }
}

#gl {
  position: fixed;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 900ms ease;
  pointer-events: none;
}
#gl.is-ready { opacity: 1; }
body.static-mode #gl { display: none; }

/* ---- content flows above the background ---------------------------------- */
main { position: relative; z-index: 3; }

.scene {
  min-height: 100vh;
  display: flex;
  align-items: center;
  padding: 12vh 8vw;
  position: relative;
}

.scene-copy {
  max-width: 640px;
  will-change: opacity, transform;
}

.eyebrow {
  font-size: 0.72rem;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 1.1rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.eyebrow::before {
  content: "//";
  color: var(--gold);
  opacity: 0.8;
}
/* the hero is a centred composition: its eyebrow centres with it */
.scene-hero .eyebrow { justify-content: center; }

.scene h2 {
  font-size: clamp(1.8rem, 4.4vw, 3.1rem);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--off-white);
  font-weight: 700;
  line-height: 1.1;
  margin-bottom: 1.1rem;
}

.scene p { color: var(--silver); max-width: 52ch; margin-bottom: 1rem; }
.scene h2,
.block-head { text-wrap: balance; }

.placeholder {
  border-left: 2px solid var(--hairline);
  padding-left: 1rem;
  color: var(--silver);
  font-style: italic;
  opacity: 0.85;
}

.rule {
  width: 64px;
  height: 2px;
  background: linear-gradient(90deg, var(--gold), transparent);
  margin: 0 0 1.4rem;
}

/* ---- header / logo lockup ------------------------------------------------ */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem 6vw;
  background: linear-gradient(180deg, rgba(3, 5, 7, 0.72), transparent);
}

.logo {
  font-size: 1.05rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.logo .the, .logo .ai { color: var(--off-white); }
.logo .apex {
  color: var(--gold);
  text-shadow: 0 0 18px rgba(200, 168, 75, 0.35);
}

/* ---- phone (added 29 Jul 2026 when Michael supplied the number) -------------
   Three placements, each for a different moment: the header for the visitor who
   decided on the way in, the hero line for the phone visitor who wants a human
   NOW (the named market is trades and cleaners, who transact by voice), and the
   form's alt-contact for the one who stalled at question nine. The header copy
   is hidden below 768px, where the bar is already tight enough that the CTA
   label is cut to "Assessment" to survive 320px: the hero line covers mobile,
   above the fold, which is the better placement there anyway. */
/* .site-header is justify-content: space-between, which distributes its CHILDREN.
   With two children that is logo-left / CTA-right, which is the intent. Adding the
   phone as a third child stranded it in the dead centre of the bar, reading as a
   number floating in the middle of the screen (Michael, 29 Jul, and he was right).
   Grouping the two right-hand controls restores a two-child header, so the number
   sits where it belongs: beside the CTA it supports, not adrift from both. */
.header-actions {
  display: flex;
  align-items: center;
  gap: 1.2rem;
}
.header-tel {
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  color: var(--silver-light);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--fast) var(--ease);
}
.header-tel:hover { color: var(--gold-light); }
.hero-call {
  margin-top: 0.8rem;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: var(--silver);
}
.hero-call a {
  color: var(--gold-light);
  text-decoration: none;
  border-bottom: 1px solid rgba(200, 168, 75, 0.45);
  padding-bottom: 1px;
  /* a phone number is a tap target on the device that matters most */
  display: inline-block;
  min-height: 24px;
}
.hero-call a:hover { color: var(--gold); border-bottom-color: var(--gold); }

/* ---- indicative pricing (services scene) ---------------------------------
   Stated as a range with the basis given, and "plus GST" is explicit because
   the audience is other businesses. */
.price-anchor {
  margin-top: 0.9rem;
  padding: 0.85rem 1.1rem;
  background: rgba(6, 9, 14, 0.6);
  border: 1px solid var(--hairline);
  border-left: 2px solid var(--gold);
  border-radius: 10px;
  font-size: 0.88rem;
  color: var(--silver);
  max-width: 62ch;
}
.price-anchor strong { color: var(--gold-light); font-weight: 700; }

.header-cta {
  font-size: 0.72rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--black);
  background: linear-gradient(135deg, var(--gold-light), var(--gold-dark));
  box-shadow: 0 4px 18px rgba(200, 168, 75, 0.25);
  padding: 0.55rem 1.1rem;
  border-radius: 999px;
  text-decoration: none;
  font-weight: 700;
}

/* ---- hero specifics (type treatment lives in the title-sequence block) ---- */
#scene-cosmos .scene-copy { max-width: 860px; }
.hero-tag {
  font-size: 0.9rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--silver);
}

.scroll-cue {
  position: fixed;
  bottom: 1.6rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  font-size: 0.62rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--silver);
  opacity: 0.7;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
}
.scroll-cue span { width: 1px; height: 34px; background: linear-gradient(var(--gold), transparent); }
.scroll-cue { transition: opacity 600ms ease; }
/* one-way: the cue dies the moment the journey starts and never returns */
body.cue-gone .scroll-cue { opacity: 0; }

/* ---- timeline scrubber (right edge) -------------------------------------- */
.timeline-scrubber {
  position: fixed;
  top: 50%;
  right: max(1.4rem, 2.4vw);
  transform: translateY(-50%);
  height: 60vh;
  z-index: 6;
  display: flex;
  align-items: stretch;
}
.ts-line {
  position: relative;
  width: 1px;
  background: rgba(196, 205, 216, 0.22);
  margin: 0 auto;
}
.ts-fill {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 0%;
  background: linear-gradient(var(--gold-light), var(--gold-dark));
}
.ts-marker {
  position: absolute;
  right: -3px;
  top: 0%;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--gold-light);
  box-shadow: 0 0 12px 2px rgba(232, 201, 106, 0.7);
  transform: translateY(-50%);
}
.ts-tick {
  position: absolute;
  right: -2px;
  transform: translateY(-50%);
  background: none;
  border: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0;
  color: var(--silver);
}
.ts-dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: rgba(196, 205, 216, 0.55);
  transition: background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.ts-label {
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  color: rgba(196, 205, 216, 0.72);
  text-shadow: 0 1px 6px rgba(3, 5, 7, 0.8);
  transition: color var(--fast) var(--ease);
  order: -1;
  text-align: right;
  min-width: 3.4rem;
}
.ts-tick.is-active .ts-dot { background: var(--gold-light); box-shadow: 0 0 8px rgba(232, 201, 106, 0.8); }
.ts-tick.is-active .ts-label { color: var(--gold-light); }
.ts-tick:hover .ts-dot { background: var(--silver-light); }
.ts-tick:hover .ts-label { color: var(--silver-light); }

/* ---- floating assessment pill --------------------------------------------- */
.consult-pill {
  position: fixed;
  bottom: 1.6rem;
  right: max(1.4rem, 2.4vw);
  z-index: 7;
  background: linear-gradient(135deg, var(--gold-light), var(--gold-dark));
  color: var(--black);
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 700;
  text-decoration: none;
  padding: 0.7rem 1.2rem;
  border-radius: 999px;
  box-shadow: 0 8px 30px rgba(200, 168, 75, 0.3);
  opacity: 0;
  transform: translateY(16px);
  pointer-events: none;
  transition: opacity 400ms ease, transform 400ms ease;
}
.consult-pill.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
/* conversion controls answer the hand: one easing language across all of them */
.header-cta,
.hero-cta,
.contact button { transition: transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease), filter var(--fast) var(--ease); }
.header-cta:hover,
.hero-cta:hover,
.contact button:hover { transform: translateY(-1px); filter: brightness(1.08); box-shadow: 0 6px 22px rgba(200, 168, 75, 0.4); }
.header-cta:active,
.hero-cta:active,
.contact button:active { transform: translateY(0); filter: brightness(0.96); }
.consult-pill.is-visible:hover { transform: translateY(-2px); box-shadow: 0 10px 36px rgba(200, 168, 75, 0.45); }
.consult-pill .cp-mark { opacity: 0.75; margin-right: 0.3rem; }

/* ---- contact / finale ---------------------------------------------------- */
.contact {
  max-width: 560px;
  background: rgba(6, 9, 14, 0.72);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  padding: 2rem;
  backdrop-filter: blur(6px);
}
.contact label {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--silver);
  margin: 0.9rem 0 0.35rem;
}
.contact input, .contact textarea {
  width: 100%;
  background: rgba(3, 5, 7, 0.8);
  border: 1px solid rgba(196, 205, 216, 0.24);
  border-radius: 8px;
  color: var(--off-white);
  font-family: var(--font);
  padding: 0.7rem 0.8rem;
  font-size: 0.95rem;
}
.contact input:focus,
.contact textarea:focus,
.contact select:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(200, 168, 75, 0.25);
}
.contact button {
  margin-top: 1.4rem;
  width: 100%;
  background: linear-gradient(135deg, var(--gold-light), var(--gold-dark));
  color: var(--black);
  border: 0;
  border-radius: 999px;
  padding: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-size: 0.8rem;
  cursor: pointer;
}

.site-footer {
  position: relative;
  z-index: 3;
  text-align: center;
  padding: 3rem 8vw 4rem;
  border-top: 1px solid var(--hairline);
  background: rgba(3, 5, 7, 0.9);
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  color: var(--silver);
}
.site-footer a { color: var(--gold); text-decoration: none; }
/* (.footer-social sizing lives AFTER the .footer-nav rules further down - rules
   placed here lost the cascade to the later equal-specificity nav styles) */
.site-footer a, .form-alt a { transition: color 250ms ease; }
.site-footer a:hover, .form-alt a:hover { color: var(--gold-light); }
.footer-nav a { padding-bottom: 2px; border-bottom: 1px solid transparent; transition: color 250ms ease, border-color 250ms ease; }
.footer-nav a:hover { border-bottom-color: var(--gold); }
.disclaimers summary { transition: color 250ms ease; }
.disclaimers summary:hover { color: var(--gold-light); }

/* ---- accessibility helper ------------------------------------------------ */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- shared content type ------------------------------------------------- */
.scene-copy.wide { max-width: 1040px; }
.lead { font-size: 1.125rem; line-height: 1.6; color: var(--silver-light); max-width: 58ch; }
.lead strong, .scene p strong { color: var(--gold-light); font-weight: 700; }
.gold { color: var(--gold); }

.block-head {
  margin-top: 2.4rem;
  font-size: 1.2rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--off-white);
}
.block-sub { color: var(--silver); margin: 0.4rem 0 1.2rem; }
/* a block-head that labels a grid binds to it: the grid's own 1.8rem top margin
   plus the heading's 2.4rem above it would otherwise float the label between the
   two blocks instead of attaching it to the one it names */
.block-head + .services-grid,
.block-head + .problem-grid { margin-top: 1rem; }

/* ---- hero: cinematic typographic title sequence --------------------------- */
.scene-hero { justify-content: center; text-align: center; }
.hero-copy { margin: 0 auto; }

.hero-logo {
  font-size: clamp(2.9rem, 9.5vw, 7.2rem);
  letter-spacing: 0.12em;
  line-height: 1.04;
  font-weight: 700;
  margin-bottom: 1.5rem;
  white-space: nowrap;
}
.hero-logo .hl { display: inline-block; will-change: transform, opacity, filter; }
.hero-logo .the .hl,
.hero-logo .ai .hl {
  color: var(--off-white);
  text-shadow: 0 2px 26px rgba(3, 5, 7, 0.6);
}
/* APEX: molten gradient metal, clipped to the letterforms */
.hero-logo .apex .hl {
  background: linear-gradient(
    105deg,
    var(--gold-dark) 0%,
    var(--gold) 34%,
    #f7e6b0 50%,
    var(--gold) 66%,
    var(--gold-dark) 100%
  );
  background-size: 240% 100%;
  background-position: 0% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 0 22px rgba(200, 168, 75, 0.3));
}
/* ignition: the shimmer sweeps the gold and the glow breathes (~60bpm family) */
body.apex-ignited .hero-logo .apex .hl {
  animation: apexShimmer 5.2s ease-in-out infinite, apexBreathe 3s ease-in-out infinite;
}
@keyframes apexShimmer {
  0%, 100% { background-position: 0% 0; }
  50% { background-position: 100% 0; }
}
@keyframes apexBreathe {
  0%, 100% { filter: drop-shadow(0 0 20px rgba(200, 168, 75, 0.28)); }
  50% { filter: drop-shadow(0 0 34px rgba(232, 201, 106, 0.5)); }
}

/* ---- SIGNATURE MOTION (restored 28 Jul 2026 from the previous theapexai.com.au)
   The brand's own motion language, carried onto the film build. The old site ran
   these as g1/g2 (AI glitch), logoFloat, goldFlow and sPulse; they were lost when
   the cinematic build replaced it. Rebuilt here rather than copied, because the
   film needs them softer and they must not fight the title sequence.

   TIMING RULE: every hero-side animation is gated on body.apex-ignited (1.75s),
   which is AFTER GSAP finishes tweening y/blur on .hl - so nothing overrides the
   reveal. All of it is disabled under prefers-reduced-motion at the end of file.

   ACCESSIBILITY: the glitch is text-shadow + transform on the real letters, NOT
   duplicated ghost text in pseudo-elements, so nothing extra reaches a screen
   reader and the ghosts can never drift out of alignment with the letterforms. */

/* 1. THE GLITCH - chromatic aberration flickers across "AI" for a few frames
   once every 7 seconds. The brand's tell. */
.hero-logo .ai .hl { --ai-shadow: 0 2px 26px rgba(3, 5, 7, 0.6); }
.logo .ai {
  display: inline-block; /* transform does not apply to a plain inline span */
  --ai-shadow: 0 0 0 rgba(0, 0, 0, 0);
}
body.apex-ignited .hero-logo .ai .hl,
.logo .ai { animation: aiGlitch 7s linear 2s infinite; }
@keyframes aiGlitch {
  0%, 82%, 100% { transform: translateX(0); text-shadow: var(--ai-shadow); }
  83% {
    transform: translateX(-3px);
    text-shadow: 3px 0 0 rgba(255, 60, 60, 0.9), -3px 0 0 rgba(0, 229, 255, 0.8), var(--ai-shadow);
  }
  85% {
    transform: translateX(3px);
    text-shadow: -3px 0 0 rgba(255, 60, 60, 0.85), 3px 0 0 rgba(0, 229, 255, 0.75), var(--ai-shadow);
  }
  88% { transform: translateX(-1px); text-shadow: 1px 0 0 rgba(0, 229, 255, 0.5), var(--ai-shadow); }
  90% { transform: translateX(0); text-shadow: var(--ai-shadow); }
}

/* 2. THE FLOAT - the lockup breathes on a slow gold glow. Softer than the old
   site's (0.6/0.85 alpha), because here it sits over moving film, not black. */
body.apex-ignited .hero-logo { animation: logoFloat 7s ease-in-out infinite; }
@keyframes logoFloat {
  0%, 100% { transform: translateY(0); filter: drop-shadow(0 0 44px rgba(200, 168, 75, 0.3)); }
  50% { transform: translateY(-10px); filter: drop-shadow(0 0 66px rgba(200, 168, 75, 0.45)); }
}

/* 3. THE GOLD SWEEP - light travels across every gold CTA, the old .btn-gold
   treatment. Needs the oversized background box to have somewhere to travel. */
.header-cta,
.hero-cta,
.contact button,
.consult-pill {
  background-size: 220% auto;
  animation: goldFlow 5s ease infinite;
}
@keyframes goldFlow {
  0%, 100% { background-position: 0% center; }
  50% { background-position: 100% center; }
}

/* 4. THE SCROLL PULSE - the cue's gold hairline breathes downward. */
.scroll-cue span { transform-origin: top center; animation: sPulse 2s ease infinite; }
@keyframes sPulse {
  0%, 100% { opacity: 0.35; transform: scaleY(1); }
  50% { opacity: 0.9; transform: scaleY(0.55); }
}
/* animated visits: letters wait for the title sequence (pre-paint class on <html>,
   belt-and-braces on body). Static / reduced-motion visits never get the class. */
.js-anim .hero-logo .hl,
body.js-anim .hero-logo .hl,
.js-anim .hero-tag,
.js-anim .hero-sub,
body.js-anim .hero-tag,
body.js-anim .hero-sub { opacity: 0; }
/* the hero CTA waits with them, but hides with visibility as well as opacity: an
   invisible tappable target is worse than invisible text. GSAP's autoAlpha writes
   inline opacity + visibility, which beats this rule when the timeline reveals it,
   and revealHeroNow() writes the same two inline properties on every fallback. */
/* .hero-call rides with the CTA it depends on. Left out of this list, the line
   "or call 0433 690 270" was the ONLY thing painted in the hero for the whole
   window before GSAP arrived: an orphan fragment under an empty space, which
   reads as a broken page at the highest-intent moment on the site. */
.js-anim .hero-cta,
.js-anim .hero-call,
body.js-anim .hero-cta,
body.js-anim .hero-call { opacity: 0; visibility: hidden; }
/* hard guarantee: once the intro has run (or GSAP failed to load), letters show
   even if inline tween styles never landed */
body.hero-in .hero-logo .hl { opacity: 1; }
body.hero-in .hero-cta,
body.hero-in .hero-call { opacity: 1; visibility: visible; }

/* ---- THE CENTRE AXIS of the two centred compositions ----------------------
   .scene-hero and .scene-finale are text-align: center and centre their
   children, but the shared `.scene p { max-width: 52ch }` (and .hero-sub's own
   cap) give those children a NARROW box with no side margins. Each one then
   pins LEFT inside the wide centred parent while its own text centres within
   itself, so the stack lands at a different offset per element depending on its
   width, while the lockup and the gold CTA (which do carry auto margins) sit
   dead on the axis. Measured on a detached clone at 1440px BEFORE this rule:
   lockup 0, CTA 0, .hero-tag -124px, .hero-call -141px, .hero-sub -163px,
   .eyebrow -163px. A perfectly centred gold button with the phone number
   hanging 141px to its left is exactly what "the number randomly floating"
   looks like. The hero eyebrow also loses the 52ch cap: it is a single-line
   micro-caps device with rule decorations, not a measure, and the cap was
   wrapping it. */
.scene-hero .eyebrow,
.hero-tag,
.hero-sub,
.hero-call,
.finale-lead,
.finale-copy .eyebrow-center { margin-left: auto; margin-right: auto; }
.scene-hero .eyebrow { max-width: none; }

/* fade the supporting hero copy as the visitor scrolls out of the hero */
body.hero-leaving .hero-tag,
body.hero-leaving .hero-sub,
body.hero-leaving .scene-hero .eyebrow { opacity: 0 !important; transition: opacity 0.5s ease; }
/* .hero-sub is the page's <h1> (the lockup above it is a div + role="img"; see
   index.html). It was a <p> until then, and a <p> inside .scene picks up three
   properties from `.scene p` that an h1 does not: max-width: 52ch,
   margin-bottom: 1rem and color. It also picks up font-weight: bold from the UA
   h1 default, which the p never had. All four are restated here so the tag swap
   changes nothing on screen. Measured at 375px before and after: same 314px box,
   same 69px height, same 11.52px/400 type. Deliberately NO auto side margins:
   the 52ch box is left-aligned inside the wider hero-copy today, and centring it
   here would be a visual change smuggled in under an SEO fix. */
.hero-sub {
  margin-top: 0.9rem;
  margin-bottom: 1rem;
  max-width: 52ch;
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--silver);
  opacity: 0.9;
}
.hero-tag, .hero-sub, .scroll-cue { text-shadow: 0 1px 14px rgba(3, 5, 7, 0.75), 0 1px 3px rgba(3, 5, 7, 0.6); }

/* ---- hero CTA: the first tappable thing on the page -----------------------
   Block-level with width: fit-content and auto side margins rather than an
   inline-flex pill, so its top margin collapses predictably against .hero-sub's
   own bottom margin and the lockup keeps a stable height at every width.
   Deliberately NOT in the body.hero-leaving fade list: the floating pill only
   arrives once the visitor is already leaving the hero, and fading this out
   first would reopen the very gap it exists to close. */
.hero-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  width: fit-content;
  max-width: 100%;
  min-height: 48px;
  margin: 1.7rem auto 0;
  padding: 0.85rem 1.9rem;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--gold-light), var(--gold-dark));
  color: var(--black);
  box-shadow: 0 8px 30px rgba(200, 168, 75, 0.3);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
}

/* ---- problem grid (DNA scene) -------------------------------------------- */
.problem-grid {
  margin-top: 1.8rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}
.problem-item {
  background: rgba(6, 9, 14, 0.55);
  border: 1px solid rgba(196, 205, 216, 0.12);
  border-left: 2px solid var(--gold);
  border-radius: 12px;
  padding: 1.1rem 1.2rem;
}
.problem-item h3 {
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--off-white);
  margin-bottom: 0.4rem;
}
.problem-item p { font-size: 0.9rem; color: var(--silver); margin: 0; }

/* ---- services grid (Pyramid scene) --------------------------------------- */
.services-grid {
  margin-top: 1.8rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}
.service-card {
  position: relative;
  background: rgba(6, 9, 14, 0.6);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 1.3rem 1.2rem 1.2rem;
  overflow: hidden;
}
.svc-num {
  display: inline-block;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--gold);
  letter-spacing: 0.06em;
  line-height: 1;
}
.svc-badge {
  position: absolute;
  top: 1.3rem; right: 1.1rem;
  font-size: 0.56rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-light);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 0.2rem 0.55rem;
}
.service-card h3 {
  margin: 0.6rem 0 0.5rem;
  font-size: 1rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--off-white);
}
.service-card p { font-size: 0.9rem; color: var(--silver); margin: 0; }

/* ---- process list (Pyramid scene) ---------------------------------------- */
.process-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin-top: 0.4rem; }
.process-step { display: flex; gap: 0.9rem; align-items: flex-start; }
.step-num {
  flex: 0 0 auto;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--gold);
  border: 1px solid var(--hairline);
  border-radius: 50%;
  width: 2.4rem; height: 2.4rem;
  display: flex; align-items: center; justify-content: center;
}
.process-step h4 { font-size: 0.92rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--off-white); margin-bottom: 0.25rem; }
.process-step p { font-size: 0.88rem; color: var(--silver); margin: 0; }

/* ---- results (Moon scene) ------------------------------------------------ */
.results-line { margin-top: 0.6rem; color: var(--silver-light); }
.results-line strong { color: var(--gold-light); }

/* ---- case study (Moon scene) --------------------------------------------- */
/* Finished-card styling. data-template below overlays the "scaffold" treatment,
   so removing that one attribute reveals the polished card underneath. */
.case-study {
  margin: 1rem 0 0.3rem;
  padding: 0.9rem 1.1rem;
  background: rgba(6, 9, 14, 0.6);
  border: 1px solid var(--hairline);
  border-left: 2px solid var(--gold);
  border-radius: 12px;
}
.case-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.5rem; }
.case-eyebrow { font-size: 0.62rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--gold); }
.case-flag {
  font-size: 0.54rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold-light);
  border: 1px dashed rgba(200, 168, 75, 0.6); border-radius: 999px; padding: 0.2rem 0.55rem;
}
.case-client { color: var(--off-white); font-size: 0.96rem; letter-spacing: 0.02em; margin: 0 0 0.4rem; }
.case-line { font-size: 0.88rem; color: var(--silver); margin: 0.22rem 0; }
.case-key {
  color: var(--gold-light); text-transform: uppercase; font-size: 0.62rem;
  letter-spacing: 0.14em; margin-right: 0.55rem;
}
.case-metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; margin: 0.75rem 0 0.2rem; }
.case-metric { text-align: center; border: 1px solid var(--hairline); border-radius: 10px; padding: 0.55rem 0.3rem; }
.case-num { display: block; font-size: 1.18rem; font-weight: 700; color: var(--gold); line-height: 1; }
.case-mlabel { display: block; margin-top: 0.3rem; font-size: 0.57rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--silver); }
.case-quote {
  margin: 0.65rem 0 0; padding-left: 0.8rem; border-left: 2px solid rgba(200, 168, 75, 0.4);
  color: var(--silver-light); font-style: italic; font-size: 0.88rem;
}

/* scaffold mode: unmistakably a template awaiting real content */
.case-study[data-template] { border-style: dashed; border-left-style: solid; }
.case-study[data-template] .case-client,
.case-study[data-template] .case-line,
.case-study[data-template] .case-quote { opacity: 0.7; }
.case-study[data-template] .case-num { color: var(--silver-light); }

.results-caption { margin-top: 1rem; font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--silver); }

/* ---- FAQ (end of the Moon scene, before the finale) ----------------------- */
/* Same card language as .problem-item: hairline box, gold left edge, dark fill.
   Nothing new is invented for it, and no new colour enters the palette. */
.faq { margin-top: 1rem; }
.faq-item {
  background: rgba(6, 9, 14, 0.55);
  border: 1px solid rgba(196, 205, 216, 0.12);
  border-left: 2px solid var(--gold);
  border-radius: 12px;
  margin-top: 0.6rem;
}
/* the padding lives on the SUMMARY, not on the details, so the whole padded row
   is the tap target rather than a 20px strip of text inside it */
.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  min-height: 48px;
  padding: 0.75rem 1.1rem;
  cursor: pointer;
  list-style: none; /* Firefox marker */
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-q {
  font-size: 0.92rem;
  letter-spacing: 0.03em;
  line-height: 1.35;
  color: var(--off-white);
  font-weight: 700;
  text-wrap: balance;
}
/* the disclosure sign is typographic, not an icon file: one gold glyph that
   swaps with the open state (rotation is avoided so it cannot be left mid-turn
   under prefers-reduced-motion) */
.faq-item summary::after {
  content: "+";
  flex: 0 0 auto;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--gold);
  transition: color var(--fast) var(--ease);
}
.faq-item[open] summary::after { content: "\2212"; }
.faq-item summary:hover .faq-q { color: var(--gold-light); }
.faq-item summary:hover::after { color: var(--gold-light); }
/* .scene p (0,1,1) supplies colour, max-width and margin-bottom to any <p> in a
   scene, and would beat a bare .faq-a (0,1,0) on all three. Qualified so the
   answer keeps its own measure and its own bottom spacing. */
.faq .faq-a {
  margin: 0;
  padding: 0 1.1rem 1rem;
  max-width: 62ch;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--silver);
}

/* ---- founder (Savannah scene) --------------------------------------------- */
.founder { margin-top: 1.4rem; }
.founder .block-head { font-size: 0.95rem; }
.founder-line { font-size: 0.92rem; color: var(--silver); margin-top: 0.45rem; max-width: 52ch; }

/* ---- workflow chain (Predators scene) ------------------------------------- */
/* Text-only pills joined by gold arrows: the one tangible automation example.
   No video, no animation - the visual design is frozen. */
.flow-chain { display: flex; flex-wrap: wrap; align-items: center; row-gap: 0.65rem; margin-top: 0.9rem; }
.flow-step {
  position: relative;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver-light);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 0.42rem 0.8rem;
  margin-right: 1.5rem;
  white-space: nowrap;
}
.flow-step:last-child { margin-right: 0; border-color: var(--gold); color: var(--gold-light); }
.flow-step:not(:last-child)::after {
  content: "\2192";
  position: absolute;
  right: -1.15rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--gold);
}
.flow-caption { margin-top: 0.8rem; font-size: 0.88rem; color: var(--silver); max-width: 52ch; }

/* ---- form privacy notice --------------------------------------------------- */
.form-privacy { margin-top: 0.7rem; font-size: 0.72rem; line-height: 1.5; color: var(--silver); max-width: 56ch; margin-left: auto; margin-right: auto; }
.form-privacy a { color: var(--gold); text-decoration: none; }
.form-privacy a:hover { color: var(--gold-light); }

/* ---- pre-submit reassurance ------------------------------------------------
   Same family as .form-privacy, one step louder because this one has to earn the
   click. Qualified with .contact so it beats `.scene p` (0,1,1) on colour,
   max-width and margin-bottom: the unqualified .form-privacy rule above loses
   those three properties to it, which is why this rule is written differently. */
.contact .form-reassure {
  margin: 1.5rem auto 0;
  max-width: 52ch;
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--silver-light);
  text-align: center;
}
.contact .form-reassure strong { color: var(--gold-light); font-weight: 700; }

/* ---- pre-submit confidentiality assurance ----------------------------------
   Same family again, one step QUIETER than .form-reassure: the reassurance has
   to earn the click, this only has to be believed, and shouting it would read as
   protesting too much. Qualified with .contact for the same reason as the rule
   above, so it beats `.scene p` (0,1,1) on colour, max-width and margin.
   The host carve-out in the copy makes this line long, so it keeps the 52ch
   measure rather than the 56ch of .form-privacy. */
.contact .form-confidential {
  margin: 0.6rem auto 0;
  max-width: 52ch;
  font-size: 0.74rem;
  line-height: 1.5;
  color: var(--silver);
  text-align: center;
}
/* the button carries its own 1.4rem top margin: with the reassurance directly
   above it, close the gap so the two read as one block.
   BOTH selectors are load-bearing. This started as `.form-reassure + button`
   alone, and inserting .form-confidential between the two silently stopped it
   matching, which would have restored the full 1.4rem and split the block in
   half. They are kept together so that deleting either paragraph hands the
   spacing back to the other instead of breaking it. */
.contact .form-reassure + button,
.contact .form-confidential + button { margin-top: 0.9rem; }
.results-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1rem;
}
.results-list li {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--silver);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 0.45rem 0.9rem;
}

/* ---- finale ------------------------------------------------------------- */
.scene-finale { justify-content: center; }
.finale-copy { margin: 0 auto; text-align: center; max-width: 620px; }
.eyebrow-center {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  font-size: 0.72rem;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 1.1rem;
}
.eyebrow-center::before, .eyebrow-center::after {
  content: "";
  width: 34px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold));
}
.eyebrow-center::after { background: linear-gradient(90deg, var(--gold), transparent); }
.finale-lead { font-size: 1.125rem; color: var(--silver-light); margin-top: 0.6rem; }
.finale-sub { color: var(--silver); max-width: 52ch; margin: 0.6rem auto 0; }
/* the taller finale scrolls its heading/lead through the scrim's edge zones:
   back them with the hero's text-shadow treatment so they stay legible over the
   bright lattice at any scroll position */
.finale-copy h2,
.finale-copy .eyebrow-center,
.finale-lead,
.finale-sub {
  text-shadow: 0 1px 14px rgba(3, 5, 7, 0.75), 0 1px 3px rgba(3, 5, 7, 0.6);
}

/* ---- what happens next (finale assessment funnel) ------------------------- */
/* card background: this copy lives OUTSIDE the form's own backed panel, and the
   deep scrim alone cannot guarantee contrast at the viewport edges it scrolls
   through (the finale is taller than one screen now) */
.next-steps-wrap {
  max-width: 460px;
  margin: 1.2rem auto 0;
  text-align: left;
  background: rgba(6, 9, 14, 0.6);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 1rem 1.2rem;
}
.next-steps-head {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--gold); text-align: center; margin-bottom: 0.7rem;
  margin-left: auto; margin-right: auto;
}
.next-steps { list-style: none; counter-reset: step; margin: 0; padding: 0; }
.next-steps li {
  counter-increment: step;
  position: relative;
  padding-left: 2.1rem;
  margin-bottom: 0.5rem;
  font-size: 0.9rem;
  color: var(--silver-light);
  line-height: 1.45;
}
.next-steps li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: 0; top: 0.1em;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--gold);
  letter-spacing: 0.04em;
}
.next-note { margin: 0.8rem auto 0; font-size: 0.82rem; color: var(--silver); text-align: center; }

/* ---- contact form: gold corner-bracket frame, no full border ------------- */
.contact {
  position: relative;
  max-width: 560px;
  margin: 2rem auto 0;
  text-align: left;
  border: 0;
  border-radius: 2px;
  backdrop-filter: none;
  background:
    linear-gradient(var(--gold), var(--gold)) 0 0 / 24px 2px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 0 / 2px 24px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 24px 2px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 2px 24px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 24px 2px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 2px 24px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 24px 2px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 2px 24px no-repeat,
    rgba(6, 9, 14, 0.82);
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; }
.field { margin-top: 0.8rem; }
.form-row .field { margin-top: 0; }
.contact select {
  width: 100%;
  background: rgba(3, 5, 7, 0.8);
  border: 1px solid rgba(196, 205, 216, 0.24);
  border-radius: 8px;
  color: var(--off-white);
  font-family: var(--font);
  padding: 0.7rem 0.8rem;
  font-size: 0.95rem;
  appearance: none;
}
.contact select {
  padding-right: 2.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23C8A84B' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
}
/* placeholder-option muting. Two SEPARATE rules on purpose: :invalid covers the
   required selects everywhere; :has() covers the optional ones (never :invalid)
   on evergreen browsers - and combining them would make a non-:has browser drop
   the whole selector list, losing both. */
.contact select:invalid { color: var(--silver); }
.contact select:has(option[value='']:checked) { color: var(--silver); }
.contact ::placeholder { color: var(--silver); opacity: 0.7; }
.btn-mark { margin-right: 0.2rem; }
.form-alt { margin-top: 1rem; text-align: center; font-size: 0.78rem; color: var(--silver); }
.form-alt a { color: var(--gold); text-decoration: none; }
.hp { position: absolute; left: -9999px; }

/* ---- footer extras ------------------------------------------------------- */
.footer-logo { font-size: 1rem; letter-spacing: 0.3em; font-weight: 700; margin-bottom: 0.5rem; }
.footer-logo .the, .footer-logo .ai { color: var(--off-white); }
.footer-logo .apex { color: var(--gold); }
.footer-line { opacity: 0.8; }
.footer-nav { display: flex; flex-wrap: wrap; gap: 1.2rem; justify-content: center; margin: 1rem 0 0.2rem; }
.footer-nav a { font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; }
/* socials sit snug under the page nav as a quieter second row (these rules must
   FOLLOW .footer-nav in source order - equal specificity, last one wins) */
.footer-nav.footer-social { margin: 0.2rem 0 1rem; }
.footer-nav.footer-social a { letter-spacing: 0.12em; }
.disclaimers { max-width: 720px; margin: 1.4rem auto 0; text-align: left; }
.disclaimers summary { cursor: pointer; color: var(--gold); letter-spacing: 0.1em; text-transform: uppercase; font-size: 0.68rem; }
.disclaimers p { font-size: 0.72rem; color: rgba(196, 205, 216, 0.7); margin-top: 0.7rem; line-height: 1.5; }
.footer-tag {
  margin-top: 2.4rem;
  padding-top: 1.6rem;
  color: var(--gold);
  opacity: 0.85;
  font-size: 0.78rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  background: linear-gradient(90deg, transparent, var(--hairline), transparent) top center / 220px 1px no-repeat;
}

/* ---- responsive ---------------------------------------------------------- */
@media (max-width: 768px) {
  .scene { padding: 14vh 7vw; }
  /* The header CTA used to be display:none here. Combined with a hero that had
     no link or button in it and a floating pill that waited until the third era,
     that left a phone visitor with nothing tappable for the first two to three
     screens. It stays, at a smaller scale: the word "Start" goes visually hidden
     (accessible name is still "Start Assessment"), the header gives back some of
     its side padding, and the logo's tracking tightens, so the pill and the
     wordmark clear each other at 320px with room to spare. */
  .site-header { padding: 0.65rem 5vw; gap: 0.7rem; }
  .logo { letter-spacing: 0.24em; }
  /* The header cannot carry a third control at 320px: logo + CTA already use
     the bar. The hero's "or call" line covers mobile above the fold, and the
     footer and form both carry the number, so nothing is lost by hiding it. */
  .header-tel { display: none; }
  .header-cta {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px; /* tap target */
    padding: 0.5rem 0.95rem;
    font-size: 0.62rem;
    letter-spacing: 0.14em;
    white-space: nowrap;
  }
  .hc-lead {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  /* THE LOCKUP MUST NEVER CROP. This clamp was written for the earlier mobile
     block near the top of the file, where it was dead code (see the note there),
     so the wordmark has been overflowing on every phone: it needs 329px at the
     base 2.9rem/0.12em but a 320px screen only offers 275px of content width, and
     a 375px screen 322px. body { overflow-x: hidden } was quietly clipping the T
     and the I. Here, AFTER the base .hero-logo rule, it wins: 238px at 320px and
     279px at 375px, both comfortably inside. */
  .hero-logo { font-size: clamp(2.1rem, 11vw, 2.9rem); letter-spacing: 0.09em; }
  /* the CTA's height is bought back out of the hero's own vertical padding and
     the gaps above it, never out of the wordmark */
  .scene-hero { padding-top: 11vh; padding-bottom: 11vh; }
  .hero-sub { margin-top: 0.7rem; }
  .hero-cta {
    margin-top: 1.3rem;
    padding: 0.8rem 1.4rem;
    font-size: 0.72rem;
    letter-spacing: 0.18em;
  }
  .ts-label { display: none; }
  .timeline-scrubber { right: 0.8rem; height: 52vh; }
  .problem-grid, .services-grid, .process-list { grid-template-columns: 1fr; }
  .form-row { grid-template-columns: 1fr; }
  .form-row .field:last-child { margin-top: 0.8rem; }
  /* 16px floor prevents iOS focus auto-zoom mid-form. It lives HERE, after the
     base .contact rules, because an earlier mobile block's copy of this rule
     was silently defeated by them (equal specificity, later source order). */
  .contact input, .contact select, .contact textarea { font-size: 1rem; }
}

/* ---- reduced motion: no smooth scroll, copy always visible --------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* #poster::after is the boot-time hero still handing over to the real footage /
     poster essay; reduced-motion visitors get the swap instantly, not a fade. */
  .header-cta, .hero-cta, .contact button, .consult-pill, .ts-dot, .ts-label,
  #poster::after { transition: none !important; }
  .header-cta:hover, .hero-cta:hover, .contact button:hover, .consult-pill.is-visible:hover { transform: none !important; }
  /* visibility too: GSAP autoAlpha can leave visibility:hidden inline */
  .scene-copy { opacity: 1 !important; transform: none !important; visibility: visible !important; }
  /* never hide the lockup in reduced-motion: target the elements js-anim hides */
  .hero-logo .hl, .hero-tag, .hero-sub, .hero-cta { opacity: 1 !important; visibility: visible !important; }
  /* the restored signature motion is all decorative: kill it outright, and reset
     the properties each animation drives so nothing freezes mid-keyframe */
  .hero-logo, .hero-logo .ai .hl, .logo .ai,
  .header-cta, .hero-cta, .contact button, .consult-pill, .scroll-cue span {
    animation: none !important;
    transform: none !important;
  }
  .hero-logo .ai .hl { text-shadow: 0 2px 26px rgba(3, 5, 7, 0.6) !important; }
  .logo .ai { text-shadow: none !important; }
  .hero-logo { filter: none !important; }
}

/* ---- print: strip the film, keep the business ----------------------------- */
@media print {
  /* .hero-cta joins the navigation controls: the header and the floating pill are
     already stripped, and a gold pill linking to an anchor is meaningless on paper */
  #poster, #gl, #video-layer, .site-header, .timeline-scrubber,
  .consult-pill, .hero-cta, .scroll-cue { display: none !important; }
  body { background: #fff; color: #000; }
  .scene { min-height: 0; padding: 1.2rem 0; background: none !important; }
  .scene-copy { opacity: 1 !important; visibility: visible !important; transform: none !important; max-width: 100% !important; }
  .scene h1, .scene h2, .scene h3, .scene h4, .scene p, .footer-line,
  .problem-item p, .service-card p, .process-step p { color: #000 !important; text-shadow: none; }
  .next-steps li { color: #000 !important; }
  .next-steps li::before { color: #806515 !important; }
  .hero-logo .apex, .logo .apex { color: #806515 !important; text-shadow: none; }
  .hero-logo .apex .hl {
    background: none !important;
    -webkit-text-fill-color: #806515 !important;
    color: #806515 !important;
    animation: none !important;
    filter: none !important;
  }
  .hero-logo .hl, .hero-tag, .hero-sub { opacity: 1 !important; visibility: visible !important; }
  /* .faq-item joins the card family. Its ANSWERS are already covered: .faq-a is a
     <p> inside a .scene, so `.scene p { color: #000 !important }` above catches
     it. Only a closed <details> withholds its answer from paper, which is the
     browser's behaviour and not something CSS can undo reliably. */
  .service-card, .problem-item, .faq-item, .contact { background: none; border: 1px solid #999; }
  .site-footer { background: none; color: #000; }
}
