/* ============================================================================
   BALLY DOES AI — CINEMATIC DEPTH  ·  cinematic-depth.css
   ----------------------------------------------------------------------------
   The static half of the cinematic engine. Every module here renders a DESIGNED
   resting state with JavaScript switched off, under prefers-reduced-motion, and
   below 768px. cinematic-3d.js only ever *adds* motion on top — it is never
   load-bearing for layout or legibility.

   Reference lineage (premium-build-system/research/expanded/awards.md):
     data-zscene   Oryzo / Lusion      true Z-axis camera travel
     data-monolith Hubtown             one lit hero object on a reflective floor
     data-room(s)  Cartier W&W         one lit room per item
     data-dissolve Igloo Inc           frost dissolve + chromatic aberration
     data-fog      Explore Primland    atmospheric depth fog
     data-unfold   Toll Brothers       poetic phrases unfolding on scroll
     data-chars    Unseen              masked per-character reveal
     fluid tokens  Lando Norris SOTY   one formula drives every size

   PALETTE: neutral-led. Teal support, burgundy emphasis, green reserved for
   CTAs / HUD / live dots. NO orange or amber anywhere in this file.
   ========================================================================== */

/* ----------------------------------------------------------------------------
   0 · FLUID DESIGN TOKENS — Lando Norris SOTY
   One clamp. Everything else is a multiple of it, so type, spacing and object
   sizes stay pixel-locked to the 1728 comp at every viewport with zero font
   media queries.
   --------------------------------------------------------------------------- */
:root {
  --design-width: 1728;
  --design-unit: 16;
  --fluid-floor: 360px;
  --fluid-ceil: 1728px;
  --fluid-base: calc(clamp(var(--fluid-floor), 100vw, var(--fluid-ceil))
                     / var(--design-width) * var(--design-unit));

  --fluid-xs:   calc(var(--fluid-base) * 0.75);
  --fluid-sm:   calc(var(--fluid-base) * 0.875);
  --fluid-md:   calc(var(--fluid-base) * 1);
  --fluid-lg:   calc(var(--fluid-base) * 1.5);
  --fluid-xl:   calc(var(--fluid-base) * 2.25);
  --fluid-2xl:  calc(var(--fluid-base) * 3.5);
  --fluid-3xl:  calc(var(--fluid-base) * 5.5);
  --fluid-hero: calc(var(--fluid-base) * 8);

  /* the real "expensive" tells: shadows TINTED TOWARD THE BACKGROUND, layered
     across four stops, never a single black blur (TECHNIQUE-LIBRARY.md) */
  --shadow-tint: 22, 38, 63;                 /* --navy rgb */
  --shadow-1: 0 1px 2px rgba(var(--shadow-tint), 0.05),
              0 2px 6px -1px rgba(var(--shadow-tint), 0.05);
  --shadow-2: 0 1px 2px rgba(var(--shadow-tint), 0.05),
              0 4px 10px -2px rgba(var(--shadow-tint), 0.07),
              0 12px 26px -8px rgba(var(--shadow-tint), 0.09);
  --shadow-3: 0 1px 2px rgba(var(--shadow-tint), 0.05),
              0 6px 14px -3px rgba(var(--shadow-tint), 0.08),
              0 20px 44px -12px rgba(var(--shadow-tint), 0.13),
              0 44px 80px -28px rgba(var(--shadow-tint), 0.16);
  --shadow-lift: 0 2px 4px rgba(var(--shadow-tint), 0.06),
                 0 12px 26px -6px rgba(var(--shadow-tint), 0.14),
                 0 34px 70px -20px rgba(var(--shadow-tint), 0.20);

  /* cinematic tell — cool-teal aberration, warmed a touch so it reads human
     rather than crypto. Amplitude stays sub-perceptual by design. */
  --ab-cool: rgba(28, 139, 124, 0.42);
  --ab-warm: rgba(124, 45, 72, 0.34);
}

/* double-bezel gradient border — inner hairline + outer gradient ring */
.cin-bezel {
  position: relative;
  border-radius: var(--r-md, 1.25rem);
  background: var(--surface);
  box-shadow: var(--shadow-2), inset 0 0 0 1px rgba(255, 255, 255, 0.55);
}
.cin-bezel::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit;
  padding: 1px; pointer-events: none;
  background: linear-gradient(150deg,
    rgba(28, 139, 124, 0.34), rgba(20, 26, 36, 0.06) 42%, rgba(124, 45, 72, 0.20));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}

/* ----------------------------------------------------------------------------
   1 · [data-zscene] — ORYZO / LUSION true Z-axis camera travel
   The camera moves through Z. Layers do NOT slide on Y. Depth children sit at
   real translateZ offsets and are counter-scaled so their apparent size at rest
   equals their layout size.
   --------------------------------------------------------------------------- */
/* The scene owns its own height (a vh figure or an aspect-ratio); .zcam is the
   camera layer and always fills it, so absolutely-positioned depth plates
   resolve their percentages against the scene, not against a zero-height wrap. */
[data-zscene] {
  position: relative; display: grid;
  perspective: var(--z-perspective, 1200px);
  perspective-origin: 50% 46%;
}
[data-zscene] > .zcam {
  grid-area: 1 / 1;
  position: relative; width: 100%; height: 100%; min-height: 100%;
  transform-style: preserve-3d;
  will-change: transform;
}
[data-zdepth] { transform-style: preserve-3d; }

/* DESIGNED RESTING STATE — no camera, no perspective. Depth is expressed as
   scale + shadow weight instead, so the composition still reads layered. */
@media (max-width: 767px), (prefers-reduced-motion: reduce) {
  [data-zscene] { perspective: none; }
  [data-zscene] > .zcam { transform: none !important; }
  [data-zdepth] { transform: none !important; }
  [data-zdepth="3"], [data-zdepth="2"] { box-shadow: var(--shadow-3); }
  [data-zdepth="1"] { box-shadow: var(--shadow-2); }
  [data-zdepth="-1"], [data-zdepth="-2"], [data-zdepth="-3"] { opacity: 0.86; }
}

/* ----------------------------------------------------------------------------
   2 · [data-monolith] — HUBTOWN. One confidently lit hero object on a
   reflective floor. The single most-reused module; wrap it around whatever the
   page's one hero artifact is.
   --------------------------------------------------------------------------- */
[data-monolith] {
  position: relative; isolation: isolate;
  --mx: 50%; --my: 34%;
  padding-bottom: var(--mono-floor, 5.5rem);
}
[data-monolith] > .mono__obj {
  position: relative; z-index: 2;
  transform-style: preserve-3d;
  will-change: transform;
}
/* key light — a soft top-left key plus the pointer-tracked reveal */
[data-monolith] > .mono__light {
  position: absolute; inset: -12% -6% 22%; z-index: 1; pointer-events: none;
  background:
    radial-gradient(38% 42% at var(--mx) var(--my),
      rgba(255, 255, 255, 0.20) 0%, rgba(255, 255, 255, 0) 68%),
    radial-gradient(72% 60% at 24% 6%,
      rgba(28, 139, 124, 0.14) 0%, rgba(28, 139, 124, 0) 70%);
  mix-blend-mode: screen;
  transition: opacity 0.5s var(--ease-out-quart, ease);
}
/* contact shadow — the object is ON something, not floating */
[data-monolith] > .mono__shadow {
  position: absolute; left: 50%; bottom: calc(var(--mono-floor, 5.5rem) - 0.5rem);
  width: 62%; height: 2.4rem; transform: translateX(-50%);
  z-index: 1; pointer-events: none;
  background: radial-gradient(50% 50% at 50% 50%,
    rgba(var(--shadow-tint), 0.34) 0%, rgba(var(--shadow-tint), 0) 72%);
  filter: blur(6px);
}
/* reflective floor — a fading mirror, not a literal duplicate (half the cost) */
[data-monolith] > .mono__floor {
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--mono-floor, 5.5rem);
  z-index: 0; pointer-events: none;
  background: linear-gradient(180deg,
    rgba(var(--shadow-tint), 0.10) 0%, rgba(var(--shadow-tint), 0.02) 44%,
    rgba(var(--shadow-tint), 0) 100%);
  -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 88%);
          mask-image: linear-gradient(180deg, #000 0%, transparent 88%);
}
[data-monolith].on-dark > .mono__floor {
  background: linear-gradient(180deg,
    rgba(243, 245, 248, 0.10) 0%, rgba(243, 245, 248, 0.02) 46%,
    rgba(243, 245, 248, 0) 100%);
}
@media (prefers-reduced-motion: reduce) {
  [data-monolith] > .mono__obj { transform: none !important; }
  [data-monolith] > .mono__light { transition: none; }
}

/* ----------------------------------------------------------------------------
   3 · [data-rooms] / [data-room] — CARTIER. One lit alcove per item; the scroll
   navigates BETWEEN rooms instead of down a list. Each room owns a light
   temperature.
   --------------------------------------------------------------------------- */
[data-rooms] { position: relative; }
[data-rooms] > .rooms__stage {
  position: sticky; top: 0; height: 100vh; height: 100svh;
  display: grid; overflow: hidden;
}
[data-room] {
  grid-area: 1 / 1; position: relative;
  display: grid; place-items: center; padding: var(--gutter, 32px);
  opacity: 0; transform: translateZ(0) scale(0.965);
  transition: opacity 0.7s var(--ease-out-quart, ease),
              transform 0.9s var(--ease-out-expo, ease);
}
[data-room].is-lit { opacity: 1; transform: none; }
[data-room]::before {                    /* the room's own light */
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(64% 58% at 50% 18%,
    var(--room-light, rgba(28, 139, 124, 0.16)) 0%, transparent 74%);
}
[data-room="teal"]     { --room-light: rgba(28, 139, 124, 0.18); }
[data-room="navy"]     { --room-light: rgba(31, 50, 83, 0.26); }
[data-room="burgundy"] { --room-light: rgba(124, 45, 72, 0.16); }
[data-room="neutral"]  { --room-light: rgba(20, 26, 36, 0.10); }

/* DESIGNED RESTING STATE — the sticky theatre unrolls into an honest stack,
   every room lit, each keeping its own temperature. */
@media (max-width: 767px), (prefers-reduced-motion: reduce) {
  [data-rooms] > .rooms__stage {
    position: static; height: auto; display: block;
  }
  [data-room] {
    grid-area: auto; opacity: 1; transform: none; transition: none;
    min-height: auto; padding-block: clamp(3rem, 9vw, 5rem);
  }
}

/* ----------------------------------------------------------------------------
   4 · [data-dissolve] — IGLOO frost dissolve with chromatic aberration.
   Budget: barely perceptible. 2px max offset, decays inside 640ms, once.
   --------------------------------------------------------------------------- */
[data-dissolve] { position: relative; }
[data-dissolve].is-dissolving { animation: cin-frost 0.64s var(--ease-out-quart, ease) both; }
[data-dissolve].is-dissolving::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 3;
  box-shadow: inset 2px 0 0 var(--ab-cool), inset -2px 0 0 var(--ab-warm);
  mix-blend-mode: screen;
  animation: cin-ab 0.64s var(--ease-out-quart, ease) both;
}
@keyframes cin-frost {
  from { filter: blur(7px) brightness(1.1) saturate(0.7); opacity: 0.2; }
  60%  { filter: blur(1.5px) brightness(1.02) saturate(0.95); opacity: 1; }
  to   { filter: none; opacity: 1; }
}
@keyframes cin-ab { from { opacity: 0.55; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  [data-dissolve].is-dissolving,
  [data-dissolve].is-dissolving::after { animation: none; }
  [data-dissolve].is-dissolving::after { content: none; }
}

/* ----------------------------------------------------------------------------
   5 · [data-fog] — EXPLORE PRIMLAND atmospheric depth fog behind photography.
   Pure CSS, zero GPU cost beyond one composited layer. Tintable per page.
   --------------------------------------------------------------------------- */
[data-fog] { position: relative; isolation: isolate; }
[data-fog]::before {
  content: ""; position: absolute; inset: -14% -10%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(52% 46% at 22% 16%, var(--fog-a) 0%, transparent 70%),
    radial-gradient(46% 42% at 82% 72%, var(--fog-b) 0%, transparent 72%),
    linear-gradient(180deg, transparent 42%, var(--fog-floor) 100%);
  filter: blur(var(--fog-blur, 26px));
  transform: translate3d(0, var(--fog-y, 0px), 0);
  will-change: transform;
}
[data-fog],
[data-fog="teal"]    { --fog-a: rgba(28,139,124,0.20); --fog-b: rgba(28,139,124,0.10); --fog-floor: rgba(234,238,241,0.55); }
[data-fog="navy"]    { --fog-a: rgba(31,50,83,0.30);   --fog-b: rgba(22,38,63,0.18);   --fog-floor: rgba(22,38,63,0.42); }
[data-fog="neutral"] { --fog-a: rgba(20,26,36,0.14);   --fog-b: rgba(20,26,36,0.07);   --fog-floor: rgba(246,246,242,0.6); }
[data-fog="burgundy"]{ --fog-a: rgba(124,45,72,0.18);  --fog-b: rgba(124,45,72,0.09);  --fog-floor: rgba(246,246,242,0.55); }

/* ----------------------------------------------------------------------------
   6 · [data-unfold] — TOLL BROTHERS. Large poetic phrases unfold progressively.
   Never blocks reading: the resting opacity floor is 0.24, never 0.
   --------------------------------------------------------------------------- */
[data-unfold] .uf__line {
  display: block;
  opacity: 0.24;
  transform: translateY(0.16em);
  transition: opacity 0.7s var(--ease-out-quart, ease),
              transform 0.9s var(--ease-out-expo, ease);
}
[data-unfold] .uf__line.is-open { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-unfold] .uf__line { opacity: 1; transform: none; transition: none; }
}

/* ----------------------------------------------------------------------------
   7 · [data-chars] — UNSEEN masked per-character reveal. The mask is the CSS
   half; the split is the JS half. Static state = fully visible text.
   --------------------------------------------------------------------------- */
[data-chars] .cin-line { display: block; overflow: hidden; padding-block: 0.08em; margin-block: -0.08em; }
[data-chars] .cin-char { display: inline-block; will-change: transform; }

/* ----------------------------------------------------------------------------
   8 · [data-wheel] — scroll-VELOCITY response. Clamped hard so text stays
   readable; desktop + motion only (JS enforces, this is only the hint).
   --------------------------------------------------------------------------- */
[data-wheel] { will-change: transform; transform-origin: 50% 50%; }
@media (max-width: 767px), (prefers-reduced-motion: reduce) {
  [data-wheel] { will-change: auto; transform: none !important; }
}

/* ----------------------------------------------------------------------------
   10 · [data-field] — canvas constellation field. The "high-tech" texture.
   --------------------------------------------------------------------------- */
[data-field] { position: relative; }
[data-field] > .field__c {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; pointer-events: none; z-index: 0;
  opacity: 0; transition: opacity 0.8s var(--ease-out-quart, ease);
}
[data-field] > .field__c.is-live { opacity: 1; }
/* static fallback — a still constellation drawn in CSS, never a blank box */
[data-field]::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    radial-gradient(1.4px 1.4px at 18% 24%, rgba(28,139,124,0.55), transparent 60%),
    radial-gradient(1.2px 1.2px at 64% 12%, rgba(20,26,36,0.30), transparent 60%),
    radial-gradient(1.6px 1.6px at 82% 58%, rgba(28,139,124,0.40), transparent 60%),
    radial-gradient(1.2px 1.2px at 36% 74%, rgba(20,26,36,0.24), transparent 60%),
    radial-gradient(1.3px 1.3px at 8% 66%, rgba(28,139,124,0.34), transparent 60%);
}
@media (max-width: 767px), (prefers-reduced-motion: reduce) {
  [data-field] > .field__c { display: none; }
}

/* ----------------------------------------------------------------------------
   11 · [data-tilt] — pointer-reactive 3D tilt with a specular sweep.
   --------------------------------------------------------------------------- */
[data-tilt] {
  position: relative; transform-style: preserve-3d;
  will-change: transform; --tx: 50%; --ty: 50%;
  transition: box-shadow 0.5s var(--ease-out-quart, ease);
}
[data-tilt]::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; opacity: 0; z-index: 4;
  background: radial-gradient(28% 42% at var(--tx) var(--ty),
    rgba(255, 255, 255, 0.30) 0%, rgba(255, 255, 255, 0) 62%);
  transition: opacity 0.4s var(--ease-out-quart, ease);
}
[data-tilt].is-tilting::after { opacity: 1; }
[data-tilt].is-tilting { box-shadow: var(--shadow-lift); }
@media (hover: none), (pointer: coarse), (prefers-reduced-motion: reduce) {
  [data-tilt] { will-change: auto; transform: none !important; }
  [data-tilt]::after { content: none; }
}

/* ----------------------------------------------------------------------------
   12 · [data-grain] — fixed film grain, ~3%. GPU-composited, inert to input.
   Applied to <body data-grain> or any full-bleed section.
   --------------------------------------------------------------------------- */
[data-grain] > .cin-grain,
.cin-grain {
  position: fixed; inset: -120px; z-index: 9998; pointer-events: none;
  opacity: var(--grain-opacity, 0.030);
  background-repeat: repeat;
  background-size: 180px 180px;
  will-change: transform;
  contain: strict;
}
@media (prefers-reduced-motion: reduce) { .cin-grain { animation: none !important; } }
@media print { .cin-grain { display: none; } }
