/* ══ index-features.css — props for the index.html feature scenes ══
   This file DRAWS each scene. The timelines in js/single-page/index-features/
   only MOVE what is drawn here.

   Five laws baked in (scene 1 is the signed-off template, everything copies it):
   1) NO frame, NO plate, NO square. The props float DIRECTLY on the doodle
      wallpaper. The only ground is the soft ellipse shadow under each station,
      which stays put while the art bobs above it: that contrast is the float.
   2) Every scene is the same size, and inside a scene every station is the
      same size, centred on one line. Sizes are in cqw (1% of the scene's own
      width) so one drawing scales 375px to desktop with zero media queries.
   3) Everything inside a station is CENTRED: the art in the square, the logo
      in the art, the chip over the station.
   4) Colors are site tokens only, so every scene re-tints in the 0.55s
      platform morph. The exceptions are third-party brand marks
      (Stripe black, Bitcoin amber, Gmail red), which must stay recognisable.
   5) The CSS state is the END of the story, so with animations off the frozen
      picture still tells it.

   Motion only runs while .scene-live is on the stage (scene-player.js adds it
   when the card is on screen, drops it when it scrolls away). Off screen the
   CSS loops stop too, not just the GSAP ones. */

/* ── the stage: an invisible positioning box, nothing drawn ── */
.scene {
  position: relative;
  aspect-ratio: 16 / 10;
  container-type: inline-size;   /* unlocks cqw for everything inside */
}
/* the old engraved plate, retired everywhere. The div stays in the HTML so no
   scene markup has to change; it just paints nothing. */
.scene-well { display: none; }

/* the one line every station sits on */
.scene-row {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 2cqw;
}

/* ── stations: identical squares, evenly spaced ── */
.sc-station { position: relative; width: 28cqw; aspect-ratio: 1; flex: none; }

/* the ground shadow. It lives on the STATION, not the art, so it stays put
   while the art bobs above it. */
.sc-station::after {
  content: "";
  position: absolute; left: 12%; right: 12%; bottom: -8%;
  height: 12%;
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(23, 24, 29, 0.16), transparent 70%);
}

/* outer bob (CSS) and inner art (GSAP) are split on purpose: two animators
   fighting over one transform is the classic way this breaks */
.sc-bob { width: 100%; height: 100%; }
.scene-live .sc-bob { animation: sc-bob 5.5s ease-in-out infinite; }
.scene-live .sc-bob-b { animation-duration: 6.4s; animation-delay: -1.8s; }
.scene-live .sc-bob-c { animation-duration: 5.9s; animation-delay: -3.2s; }
@keyframes sc-bob { 50% { transform: translateY(-3.4%); } }

.sc-art { position: relative; width: 100%; height: 100%; }
.sc-svg { width: 100%; height: 100%; overflow: visible; display: block; }

/* ── shared SVG paint, all token-driven ── */
.sc-svg .card { fill: var(--panel); stroke: var(--line); stroke-width: 2; }
.sc-svg .ink { fill: var(--ink); }
.sc-svg .soft { fill: var(--line); }
.sc-svg .accent { fill: var(--blurple); transition: fill 0.55s ease; }
.sc-svg .tint { fill: var(--blurple-tint); transition: fill 0.55s ease; }
.sc-svg .vent { stroke: var(--line); stroke-width: 2.6; stroke-linecap: round; }
.sc-svg .drop { filter: drop-shadow(0 4px 8px rgba(23, 24, 29, 0.1)); }
/* status badges: green = good news, red = pain only (declines) */
.sc-svg .badge-green { fill: var(--green); }
.sc-svg .badge-red { fill: var(--red); }
.sc-svg .mark { fill: none; stroke: #fff; stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round; }

/* ── the chips that carry the words ──
   The SLOT positions (dead centre over its own station), the CHIP animates. */
.sc-chip-slot {
  position: absolute; left: 50%;
  transform: translateX(-50%);
  width: max-content;
  display: flex; justify-content: center;
  pointer-events: none;
}
.sc-chip-slot.above { bottom: calc(100% + 9%); }
.sc-chip-slot.below { top: calc(100% + 9%); }
.sc-chip {
  display: inline-flex; align-items: center; gap: 1.2cqw;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 99px;
  box-shadow: var(--shadow);
  font-size: max(9px, 2.9cqw); font-weight: 700; color: var(--ink);
  padding: 1.4cqw 2.6cqw;
  white-space: nowrap;
}
.sc-chip .ok { color: var(--green); font-style: normal; }
.sc-chip .no { color: var(--red); font-style: normal; }

/* ── the couriers ──
   A walker is whatever GSAP drives across the scene. Greetster's version:
   him centred and big, the thing he carries riding at his side so one tween
   moves both. Scene 2 and 5 give the same wrapper to the member avatar. */
.sc-walker { position: relative; width: 100%; height: 100%; }
.sc-greetster {
  position: absolute; left: 0; right: 0; bottom: 0;
  margin: 0 auto;
  width: 64%; height: auto;
  filter: drop-shadow(0 6px 10px rgba(23, 24, 29, 0.16));
}

/* the ticket a courier carries (INVITE / REMINDER / DIGEST) */
.sc-ticket {
  position: absolute; right: -4%; top: 34%;
  display: inline-flex; align-items: center;
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 0.9cqw solid var(--blurple);
  border-radius: 4px;
  box-shadow: var(--shadow);
  padding: 1.1cqw 1.8cqw;
  font-size: max(7px, 2.2cqw); font-weight: 800; letter-spacing: 0.06em;
  color: var(--ink);
  opacity: 0;
  transition: border-color 0.55s ease;
}

/* the member avatar (walks in scene 2, walks out in scene 5) */
.sc-avatar {
  position: absolute; left: 0; right: 0; bottom: 4%;
  margin: 0 auto;
  width: 40%; height: auto;
  filter: drop-shadow(0 4px 8px rgba(23, 24, 29, 0.12));
}
.sc-svg .mouth { fill: none; stroke: var(--ink); stroke-width: 3.2; stroke-linecap: round; }

/* ── sound waves crossing a lane, three ")" arcs of growing size.
   They overflow their narrow lane on purpose; absolute + no clipping. ── */
.sc-link { position: relative; flex: 1 1 auto; height: 28cqw; }
.sc-wave {
  position: absolute; top: 50%;
  border: 0.7cqw solid transparent;
  border-right-color: var(--blurple);
  border-radius: 50%;
  transition: border-color 0.55s ease;
  opacity: 0;
}
.sc-wave.w1 { left: 12%; width: 2.4cqw; height: 5cqw;   margin-top: -2.5cqw; }
.sc-wave.w2 { left: 38%; width: 3.4cqw; height: 7.5cqw; margin-top: -3.75cqw; }
.sc-wave.w3 { left: 66%; width: 4.4cqw; height: 10cqw;  margin-top: -5cqw; }

/* the platform mark (Discord face / Telegram plane). One drawing, the badge
   swaps with the platform toggle. Used by scenes 2 and 5. */
.sc-mark-telegram { display: none; }
html[data-platform="telegram"] .sc-mark-discord { display: none; }
html[data-platform="telegram"] .sc-mark-telegram { display: block; }

/* ══ SCENE 1: listens-to-payments (THE TEMPLATE) ══
   Terminal → waves → Greetster carries the invite → member's Gmail eats it. */

/* the coin that drops into the terminal slot */
.sc-coin {
  position: absolute; left: 50%; top: 46%;
  width: 7.5cqw; height: 7.5cqw; margin-left: -3.75cqw;
  border-radius: 50%;
  background: var(--panel); border: 1px solid var(--line);
  box-shadow: var(--shadow);
  display: flex; align-items: center; justify-content: center;
  font-size: 4cqw; font-weight: 800; color: var(--green);
}

/* the terminal screen's two rails, crossfading so nobody can miss that we
   take BOTH. Brand colors on purpose: black stripe, amber bitcoin.
   Never on screen together: an overlap reads as a rendering bug. */
.sc-rail { font-weight: 800; font-family: inherit; }
.sc-rail-stripe { font-size: 15px; fill: #ffffff; }
.sc-rail-crypto { font-size: 22px; fill: #f7931a; opacity: 0; }
.scene-live .sc-rail-stripe { animation: sc-rail-a 7s ease-in-out infinite; }
.scene-live .sc-rail-crypto { animation: sc-rail-b 7s ease-in-out infinite; }
@keyframes sc-rail-a { 0%, 42% { opacity: 1 } 46%, 96% { opacity: 0 } 100% { opacity: 1 } }
@keyframes sc-rail-b { 0%, 46% { opacity: 0 } 50%, 92% { opacity: 1 } 96%, 100% { opacity: 0 } }

/* the Gmail M on the member's inbox, and the unread badge that pops.
   Scenes 1, 4 and 6 all end at this inbox: email is how invites travel. */
.sc-svg .gmail-m {
  fill: none; stroke: #ea4335;
  stroke-width: 6.5; stroke-linecap: round; stroke-linejoin: round;
}
.sc-svg .sc-note-dot { fill: #ea4335; }
.sc-svg .sc-note-num { fill: #ffffff; font-size: 11px; font-weight: 800; }
.sc-note { opacity: 0; }

/* ══ SCENE 2: every-join-checked ══
   The member walks up with their invite → Greetster scans and matches the
   payment → role pill on → the server icon lets them in. */

/* the scan beam that sweeps the avatar head to toe */
.sc-scan {
  position: absolute; left: 24%; right: 24%; top: 20%;
  height: 1cqw; border-radius: 99px;
  background: var(--blurple);
  opacity: 0;
  transition: background 0.55s ease;
}

/* the three checks Greetster ticks off while matching the payment */
.sc-pop-tick {
  position: absolute; left: 7%;
  width: 6cqw; height: 6cqw; border-radius: 50%;
  background: var(--green); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 3.1cqw; font-weight: 800;
  box-shadow: var(--shadow);
  opacity: 0;
}
.sc-pop-tick.t1 { top: 22%; }
.sc-pop-tick.t2 { top: 40%; }
.sc-pop-tick.t3 { top: 58%; }

/* the role pill that snaps under the avatar once the check passes */
.sc-role {
  position: absolute; left: 50%; bottom: -6%;
  transform: translateX(-50%) scale(0);
  background: var(--blurple); color: #fff;
  border-radius: 99px;
  font-size: max(7px, 2cqw); font-weight: 800; letter-spacing: 0.06em;
  padding: 0.5cqw 1.7cqw;
  white-space: nowrap;
  transition: background 0.55s ease;
}

/* the joiner carries his invite lower and closer than Greetster does */
#scene-every-join-checked .sc-ticket { right: 4%; top: 38%; }

/* ══ SCENE 3: member-list-runs-itself ══
   Terminal pings → Greetster writes the row and files it himself → the list
   card gains the row, then the search filters straight to it. */

/* the row he carries over: avatar dot + name line in a chip */
.s3-rowchip {
  position: absolute; right: -2%; top: 36%;
  display: inline-flex; align-items: center; gap: 1cqw;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 99px;
  box-shadow: var(--shadow);
  padding: 1.2cqw 1.8cqw;
  opacity: 0;
}
.s3-rowchip .dot { width: 2.8cqw; height: 2.8cqw; border-radius: 50%; background: var(--blurple-tint); border: 1px solid var(--line); }
.s3-rowchip .ln { width: 7cqw; height: 1.6cqw; border-radius: 99px; background: var(--line); }

/* pieces GSAP reveals on the list card */
.sc-svg .s3-letter { fill: var(--ink); opacity: 0; }
.sc-svg .s3-hl { fill: var(--blurple-tint); opacity: 0; transition: fill 0.55s ease; }
.sc-svg .ok-dot { fill: var(--green); }

/* ══ SCENE 4: hunts-failed-payments ══
   The member's card declines → Greetster carries the reminder to their Gmail
   → the payment flies back → the card turns green. */

/* the payment that comes back after the reminder */
.s4-coin {
  position: absolute; left: 50%; top: 26%;
  width: 7.5cqw; height: 7.5cqw; margin-left: -3.75cqw;
  border-radius: 50%;
  background: var(--panel); border: 1px solid var(--line);
  box-shadow: var(--shadow);
  display: flex; align-items: center; justify-content: center;
  font-size: 4cqw; font-weight: 800; color: var(--green);
  opacity: 0;
}

/* ══ SCENE 5: exit-handled ══
   The subscription ends → Greetster walks over and escorts the member OUT of
   the server → the billing toggle clicks off. */

/* the ENDED stamp on the billing card */
.sc-stamp {
  position: absolute; left: 50%; top: 8%;
  transform: translateX(-50%) rotate(-8deg);
  background: var(--panel);
  border: 0.6cqw solid var(--muted);
  border-radius: 6px;
  color: var(--muted);
  font-size: max(8px, 2.6cqw); font-weight: 800; letter-spacing: 0.12em;
  padding: 0.8cqw 2cqw;
  opacity: 0;
}

/* toggle knobs (scenes 5 and 7): the grey OFF circle sits under the accent ON
   circle; GSAP slides the pair and fades the accent one. No color tweening,
   so the platform morph never fights the animation. */
.sc-svg .k-off { fill: var(--muted); }

/* ══ SCENE 6: crypto-bonus ══
   The pay-link phone takes a ₿ → confirmations tick down the chain →
   Greetster carries the invite to Gmail. Money went wallet-direct. */

.s6-bcoin { color: #f7931a; }   /* the coin is a bitcoin, amber like the rail */

/* the verdict chips above Greetster: "checking" is a passing moment, so the
   frozen story only shows the confirmed one */
.s6-checking { opacity: 0; }

/* ══ SCENE 7: ai-automations ══
   Toggles flip on → Greetster types the digest → carries it to the channel. */

/* the typing bubble over his head, three dots GSAP bounces */
.s7-bubble {
  position: absolute; left: 60%; top: 2%;
  display: inline-flex; align-items: center; gap: 1.1cqw;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 99px;
  box-shadow: var(--shadow);
  padding: 1.6cqw 2cqw;
  opacity: 0;
}
.s7-dot { width: 1.9cqw; height: 1.9cqw; border-radius: 50%; background: var(--muted); }

/* ── drawn-state exceptions ──
   The law says CSS draws the END of each story. These props differ from the
   default because their story REPLACES them: the decline is history once the
   payment recovers, and the leaver is gone once the exit is handled. */
.sc-svg .s4-bad { opacity: 0; }     /* red badge, only during the decline beat */
.s4-declined { opacity: 0; }        /* its chip, swapped for "recovered" */
.sc-svg .s5-kon { opacity: 0; }     /* accent knob: end state is billing OFF */
.s5-exit {                          /* the leaver overlays the icon, then leaves */
  position: absolute; inset: 0;
  opacity: 0;
}
.sc-rail-fixed { font-weight: 800; font-size: 22px; fill: #f7931a; } /* the ₿ pay screen */

/* ── placeholders (none left once all 7 are built, kept for safety) ── */
.scene-pending { display: flex; align-items: center; justify-content: center; }
.scene-pending p {
  position: relative;
  color: var(--muted); font-size: 0.9rem; font-weight: 600;
  text-align: center; padding: 0 8%;
}

@media (prefers-reduced-motion: reduce) {
  .sc-bob { animation: none !important; }
}
