/* ============================================================
   motion.css — "NUR · Light Through Geometry" background layer
   Pairs with motion.js. See MOTION.md for the asset contract.

   Layer order inside a host (bottom → top):
     video / poster   →  .motion__media      (object-cover, inset 0)
     scrim gradient   →  .motion__scrim      (navy #03294F only)
     grain overlay    →  .motion__grain      (opacity .06, overlay)
     page content     →  host children       (z-index 10)

   BRAND LOCK: the only colour permitted in this file over the
   footage is navy #03294F. No warm, purple or neutral tints.
   ============================================================ */

:root {
  --nur-navy: #03294F;
}

/* ---- the host section ------------------------------------ */
/* `isolate` keeps the grain's mix-blend-mode from reaching the
   page behind the section; `overflow:hidden` clips object-cover. */
.has-motion {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-color: var(--nur-navy);
}

/* Everything the section already renders sits above the layer.
   (.hero-copy, .page-hero > *, .cta-band > * already carry their
   own z-index; this catches plain children such as .stats.) */
.has-motion>*:not(.motion) {
  position: relative;
  z-index: 10;
}

/* A full-bleed band that hosts footage behind a normal `.section`.
   The inner `.section` keeps the 1320px measure and the padding;
   the band itself spans the viewport so the video is edge-to-edge. */
.motion-band {
  display: block;
  width: 100%;
}

/* The footage IS the background now — retire the aurora wash and
   the hero-bg.jpg photo underneath it, or they fight the scrim. */
.has-motion::before {
  display: none !important;
}

.has-motion.hero--bg,
.has-motion.page-hero {
  background-image: none;
}

/* The CTA band is a rounded card, not a full-bleed strip: its
   accent gradient is replaced by the footage, so re-clip it. */
.has-motion.cta-band {
  background: var(--nur-navy);
}

.has-motion.cta-band::after {
  display: none !important;
}

/* ---- the layer ------------------------------------------- */
.motion {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  border-radius: inherit;
  /* painted before any media decodes, so the section is never white */
  background-color: var(--nur-navy);
}

.motion__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the two shots whose negative space must follow reading
     direction; motion.js sets .is-mirrored per locale. */
  transform: none;
}

.motion.is-mirrored .motion__media {
  transform: scaleX(-1);
}

/* poster underneath, video fades in over it once it actually plays,
   so a slow decode never shows a black or empty frame */
.motion__poster {
  z-index: 0;
}

.motion__video {
  z-index: 1;
  opacity: 0;
  transition: opacity .6s cubic-bezier(.22, .61, .36, 1);
}

.motion__video.is-playing {
  opacity: 1;
}

/* ---- scrim (navy only — spec §3) ------------------------- */
.motion__scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
}

/* strong — hero, and any section with a headline over it */
.motion[data-scrim="strong"] .motion__scrim {
  background: linear-gradient(180deg,
      rgba(3, 41, 79, .35) 0%,
      rgba(3, 41, 79, .55) 45%,
      rgba(3, 41, 79, .90) 100%);
}

/* soft — decorative sections with no text directly over the video */
.motion[data-scrim="soft"] .motion__scrim {
  background: linear-gradient(180deg,
      rgba(3, 41, 79, .25) 0%,
      rgba(3, 41, 79, .65) 100%);
}

.motion[data-scrim="none"] .motion__scrim {
  display: none;
}

/* ---- copy-side veil --------------------------------------
   The vertical scrim alone cannot carry a headline that sits
   beside a backlit area (measured 2.56:1 on the hero). Rather
   than lighten the type — forbidden by spec §3 — this raises
   the scrim only on the side the copy occupies, so the carved
   geometry on the far side keeps its full contrast.
   Navy #03294F only; opt in with data-motion-veil="start".
   ---------------------------------------------------------- */
.motion__veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  /* Tuned by measurement, not by eye: .66 is the lightest veil that
     puts the hero h1 over 4.5:1 against the brightest frame (4.72).
     Heavier values do clear it by more, but flatten the carved
     geometry the whole direction exists to show. */
  /* LTR: copy sits on the left */
  background: linear-gradient(to right,
      rgba(3, 41, 79, .66) 0%,
      rgba(3, 41, 79, .46) 30%,
      rgba(3, 41, 79, 0) 64%);
}

[dir="rtl"] .motion__veil {
  /* RTL: copy sits on the right */
  background: linear-gradient(to left,
      rgba(3, 41, 79, .66) 0%,
      rgba(3, 41, 79, .46) 30%,
      rgba(3, 41, 79, 0) 64%);
}

/* Full-bleed bands carry their `.sec-head` hard against the top
   edge, which is exactly where both scrims are weakest (.25/.35).
   Over the brightest shots that left the small accent label at
   2.3:1, so the top edge gets its own falloff. */
.motion__veil--top,
[dir="rtl"] .motion__veil--top {
  background: linear-gradient(to bottom,
      rgba(3, 41, 79, .84) 0%,
      rgba(3, 41, 79, .62) 16%,
      rgba(3, 41, 79, .18) 34%,
      rgba(3, 41, 79, 0) 46%);
}

/* Centred layouts — the inner page headers and the CTA band. Several
   shots (05, 08) put their brightest element dead centre, exactly
   where a centred headline lands, so the veil is centred too.
   Direction-independent, so no RTL variant is needed. */
.motion__veil--center,
[dir="rtl"] .motion__veil--center {
  background: radial-gradient(ellipse 62% 78% at 50% 50%,
      rgba(3, 41, 79, .78) 0%,
      rgba(3, 41, 79, .58) 42%,
      rgba(3, 41, 79, .12) 82%,
      rgba(3, 41, 79, 0) 100%);
}

/* The CTA band is the one centred host whose shot puts a hard
   specular beam dead behind the headline (08 closing), and it is a
   small rounded card rather than a full page header — so it takes a
   heavier centre veil to reach 4.5:1 without dimming the inner-page
   headers, which already clear it at the value above. */
.has-motion.cta-band .motion__veil--center {
  background: radial-gradient(ellipse 70% 88% at 50% 50%,
      rgba(3, 41, 79, .93) 0%,
      rgba(3, 41, 79, .76) 42%,
      rgba(3, 41, 79, .20) 82%,
      rgba(3, 41, 79, 0) 100%);
}

/* ---- grain ----------------------------------------------- */
.motion__grain {
  position: absolute;
  inset: 0;
  z-index: 3;
  background-image: url('./media/motion/grain.png?v=1');
  background-repeat: repeat;
  background-size: 256px 256px;
  opacity: .06;
  mix-blend-mode: overlay;
}

/* ============================================================
   Readability of the existing copy once it sits on navy footage.
   The light themes (.theme-cyan / .theme-warm) paint dark text by
   default; over the footage that would fail 4.5:1, so motion
   sections re-point the text tokens at the dark-surface values.
   Overlaid text is NEVER lightened to fix contrast — the scrim is
   raised instead (spec §3) — this only restores the light-on-dark
   pairing the footage was graded for.
   ============================================================ */
.has-motion {
  --text: #eef4ff;
  --muted: color-mix(in srgb, #eef4ff 72%, transparent);
  --hero-text: #eef4ff;
  --line: rgba(238, 244, 255, .16);
  color: var(--text);
}

.has-motion .sec-head h2,
.has-motion .sec-head .num,
.has-motion .sec-head .mirror,
.has-motion h2,
.has-motion h3,
.has-motion h4 {
  color: #eef4ff;
}

.has-motion .btn.ghost {
  border-color: rgba(238, 244, 255, .42);
  color: #eef4ff;
}

/* stat counters sit in the upper empty area of 02-tessellation */
.has-motion .stat .num {
  color: #eef4ff;
}

.has-motion .stat .lbl {
  color: color-mix(in srgb, #eef4ff 78%, transparent);
}

/* Panels that carry copy over footage are NAVY glass, not white
   glass: a 6% white veil left small accent type at 1.3–1.6:1 over
   the backlit areas of 03 and 06. Navy at .62–.72 gives every
   child a dependable dark ground (and keeps the brand lock), so
   the type inside is read against the panel, not the video. */
.has-motion .card,
.has-motion .svc-detail,
.has-motion .svc-list,
.has-motion .stat,
.has-motion .work,
.has-motion .work .info {
  background: rgba(3, 41, 79, .72);
  border-color: rgba(238, 244, 255, .16);
  backdrop-filter: blur(16px) saturate(1.1);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
}

/* .stat and .work are opaque WHITE cards in the light themes — left
   alone they would carry the light-on-dark text set above on a white
   ground. They must be re-grounded, not just re-coloured. */
.has-motion .stat {
  border: 1px solid rgba(238, 244, 255, .16);
}

.has-motion .work .info {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.has-motion .svc-list {
  border-radius: 18px;
  padding: 6px 14px;
}

.has-motion .card p,
.has-motion .svc-detail p {
  color: color-mix(in srgb, #eef4ff 82%, transparent);
}

/* accent type is the weakest link over backlit footage — on navy
   glass it clears 4.5:1, but nudge it lighter than the light-theme
   #00A6FB so it never sits at the bottom of the range */
.has-motion .d-tag,
.has-motion .kick,
.has-motion .work .info .m,
.has-motion .sec-head .num,
.has-motion .card .ix,
.has-motion .tags span,
.has-motion .svc-detail .tags span,
.has-motion .svc-detail .d-tag,
.has-motion .svc-detail .d-ico,
.has-motion .svc-row .go,
.has-motion .svc-row.on .svc-ico,
.has-motion .svc-row:hover .svc-ico {
  color: #7fd0ff;
}

/* ---- reduced motion -------------------------------------- */
/* motion.js never requests a video file in this mode; this is the
   belt-and-braces half in case a video element is already live
   when the user flips the OS setting. */
@media (prefers-reduced-motion: reduce) {
  .motion__video {
    display: none !important;
  }
}
