/*
[MODULE] v3_immersive_css | Styles the Immersive pages (home + cases): dark aurora gradients, glassmorphism panels, lifecycle scenes with sticky cross-fade image stage
[IFACE]  layer: template | in: class names (.mesh .aurora .hero(.hero__bg/__bg-layer/__wave) .journey .scene .stage__layer .diagram(.beam-card .node .diagram__links/__inputs/__outputs/__loop) .caps .cases .glass .vision .case-*) → out: styled layout | crosses: []
[GRAPH]  needs: [] | feeds: [v3_immersive_page, v3_case_retail, v3_case_corporate_kb, v3_case_decision_agents, v3_caseidx_retail, v3_caseidx_healthcare, v3_caseidx_corporate_knowledge, v3_caseidx_operational_intelligence] | group: v3_immersive
[STATE]  stateless | persists: nothing | raises: —
*/

:root {
  --bg: #07070c;
  --text: #f2f1f7;
  --text-dim: #9d9bb0;
  --violet: #8b5cf6;
  --cyan: #22d3ee;
  --glass-bg: rgba(255, 255, 255, 0.045);
  --glass-edge: rgba(255, 255, 255, 0.12);
  --sans: system-ui, "Segoe UI", Helvetica, Arial, sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1.05rem;
  line-height: 1.65;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* ---------- fixed generative background ---------- */

.mesh {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

/* No filter: blur() here. The gradients already fall off to transparent, so a blur was
   visually inert — but it forced a full repaint of this oversized fixed surface on every
   animation frame, which alone cost ~20fps. will-change promotes the layer once so the
   drift is a compositor-only transform. */
.aurora {
  position: fixed;
  inset: -20%;
  z-index: -1;
  background:
    radial-gradient(ellipse 55% 45% at 22% 28%, rgba(139, 92, 246, 0.22), transparent 65%),
    radial-gradient(ellipse 50% 40% at 78% 68%, rgba(34, 211, 238, 0.16), transparent 65%),
    radial-gradient(ellipse 45% 50% at 55% 15%, rgba(99, 60, 220, 0.12), transparent 60%);
  will-change: transform;
  animation: aurora-drift 26s ease-in-out infinite alternate;
}

@keyframes aurora-drift {
  from { transform: translate3d(-2%, -1%, 0) rotate(-1.5deg) scale(1); }
  to   { transform: translate3d(2%, 2%, 0) rotate(1.5deg) scale(1.06); }
}

/* content sits above the canvas */
.site-header, .hero, .journey, .caps, .cases, .vision, .site-footer,
.case-header, .case-hero, .case-section {
  position: relative;
  z-index: 1;
}

/* ---------- header ---------- */

.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 5;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 1.75rem clamp(1.5rem, 5vw, 4rem);
}

.site-nav {
  display: flex;
  gap: 1.75rem;
}

.site-nav a {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.site-nav a:hover { color: var(--cyan); }

.brand {
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
}

.brand__accent {
  background: linear-gradient(90deg, var(--violet), var(--cyan));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- hero ---------- */

.hero {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 6rem clamp(1.5rem, 5vw, 4rem);
  overflow: hidden;
}

/* hero background: two cross-fading photos above the mesh/aurora, below the text.
   A scrim keeps the aurora reading through and holds title contrast. */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* Opacity and zoom are driven by two separate classes that js/main.js toggles, both on
   the swap's clock so neither can drift from it. They are split because they have
   different lifetimes: .is-active covers the hold, .is-zooming covers the hold *plus*
   the fade-out, so the outgoing layer keeps zooming as it disappears instead of having
   its transform yanked to an end value the animation never actually reached. */
.hero__bg-layer {
  --hero-fade: 1.5s;
  --hero-zoom-to: 1.08;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1);
  transition: opacity var(--hero-fade) ease-in-out;
}

.hero__bg-layer.is-active { opacity: 1; }

.hero__bg-layer.is-zooming {
  animation: hero-bg-zoom var(--hero-zoom-duration, 8.5s) linear forwards;
}

@keyframes hero-bg-zoom {
  from { transform: scale(1); }
  to   { transform: scale(var(--hero-zoom-to)); }
}

/* Radial wave: soft rings of light expanding from the hero centre, over the photos but
   under the scrim so the vignette still tames them at the edges. CSS cannot distort the
   image pixels, so this is additive light, not refraction.

   --wave-travel  how long one ring takes to cross the screen (its speed)
   --wave-gap     how long between one ring launching and the next (the pause)

   Each ring's animation period is gap x ringCount, so the rings launch evenly. The travel
   is a fraction of that period, and the remainder is the ring sitting idle at opacity 0 —
   that idle tail is what reads as the pause. Raising --wave-gap widens the pause without
   changing how fast a ring moves; raising --wave-travel slows the ring itself. */
.hero__wave {
  --wave-travel: 9s;
  --wave-gap: 6s;
  --wave-period: calc(var(--wave-gap) * 2);   /* 2 rings */
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* No mix-blend-mode: on low-alpha light over a near-black backdrop `screen` and `normal`
   are indistinguishable, but the blend disqualifies the ring from compositor-only
   animation and cost ~11fps. will-change keeps each ring on its own GPU layer. */
.hero__wave span {
  position: absolute;
  top: 50%;
  left: 50%;
  /* square + diagonal-sized: stays circular at any aspect ratio and clears the viewport
     before it fades, so a ring never visibly pops out of existence mid-screen. */
  width: 150vmax;
  height: 150vmax;
  margin: -75vmax 0 0 -75vmax;
  border-radius: 50%;
  opacity: 0;
  will-change: transform, opacity;
  background: radial-gradient(closest-side,
    transparent 58%,
    rgba(139, 92, 246, 0.10) 66%,
    rgba(34, 211, 238, 0.16) 72%,
    rgba(139, 92, 246, 0.07) 78%,
    transparent 86%);

  animation: hero-wave var(--wave-period) linear infinite;
}

/* two rings, half a period apart => one launches every --wave-gap */
.hero__wave span:nth-child(2) { animation-delay: calc(var(--wave-period) / -2); }

/* The 75% mark is --wave-travel / --wave-period (9s / 12s). Keyframe percentages cannot
   read custom properties, so if you change either variable, move this stop to match or
   the ring will finish early and freeze, or get cut off mid-flight. Past it the ring is
   invisible: that idle tail is the pause between impulses.
   `ease-out` lives here on the expansion rather than on the animation, so it shapes only
   the travel and not the idle tail. */
@keyframes hero-wave {
  0%   { transform: scale(0.04); opacity: 0; animation-timing-function: ease-out; }
  9%   { opacity: 0.9;                        animation-timing-function: ease-out; }
  75%  { transform: scale(1); opacity: 0; }
  100% { transform: scale(1); opacity: 0; }
}

.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 70% 60% at 50% 50%, transparent 25%, rgba(6, 8, 20, 0.55) 85%),
    linear-gradient(180deg, rgba(6, 8, 20, 0.55), rgba(6, 8, 20, 0.25) 45%, rgba(6, 8, 20, 0.75));
}

/* hero text sits above the background + scrim */
.hero__title,
.hero__sub {
  position: relative;
  z-index: 1;
}

.hero__title {
  font-size: clamp(3rem, 10vw, 6.5rem);
  line-height: 0.98;
  font-weight: 800;
  letter-spacing: -0.03em;
  background: linear-gradient(120deg, #fff 30%, var(--violet) 75%, var(--cyan));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  padding-bottom: 20px;
}

.hero__sub {
  margin-top: 2rem;
  font-size: clamp(2rem, 2.2vw, 1.35rem);
  color: var(--text-dim);
  letter-spacing: 0.06em;
}

.hero__scroll {
  position: absolute;
  z-index: 1;
  bottom: 2.5rem;
  width: 1.4rem;
  height: 2.4rem;
  border: 1px solid var(--glass-edge);
  border-radius: 1rem;
  display: flex;
  justify-content: center;
}

.hero__scroll span {
  width: 3px;
  height: 8px;
  margin-top: 6px;
  border-radius: 2px;
  background: var(--cyan);
  animation: scroll-nudge 1.8s ease-in-out infinite;
}

@keyframes scroll-nudge {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50%      { transform: translateY(10px); opacity: 0.3; }
}

/* ---------- journey ---------- */

.journey {
  position: relative;
  padding: 4rem 0;
}

.journey__rail {
  position: absolute;
  left: clamp(1.25rem, 4vw, 3rem);
  top: 0;
  bottom: 0;
  width: 2px;
  background: rgba(255, 255, 255, 0.08);
}

.journey__rail-fill {
  display: block;
  width: 100%;
  height: 0%;
  background: linear-gradient(var(--violet), var(--cyan));
}

.journey__layout {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(2rem, 4vw, 4.5rem);
  max-width: 96rem;
  margin: 0 auto;
  padding: 0 clamp(1.5rem, 5vw, 4rem) 0 clamp(3.5rem, 8vw, 7rem);
}

/* right column: sticky glass stage that holds the four cross-fading image layers.
   Stays pinned in the viewport while .journey__track scrolls past it on the left. */
.journey__stagewrap { position: relative; }

.journey__stage {
  position: sticky;
  top: 13vh;
  height: 74vh;
  border-radius: 1.75rem;
  overflow: hidden;
  border: 1px solid var(--glass-edge);
  background: var(--glass-bg);
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.5);
}

.scene {
  min-height: 90vh;
  display: flex;
  align-items: center;
  padding: 4rem 0;
}

.scene__panel {
  max-width: 40rem;
  opacity: 0.25;
  transform: translateY(2rem) scale(0.98);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.scene.is-active .scene__panel {
  opacity: 1;
  transform: none;
}

.scene__num {
  font-size: 0.85rem;
  letter-spacing: 0.5em;
  color: var(--cyan);
}

.scene__title {
  font-size: clamp(2.4rem, 6vw, 4.5rem);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  margin: 0.5rem 0 1.25rem;
}

.scene__panel > p {
  color: var(--text-dim);
  font-size: clamp(1.05rem, 2vw, 1.3rem);
  max-width: 32rem;
}

/* generated scene visuals */

.scene__visual {
  position: relative;
  margin-top: 2.25rem;
  min-height: 14rem;
  border-radius: 1rem;
  border: 1px solid var(--glass-edge);
  background: rgba(255, 255, 255, 0.02);
  overflow: hidden;
}

.scene__visual span {
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--violet);
  box-shadow: 0 0 14px rgba(139, 92, 246, 0.8);
}

/* scattered signals pulsing into alignment (Perceive) */
.scene__visual--perceive span { animation: perceive-align 3.6s ease-in-out infinite; }
.scene__visual--perceive span:nth-child(1) { top: 18%; left: 12%; animation-delay: 0s;   }
.scene__visual--perceive span:nth-child(2) { top: 65%; left: 20%; animation-delay: 0.6s; background: var(--cyan); box-shadow: 0 0 14px rgba(34,211,238,0.8); }
.scene__visual--perceive span:nth-child(3) { top: 30%; left: 45%; animation-delay: 1.2s; }
.scene__visual--perceive span:nth-child(4) { top: 75%; left: 55%; animation-delay: 1.8s; background: var(--cyan); box-shadow: 0 0 14px rgba(34,211,238,0.8); }
.scene__visual--perceive span:nth-child(5) { top: 22%; left: 78%; animation-delay: 2.4s; }
.scene__visual--perceive span:nth-child(6) { top: 60%; left: 86%; animation-delay: 3s;   }

@keyframes perceive-align {
  0%, 100% { transform: translateY(0) scale(1); opacity: 0.35; }
  50%      { transform: translateY(-14px) scale(1.35); opacity: 1; }
}

/* pulses radiating outward from a core (Act) */
.scene__core {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 22px rgba(34, 211, 238, 0.9);
}

.scene__visual--act span {
  top: 50%;
  left: 50%;
  margin: -5px 0 0 -5px;
  animation: act-radiate 2.8s ease-out infinite;
}

.scene__visual--act span:nth-child(1) { --rx: -120px; --ry: -46px; animation-delay: 0s;   }
.scene__visual--act span:nth-child(2) { --rx: 130px;  --ry: -38px; animation-delay: 0.7s; background: var(--cyan); box-shadow: 0 0 14px rgba(34,211,238,0.8); }
.scene__visual--act span:nth-child(3) { --rx: -95px;  --ry: 52px;  animation-delay: 1.4s; background: var(--cyan); box-shadow: 0 0 14px rgba(34,211,238,0.8); }
.scene__visual--act span:nth-child(4) { --rx: 110px;  --ry: 48px;  animation-delay: 2.1s; }

@keyframes act-radiate {
  0%   { transform: translate(0, 0) scale(0.4); opacity: 0; }
  20%  { opacity: 1; }
  100% { transform: translate(var(--rx), var(--ry)) scale(1); opacity: 0; }
}

/* nodes converging into a profile card */
.scene__visual--converge span { animation: converge 4s ease-in-out infinite; }
.scene__visual--converge span:nth-child(1) { top: 12%; left: 8%;  animation-delay: 0s;   }
.scene__visual--converge span:nth-child(2) { top: 75%; left: 14%; animation-delay: 0.4s; }
.scene__visual--converge span:nth-child(3) { top: 20%; left: 82%; animation-delay: 0.8s; background: var(--cyan); box-shadow: 0 0 14px rgba(34,211,238,0.8); }
.scene__visual--converge span:nth-child(4) { top: 80%; left: 78%; animation-delay: 1.2s; }
.scene__visual--converge span:nth-child(5) { top: 45%; left: 4%;  animation-delay: 1.6s; background: var(--cyan); box-shadow: 0 0 14px rgba(34,211,238,0.8); }

/* 0%/100% frames are implicit: each node returns to its own top/left position */
@keyframes converge {
  50% { top: 50%; left: 50%; opacity: 0.15; }
}

.scene__card {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-style: normal;
  font-family: Consolas, monospace;
  font-size: 0.8rem;
  letter-spacing: 0.15em;
  color: var(--text);
  padding: 1rem 1.6rem;
  border: 1px solid var(--glass-edge);
  border-radius: 0.6rem;
  background: var(--glass-bg);
  backdrop-filter: blur(8px);
}

/* graph growing new nodes */
.scene__visual--grow span { animation: grow-pulse 3.2s ease-in-out infinite; }
.scene__visual--grow span:nth-child(1) { top: 48%; left: 48%; width: 14px; height: 14px; background: var(--cyan); box-shadow: 0 0 18px rgba(34,211,238,0.9); animation-delay: 0s; }
.scene__visual--grow span:nth-child(2) { top: 25%; left: 35%; animation-delay: 0.5s; }
.scene__visual--grow span:nth-child(3) { top: 68%; left: 62%; animation-delay: 1s; }
.scene__visual--grow span:nth-child(4) { top: 30%; left: 68%; animation-delay: 1.5s; }
.scene__visual--grow span:nth-child(5) { top: 72%; left: 30%; animation-delay: 2s; }
.scene__visual--grow span:nth-child(6) { top: 15%; left: 52%; animation-delay: 2.5s; }

@keyframes grow-pulse {
  0%   { transform: scale(0); opacity: 0; }
  35%  { transform: scale(1.25); opacity: 1; }
  70%  { transform: scale(1); opacity: 0.85; }
  100% { transform: scale(0.9); opacity: 0.5; }
}

/* ---------- loop-step diagrams (fan-in / strata / dispatch / feedback) ---------- */

:root {
  --hot: #ff6600;
  --hot-grad: linear-gradient(135deg, #ff6600, #ffe000);
}

/* diagram = centered, content-sized card floating above the ambient dot backdrop */
.diagram {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.2rem;
  padding: 3.5rem 4rem;
  font-family: var(--sans);
  min-width: 26rem;
}

/* corner-cut card with a rotating neon border beam (orange→yellow).
   The beam is a full conic on a ::before, clipped to the corner-cut shape and
   masked to a thin ring so it never bleeds into the translucent interior. */
.beam-card {
  --radius: 24px;
  --beam: 1.5px;
  position: absolute;
  border-radius: var(--radius);
  background: rgba(12, 10, 22, 0.4);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.05);
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.beam-card::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  background: conic-gradient(from var(--beam-angle, 0deg),
      rgba(255,102,0,0) 0deg,
      rgba(255,102,0,0) 270deg,
      #ff6600 340deg, #ffe000 360deg);
  padding: var(--beam);
  -webkit-mask: linear-gradient(#fff 0 0) content-box exclude, linear-gradient(#fff 0 0);
          mask: linear-gradient(#fff 0 0) content-box exclude, linear-gradient(#fff 0 0);
  animation: beam-spin 4.5s linear infinite;
  opacity: 0.9;
}

@property --beam-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes beam-spin {
  to { --beam-angle: 360deg; }
}

/* fallback: browsers without @property animate no angle → static hot ring, still fine */

/* ---- nodes ---- */
.node {
  font-style: normal;
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
  padding: 0.7rem 1.4rem;
  border-radius: 2rem;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.node--in,
.node--out,
.node--sat { 
  border-color: rgba(34, 211, 238, 0.35); 
  background: rgba(34, 211, 238, 0.06); 
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2), inset 0 0 12px rgba(34, 211, 238, 0.1); 
}
.node--faint { opacity: 0.5; }
/* --new sits 18px below its grid cell (static fallback; the animation re-applies
   this same translateY inside its keyframes so the offset survives the pulse) */
.node--new {
  border: 1px dashed rgba(255, 224, 0, 0.5);
  background: transparent;
  box-shadow: none;
  transform: translateY(18px);
  animation: node-emerge 3.4s ease-in-out infinite;
}

/* the pulsing MAIN node: hot gradient fill + slow inner-shadow pulse + neon halo */
.node--core {
  color: #1a0d00;
  border: 0;
  background: var(--hot-grad);
  box-shadow:
    0 0 24px rgba(255, 102, 0, 0.5),
    0 0 48px rgba(255, 102, 0, 0.3),
    inset 0 1px 2px rgba(255, 255, 255, 0.8);
  animation: core-pulse 3s ease-in-out infinite;
  font-size: 1.25rem;
  padding: 15px 40px;
}

@keyframes core-pulse {
  0%, 100% {
    box-shadow: 0 0 20px rgba(255, 102, 0, 0.4), 0 0 40px rgba(255, 102, 0, 0.2),
                inset 0 1px 2px rgba(255, 255, 255, 0.6);
  }
  50% {
    box-shadow: 0 0 35px rgba(255, 102, 0, 0.8), 0 0 65px rgba(255, 170, 0, 0.4),
                inset 0 1px 2px rgba(255, 255, 255, 0.9);
  }
}

@keyframes node-emerge {
  /* keep the --new node's downward offset while it pulses (a lone `transform`
     declaration on the rule would be overridden by these keyframes) */
  0%, 100% { opacity: 0.35; transform: translateY(18px) scale(0.9); }
  50%      { opacity: 1;    transform: translateY(18px) scale(1); }
}

/* ---- connectors: four spoke lines that fan between a single convergence point
   (at the core) and the four chips, so the lines actually connect node to node.
   Each <i> is a thin line anchored at bottom-center and rotated toward its chip. ---- */
.diagram__links {
  --spoke: 4rem;         /* spoke length; overridden per scale */
  position: relative;
  width: 100%;
  height: 3.2rem;          /* spans the gap between the chip row and the core */
  margin: -1rem 0 -0.6rem; /* pull spokes up to meet the chips, down toward the core */
}
/* convergence point: a small hot dot where all spokes meet at the core side */
.diagram__links::after {
  content: "";
  position: absolute;
  left: 50%; bottom: -10px;
  width: 6px; height: 6px;
  margin: 0 0 -3px -3px;
  border-radius: 50%;
  background: var(--hot-grad);
  box-shadow: 0 0 10px 1px rgba(255, 150, 0, 0.9);
}
.diagram__links i {
  position: absolute;
  left: 50%; bottom: 3px;   /* anchored at the convergence point */
  width: 1px;
  height: var(--spoke);     /* long enough to reach the outer chips when rotated */
  transform-origin: bottom center;
  background: linear-gradient(to top, rgba(255,102,0,0.7), rgba(255,102,0,0.12));
  overflow: hidden;
}
/* travelling spark riding each spoke */
.diagram__links i::before {
  content: "";
  position: absolute;
  left: -1px; top: 0;
  width: 3px; height: 26%;
  border-radius: 2px;
  background: linear-gradient(to top, transparent, #ffe000);
  box-shadow: 0 0 7px rgba(255, 150, 0, 0.9);
  animation: spoke-flow 2.4s linear infinite;
}
@keyframes spoke-flow {         /* fan-in: spark travels from chip → core (top → bottom) */
  0%   { top: -30%; opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { top: 100%; opacity: 0; }
}
/* spoke angles: outer chips lean more, inner chips nearly upright */
/* spoke angles */
.diagram--fanin  .diagram__links i:nth-child(1),
.diagram--dispatch .diagram__links i:nth-child(1) { transform: rotate(-50deg) translate(-25px, -30px); height: calc(var(--spoke) * 1.5); }
.diagram--fanin  .diagram__links i:nth-child(2),
.diagram--dispatch .diagram__links i:nth-child(2) { transform: rotate(-23deg) translate(-5px, -8px); height: calc(var(--spoke) * 1.1); }
.diagram--fanin  .diagram__links i:nth-child(3),
.diagram--dispatch .diagram__links i:nth-child(3) { transform: rotate(23deg) translate(5px, -8px); height: calc(var(--spoke) * 1.1); }
.diagram--fanin  .diagram__links i:nth-child(4),
.diagram--dispatch .diagram__links i:nth-child(4) { transform: rotate(50deg) translate(25px, -30px); height: calc(var(--spoke) * 1.5); }
.diagram--fanin  .diagram__links i:nth-child(2)::before,
.diagram--dispatch .diagram__links i:nth-child(2)::before,
.diagram--fanin  .diagram__links i:nth-child(4)::before,
.diagram--dispatch .diagram__links i:nth-child(4)::before { animation-delay: 1.1s; }

/* dispatch (Act): core is ABOVE, outputs below → flip the whole spoke fan and
   reverse the spark direction so it reads core → outputs */
.diagram--dispatch .diagram__links { transform: scaleY(-1); }
.diagram--dispatch .diagram__links i::before { animation-name: spoke-flow-rev; }
@keyframes spoke-flow-rev {
  0%   { top: 100%; opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  100% { top: -30%; opacity: 0; }
}

/* 01 Perceive / 03 Act — chip rows */
.diagram--fanin .diagram__inputs,
.diagram--dispatch .diagram__outputs {
  display: flex;
  gap: 0.55rem;
  flex-wrap: nowrap;
  justify-content: center;
}

/* 02 Understand — layered strata stack, core stratum in the middle */
.diagram--strata { gap: 0.45rem; }
.diagram--strata .node--layer { min-width: 12rem; text-align: center; }

/* 04 Evolve — feedback loop: core + satellites, a spark orbits the return arc.
   Markup order: Interactions, Model(core), Signals, +new node, .loop */
.diagram--feedback {
  display: grid;
  grid-template-columns: repeat(3, auto);
  grid-template-rows: auto auto;
  align-items: center;
  justify-items: center;
  gap: 1.8rem 1.2rem;      /* taller cluster → rounder encircling ring */
  padding: 3.4rem 2.4rem;
}
.diagram--feedback .node { position: relative; }
.diagram--feedback .node:nth-child(1) { grid-area: 1 / 1; } /* Interactions — left  */
.diagram--feedback .node:nth-child(2) { grid-area: 1 / 2; } /* Model (core) — center */
.diagram--feedback .node:nth-child(3) { grid-area: 1 / 3; } /* Signals — right */
.diagram--feedback .node:nth-child(4) { grid-area: 2 / 2; } /* + new node — below core */
/* hub connectors: each satellite links to the central Model core */
.diagram--feedback .node--sat::after,
.diagram--feedback .node--new::after {
  content: "";
  position: absolute;
  background: linear-gradient(90deg, rgba(34,211,238,0.15), rgba(255,102,0,0.6));
  z-index: -1;
}
/* Interactions (left)  → core: line off the right edge */
.diagram--feedback .node:nth-child(1)::after { top: 50%; left: 100%; width: 1.1rem; height: 1px; }
/* Signals (right) → core: line off the left edge */
.diagram--feedback .node:nth-child(3)::after { top: 50%; right: 100%; width: 1.1rem; height: 1px; }
/* + new node (below) → core: vertical line off the top edge */
.diagram--feedback .node:nth-child(4)::after {
  left: 50%; bottom: 100%; width: 1px; height: 1.4rem;
  background: linear-gradient(0deg, rgba(255,224,0,0.5), rgba(255,102,0,0.6));
}
/* dashed horizontal feedback line across the middle of the Evolve cluster,
   with a travelling hot pulse that reads left-to-right. */
.diagram__loop {
  grid-area: 1 / 1 / 3 / 4;
  justify-self: stretch;
  align-self: center;
  position: relative;
  margin: 0;
  border: 0;
  border-top: 1px dashed rgba(255, 102, 0, 0.34);
  pointer-events: none;
}
/* the travelling hot pulse: a short gradient segment that sweeps across the line */
.diagram__loop::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: 25%;
  height: 1.5px;
  background: linear-gradient(90deg, transparent, var(--hot), #ffe000, transparent);
  filter: drop-shadow(0 0 4px rgba(255, 140, 0, 0.8));
  animation: loop-flow 3s linear infinite;
}
@keyframes loop-flow {
  0%   { left: -25%; opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}

/* in-panel diagrams are compact */
.scene__panel .diagram {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 1.8rem 2rem;
  gap: 1.4rem;
  min-width: auto;
}
.scene__panel .beam-card {
  --radius: 16px;
  --beam: 1.5px;
}
.scene__panel .node {
  padding: 0.5rem 1rem;
  font-size: 0.65rem;
}

/* one layer per scene; generated image goes on background-image (see ASSETS.md) */
.stage__layer {
  position: absolute;
  inset: 0;
  margin: 0;
  overflow: hidden;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transform: scale(1.06);
  filter: blur(14px);
  transition: opacity 0.9s ease, transform 0.9s ease, filter 0.9s ease;
}

.stage__layer.is-active {
  opacity: 1;
  transform: none;
  filter: none;
}

/* per-layer image + fallback gradient grade */
.stage__layer--perceive {
  background-image: url("../assets/v3-loop-perceive.jpg"), radial-gradient(ellipse 80% 65% at 30% 30%, rgba(139, 92, 246, 0.18), transparent 70%);
}
.stage__layer--understand {
  background-image: url("../assets/v3-loop-understand.jpg"), radial-gradient(ellipse 75% 70% at 50% 45%, rgba(99, 60, 220, 0.20), transparent 70%);
}
.stage__layer--act {
  background-image: url("../assets/v3-loop-act.jpg"), radial-gradient(ellipse 80% 70% at 50% 50%, rgba(34, 211, 238, 0.14), transparent 70%);
}
.stage__layer--evolve {
  background-image: url("../assets/v3-loop-evolve.jpg"), radial-gradient(ellipse 85% 70% at 60% 60%, rgba(139, 92, 246, 0.14), rgba(34, 211, 238, 0.08) 55%, transparent 75%);
}

/* generative pattern fills the layer as placeholder / ambient overlay */
.stage__layer .scene__visual {
  position: absolute;
  inset: 0;
  margin: 0;
  min-height: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.stage__layer .scene__visual span {
  width: 14px;
  height: 14px;
}

/* act pattern radiates further at stage scale */
.stage__layer .scene__visual--act span:nth-child(1) { --rx: -14rem; --ry: -9rem; }
.stage__layer .scene__visual--act span:nth-child(2) { --rx: 15rem;  --ry: -7rem; }
.stage__layer .scene__visual--act span:nth-child(3) { --rx: -12rem; --ry: 10rem; }
.stage__layer .scene__visual--act span:nth-child(4) { --rx: 13rem;  --ry: 9rem;  }

/* stage-scale diagrams: bigger nodes, more breathing room over the image */
.stage__layer .diagram { padding: clamp(2.5rem, 5vw, 4.5rem) clamp(3rem, 6vw, 3rem); gap: clamp(1.8rem, 4vw, 3rem); min-width: 32rem; }
.stage__layer .diagram--strata .node--layer { min-width: clamp(14rem, 24vw, 19rem); }
.stage__layer .diagram__links { height: 4.5rem; --spoke: 5.5rem; }
.stage__layer .diagram__inputs,
.stage__layer .diagram__outputs { gap: 1rem; }
.stage__layer .beam-card { --radius: 32px; --beam: 2px; }

/* on desktop the stage carries the visual; hide the in-panel copies */
@media (min-width: 56.0625rem) {
  .scene__panel .scene__visual { display: none; }
}

/* ---------- capabilities ---------- */

.caps {
  padding: clamp(5rem, 12vh, 9rem) clamp(1.5rem, 6vw, 5rem);
  max-width: 78rem;
  margin: 0 auto;
}

.caps__heading {
  font-size: clamp(1.8rem, 4vw, 2.8rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 3rem;
}

.caps__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

.glass {
  padding: 2.25rem;
  border-radius: 1.25rem;
  border: 1px solid var(--glass-edge);
  background: var(--glass-bg);
  backdrop-filter: blur(14px);
  transition: transform 0.35s ease, border-color 0.35s ease;
}

.glass:hover {
  transform: translateY(-4px);
  border-color: rgba(139, 92, 246, 0.5);
}

.glass h3 {
  font-size: 1.3rem;
  margin-bottom: 0.8rem;
  background: linear-gradient(90deg, var(--text), var(--cyan));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.glass p { color: var(--text-dim); font-size: 0.98rem; }

/* ---------- cases (glass cards) ---------- */

.cases {
  padding: clamp(5rem, 12vh, 9rem) clamp(1.5rem, 6vw, 5rem);
  max-width: 78rem;
  margin: 0 auto;
}

.cases__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

.glass--case {
  display: block;
  text-decoration: none;
  color: inherit;
}

.glass__tag {
  display: inline-block;
  font-family: Consolas, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--cyan);
  margin-bottom: 1rem;
}

.glass__cta {
  display: inline-block;
  margin-top: 1.25rem;
  font-size: 0.8rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--violet);
  opacity: 0;
  transition: opacity 0.35s ease;
}

.glass--case:hover .glass__cta { opacity: 1; }

/* ---------- case sub-pages ---------- */

.case-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 1.75rem clamp(1.5rem, 5vw, 4rem);
}

.case-header .brand { text-decoration: none; color: var(--text); }

.backlink {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.backlink:hover { color: var(--cyan); }

.case-hero {
  padding: clamp(3.5rem, 10vh, 7rem) clamp(1.5rem, 6vw, 5rem) clamp(2rem, 5vh, 3.5rem);
  max-width: 64rem;
  margin: 0 auto;
}

.case-hero__tag {
  font-family: Consolas, monospace;
  font-size: 0.78rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--cyan);
  margin-bottom: 1.25rem;
}

.case-hero h1 {
  font-size: clamp(2.2rem, 6vw, 4.2rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  background: linear-gradient(110deg, #fff 40%, var(--violet) 85%, var(--cyan));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  padding-bottom: 10px;
}

.case-hero__promise {
  margin-top: 1.5rem;
  font-size: clamp(1.05rem, 2vw, 1.3rem);
  color: var(--text-dim);
  max-width: 36rem;
}

.case-section {
  padding: clamp(2rem, 5vh, 3.5rem) clamp(1.5rem, 6vw, 5rem);
  max-width: 64rem;
  margin: 0 auto;
}

.case-section__label {
  font-family: Consolas, monospace;
  font-size: 0.75rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--cyan);
  margin-bottom: 1.5rem;
}

.case-section > p { color: var(--text-dim); max-width: 54rem; }

.case-section ul {
  list-style: none;
  display: grid;
  gap: 0.9rem;
  max-width: 54rem;
}

.case-section ul li {
  padding: 1.1rem 1.4rem;
  border: 1px solid var(--glass-edge);
  border-radius: 0.9rem;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  color: var(--text-dim);
}

.case-section ul li strong { color: var(--text); font-weight: 600; }

.case-flow {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
  max-width: 54rem;
}

.case-flow__step {
  padding: 1.5rem;
  border: 1px solid var(--glass-edge);
  border-radius: 1rem;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
}

.case-flow__step h3 {
  font-size: 1rem;
  margin-bottom: 0.5rem;
  color: var(--text);
}

.case-flow__step p { font-size: 0.9rem; color: var(--text-dim); }

.case-outcomes {
  margin-top: 1.75rem;
  color: var(--text);
  max-width: 54rem;
}

.case-related {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
}

.case-related a {
  color: var(--cyan);
  text-decoration: none;
  font-size: 0.8rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  border: 1px solid var(--glass-edge);
  border-radius: 2rem;
  padding: 0.55rem 1.2rem;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
}

.case-related a:hover { border-color: var(--cyan); }

/* ---------- selected cases index (section #3) ---------- */

.case-index {
  padding: clamp(5rem, 12vh, 9rem) clamp(1.5rem, 6vw, 5rem);
  max-width: 78rem;
  margin: 0 auto;
}

.case-index__heading {
  font-size: clamp(1.8rem, 4vw, 2.8rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 0.9rem;
}

.case-index__lead {
  color: var(--text-dim);
  max-width: 40rem;
  margin-bottom: 3rem;
}

.case-index__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

.glass--index {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
  position: relative;
  overflow: hidden;
}

.glass--index::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 100% 0%, rgba(139, 92, 246, 0.14), transparent 55%);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.glass--index:hover::before { opacity: 1; }

.glass--index h3 { margin-top: 0.2rem; }

.glass--index p { flex: 1; }

/* ---------- case sub-page rich blocks ---------- */

.case-lead {
  color: var(--text) !important;
  font-size: clamp(1.05rem, 1.6vw, 1.2rem);
  max-width: 54rem;
  line-height: 1.7;
}

.case-note {
  margin-top: 1.4rem;
  color: var(--text-dim);
  max-width: 54rem;
}

.case-feature {
  border-left: 2px solid var(--violet);
  padding-left: clamp(1.5rem, 6vw, 5rem);
}

.case-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1.4rem;
  max-width: 54rem;
}

.case-chips span {
  font-size: 0.82rem;
  color: var(--text);
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--glass-edge);
  border-radius: 2rem;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  transition: border-color 0.3s ease, color 0.3s ease;
}

.case-chips span:hover {
  border-color: rgba(34, 211, 238, 0.5);
  color: var(--cyan);
}

.case-quotes {
  display: grid;
  gap: 0.9rem;
  margin-top: 1.4rem;
  max-width: 54rem;
}

.case-quotes blockquote {
  margin: 0;
  padding: 1rem 1.4rem;
  border: 1px solid var(--glass-edge);
  border-left: 2px solid var(--cyan);
  border-radius: 0.4rem 0.9rem 0.9rem 0.4rem;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  color: var(--text);
  font-style: italic;
}

.case-next {
  max-width: 64rem;
  margin: 0 auto;
  padding: clamp(2rem, 5vh, 3.5rem) clamp(1.5rem, 6vw, 5rem) clamp(4rem, 8vh, 6rem);
}

.case-next a {
  display: inline-block;
  color: var(--violet);
  text-decoration: none;
  font-size: 0.82rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.9rem 1.5rem;
  border: 1px solid var(--glass-edge);
  border-radius: 2rem;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  transition: border-color 0.3s ease, transform 0.3s ease;
}

.case-next a:hover {
  border-color: rgba(139, 92, 246, 0.5);
  transform: translateX(4px);
}

/* ---------- vision ---------- */

.vision {
  min-height: 80vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 6rem clamp(1.5rem, 5vw, 4rem);
}

.vision__title {
  font-size: clamp(2.6rem, 8vw, 6rem);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.03em;
  background: linear-gradient(120deg, var(--cyan), #fff 55%, var(--violet));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  padding-bottom: 13px;
}

.vision__copy {
  margin-top: 2rem;
  max-width: 36rem;
  color: var(--text-dim);
  font-size: clamp(1rem, 2vw, 1.2rem);
}

/* ---------- footer ---------- */

.site-footer {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2.5rem;
  justify-content: space-between;
  align-items: baseline;
  padding: 2.5rem clamp(1.5rem, 6vw, 5rem);
  border-top: 1px solid var(--glass-edge);
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  color: var(--text-dim);
}

/* ---------- responsive ---------- */

@media (max-width: 56rem) {
  .caps__grid { grid-template-columns: 1fr; }
  .cases__grid { grid-template-columns: 1fr; }
  .case-index__grid { grid-template-columns: 1fr; }
  .case-flow { grid-template-columns: 1fr; }
  .journey__layout {
    grid-template-columns: 1fr;
    padding-left: clamp(3rem, 12vw, 5rem);
    padding-right: 1.5rem;
  }
  .journey__stagewrap { display: none; }
  .site-nav { gap: 1rem; }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .mesh { display: none; }
  .aurora { animation: none; }
  .hero__scroll span { animation: none; }
  /* .hero__bg-layer keeps its opacity cross-fade (≥1s, exempted by the root AGENTS.md
     carve-out), but the zoom is a transform, so it is disabled here. The selector must
     match .is-zooming's specificity to beat it. */
  .hero__bg-layer.is-zooming { animation: none; transform: none; }
  /* the wave is pure motion with no static equivalent — remove it outright rather than
     freezing a ring mid-expansion on screen */
  .hero__wave { display: none; }
  .scene__panel { opacity: 1; transform: none; transition: none; }
  .stage__layer { transition: none; }
  .scene__visual span { animation: none; opacity: 0.8; transform: none; }
  .scene__visual--act span { transform: translate(var(--rx), var(--ry)); opacity: 0.8; }
  .glass { transition: none; }
  .glass__cta { opacity: 1; }
  .beam-card::before { animation: none; }
  .node--core, .node--new { animation: none; }
  .node--core { box-shadow: 0 0 22px rgba(255, 102, 0, 0.6), inset 0 0 10px rgba(150, 55, 0, 0.5); }
  .diagram__links i::before { animation: none; display: none; }
  .diagram__loop { animation: none; }
  .diagram__loop::before { display: none; }
}
