/* ==========================================================================
   Sous — presentation page styles (index.html)
   --------------------------------------------------------------------------
   Layout + player chrome for the GSAP-driven presentation. Every color, font,
   spacing value, radius and transition comes from the tokens in main.css.
   ========================================================================== */

/* ----- Page frame ---------------------------------------------------------- */
html,
body {
  height: 100%;
}

body {
  overflow: hidden;
}

.player {
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* ----- Stage & scenes ------------------------------------------------------- */
.stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  /* The Observer scrubs touch gestures here while paused */
  touch-action: none;
}

.scene {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--sous-space-l);
  overflow: hidden;
  /* All scenes except the intro start hidden (GSAP takes over via autoAlpha) */
  opacity: 0;
  visibility: hidden;
}

.scene[data-scene="intro"] {
  opacity: 1;
  visibility: visible;
}

.scene-inner {
  width: 100%;
  max-width: 46rem;
}

/* While scrub mode is active, pointer-dragging must not select scene text */
.player.is-scrubbable .stage {
  user-select: none;
}

/* ----- Scene typography ------------------------------------------------------ */
/* Intro logo (replaces the old "Sous" text mark). Two theme-specific assets
   swap with the color scheme, same pattern as the theme-toggle icons. */
.scene-logo {
  display: block;
  height: clamp(8rem, 48vh, 32rem);
  margin: 0 auto var(--sous-space-m);
}

.scene-logo img {
  display: block;
  width: auto;
  height: 100%;
  margin: 0 auto;
}

.scene-logo .logo-dark { display: none; }

html[data-sous-theme="dark"] .scene-logo .logo-light { display: none; }
html[data-sous-theme="dark"] .scene-logo .logo-dark { display: block; }

@media (prefers-color-scheme: dark) {
  html:not([data-sous-theme="light"]) .scene-logo .logo-light { display: none; }
  html:not([data-sous-theme="light"]) .scene-logo .logo-dark { display: block; }
}

/* Slide-type pills inside problem-slide kickers. Unobtrusive: transparent
   background, border and text in the kicker's own color (inherited green via
   currentColor); the pill-<type> classes remain on the markup for future use. */
.kicker .pill {
  display: inline-block;
  padding: 0 var(--sous-space-s);
  font-family: var(--sous-font-family-base);
  font-size: var(--sous-font-size-xs);
  font-weight: var(--sous-font-weight-bold);
  letter-spacing: 0.08em;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: var(--sous-border-radius-xxl);
  vertical-align: middle;
}

/* Problem kickers stack two lines: "Problem #<x> (pill)" / brief. Tighter
   tracking than the base kicker; the brief carries a whole sentence. */
.kicker-problem {
  letter-spacing: 0.12em;
}

/* Line 1: "Problem #<x> (pill)"; line 2: the brief */
.kicker-problem .kicker-brief {
  display: block;
  margin-top: var(--sous-space-xs);
}

.kicker-problem .pill {
  margin-left: var(--sous-space-s);
}


.mark,
.kicker {
  font-family: var(--sous-font-family-monospace);
  font-size: var(--sous-font-size-s);
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: var(--sous-primary);
  margin-bottom: var(--sous-space-m);
}

.scene-title {
  font-size: clamp(var(--sous-h2), 6vw, var(--sous-h1));
  letter-spacing: -0.02em;
  margin-bottom: var(--sous-space-m);
}

.scene[data-scene="intro"] .scene-title {
  font-size: clamp(var(--sous-h1), 8vw, var(--sous-font-size-xxl));
}

/* Emphasized words in titles: subtle color shift to the brand green */
.scene-title em {
  color: var(--sous-primary);
}

.scene-title .cursor {
  display: inline-block;
  width: 0.08em;
  margin-left: 0.06em;
  background: var(--sous-primary);
  animation: blink 1.1s steps(1) infinite;
}

@keyframes blink {
  50% { opacity: 0; }
}

.lead {
  font-size: var(--sous-font-size-l);
  color: var(--sous-body-text-muted);
  margin-bottom: var(--sous-space-m);
  /* Distribute words so lines break near-equal in length — no orphan words */
  text-wrap: balance;
}

.lead strong,
.lead code {
  color: var(--sous-body-text);
}

/* Terminal-prompt motif */
.prompt {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--sous-font-family-monospace);
  padding: var(--sous-space-s) var(--sous-space-m);
  margin-bottom: var(--sous-space-m);
}

.prompt .dollar {
  color: var(--sous-primary);
  user-select: none;
}

/* Give the install command room to breathe between the text above it and
   the button below it (intro and outro share the treatment) */
.scene[data-scene="intro"] .prompt,
.scene[data-scene="outro"] .prompt {
  margin-top: var(--sous-space-m);
  margin-bottom: var(--sous-space-l);
}

/* Followup scene: typed lines stack; each keeps its own hopping cursor */
.followup-typer .type-line {
  display: block;
  min-height: 1.2em;
}

.followup-desc {
  margin-top: var(--sous-space-l);
}

/* Side-by-side CTA buttons (outro) */
.btn-row {
  display: flex;
  justify-content: center;
  gap: var(--sous-space-s);
}

/* The outro's logo is a smaller reprise of the intro's */
.scene[data-scene="outro"] .scene-logo {
  height: clamp(6rem, 20vh, 12rem);
}

/* The Helm one-liner sits below the features grid */
.features-tagline {
  margin-top: var(--sous-space-l);
}

/* ----- Orbit diagram (aggregator scene) -------------------------------------- */
.orbit-diagram {
  display: block;
  width: 100%;
  max-width: 40rem;
  height: auto;
  margin: var(--sous-space-m) auto 0;
}

.orbit-diagram text {
  font-family: var(--sous-font-family-base);
  font-size: 15px;
  font-weight: var(--sous-font-weight-semibold);
  text-anchor: middle;
  dominant-baseline: central;
}

/* Flow lines: green dashes marching toward the center circle. The march is
   driven by GSAP (see presentation.js), NOT a CSS keyframe: stroke-dashoffset
   animation is paint-bound and freezes on some machines. */
.orbit-lines line {
  stroke: var(--sous-primary);
  stroke-width: 2;
  stroke-dasharray: 6 6;
  marker-end: url(#flowArrow);
}

#flowArrow path {
  fill: var(--sous-primary);
}

/* Repo nodes: flat bordered tiles, circle edition */
.orbit-node circle {
  fill: var(--sous-bg-tile);
  stroke: var(--sous-border-medium);
  stroke-width: 2;
}

.orbit-node text {
  fill: var(--sous-body-text);
  font-size: 13px;
}

/* Public repos stand out: dark blue fill, white label */
.orbit-node circle.node-public {
  fill: var(--sous-blue-800);
  stroke: var(--sous-blue-600);
}

.orbit-node text.node-public-label {
  fill: var(--sous-white);
}

/* The project: same tile treatment, but green (the interactive voice) */
.orbit-center circle {
  fill: var(--sous-bg-tile);
  stroke: var(--sous-primary);
  stroke-width: 2.5;
}

.orbit-center text {
  fill: var(--sous-primary);
}

/* ----- Flow diagrams (solution scenes) ------------------------------------------
   A source box fans out to destination boxes over green dashed flow lines
   (same marching-dash motif as the orbit diagram). Each SVG carries its OWN
   arrow-marker id (ids are document-global); lines reference it via their
   marker-end attribute. */
.flow-diagram {
  display: block;
  width: 100%;
  max-width: 40rem;
  height: auto;
  margin: var(--sous-space-m) auto 0;
}

.flow-lines line {
  stroke: var(--sous-primary);
  stroke-width: 2;
  stroke-dasharray: 6 6;
}

.flow-diagram marker path {
  fill: var(--sous-primary);
}

/* Boxes: flat bordered tiles, SVG edition */
.flow-node rect {
  fill: var(--sous-bg-tile);
  stroke: var(--sous-border-medium);
  stroke-width: 2;
}

.flow-node text {
  font-family: var(--sous-font-family-base);
  font-size: 15px;
  font-weight: var(--sous-font-weight-semibold);
  text-anchor: middle;
  dominant-baseline: central;
  fill: var(--sous-body-text);
}

.flow-node text.flow-path {
  font-family: var(--sous-font-family-monospace);
  font-size: 12px;
  font-weight: var(--sous-font-weight-normal);
  fill: var(--sous-body-text-muted);
}

/* The Sous engine box: solid green, white label */
.flow-node.flow-engine rect {
  fill: var(--sous-primary);
  stroke: var(--sous-brand-tertiary);
}

.flow-node.flow-engine text {
  fill: var(--sous-white);
}

/* The source box speaks green, like the orbit center */
.flow-node.flow-src rect {
  stroke: var(--sous-primary);
  stroke-width: 2.5;
}

.flow-node.flow-src text {
  fill: var(--sous-primary);
}

.flow-node.flow-src text.flow-path {
  fill: var(--sous-body-text-muted);
}

/* ----- Code window (templates scene, VS Code-like) ---------------------------- */
/* Template + output panes overlap in one grid cell; the timeline crossfades
   between them (sub-scenes), which frees room for a larger code font. */
.code-stack {
  display: grid;
  max-width: 44rem;
  margin: var(--sous-space-m) auto 0;
}

.code-stack .code-window {
  grid-area: 1 / 1;
  align-self: start;
  width: 100%;
}

/* overflow stays VISIBLE so callout tooltips can extend past the window
   edges; the titlebar rounds its own top corners instead. Long code lines
   must therefore fit the window (no horizontal scroll). */
.code-window {
  text-align: left;
  background: var(--sous-editor-bg);
  border: 1px solid var(--sous-editor-border);
  border-radius: var(--sous-tile-radius);
}

.code-titlebar {
  display: flex;
  align-items: center;
  gap: var(--sous-space-s);
  padding: var(--sous-space-s) var(--sous-space-m);
  background: var(--sous-editor-chrome);
  border-bottom: 1px solid var(--sous-editor-border);
  border-radius: calc(var(--sous-tile-radius) - 1px) calc(var(--sous-tile-radius) - 1px) 0 0;
}

.code-dot {
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 50%;
  background: var(--sous-editor-muted);
  opacity: 0.55;
}

.code-tab {
  margin-left: var(--sous-space-s);
  font-family: var(--sous-font-family-monospace);
  font-size: var(--sous-font-size-s);
  color: var(--sous-editor-muted);
}

.code-body {
  margin: 0;
  padding: var(--sous-space-m);
  overflow: visible; /* tooltips may extend beyond the window */
  background: none;
  border: 0;
  border-radius: 0;
  font-size: var(--sous-font-size-base);
  line-height: 1.7;
  color: var(--sous-editor-text);
}

.code-body .tok-liquid { color: var(--sous-editor-keyword); }
.code-body .tok-var { color: var(--sous-editor-variable); }
.code-body .tok-str { color: var(--sous-editor-string); }
.code-body .tok-fn { color: var(--sous-editor-function); }
.code-body .tok-md { color: var(--sous-editor-heading); }
.code-body .tok-dim { color: var(--sous-editor-muted); }

/* ----- Timeline-synced highlights + tooltips (code windows) -------------------
   GSAP fades .hl-bg / .hl-tip in and out during a scene's hold; colors live
   here so the JS only ever animates opacity. */
.hl {
  position: relative;
  z-index: 0;
}

/* Multi-line highlights: a fragmented inline's abspos reference box ends at
   the LAST fragment's right edge (e.g. a short `{% endif %}`), truncating the
   .hl-bg. inline-block makes the span a real box sized to its longest line. */
.hl-block {
  display: inline-block;
}

.hl-bg {
  position: absolute;
  inset: -2px -4px;
  z-index: -1;
  background: rgba(81, 177, 62, 0.22);
  border: 1px solid var(--sous-hl-outline);
  box-shadow: var(--sous-hl-glow);
  border-radius: var(--sous-border-radius);
  opacity: 0;
}

.hl-tip {
  position: absolute;
  bottom: calc(100% + 16px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 10; /* above the code windows */
  padding: var(--sous-space-s) var(--sous-space-m);
  font-family: var(--sous-font-family-base);
  font-size: var(--sous-font-size-l);
  font-weight: var(--sous-font-weight-normal);
  width: max-content;
  max-width: 26rem;
  text-align: center;
  text-wrap: balance;
  color: var(--sous-black);
  /* Metal-plate sheen layered over the brand green */
  background: var(--sous-metal-sheen), var(--sous-primary);
  border: 1px solid var(--sous-brand-tertiary);
  border-radius: var(--sous-border-radius);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35),
    inset 0 -1px 0 rgba(0, 0, 0, 0.15);
  opacity: 0;
  pointer-events: none;
}

/* Arrow from the tooltip down to the highlighted code (bordered triangle) */
.hl-tip::before,
.hl-tip::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 8px solid transparent;
  border-top-color: var(--sous-brand-tertiary);
  border-bottom-width: 0;
}

.hl-tip::after {
  border-width: 7px 7px 0;
  border-top-color: var(--sous-primary);
  margin-top: -1.5px;
}

/* Card grid used by the "features", alternatives and "speed-mitigation" scenes
   (side-by-side code windows use it too; also the retired
   "problems"/"how" scenes) */
.scene-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sous-space-m);
  margin-top: var(--sous-space-l);
  text-align: left;
}

/* Stacked variant: one tile per row, centered column */
.scene-grid-stack {
  grid-template-columns: 1fr;
  max-width: 36rem;
  margin-left: auto;
  margin-right: auto;
}

.scene-card {
  padding: var(--sous-space-m);
}

.scene-card h3 {
  font-size: var(--sous-font-size-base);
  margin-bottom: var(--sous-space-xs);
  color: var(--sous-primary);
}

/* Lucide icons in card headings (stroke follows the heading's green) */
.scene-card h3 svg.card-icon {
  width: 1.125em;
  height: 1.125em;
  margin-right: var(--sous-space-s);
  vertical-align: -0.2em;
}

.scene-card p {
  margin: 0;
  color: var(--sous-body-text-muted);
}

/* Bullet list used by the "non-goals" scene */
.scene-list {
  display: inline-block;
  margin: var(--sous-space-m) auto 0;
  padding-left: var(--sous-space-l);
  text-align: left;
  max-width: 36rem;
}

.scene-list li {
  margin-bottom: var(--sous-space-s);
}

.scene-list li::marker {
  color: var(--sous-primary);
}

/* Prominent play button on the title scene */
.intro-play {
  display: inline-flex;
  align-items: center;
  gap: var(--sous-space-s);
  font-size: var(--sous-font-size-l);
  padding: var(--sous-space-s) var(--sous-space-l);
}

.intro-play svg {
  width: 1em;
  height: 1em;
}

/* ----- Player controls (bottom bar) ------------------------------------------ */
.player-controls {
  /* starts hidden (revealed by the intro-exit tween); CSS-hidden so it never
     flashes before the scripts run */
  opacity: 0;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--sous-space-m);
  padding: var(--sous-space-s) var(--sous-space-m);
  background: var(--sous-bg-tile);
  border-top: 1px solid var(--sous-border-medium);
}

.playpause {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  background: var(--sous-bg-tile);
  color: var(--sous-primary);
  border: 1px solid var(--sous-border-medium);
  border-radius: var(--sous-border-radius);
  cursor: pointer;
  transition: color var(--sous-transition-fast) ease,
    border-color var(--sous-transition-fast) ease;
}

.playpause:hover {
  border-color: var(--sous-primary);
}

.playpause:focus-visible {
  outline: none;
  box-shadow: var(--sous-focus-ring);
}

.playpause svg {
  width: 1rem;
  height: 1rem;
}

.playpause .icon-pause { display: none; }
.player.is-playing .playpause .icon-pause { display: block; }
.player.is-playing .playpause .icon-play { display: none; }

.timeline {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sous-space-xs);
}

/* Elapsed/remaining counters flank the scrub slider */
.scrub-row {
  display: flex;
  align-items: center;
  gap: var(--sous-space-s);
}

.scrub-row .scrub {
  flex: 1 1 auto;
  width: auto;
}

.time-badge {
  flex: 0 0 auto;
  min-width: 2.5rem;
  font-family: var(--sous-font-family-monospace);
  font-size: var(--sous-font-size-xs);
  color: var(--sous-body-text-muted);
  text-align: center;
}

/* Scrub slider: accessible core of the chapter bar */
.scrub {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 0.25rem;
  margin: var(--sous-space-xs) 0;
  padding: 0;
  border: 0;
  border-radius: var(--sous-border-radius);
  background: linear-gradient(
    to right,
    var(--sous-primary) var(--fill, 0%),
    var(--sous-border-medium) var(--fill, 0%)
  );
  cursor: pointer;
}

.scrub::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 0.875rem;
  height: 0.875rem;
  border: 0;
  border-radius: 50%;
  background: var(--sous-primary);
}

.scrub::-moz-range-thumb {
  width: 0.875rem;
  height: 0.875rem;
  border: 0;
  border-radius: 50%;
  background: var(--sous-primary);
}

.scrub:focus-visible {
  outline: none;
  box-shadow: var(--sous-focus-ring);
}

/* Named segments (widths set from timeline label durations by JS). Two rows:
   groups on top, the ACTIVE group's scenes below. */
.scene-segments {
  display: flex;
  gap: var(--sous-space-xs);
}

.scene-segments-sub .scene-btn {
  padding: var(--sous-space-xxs) var(--sous-space-xs);
  font-size: var(--sous-font-size-xs);
  font-weight: var(--sous-font-weight-normal);
}

.scene-btn {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  padding: var(--sous-space-xs) var(--sous-space-s);
  font-size: var(--sous-font-size-s);
  font-weight: var(--sous-font-weight-semibold);
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--sous-body-text-muted);
  background: var(--sous-bg-tile);
  border: 1px solid var(--sous-border-medium);
  border-radius: var(--sous-border-radius);
  cursor: pointer;
  transition: color var(--sous-transition-fast) ease,
    border-color var(--sous-transition-fast) ease;
}

.scene-btn:hover {
  color: var(--sous-primary);
  border-color: var(--sous-primary);
}

.scene-btn:focus-visible {
  outline: none;
  box-shadow: var(--sous-focus-ring);
}

.scene-btn[aria-current="true"] {
  color: var(--sous-primary);
  border-color: var(--sous-primary);
}

/* Per-scene progress fill (scaleX set by JS) */
.scene-btn-fill {
  position: absolute;
  inset: 0;
  background: var(--sous-success-dim-bg);
  transform: scaleX(0);
  transform-origin: left center;
}

.scene-btn-title {
  position: relative;
}

/* The corner-button chrome (.repo-link, .npm-link, .theme-toggle) lives in
   the shared css/chrome.css; this page arranges [speed] [theme] [GitHub]
   [npm] top-right, plus the top-LEFT "Documentation" text link (.docs-link). */

/* ----- Speed control (next to the theme toggle) --------------------------------- */
.speed-control {
  /* starts hidden (revealed by the intro-exit tween); no pre-script flash */
  opacity: 0;
  position: fixed;
  top: var(--sous-space-m);
  right: calc(var(--sous-space-m) + 3 * (2.5rem + var(--sous-space-s)));
  z-index: 10;
  display: flex;
  align-items: center;
  gap: var(--sous-space-xs);
  height: 2.5rem;
  padding: 0 var(--sous-space-s);
  background: var(--sous-bg-tile);
  border: 1px solid var(--sous-border-medium);
  border-radius: var(--sous-border-radius);
}

.speed-label {
  font-size: var(--sous-font-size-s);
  font-weight: var(--sous-font-weight-semibold);
  color: var(--sous-body-text-muted);
  margin-right: var(--sous-space-xs);
}

.speed-btn {
  padding: var(--sous-space-xs) var(--sous-space-s);
  font-size: var(--sous-font-size-s);
  font-weight: var(--sous-font-weight-semibold);
  color: var(--sous-body-text-muted);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--sous-border-radius);
  cursor: pointer;
  transition: color var(--sous-transition-fast) ease,
    border-color var(--sous-transition-fast) ease;
}

.speed-btn:hover {
  color: var(--sous-primary);
}

.speed-btn:focus-visible {
  outline: none;
  box-shadow: var(--sous-focus-ring);
}

.speed-btn[aria-pressed="true"] {
  color: var(--sous-primary);
  border-color: var(--sous-primary);
  background: var(--sous-success-dim-bg);
}

/* ----- Sad/happy effects (status-quo vs mitigation/example slides) -------------
   REMOVABLE AS A UNIT: this section, the .fx-* markup in index.html, and the
   "Sad/happy effects" section of presentation.js.
   The stage desaturates for the sad effect via --fx-gray (GSAP animates it). */
.stage {
  --fx-gray: 0;
  /* full desaturation plus a slight dim as the sad effect takes hold */
  filter: grayscale(var(--fx-gray)) brightness(calc(1 - var(--fx-gray) * 0.07));
}

/* Sad-effect gloom: faint diagonal rain (behind the scenes) and an edge
   vignette (above them). Both fade in with the sad transition; the slight
   dim rides --fx-gray in the .stage filter above. */
/* Rain: JS-built DOM drops, each tweened by GSAP on transform only (the
   compositor-safe property; the previous background-position approach was
   paint-bound and Chromium throttles it under window occlusion). Drops live
   in a wrapper carrying ONE static tilt so the fall slants without per-drop
   rotation. Reduced motion: no drops are built at all. */
.fx-rain {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: strict;
  opacity: 0;
}

.fx-rain-drops {
  position: absolute;
  inset: -15% -10%;
  transform: rotate(8deg);
}

.fx-rain .drop {
  position: absolute;
  top: -12%;
  width: 1px;
  height: 10vh;
  background: linear-gradient(to bottom, transparent, var(--sous-fx-rain));
  will-change: transform;
}

.fx-rain .drop-far {
  height: 6vh;
}

.fx-gloom {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  opacity: 0;
  background: var(--sous-fx-gloom);
}

/* Corner ribbons: rotated strips crossing the bottom-right corner; the stage's
   overflow clips them. GSAP owns their transform (rotation + fly-in offset). */
.fx-banner {
  position: absolute;
  right: -84px;
  bottom: 48px;
  z-index: 6;
  width: 320px;
  padding: var(--sous-space-s) 0;
  text-align: center;
  font-size: var(--sous-font-size-base);
  font-weight: var(--sous-font-weight-bold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  pointer-events: none;
  opacity: 0;
}

/* Both tokens flip with the theme, so text always contrasts the strip:
   light mode is near-black bg + near-white text; dark mode inverts. */
.fx-banner-sad {
  background: var(--sous-neutral-800);
  color: var(--sous-neutral-100);
}

.fx-banner-happy {
  background: var(--sous-blue-600);
  color: var(--sous-white);
}

/* The happy-effect sky: a blue-tinted backdrop, a soft orb (sun in light mode,
   moon in dark, via the --sous-fx-* tokens) and three drifting clouds, all
   behind the scenes. The tint fades; the orb and clouds FLY in and out (GSAP
   moves the .fx-cloud-wrap/.fx-orb transforms, so the ambient CSS drift lives
   on the inner .fx-cloud where the two never fight). */
.fx-sky {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.fx-sky-tint {
  position: absolute;
  inset: 0;
  background: var(--sous-fx-sky-tint);
  opacity: 0;
}

.fx-orb {
  position: absolute;
  top: 10%;
  right: 14%;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: var(--sous-fx-orb-core);
  box-shadow: 0 0 80px 30px var(--sous-fx-orb-glow);
  /* GSAP fades this up to 0.55 during the happy transition */
  opacity: 0;
}

.fx-cloud-wrap {
  position: absolute;
  opacity: 0; /* GSAP reveals with the fly-in */
}

.fx-cloud-wrap-1 { top: 16%; left: 8%; width: 220px; height: 44px; }
.fx-cloud-wrap-2 { top: 30%; right: 22%; width: 170px; height: 36px; }
.fx-cloud-wrap-3 { top: 8%; left: 42%; width: 140px; height: 30px; }

.fx-cloud,
.fx-cloud::before,
.fx-cloud::after {
  position: absolute;
  background: var(--sous-fx-cloud);
  border-radius: 999px;
}

.fx-cloud {
  inset: 0;
}

.fx-cloud::before,
.fx-cloud::after {
  content: "";
}

.fx-cloud-1 { animation: fx-drift 53s ease-in-out infinite alternate; }
.fx-cloud-2 { animation: fx-drift 71s ease-in-out infinite alternate-reverse; }
.fx-cloud-3 { animation: fx-drift 89s ease-in-out infinite alternate; }

/* two puffs give each pill a cloud silhouette */
.fx-cloud::before { width: 45%; height: 160%; left: 18%; bottom: 30%; }
.fx-cloud::after { width: 34%; height: 120%; right: 20%; bottom: 45%; }

@keyframes fx-drift {
  from { transform: translateX(-48px); }
  to { transform: translateX(48px); }
}

/* ----- Fallbacks & small screens ----------------------------------------------- */
/* If GSAP failed to load, show the title scene statically and hide the player UI */
html.no-gsap .player-controls,
html.no-gsap .speed-control {
  display: none;
}

@media (max-width: 640px) {
  .scene-grid {
    grid-template-columns: 1fr;
    gap: var(--sous-space-s);
  }

  .scene-btn-title {
    display: none;
  }
}

