/*
 * Structural / mechanical CSS only. There are no per-pillar coordinates,
 * colors, or durations hardcoded here — every number and color in the page
 * comes from data.json, applied at runtime by js/render.js either as
 * --custom-property values on :root (tokens: colors, motion, typography,
 * radius, z-index) or as inline left/top/width/height/transform on each
 * element it creates (geometry). This file only says HOW those values are
 * used (flex layout, transitions referencing var(--motion-*), :hover
 * selectors), never WHAT the values are.
 */

*, *::before, *::after { box-sizing: border-box; }

/* Embed rules (Webflow iframe): transparent page, no viewport-height floor,
   no vertical padding. The resize script in index.html reports the natural
   content height to the host page, so the page must be able to shrink. */
html, body {
  margin: 0;
  background: transparent;
  font-family: var(--font-family);
  color: var(--color-white);
}

.page {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
}

.stage-scroll {
  width: 100%;
}

/*
 * .stage is the data.json `stage` composition (1693 x 1271 by default).
 * container-type:inline-size + cqw units let every absolute child scale
 * fluidly and in lock-step (both x and y use the SAME width-based
 * reference, because the stage's aspect-ratio is locked, so 100cqw always
 * corresponds to a fixed height too). This reproduces the Figma frame as a
 * scalable vector-like composition while staying real, selectable HTML text.
 */
.stage {
  position: relative;
  width: min(100%, calc(var(--stage-w) * 1px));
  aspect-ratio: var(--stage-w) / var(--stage-h);
  margin-inline: auto;
  background: transparent;
  overflow: hidden;
  border-radius: 4px;
  container-type: inline-size;
  isolation: isolate;
}

.ring, .hub, .pillar {
  position: absolute;
}

/* ---------- Center connecting ring ---------- */

.ring {
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-ring);
  opacity: 0.9;
  transition: opacity var(--motion-default) var(--ease-standard);
}

/* Continuous idle rotation — separate from .ring (entrance fade/scale) and
   .ring__spin (the static per-arc alignment transform) so the three don't
   fight over the `transform` property. */
.ring__loop {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: ring-spin var(--ring-rotation-s) linear infinite;
}

@keyframes ring-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.ring__spin {
  position: relative;
}

.ring__arc {
  position: absolute;
}
.ring__arc img { display: block; width: 100%; height: 100%; }

/* ---------- Hub (center title) ---------- */

.hub {
  padding: calc(18 / var(--stage-w) * 100cqw);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-hub);
  text-align: center;
}

.hub__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(18 / var(--stage-w) * 100cqw);
}

.hub__title {
  margin: 0;
  font-weight: var(--fw-hub-title);
  font-size: var(--fs-hub-title);
  line-height: var(--lh-hub-title);
  letter-spacing: var(--ls-hub-title);
  color: var(--color-yellow);
  text-transform: capitalize;
}

.hub__desc {
  margin: 0;
  font-weight: var(--fw-body1);
  font-size: var(--fs-body1);
  line-height: var(--lh-body1);
  color: var(--color-white-80);
}

/* ---------- Pillar (one of the 4 capability nodes) ---------- */

.pillar { z-index: var(--z-deco); }

.pillar__deco {
  position: absolute;
  cursor: pointer;
}

.pillar__icon {
  position: absolute;
  width: calc(102.629 / var(--stage-w) * 100cqw);
  height: calc(102.629 / var(--stage-w) * 100cqw);
  border-radius: var(--radius-icon);
  background: var(--color-on-secondary);
  border: calc(10 / var(--stage-w) * 100cqw) solid var(--color-yellow);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  z-index: var(--z-icon);
  cursor: pointer;
  padding: 0;
  /* Bounce: the lift overshoots past its resting position and springs back,
     using a "back ease out" curve instead of a smooth/linear one. Starts
     moving the instant hover/focus begins — the spring character comes from
     the easing curve, not from a delay. */
  transition: top var(--motion-bounce) var(--ease-bounce),
              box-shadow var(--motion-bounce) var(--ease-bounce);
  box-shadow: 0px 4px 84px 0px rgba(238, 255, 64, 0);
}
.pillar__icon img { width: 54%; height: 54%; display: block; }

/* Active icon: exact Figma box-shadow; the hover TARGET position comes from
   --hover-top, set per-icon by render.js from data.json pillars[].icon.hoverTop. */
.pillar:hover .pillar__icon,
.pillar:focus-within .pillar__icon,
.pillar.is-active .pillar__icon {
  top: var(--hover-top);
  box-shadow: 0px 4px 84px 0px rgba(238, 255, 64, 1);
}

.pillar__chip {
  position: absolute;
  width: calc(298.8 / var(--stage-w) * 100cqw);
  height: calc(87.6 / var(--stage-w) * 100cqw);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(21.6 / var(--stage-w) * 100cqw);
  border-radius: var(--radius-chip);
  background: var(--color-white-10);
  backdrop-filter: blur(calc(12 / var(--stage-w) * 100cqw));
  -webkit-backdrop-filter: blur(calc(12 / var(--stage-w) * 100cqw));
  overflow: hidden;
  z-index: var(--z-chip);
}
/* Chips do not move or recolor on activation — confirmed identical classes
   across all 5 Figma variants — so no hover rule here. */

.pillar__chip p {
  margin: 0;
  font-weight: var(--fw-chip);
  font-size: var(--fs-chip);
  line-height: var(--lh-chip);
  letter-spacing: var(--ls-chip);
  color: var(--color-yellow);
  text-align: center;
}

.pillar__copy {
  position: absolute;
  padding: calc(18 / var(--stage-w) * 100cqw);
  border-radius: var(--radius-copy);
  z-index: var(--z-copy);
  display: flex;
  align-items: flex-start;
  gap: calc(16 / var(--stage-w) * 100cqw);
}

/* Only Cloud's copy block repositions on activation (it sits at the very
   top of the canvas with no headroom to grow downward when its lede line
   appears); render.js adds this modifier class + --copy-hover-top only to
   the pillar(s) whose data.json copy.hoverTop is non-null. */
.pillar__copy--hover-shift {
  transition: top var(--motion-bounce) var(--ease-bounce);
}
.pillar:hover .pillar__copy--hover-shift,
.pillar:focus-within .pillar__copy--hover-shift,
.pillar.is-active .pillar__copy--hover-shift {
  top: var(--copy-hover-top);
}

.pillar__copy-col {
  display: flex;
  flex-direction: column;
  gap: calc(18 / var(--stage-w) * 100cqw);
  width: calc(261 / var(--stage-w) * 100cqw);
}

.pillar__title {
  margin: 0;
  font-weight: var(--fw-h4);
  font-size: var(--fs-h4);
  line-height: var(--lh-h4);
  letter-spacing: var(--ls-h4);
  color: var(--color-yellow);
  text-transform: capitalize;
}

/*
 * Figma authors this copy with `color: transparent` in its default state —
 * it renders invisible in the static screenshot (verified: no bullet text
 * appears in the exported PNG). That is a strong signal the live prototype
 * reveals it on interaction, so it is treated here as a hover/focus/tap
 * reveal. See prototype.json → interactions.
 */
.pillar__lede,
.pillar__list {
  color: transparent;
  transition: color var(--motion-bounce) var(--ease-bounce);
}
.pillar__lede {
  margin: 0 0 calc(6 / var(--stage-w) * 100cqw) 0;
  font-weight: var(--fw-body1);
  font-size: var(--fs-body1);
  line-height: var(--lh-body1);
}
.pillar__list {
  margin: 0;
  padding-left: calc(24 / var(--stage-w) * 100cqw);
  list-style: disc;
  font-weight: var(--fw-body1);
  font-size: var(--fs-body1);
  line-height: var(--lh-body1);
}

.pillar:hover .pillar__lede,
.pillar:focus-within .pillar__lede,
.pillar.is-active .pillar__lede,
.pillar:hover .pillar__list,
.pillar:focus-within .pillar__list,
.pillar.is-active .pillar__list {
  color: var(--color-white-80);
}

/* ---------- Hex sub-shapes (all geometry set inline by render.js) ---------- */

.hex-face, .hex-line, .hex-dot, .hex-rect, .hex-slab {
  position: absolute;
}
.hex-rect img { display: block; width: 100%; height: 100%; }

/*
 * Hex faces and edge lines are INLINE <svg> (not <img src="*.svg">) — this
 * rendering engine drops thin (~2px) SVG strokes along one edge of a
 * rasterized <img> nested under a rotated ancestor; inline SVG stays vector
 * through the rotation/compositing pipeline and doesn't exhibit the bug.
 */
.hex-face { overflow: visible; }
.hex-face svg {
  position: absolute;
  left: 6.7%;
  top: 0;
  width: 86.6%;
  height: 100%;
  overflow: visible;
  display: block;
}

/*
 * Hex "glow" on activation: extracted directly from Figma's Step0X variants.
 * Each hex face's gradient-overlay path animates its opacity — top faces
 * 0 -> 0.8, the front face 0.2 -> 0.7 (values from data.json shared.glowOpacity,
 * applied as --glow-* custom properties on :root).
 */
.hex-face__glow {
  transition: opacity var(--motion-bounce) var(--ease-bounce);
}
.hex-face--top .hex-face__glow { opacity: var(--glow-top-default); }
.hex-face--front .hex-face__glow { opacity: var(--glow-front-default); }
.pillar:hover .hex-face--top .hex-face__glow,
.pillar:focus-within .hex-face--top .hex-face__glow,
.pillar.is-active .hex-face--top .hex-face__glow { opacity: var(--glow-top-active); }
.pillar:hover .hex-face--front .hex-face__glow,
.pillar:focus-within .hex-face--front .hex-face__glow,
.pillar.is-active .hex-face--front .hex-face__glow { opacity: var(--glow-front-active); }

.hex-line { display: flex; align-items: center; justify-content: center; mix-blend-mode: screen; }
.hex-line__inner { position: relative; }
.hex-line__inner svg { display: block; width: 100%; height: 100%; overflow: visible; }

.hex-dot {
  width: calc(8.03 / var(--stage-w) * 100cqw);
  height: calc(8.03 / var(--stage-w) * 100cqw);
  border-radius: 50%;
  background: var(--color-green);
}

.hex-slab { display: flex; align-items: center; justify-content: center; }
.hex-slab__inner img { display: block; width: 100%; height: 100%; }

/* ---------- Entrance choreography (JS adds .is-in-view once visible;
   per-element transition-delay values come from data.json entrance.delaysMs) ---------- */

.hub, .ring { opacity: 0; }
.pillar { opacity: 1; } /* children (deco/icon/chip/copy) carry their own entrance opacity below */
.hub { transform: translateY(14px) scale(0.98); }
.ring { transform: scale(0.94); }
.pillar__deco { opacity: 0; transform: scale(0.9); transition: opacity var(--motion-slow) var(--ease-enter), transform var(--motion-slow) var(--ease-enter); }
.pillar__icon { opacity: 0; transform: scale(0.6); }
.pillar__chip { opacity: 0; transform: translateY(10px); }
.pillar__copy { opacity: 0; transform: translateY(10px); }

.stage.is-in-view .ring {
  opacity: 0.9;
  transform: scale(1);
  transition: opacity var(--motion-slow) var(--ease-enter), transform var(--motion-slow) var(--ease-enter);
}
.stage.is-in-view .hub {
  opacity: 1;
  transform: translateY(0) scale(1);
  transition: opacity var(--motion-default) var(--ease-enter), transform var(--motion-default) var(--ease-enter);
}
.stage.is-in-view .pillar__deco { opacity: 1; transform: scale(1); }
.stage.is-in-view .pillar__icon {
  opacity: 1;
  transform: scale(1);
  transition: opacity var(--motion-default) var(--ease-enter), transform var(--motion-default) var(--ease-enter),
              top var(--motion-bounce) var(--ease-bounce), box-shadow var(--motion-bounce) var(--ease-bounce);
}
.stage.is-in-view .pillar__chip {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-default) var(--ease-enter), transform var(--motion-default) var(--ease-enter);
}
.stage.is-in-view .pillar__copy {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--motion-default) var(--ease-enter), transform var(--motion-default) var(--ease-enter);
}

@media (prefers-reduced-motion: reduce) {
  .hub, .pillar, .ring, .pillar__deco, .pillar__icon, .pillar__chip, .pillar__copy {
    transition: opacity 1ms linear !important;
    transform: none !important;
  }
  .stage.is-in-view * { opacity: 1 !important; }
  .ring__loop { animation: none; }
}

/* ---------- Small screens ----------
   The stage scales down with the iframe width (fluid cqw units), the same
   way the other LEAP infographics do. The old fixed 640px stage inside a
   horizontal scroller was removed: no horizontal scroll at 375px. */
