/* ==========================================================================
   BusayoDisu.com  |  Story Animations
   Custom narrative SVG scenes that replace step-by-step copy. Each scene
   renders as its FINISHED frame by default; js/stories.js adds .st-play on
   scroll-in to replay it once, and never under reduced motion, so the
   finished still is the accessible fallback. Full step text lives in the
   captions and the SVG aria-label for screen readers.

   Everything is namespaced (st-) and scoped so it cannot touch the design
   system in main.css. Colours come from main.css tokens, so light, dark and
   cultural modes are inherited for free.

   CSS gotcha honoured throughout: a CSS `transform` overrides an element's
   SVG `transform` attribute, so animated elements either carry the full
   position in their keyframes, or animate a child while a parent group holds
   the base position via the attribute.
   ========================================================================== */

/* ---------- Layout shared by every scene ---------- */
.st-scene { max-width: 840px; margin-inline: auto; }
.st-stage { width: 100%; }
.st-stage svg { display: block; width: 100%; height: auto; overflow: visible; }

.st-caps {
  list-style: none; padding: 0; margin: 26px 0 0;
  display: grid; gap: 16px 22px;
  grid-template-columns: repeat(3, 1fr);
}
.st-caps.four { grid-template-columns: repeat(4, 1fr); }
.st-caps li { padding-top: 16px; border-top: 1px solid var(--line); }
.st-caps .c-no { font-family: var(--serif); font-style: italic; color: var(--gold); font-size: 0.95rem; }
.st-caps h3 { font-family: var(--serif); color: var(--ink); margin: 0.15em 0 0.35em; font-size: 1.14rem; font-weight: 500; }
.st-caps p { margin: 0; font-size: 0.9rem; line-height: 1.55; color: var(--body); }
.st-caps a { color: var(--terracotta); border-bottom: 1px solid transparent; }
.st-caps a:hover { border-bottom-color: currentColor; }

/* Finished frame = all captions lit. During replay they dim then light in
   step with the scene. */
.st-scene.st-play .st-caps li {
  opacity: 0.42;
  animation: st-capLight 0.5s ease forwards;
  animation-delay: var(--cap, 0s);
}
@keyframes st-capLight { to { opacity: 1; } }

@media (max-width: 640px) {
  .st-caps, .st-caps.four { grid-template-columns: 1fr 1fr; }
}

/* ---------- People + ground, drawn in the site's fine-line icon language ---------- */
.st-scene .fig .head, .st-scene .fig .torso {
  fill: none; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round;
}
.st-scene .fig.terra .head, .st-scene .fig.terra .torso { stroke: var(--terracotta); }
.st-scene .fig.forest .head, .st-scene .fig.forest .torso { stroke: var(--forest); }
.st-scene .ground { stroke: var(--line-soft); stroke-width: 2; stroke-linecap: round; }

/* ---------- Shared keyframes ---------- */
@keyframes st-fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
@keyframes st-draw { to { stroke-dashoffset: 0; } }
@keyframes st-popIn { to { opacity: 1; transform: scale(1); } }

/* ==========================================================================
   SCENE — BRIDGE (human): Listen / Understand / Bridge / Sustain
   ========================================================================== */
.st-bridge .fig { opacity: 1; }
.st-bridge.st-play .fig { opacity: 0; animation: st-fadeUp 0.7s cubic-bezier(0.22,1,0.36,1) forwards; }
.st-bridge.st-play .fig.right { animation-delay: 0.18s; }

.st-bridge .speech .d { fill: var(--terracotta); opacity: 0; }
.st-bridge .speech.r2l .d { fill: var(--forest); }
.st-bridge.st-play .speech.l2r .d { animation: st-sayR 1.5s ease-in-out forwards; }
.st-bridge.st-play .speech.r2l .d { animation: st-sayL 1.5s ease-in-out forwards; }
.st-bridge.st-play .speech.l2r .d1 { animation-delay: 0.9s; }
.st-bridge.st-play .speech.l2r .d2 { animation-delay: 1.12s; }
.st-bridge.st-play .speech.l2r .d3 { animation-delay: 1.34s; }
.st-bridge.st-play .speech.r2l .d1 { animation-delay: 2.1s; }
.st-bridge.st-play .speech.r2l .d2 { animation-delay: 2.32s; }
.st-bridge.st-play .speech.r2l .d3 { animation-delay: 2.54s; }
@keyframes st-sayR { 0% { opacity: 0; transform: translateX(0); } 16% { opacity: 0.85; } 84% { opacity: 0.85; } 100% { opacity: 0; transform: translateX(500px); } }
@keyframes st-sayL { 0% { opacity: 0; transform: translateX(0); } 16% { opacity: 0.85; } 84% { opacity: 0.85; } 100% { opacity: 0; transform: translateX(-500px); } }

.st-bridge .spark { fill: var(--gold); transform-box: fill-box; transform-origin: center; opacity: 1; }
.st-bridge .spark-glow { fill: var(--gold); opacity: 0.16; transform-box: fill-box; transform-origin: center; }
.st-bridge.st-play .spark { opacity: 0; transform: scale(0) rotate(-20deg); animation: st-sparkIn 1s cubic-bezier(0.22,1,0.36,1) 3.4s forwards; }
.st-bridge.st-play .spark-glow { opacity: 0; transform: scale(0.3); animation: st-glowIn 1.3s ease-out 3.4s forwards; }
@keyframes st-sparkIn { 60% { opacity: 1; } 100% { opacity: 1; transform: scale(1) rotate(0); } }
@keyframes st-glowIn { 50% { opacity: 0.2; } 100% { opacity: 0.16; transform: scale(1); } }

.st-bridge .arch { fill: none; stroke: var(--gold); stroke-width: 6; stroke-linecap: round; }
.st-bridge .arch-echo { fill: none; stroke: var(--terracotta); stroke-width: 2; opacity: 0.5; }
.st-bridge.st-play .arch, .st-bridge.st-play .arch-echo { stroke-dasharray: var(--len) var(--len); stroke-dashoffset: var(--len); animation: st-draw 2.1s ease-in-out 5.6s forwards; }
.st-bridge.st-play .arch-echo { animation-delay: 5.8s; }

.st-bridge .gem .sq { fill: var(--gold); transform-box: fill-box; transform-origin: center; transform: rotate(45deg); }
.st-bridge .gem { opacity: 1; }
.st-bridge.st-play .gem { opacity: 0; animation: st-capLight 0.5s ease forwards; }
.st-bridge.st-play .gem .sq { transform: rotate(45deg) scale(0.2); animation: st-gemPop 0.55s cubic-bezier(0.22,1,0.36,1) forwards; }
.st-bridge.st-play .gem, .st-bridge.st-play .gem .sq { animation-delay: calc(6.3s + var(--i, 0) * 0.32s); }
@keyframes st-gemPop { to { transform: rotate(45deg) scale(1); } }

.st-bridge .stem { fill: none; stroke: var(--gold); stroke-width: 2.4; stroke-linecap: round; }
.st-bridge.st-play .stem { stroke-dasharray: var(--len) var(--len); stroke-dashoffset: var(--len); animation: st-draw 1.3s ease-out 8.6s forwards; }
.st-bridge .leaf { fill: var(--forest); transform-box: fill-box; transform-origin: center bottom; opacity: 1; }
.st-bridge.st-play .leaf { opacity: 0; transform: scale(0); animation: st-popIn 0.7s cubic-bezier(0.22,1,0.36,1) forwards; animation-delay: 9.3s; }
.st-bridge.st-play .leaf.l2 { animation-delay: 9.55s; }

/* ==========================================================================
   SCENE — ACCESS (object): Choose / Receive code / Unlock player
   ========================================================================== */
.st-access .frame { fill: var(--cream); stroke: var(--terracotta); stroke-width: 2; }
.st-access .frame.forest { stroke: var(--forest); }
.st-access .glyph { fill: var(--terracotta); }
.st-access .wire { fill: none; stroke: var(--line); stroke-width: 2; stroke-dasharray: 2 7; stroke-linecap: round; }
.st-access .station { opacity: 1; }
.st-access.st-play .station { opacity: 0; animation: st-fadeUp 0.6s cubic-bezier(0.22,1,0.36,1) forwards; }
.st-access.st-play .station.b { animation-delay: 0.15s; }
.st-access.st-play .station.c { animation-delay: 0.3s; }

.st-access .sel { fill: none; stroke: var(--gold); stroke-width: 2; opacity: 0; transform-box: fill-box; transform-origin: center; }
.st-access.st-play .sel { animation: st-sel 1.1s ease-out 0.6s 2; }
@keyframes st-sel { 0% { opacity: 0.8; transform: scale(0.7); } 100% { opacity: 0; transform: scale(1.25); } }

.st-access .token rect { fill: var(--gold); stroke: none; }
.st-access .token text { fill: #3a2c18; font-family: var(--sans); font-weight: 700; font-size: 13px; letter-spacing: 0.06em; }
.st-access .token { transform: translate(700px, 139px); opacity: 1; }
.st-access.st-play .token { opacity: 0; animation: st-journey 8.2s cubic-bezier(0.65,0.02,0.35,1) 1.6s forwards; }
@keyframes st-journey {
  0% { opacity: 0; transform: translate(126px, 139px); }
  8% { opacity: 1; transform: translate(126px, 139px); }
  26% { transform: translate(462px, 139px); }
  40% { transform: translate(462px, 139px); }
  46% { opacity: 1; }
  64% { transform: translate(788px, 139px); }
  72% { opacity: 0; transform: translate(788px, 139px); }
  100% { opacity: 0; transform: translate(788px, 139px); }
}

.st-access .flap { fill: none; stroke: var(--gold); stroke-width: 2; }
.st-access .pulse { fill: var(--gold); opacity: 0; transform-box: fill-box; transform-origin: center; }
.st-access.st-play .pulse.env { animation: st-pulse 1s ease-out 3.4s; }
.st-access.st-play .pulse.scr { animation: st-pulse 1.1s ease-out 6.6s; }
@keyframes st-pulse { 0% { opacity: 0.5; transform: scale(0.5); } 100% { opacity: 0; transform: scale(1.5); } }

.st-access .screen-glow { fill: var(--gold); opacity: 0; }
.st-access .play-tri { fill: var(--forest); transform-box: fill-box; transform-origin: center; }
.st-access.st-play .play-tri { fill: var(--faint); animation: st-triLight 0.7s cubic-bezier(0.22,1,0.36,1) 6.7s forwards; }
@keyframes st-triLight { 0% { fill: var(--faint); transform: scale(0.82); } 100% { fill: var(--forest); transform: scale(1); } }
.st-access.st-play .screen-glow { animation: st-glow 1.5s ease-out 6.5s forwards; }
@keyframes st-glow { 0% { opacity: 0; } 45% { opacity: 0.3; } 100% { opacity: 0.14; } }

/* ==========================================================================
   SCENE — REFERRAL (human): Reach out / We listen / We connect you
   ========================================================================== */
.st-referral .station { opacity: 1; }
.st-referral.st-play .station { opacity: 0; animation: st-fadeUp 0.6s cubic-bezier(0.22,1,0.36,1) forwards; }
.st-referral.st-play .station.b { animation-delay: 0.15s; }
.st-referral.st-play .station.c { animation-delay: 0.3s; }

.st-referral .msg rect, .st-referral .msg path { fill: none; stroke: var(--gold); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.st-referral .msg { transform: translate(452px, 150px); opacity: 0; }
.st-referral.st-play .msg { animation: st-send 1.7s cubic-bezier(0.4,0,0.3,1) 0.9s forwards; }
@keyframes st-send { 0% { opacity: 0; transform: translate(176px, 150px); } 14% { opacity: 1; } 82% { opacity: 1; transform: translate(452px, 150px); } 100% { opacity: 0; transform: translate(452px, 150px); } }

.st-referral .heart { fill: var(--terracotta); transform-box: fill-box; transform-origin: center bottom; opacity: 1; }
.st-referral.st-play .heart { opacity: 0; transform: scale(0) translateY(6px); animation: st-heartUp 1s cubic-bezier(0.22,1,0.36,1) 2.7s forwards; }
@keyframes st-heartUp { 55% { opacity: 1; } 100% { opacity: 1; transform: scale(1) translateY(0); } }

.st-referral .listen-arc { fill: none; stroke: var(--forest); stroke-width: 2; opacity: 0; transform-box: fill-box; transform-origin: center; }
.st-referral.st-play .listen-arc { animation: st-sel 1.2s ease-out 2.6s 2; }

.st-referral .door-frame { fill: none; stroke: var(--forest); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.st-referral .door-light { fill: var(--gold); opacity: 0.3; }
.st-referral.st-play .door-light { opacity: 0; animation: st-doorGlow 1.5s ease-out 4.6s forwards; }
@keyframes st-doorGlow { 0% { opacity: 0; } 55% { opacity: 0.42; } 100% { opacity: 0.3; } }

.st-referral .guide-draw { fill: none; stroke: var(--gold); stroke-width: 2.4; stroke-linecap: round; }
.st-referral.st-play .guide-draw { stroke-dasharray: var(--len) var(--len); stroke-dashoffset: var(--len); animation: st-draw 1.1s ease-out 3.9s forwards; }
.st-referral .marker { fill: var(--terracotta); transform: translate(300px, 0); opacity: 1; }
.st-referral.st-play .marker { opacity: 0; animation: st-walk 1.6s cubic-bezier(0.4,0,0.3,1) 4.4s forwards; }
@keyframes st-walk { 0% { opacity: 0; transform: translate(0, 0); } 18% { opacity: 1; } 100% { opacity: 1; transform: translate(300px, 0); } }

/* ==========================================================================
   NUMBERED LISTS — the index thread
   Applied to any .detail-list marked data-story with class st-list. A single
   gold spine draws down the left of the list while each number lights in turn,
   top to bottom: one coordinated motion that makes the numbering feel alive,
   echoing the site's story-thread. Content itself never reveals.
   ========================================================================== */
.st-list { position: relative; }
.st-list::before {
  content: ""; position: absolute; left: -14px; top: 2px; bottom: 2px; width: 2px;
  background: linear-gradient(var(--gold), var(--terracotta)); opacity: 0.45;
  transform-origin: top;
}
.st-list.st-play::before { transform: scaleY(0); animation: st-drawY 1.9s ease-out 0.1s forwards; }
@keyframes st-drawY { to { transform: scaleY(1); } }

.st-list .detail-row .index { transform-origin: left center; }
.st-list.st-play .detail-row .index {
  opacity: 0.22; transform: translateY(7px) scale(0.82);
  animation: st-idx 0.55s cubic-bezier(0.22,1,0.36,1) forwards;
}
@keyframes st-idx { to { opacity: 1; transform: translateY(0) scale(1); } }
.st-list.st-play .detail-row:nth-child(1) .index { animation-delay: 0.15s; }
.st-list.st-play .detail-row:nth-child(2) .index { animation-delay: 0.40s; }
.st-list.st-play .detail-row:nth-child(3) .index { animation-delay: 0.62s; }
.st-list.st-play .detail-row:nth-child(4) .index { animation-delay: 0.82s; }
.st-list.st-play .detail-row:nth-child(5) .index { animation-delay: 1.02s; }
.st-list.st-play .detail-row:nth-child(6) .index { animation-delay: 1.22s; }
.st-list.st-play .detail-row:nth-child(7) .index { animation-delay: 1.42s; }
.st-list.st-play .detail-row:nth-child(8) .index { animation-delay: 1.62s; }
.st-list.st-play .detail-row:nth-child(9) .index { animation-delay: 1.82s; }
.st-list.st-play .detail-row:nth-child(10) .index { animation-delay: 2.02s; }
.st-list.st-play .detail-row:nth-child(11) .index { animation-delay: 2.22s; }
.st-list.st-play .detail-row:nth-child(12) .index { animation-delay: 2.42s; }

/* ==========================================================================
   TIMELINE — the road draws itself
   Applied to a .timeline marked data-story with class st-timeline. The spine
   draws down and each milestone diamond lights as it is reached.
   ========================================================================== */
.st-timeline.st-play::before { transform: scaleY(0); transform-origin: top; animation: st-drawY 1.7s ease-out 0.1s forwards; }
.st-timeline.st-play .moment::before { opacity: 0; transform: rotate(45deg) scale(0.3); animation: st-diaPop 0.55s cubic-bezier(0.22,1,0.36,1) forwards; }
@keyframes st-diaPop { to { opacity: 1; transform: rotate(45deg) scale(1); } }
.st-timeline.st-play .moment:nth-child(1)::before { animation-delay: 0.30s; }
.st-timeline.st-play .moment:nth-child(2)::before { animation-delay: 0.62s; }
.st-timeline.st-play .moment:nth-child(3)::before { animation-delay: 0.94s; }
.st-timeline.st-play .moment:nth-child(4)::before { animation-delay: 1.26s; }
.st-timeline.st-play .moment:nth-child(5)::before { animation-delay: 1.58s; }
.st-timeline.st-play .moment:nth-child(6)::before { animation-delay: 1.90s; }

/* ==========================================================================
   SCENE — ROOTS (concept): "three ways this work takes root"
   A seed roots downward, a trunk rises and splits into three branches, each
   blooming into one arena: community, schools, healthcare.
   ========================================================================== */
.st-roots .root, .st-roots .trunk, .st-roots .branch { fill: none; stroke-linecap: round; }
.st-roots .root { stroke: var(--forest); stroke-width: 2.4; }
.st-roots .trunk { stroke: var(--forest); stroke-width: 3; }
.st-roots .branch { stroke: var(--gold); stroke-width: 3; }
.st-roots .seed { fill: var(--gold); }
.st-roots .node { transform-box: fill-box; transform-origin: center; }
.st-roots .node .terra { fill: var(--terracotta); }
.st-roots .node .gold { fill: var(--gold); }
.st-roots .node .forest { fill: var(--forest); }
.st-roots .node .pip { fill: var(--ivory); }

.st-roots.st-play .root { stroke-dasharray: var(--len) var(--len); stroke-dashoffset: var(--len); animation: st-draw 2s ease-out 0.3s forwards; }
.st-roots.st-play .trunk { stroke-dasharray: var(--len) var(--len); stroke-dashoffset: var(--len); animation: st-draw 1.2s ease-out 1.8s forwards; }
.st-roots.st-play .branch { stroke-dasharray: var(--len) var(--len); stroke-dashoffset: var(--len); animation: st-draw 2s ease-out 3s forwards; }
.st-roots.st-play .branch.b2 { animation-delay: 3.3s; }
.st-roots.st-play .branch.b3 { animation-delay: 3.6s; }
.st-roots .seed { opacity: 1; }
.st-roots.st-play .seed { opacity: 0; animation: st-capLight 0.4s ease 0.1s forwards; }
.st-roots .node { opacity: 1; }
.st-roots.st-play .node { opacity: 0; transform: scale(0); animation: st-popIn 0.6s cubic-bezier(0.22,1,0.36,1) forwards; }
.st-roots.st-play .node.n1 { animation-delay: 4.6s; }
.st-roots.st-play .node.n2 { animation-delay: 5.0s; }
.st-roots.st-play .node.n3 { animation-delay: 5.4s; }

/* ---------- Reduced motion: never animate; the finished frame stands ---------- */
@media (prefers-reduced-motion: reduce) {
  .st-scene.st-play *, .st-list.st-play *, .st-timeline.st-play * { animation: none !important; }
  .st-list.st-play::before, .st-timeline.st-play::before { animation: none !important; transform: none; }
}
