/* =====================================================================
   RASA MOTION LAYER — css/motion.css
   Companion stylesheet to js/motion.js. Every rule is namespaced mx-
   and most initial "hidden" states are gated on html.mx (added by the
   engine at boot), so a page with JS disabled — or a stale service-
   worker copy — never hides content.

   Tokens fall back gracefully whether the page loads styles.css
   (--color-accent) or carries its own inline vars (--accent).
   ===================================================================== */

:root {
  --mx-accent: var(--color-accent, var(--accent, #f5a623));
  --mx-gold: var(--color-accent-light, #ffd700);
  --mx-char: #e63946;
  --mx-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --mx-ease-soft: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ------------------------------------------------------------------
   Shared canvas hosts (simmer wisps, bloom bursts)
------------------------------------------------------------------ */
.mx-fx-host {
  position: relative;
}
.mx-simmer-canvas,
.mx-bloom-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}
.mx-bloom-canvas {
  z-index: 3;
}

/* ------------------------------------------------------------------
   Directional reveals — [data-mxr] (up | left | right | fade)
   Hidden states apply ONLY once the engine has booted (html.mx).
------------------------------------------------------------------ */
html.mx [data-mxr] {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity 0.85s var(--mx-ease),
    transform 0.85s var(--mx-ease);
  will-change: opacity, transform;
}
html.mx [data-mxr='left'] {
  transform: translateX(-64px);
}
html.mx [data-mxr='right'] {
  transform: translateX(64px);
}
html.mx [data-mxr='fade'] {
  transform: none;
}
html.mx [data-mxr].mx-in {
  opacity: 1;
  transform: none;
}
html.mx [data-mxr].mx-settled {
  will-change: auto;
}

/* ------------------------------------------------------------------
   Maillard Ignite — words brown from raw -> toasting -> developed.
   Raw: barely-there. Hot (the freshly lit edge): saffron, like the
   browning front moving through the pan. Lit: white-hot, settled.
   Emphasis words (.mxw-hi) keep the saffron permanently.
------------------------------------------------------------------ */
.mx-ignite .mxw {
  color: rgba(255, 255, 255, 0.16);
  transition: color 0.45s var(--mx-ease-soft), text-shadow 0.45s var(--mx-ease-soft);
}
.mx-ignite .mxw.lit {
  color: rgba(255, 255, 255, 0.94);
}
.mx-ignite .mxw.lit.hot {
  color: var(--mx-accent);
  text-shadow: 0 0 22px rgba(245, 166, 35, 0.35);
}
.mx-ignite .mxw-hi.lit {
  color: var(--mx-accent);
}

/* ------------------------------------------------------------------
   Reduction counters — the animated number keeps tabular width so
   surrounding copy never shivers while it counts.
------------------------------------------------------------------ */
.mx-count-num {
  /* display:contents lets the number rejoin the surrounding text as one
     inline run — inside flex-layout list items a plain span would become
     its own flex item and pick up the container's gap */
  display: contents;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------
   Rising-heat scroll bar
------------------------------------------------------------------ */
.mx-heatbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  z-index: 1200;
  background: linear-gradient(
    90deg,
    var(--mx-char) 0%,
    var(--mx-accent) 45%,
    var(--mx-gold) 100%
  );
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
  box-shadow: 0 0 12px rgba(245, 166, 35, 0.35);
}

/* ------------------------------------------------------------------
   Three Burners deck — [data-fx="deck"]
   DEFAULT (no class / .mx-deck--flat): the page's own layout stands,
   untouched. Only .mx-deck--on (desktop, motion allowed) switches to
   the pinned runway + sticky stage.
------------------------------------------------------------------ */
/* an ancestor that clipped with overflow:hidden gets clip instead, so the
   deck's position:sticky pins against the viewport as intended */
.mx-clip-fix {
  overflow: clip !important;
}

.mx-deck--on {
  height: 420vh; /* the scroll runway: generous room per burner */
}
.mx-deck--on .mx-deck__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding-top: 88px; /* clear the fixed nav */
  box-sizing: border-box;
}
.mx-deck--on .mx-deck__stage {
  position: relative;
  display: block;
  width: min(560px, 86vw);
  height: clamp(400px, 50vh, 560px);
  margin-top: 0.75rem;
}
/* compact the pinned header so title + stage + dial share 100vh */
.mx-deck--on .rasa-universe__title {
  font-size: clamp(1.6rem, 3.2vw, 2.6rem);
}
.mx-deck--on .mx-deck__stage > * {
  position: absolute;
  inset: 0;
  margin: 0;
  will-change: transform, opacity;
  /* the deck's render loop owns transform/opacity every frame — any
     inherited reveal/hover transition would smear it into mush */
  transition: none !important;
  opacity: 1;
}
/* keep the pinned header compact so header + stage + dial fit 100vh */
.mx-deck--on .rasa-universe__header {
  margin-bottom: 0.5rem;
}
.mx-deck--on .rasa-universe__header .rasa-universe__subtitle {
  margin-bottom: 0;
}
@media (max-height: 760px) {
  .mx-deck--on .rasa-universe__header .rasa-universe__subtitle {
    display: none;
  }
  .mx-deck--on .mx-deck__stage {
    height: 56vh;
  }
}
/* the active burner's icon ignites like a flame catching */
.mx-deck--on .mx-deck__stage > .is-active .universe-card__icon {
  filter: drop-shadow(0 0 14px rgba(245, 166, 35, 0.55));
  transition: filter 0.6s var(--mx-ease);
}

/* ghost numeral — an oversized serif digit behind the stage */
.mx-deck__ghost {
  display: none;
}
.mx-deck--on .mx-deck__ghost {
  display: block;
  position: absolute;
  top: 50%;
  left: 6%;
  transform: translateY(-52%);
  font-family: 'Cormorant Garamond', serif;
  font-weight: 300;
  font-size: clamp(9rem, 22vw, 20rem);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(245, 166, 35, 0.14);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

/* heat label — mono, uppercase, like a dial setting */
.mx-deck__meta {
  display: none;
}
.mx-deck--on .mx-deck__meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1.4rem;
  z-index: 2;
}
.mx-deck__heat {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(245, 166, 35, 0.75);
}
.mx-deck__heat.mx-heat-flip {
  animation: mx-heat-flip 0.5s var(--mx-ease);
}
@keyframes mx-heat-flip {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* burner dots — three small rings, the active one alight */
.mx-deck__dots {
  display: none;
}
.mx-deck--on .mx-deck__dots {
  display: flex;
  gap: 0.7rem;
  margin-top: 1rem;
  z-index: 2;
}
.mx-deck__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid rgba(245, 166, 35, 0.4);
  background: transparent;
  transition:
    background 0.4s var(--mx-ease),
    box-shadow 0.4s var(--mx-ease);
}
.mx-deck__dot.on {
  background: var(--mx-accent);
  box-shadow: 0 0 10px rgba(245, 166, 35, 0.6);
}

/* ------------------------------------------------------------------
   The Pan at Midnight — [data-fx="flashlight"]
   .mx-flash__dim: the near-dark base (always visible).
   .mx-flash__lit: the true-colour layer, masked to a small soft circle
   at (--mx, --my). Small, tight radius — restraint beats a big glow.
------------------------------------------------------------------ */
.mx-flash {
  position: relative;
  overflow: hidden;
}
/* anything else inside the stage (headline, copy) rides above the image */
.mx-flash > *:not(.mx-flash__dim):not(.mx-flash__lit):not(.mx-flash__hint) {
  position: relative;
  z-index: 2;
}
/* when a hero becomes a flashlight stage, the mx-flash layers own the
   imagery — retire the section's legacy background and dark overlay */
.mx-flash.cinematic-hero {
  background-image: none !important;
}
.mx-flash.cinematic-hero::after {
  content: none !important;
}
.mx-flash__dim,
.mx-flash__lit {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
}
.mx-flash__dim {
  filter: brightness(0.22) saturate(0.55);
}
.mx-flash__lit {
  --mx: 50%;
  --my: 55%;
  --mx-flash-r: 170px;
  opacity: 0;
  transition: opacity 0.5s ease;
  -webkit-mask-image: radial-gradient(
    circle var(--mx-flash-r) at var(--mx) var(--my),
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 0.85) 55%,
    rgba(0, 0, 0, 0) 100%
  );
  mask-image: radial-gradient(
    circle var(--mx-flash-r) at var(--mx) var(--my),
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 0.85) 55%,
    rgba(0, 0, 0, 0) 100%
  );
}
.mx-flash__lit.is-ambient {
  opacity: 1;
  --mx-flash-r: 200px;
}
/* reduced motion: show the image plainly, no tricks */
.mx-flash--static .mx-flash__dim {
  filter: brightness(0.7) saturate(0.9);
}
.mx-flash--static .mx-flash__lit {
  display: none;
}
.mx-flash__hint {
  position: absolute;
  left: 50%;
  bottom: 1.4rem;
  transform: translateX(-50%);
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  pointer-events: none;
  z-index: 2;
}
.mx-flash--static .mx-flash__hint {
  display: none;
}

/* ------------------------------------------------------------------
   Mise en Place timeline — [data-fx="mise"]
   A horizontal track (vertical on mobile) that fills with saffron as
   --jp goes 0 -> 1; an ember rides the tip; nodes ignite; cards rise.
------------------------------------------------------------------ */
.mx-mise__stepper {
  --jp: 0;
  --jp-dot: 0;
  position: relative;
}
.mx-mise__step {
  position: relative;
  padding-top: 2.4rem;
}
.mx-mise__step .mx-mise__node {
  position: absolute;
  top: -7px;
  left: 50%;
  transform: translateX(-50%);
}
.mx-mise__track {
  position: absolute;
  top: 0;
  left: 4%;
  right: 4%;
  height: 2px;
  background: rgba(255, 255, 255, 0.08);
  overflow: visible;
}
@media (max-width: 820px) {
  /* stacked cards: the horizontal line no longer connects anything */
  .mx-mise__track {
    display: none;
  }
  .mx-mise__step .mx-mise__node {
    display: none;
  }
  .mx-mise__step {
    padding-top: 0;
  }
}
.mx-mise__fill {
  position: absolute;
  inset: 0;
  transform-origin: left center;
  transform: scaleX(var(--jp));
  background: linear-gradient(90deg, var(--mx-accent), var(--mx-gold));
  box-shadow: 0 0 10px rgba(245, 166, 35, 0.5);
}
/* the ember riding the fill tip */
.mx-mise__ember {
  position: absolute;
  top: 50%;
  left: calc(var(--jp) * 100%);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: var(--mx-gold);
  box-shadow:
    0 0 12px rgba(255, 215, 0, 0.9),
    0 0 30px rgba(245, 166, 35, 0.5);
  opacity: var(--jp-dot);
  transition: opacity 0.3s ease;
}
.mx-mise__step {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 0.7s var(--mx-ease),
    transform 0.7s var(--mx-ease);
}
.mx-mise__step.in {
  opacity: 1;
  transform: none;
}
.mx-mise__node {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid rgba(245, 166, 35, 0.45);
  background: #080c14;
  transition:
    background 0.45s var(--mx-ease),
    box-shadow 0.45s var(--mx-ease);
}
.mx-mise__node.lit {
  background: var(--mx-accent);
  box-shadow: 0 0 14px rgba(245, 166, 35, 0.65);
}
.mx-mise--static .mx-mise__step {
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------------------------
   Self-drawing SVG line art — [data-fx-draw]
   The engine sets pathLength="1" on every shape; armed shapes start
   fully offset and draw to zero when .mx-drawn lands.
------------------------------------------------------------------ */
svg.mx-draw-armed path,
svg.mx-draw-armed circle,
svg.mx-draw-armed ellipse,
svg.mx-draw-armed line,
svg.mx-draw-armed polyline,
svg.mx-draw-armed rect {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  fill-opacity: 0;
  transition:
    stroke-dashoffset 1.1s var(--mx-ease-soft),
    fill-opacity 0.8s ease 0.7s;
}
svg.mx-drawn path,
svg.mx-drawn circle,
svg.mx-drawn ellipse,
svg.mx-drawn line,
svg.mx-drawn polyline,
svg.mx-drawn rect {
  stroke-dashoffset: 0;
  fill-opacity: 1;
}

/* ------------------------------------------------------------------
   Progressive edge blur — frosted dissolve at the viewport's bottom
------------------------------------------------------------------ */
.mx-edgeblur {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 120px;
  z-index: 1100;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.45s ease;
}
.mx-edgeblur.is-hidden {
  opacity: 0;
}
.mx-edgeblur__layer {
  position: absolute;
  inset: 0;
}

/* ------------------------------------------------------------------
   Reduced motion — neutralize everything this layer animates.
   (Each JS effect also branches to a static path; this is the belt
   to that suspenders.)
------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html.mx [data-mxr] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .mx-ignite .mxw {
    color: rgba(255, 255, 255, 0.94);
    transition: none;
  }
  .mx-ignite .mxw-hi {
    color: var(--mx-accent);
  }
  .mx-heatbar,
  .mx-deck__heat.mx-heat-flip,
  .mx-mise__ember {
    animation: none;
    transition: none;
  }
  svg.mx-draw-armed path,
  svg.mx-draw-armed circle,
  svg.mx-draw-armed ellipse,
  svg.mx-draw-armed line,
  svg.mx-draw-armed polyline,
  svg.mx-draw-armed rect {
    stroke-dashoffset: 0;
    fill-opacity: 1;
    transition: none;
  }
  .mx-edgeblur {
    transition: none;
  }
}
