/* ==========================================================================
   SAMPLE — launch animations
   ==========================================================================
   Twelve splash screens, each built on a different technique, each replayable.
   Every one is CSS and SVG: no library, no video, nothing to download. A splash
   screen exists to cover a cold start, so it has to be the cheapest thing in
   the app — a 400 KB animation library defeats the entire purpose.

   Scoped under .spl.
   ========================================================================== */

.spl {
  --ink:   #e8eaf2;
  --ink-2: #9aa1b8;
  --ink-3: #7f88a3;   /* 5.2:1 on --bg-2; #666e86 was 3.6 and failed */
  --bg:    #0a0b10;
  --bg-2:  #12141c;
  --line:  #232838;

  --sans: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, Consolas, monospace;

  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
.spl *, .spl *::before, .spl *::after { box-sizing: border-box; }
.spl svg { display: block; }

.spl-wrap { width: 100%; max-width: 78rem; margin-inline: auto; padding-inline: clamp(1.25rem, 4vw, 2.5rem); }
.spl-head { padding-block: clamp(2.5rem, 6vw, 4.5rem) 1rem; }
.spl-head h1 {
  font-size: clamp(2.2rem, 5.5vw, 3.6rem);
  letter-spacing: -0.035em;
  line-height: 1.03;
  margin: 0 0 .6rem;
  font-weight: 600;
}
.spl-head p { color: var(--ink-2); max-width: 44rem; margin: 0; font-size: 1.02rem; line-height: 1.6; }

.spl-actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.6rem; align-items: center; }
.spl-btn {
  font: inherit;
  font-size: .86rem;
  color: var(--ink);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: .55rem 1rem;
  cursor: pointer;
  transition: border-color .2s, background .2s, transform .12s;
}
.spl-btn:hover { border-color: #3a4257; background: #171a24; }
.spl-btn:active { transform: scale(.97); }
.spl-btn--go { background: #8b7cf6; border-color: #8b7cf6; color: #0a0b10; font-weight: 600; }
.spl-btn--go:hover { background: #a897ff; border-color: #a897ff; }

/* ----------------------------------------------------------- the grid --- */

.spl-grid {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  padding-block: 2rem 5rem;
}

.spl-card { display: flex; flex-direction: column; gap: 1rem; align-items: center; }
.spl-card__meta { width: 100%; }
.spl-card h2 {
  font-size: 1rem;
  margin: 0 0 .25rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  display: flex;
  align-items: center;
  gap: .5rem;
}
.spl-card h2 i {
  font-family: var(--mono);
  font-style: normal;
  font-size: .66rem;
  color: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: .1rem .35rem;
}
.spl-card p { margin: 0; font-size: .84rem; color: var(--ink-2); line-height: 1.5; }
.spl-card__foot { display: flex; gap: .5rem; margin-top: .6rem; }
.spl-replay {
  font: inherit;
  font-size: .76rem;
  color: var(--ink-2);
  background: none;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: .3rem .7rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  transition: color .2s, border-color .2s;
}
.spl-replay:hover { color: var(--ink); border-color: #3a4257; }
.spl-replay svg { width: 12px; height: 12px; }

/* =========================================================== the screens ==
   Each screen is its own stage. Animations are keyed off a `.go` class that
   the script removes and re-adds, which is what makes replay work without
   rebuilding the DOM. */

.stage {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.stage > * { grid-area: 1 / 1; }

/*
 * Layering, stated rather than inferred.
 *
 * Each screen's backdrop is an absolutely positioned child, and a positioned
 * element paints above its static siblings — so the backdrop was covering the
 * artwork. It looked like it worked, because an element with a running
 * animation gets its own stacking context and escaped: the animated wordmarks
 * showed and the static SVG marks did not, which is a maddening thing to debug
 * and an even worse thing to leave to chance.
 */
.stage .stage-bg { position: absolute; inset: 0; z-index: 0; }
.stage > *:not(.stage-bg) { position: relative; z-index: 1; }

/* Nothing moves until the screen is told to play. */
.stage :where(.a) { animation-play-state: paused; opacity: 0; }
.stage.go :where(.a) { animation-play-state: running; }

/* --------------------------------------------------- 01 · stroke draw --- */

.s-draw { background: radial-gradient(120% 90% at 50% 0%, #16203a, #05070d 70%); }
.s-draw__mark { width: 46%; overflow: visible; }
.s-draw__mark path {
  fill: none;
  stroke: #5eead4;
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.stage.go .s-draw__mark path {
  animation: draw-in 1.1s cubic-bezier(.65,0,.35,1) forwards;
}
.stage.go .s-draw__mark path:nth-child(2) { animation-delay: .12s; }
.stage.go .s-draw__mark path:nth-child(3) { animation-delay: .24s; }
@keyframes draw-in { to { stroke-dashoffset: 0; } }

.s-draw__word {
  align-self: end;
  margin-bottom: 22%;
  font-size: .8rem;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: #7dd3c0;
  animation: fade-up .7s .9s cubic-bezier(.16,1,.3,1) forwards;
}
@keyframes fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ------------------------------------------------------- 02 · liquid --- */

.s-fill { background: #0d1117; }
.s-fill__wave {
  align-self: end;
  width: 100%;
  height: 130%;
  animation: rise 1.6s cubic-bezier(.5,0,.2,1) forwards;
  transform: translateY(100%);
}
@keyframes rise { to { transform: translateY(18%); opacity: 1; } }
.s-fill__wave path { fill: #2563eb; }
.s-fill__wave path:nth-child(2) { fill: #3b82f6; opacity: .55; }
.s-fill__logo {
  position: relative;
  z-index: 2;
  font-size: 2.6rem;
  font-weight: 700;
  letter-spacing: -0.05em;
  color: #fff;
  mix-blend-mode: difference;
  animation: pop .6s .55s cubic-bezier(.34,1.5,.64,1) forwards;
  transform: scale(.7);
}
@keyframes pop { to { opacity: 1; transform: none; } }

/* -------------------------------------------------- 03 · mask reveal --- */

.s-mask { background: #f5f2ec; }
.s-mask__row {
  display: flex;
  gap: .06em;
  font-size: 2.4rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  color: #12130f;
  opacity: 1;
}
.s-mask__row span { display: block; overflow: hidden; }
.s-mask__row span i {
  display: block;
  font-style: normal;
  transform: translateY(105%);
  animation: mask-up .8s cubic-bezier(.16,1,.3,1) forwards;
  animation-play-state: paused;
}
.stage.go .s-mask__row span i { animation-play-state: running; }
.s-mask__row span:nth-child(2) i { animation-delay: .07s; }
.s-mask__row span:nth-child(3) i { animation-delay: .14s; }
.s-mask__row span:nth-child(4) i { animation-delay: .21s; }
.s-mask__row span:nth-child(5) i { animation-delay: .28s; }
.s-mask__row span:nth-child(6) i { animation-delay: .35s; }
@keyframes mask-up { to { transform: none; } }
.s-mask__rule {
  align-self: end;
  margin-bottom: 26%;
  width: 46%;
  height: 2px;
  background: #d94f2b;
  transform-origin: 0 50%;
  transform: scaleX(0);
  animation: rule-in .7s .5s cubic-bezier(.16,1,.3,1) forwards;
}
@keyframes rule-in { to { opacity: 1; transform: scaleX(1); } }

/* --------------------------------------------------- 04 · particles --- */

.s-burst { background: radial-gradient(90% 70% at 50% 50%, #1b1030, #07050d 72%); }
.s-burst__core {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #f0abfc;
  box-shadow: 0 0 30px 6px rgba(240, 171, 252, .7);
  animation: core 1.5s cubic-bezier(.16,1,.3,1) forwards;
  transform: scale(0);
}
@keyframes core {
  0%   { opacity: 1; transform: scale(0); }
  35%  { opacity: 1; transform: scale(1.6); }
  100% { opacity: 1; transform: scale(1); }
}
.s-burst__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: #c084fc;
  animation: shoot 1.3s cubic-bezier(.16,1,.3,1) forwards;
}
@keyframes shoot {
  0%   { opacity: 0; transform: translate(0, 0) scale(.4); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--tx), var(--ty)) scale(1); }
}
.s-burst__name {
  align-self: end;
  margin-bottom: 24%;
  font-size: 1.1rem;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: #e9d5ff;
  animation: fade-up .8s 1s cubic-bezier(.16,1,.3,1) forwards;
}

/* ------------------------------------------------------ 05 · morph --- */

.s-morph { background: #0f172a; }
.s-morph__shape {
  width: 42%;
  aspect-ratio: 1;
  background: #38bdf8;
  animation: morph 2.2s cubic-bezier(.65,0,.35,1) forwards;
  border-radius: 50%;
  transform: rotate(0deg) scale(.4);
}
@keyframes morph {
  0%   { opacity: 0; border-radius: 50%;  transform: rotate(0)      scale(.4); }
  22%  { opacity: 1; border-radius: 50%;  transform: rotate(0)      scale(1); }
  55%  { opacity: 1; border-radius: 34%;  transform: rotate(135deg) scale(1); background: #0ea5e9; }
  100% { opacity: 1; border-radius: 22%;  transform: rotate(45deg)  scale(.86); background: #0284c7; }
}
.s-morph__tag {
  position: relative;
  z-index: 2;
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: #f0f9ff;
  animation: fade-up .7s 1.5s cubic-bezier(.16,1,.3,1) forwards;
}

/* ------------------------------------------------------ 06 · stagger --- */

.s-grid { background: #101014; }
.s-grid__tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  width: 56%;
}
.s-grid__tiles i {
  display: block;
  aspect-ratio: 1;
  border-radius: 8px;
  background: #f97316;
  transform: scale(.2);
  animation: tile-in .6s cubic-bezier(.34,1.5,.64,1) forwards;
}
@keyframes tile-in { to { opacity: 1; transform: none; } }
.s-grid__tiles i:nth-child(1) { animation-delay: 0s;    background: #fb923c; }
.s-grid__tiles i:nth-child(2) { animation-delay: .06s; }
.s-grid__tiles i:nth-child(3) { animation-delay: .12s;  background: #fdba74; }
.s-grid__tiles i:nth-child(4) { animation-delay: .06s;  background: #fdba74; }
.s-grid__tiles i:nth-child(5) { animation-delay: .12s;  background: #f97316; }
.s-grid__tiles i:nth-child(6) { animation-delay: .18s; }
.s-grid__tiles i:nth-child(7) { animation-delay: .12s;  background: #fb923c; }
.s-grid__tiles i:nth-child(8) { animation-delay: .18s; }
.s-grid__tiles i:nth-child(9) { animation-delay: .24s;  background: #fdba74; }
.s-grid__word {
  align-self: end;
  margin-bottom: 20%;
  font-weight: 600;
  letter-spacing: -0.02em;
  font-size: 1.15rem;
  color: #fff7ed;
  animation: fade-up .6s .7s cubic-bezier(.16,1,.3,1) forwards;
}

/* ------------------------------------------------------- 07 · loader --- */

.s-load { background: #071a14; }
.s-load__ring { width: 44%; overflow: visible; }
.s-load__ring circle {
  fill: none;
  stroke-width: 6;
  stroke-linecap: round;
  transform-origin: 50% 50%;
}
.s-load__ring .track { stroke: rgba(255, 255, 255, .09); }
.s-load__ring .arc {
  stroke: #34d399;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transform: rotate(-90deg);
  animation: arc 1.8s cubic-bezier(.5,0,.2,1) forwards;
}
@keyframes arc { 0% { opacity: 1; stroke-dashoffset: 1; } 100% { opacity: 1; stroke-dashoffset: 0; } }
.s-load__pct {
  position: relative;
  z-index: 2;
  font-family: var(--mono);
  font-size: 1.5rem;
  color: #a7f3d0;
  animation: fade-in .3s forwards;
}
@keyframes fade-in { to { opacity: 1; } }
.s-load__done {
  align-self: end;
  margin-bottom: 22%;
  font-size: .78rem;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: #34d399;
  animation: fade-up .5s 1.9s cubic-bezier(.16,1,.3,1) forwards;
}

/* --------------------------------------------------- 08 · door open --- */

.s-door { background: #18120b; }
.s-door__half {
  width: 100%; height: 100%;
  background: linear-gradient(180deg, #2a1f13, #120d07);
  animation: door 1.4s .5s cubic-bezier(.65,0,.35,1) forwards;
  opacity: 1;
  z-index: 3;
}
.s-door__half--l { transform-origin: left center; clip-path: inset(0 50% 0 0); }
.s-door__half--r { transform-origin: right center; clip-path: inset(0 0 0 50%); }
.stage.go .s-door__half--l { animation-name: door-l; }
.stage.go .s-door__half--r { animation-name: door-r; }
@keyframes door-l { to { transform: translateX(-100%); } }
@keyframes door-r { to { transform: translateX(100%); } }
.s-door__inner {
  display: grid;
  place-items: center;
  gap: .8rem;
  animation: fade-in .6s 1.1s forwards;
}
.s-door__inner b {
  font-size: 2rem;
  letter-spacing: -0.04em;
  color: #fbbf24;
}
.s-door__inner span {
  font-size: .72rem;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: #a8a29e;
}


/* --------------------------------------------------- 09 · typewriter --- */

/*
 * The only one here driven by text rather than by shape. `steps()` on a width
 * animation is what makes it read as typing instead of as a wipe — an eased
 * width slides a half-letter into view and the eye reads it as a smudge.
 */
.s-type { background: #0b1a14; }

/*
 * Every direct child of .stage is pinned to grid-area 1/1, because eleven of
 * these twelve screens are a backdrop with artwork laid over it. This one is
 * the exception: it has two lines of text that belong one above the other, and
 * pinned to the same cell they printed on top of each other — the word and its
 * caption overlapping into a smudge. One wrapper makes them a single grid
 * child, and they stack inside it normally.
 */
.s-type__stack { display: flex; flex-direction: column; align-items: center; }

.s-type__line {
  display: flex; align-items: baseline;
  font-family: "JetBrains Mono", ui-monospace, Consolas, monospace;
  font-size: 1.5rem; font-weight: 600; letter-spacing: -0.02em;
  color: #6ee7b7;
}
.s-type__word {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  width: 0;
  /* Six steps for six letters. It was eight of each, so the last two steps
     revealed nothing and the caret ended up parked two characters past the D. */
  animation: type-in .9s steps(6, end) forwards;
  animation-play-state: paused;
}
.stage.go .s-type__word { animation-play-state: running; }
@keyframes type-in { to { width: 6ch; } }

.s-type__caret {
  width: .6ch; height: 1.15em;
  margin-left: .1ch;
  background: #6ee7b7;
  animation: caret 1s steps(2, end) infinite;
  animation-play-state: paused;
}
.stage.go .s-type__caret { animation-play-state: running; }
@keyframes caret { 50% { opacity: 0; } }

.s-type__sub {
  margin-top: .9rem;
  font-family: "JetBrains Mono", ui-monospace, Consolas, monospace;
  font-size: .6rem; letter-spacing: .28em; text-transform: uppercase;
  /* On a black phone screen #2f6b56 came to 3.35:1 at this size. Still a
     terminal green, just one a person can actually read. */
  color: #37866a;
  opacity: 0;
  animation: fade-in .5s ease-out .95s forwards;
  animation-play-state: paused;
}
.stage.go .s-type__sub { animation-play-state: running; }
@keyframes fade-in { to { opacity: 1; } }

/* ------------------------------------------------------- 10 · portal --- */

/*
 * The mark does not sit on the background, it BECOMES it: one element scales
 * past the viewport while its colour takes over. Transform and background-color
 * only, so it still composites — the version of this that animates width and
 * height janks on exactly the frame the app is busiest.
 */
.s-zoom { background: #16121f; }
.s-zoom__disc {
  width: 74px; height: 74px; border-radius: 50%;
  background: #a78bfa;
  transform: scale(0);
  animation: zoom-grow 1s cubic-bezier(.65,0,.35,1) forwards;
  animation-play-state: paused;
}
.stage.go .s-zoom__disc { animation-play-state: running; }
@keyframes zoom-grow {
  35%  { transform: scale(1); }
  100% { transform: scale(16); }
}
.s-zoom__mark {
  position: absolute;
  font-size: 1.6rem; font-weight: 800; letter-spacing: -0.03em;
  color: #16121f;
  opacity: 0;
  transform: scale(.85);
  animation: zoom-mark .5s cubic-bezier(.16,1,.3,1) .62s forwards;
  animation-play-state: paused;
}
.stage.go .s-zoom__mark { animation-play-state: running; }
@keyframes zoom-mark { to { opacity: 1; transform: none; } }

/* ----------------------------------------------------- 11 · skeleton --- */

/*
 * The honest one. Instead of a logo, the screen shows the SHAPE of what is
 * loading and then fills it in — so the wait is spent telling the user where
 * things will be rather than showing them a badge they have already seen.
 */
.s-skel { background: #f7f7f5; }
/* The stage is a GRID, not a flex row — so `flex: 1` on a line gets no space
   to grow into and collapses to zero width. Every skeleton element carries an
   explicit width instead of relying on a parent that was never flex. */
.s-skel__row { display: flex; gap: .5rem; align-items: center; width: 74%; margin-bottom: .7rem; }
.s-skel__b {
  background: #dedbd5;
  border-radius: 5px;
  position: relative;
  overflow: hidden;
  animation: skel-fill .5s ease-out forwards;
  animation-play-state: paused;
  animation-delay: calc(var(--i, 0) * .09s + .55s);
}
.stage.go .s-skel__b { animation-play-state: running; }
.s-skel__b::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.85), transparent);
  transform: translateX(-100%);
  /* Two animations: the loop, and a one-shot that switches it off at exactly
     the moment this block fills in. Without the second one the shimmer keeps
     sweeping over finished content, which is the thing the write-up says it
     does not do. */
  animation: skel-shine 1.1s ease-in-out infinite,
             skel-stop .01s linear calc(var(--i, 0) * .09s + .55s) forwards;
  animation-play-state: paused;
}
.stage.go .s-skel__b::after { animation-play-state: running; }
@keyframes skel-shine { to { transform: translateX(100%); } }
@keyframes skel-stop  { to { opacity: 0; } }
@keyframes skel-fill { to { background: #2f6bd8; } }

.s-skel__avatar { width: 34px; height: 34px; border-radius: 50%; flex: none; }
.s-skel__line   { height: 9px; flex: 1 1 auto; min-width: 0; }
.s-skel__line--s{ flex: 0 0 46%; }
.s-skel__card   { width: 74%; height: 54px; border-radius: 8px; margin-bottom: .6rem; }

/* ------------------------------------------------------- 12 · spring --- */

/*
 * Easing as the whole subject. The mark is thrown in and settles with a real
 * spring curve expressed as a linear() ramp — the modern way to get physical
 * motion out of CSS without a physics loop running during a cold start.
 */
.s-spring { background: #1a1206; }

/*
 * The icon and the name belong one above the other, so they need to be one
 * grid child — pinned separately to grid-area 1/1 the name printed across the
 * bottom of the icon. The same fix as the typewriter, and for the same reason.
 */
.s-spring__stack { display: flex; flex-direction: column; align-items: center; }

.s-spring__mark {
  width: 78px; height: 78px; border-radius: 20px;
  background: linear-gradient(140deg, #fbbf24, #f97316);
  display: grid; place-items: center;
  font-size: 2rem; font-weight: 900; color: #2b1204;
  transform: translateY(-160%);
  animation: spring-drop .95s linear(
      0, 0.38 12%, 0.72 22%, 0.94 30%, 1.06 37%, 1.09 44%,
      1.04 53%, 0.99 62%, 0.98 71%, 1.005 84%, 1
    ) forwards;
  animation-play-state: paused;
}
.stage.go .s-spring__mark { animation-play-state: running; }
@keyframes spring-drop { to { transform: none; } }

.s-spring__word {
  margin-top: 1rem;
  font-size: .95rem; font-weight: 700; letter-spacing: .02em;
  color: #f5deb8;
  opacity: 0; transform: translateY(8px);
  animation: spring-word .45s cubic-bezier(.16,1,.3,1) .5s forwards;
  animation-play-state: paused;
}
.stage.go .s-spring__word { animation-play-state: running; }
@keyframes spring-word { to { opacity: 1; transform: none; } }

/* ------------------------------------------------------------ notes --- */

.spl-note {
  border-top: 1px solid var(--line);
  padding-block: 2.5rem 4rem;
  color: var(--ink-2);
  font-size: .95rem;
  line-height: 1.65;
  max-width: 44rem;
}
.spl-note h2 { color: var(--ink); font-size: 1.2rem; margin: 0 0 .6rem; letter-spacing: -0.02em; }
.spl-note code {
  font-family: var(--mono);
  font-size: .86em;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: .1em .35em;
  color: #a5b4fc;
}
.spl-note p + p { margin-top: .9rem; }

/*
 * Reduced motion holds every screen at its finished frame. Each selector is
 * qualified with :not(.spl--motion) so that a visitor who explicitly asks for
 * the animations gets them — motion the user requests is allowed, and a page
 * about motion that can only ever be described to them is a poor trade.
 *
 * Written as :not() rather than as a separate class the script adds, so the
 * still version is still correct with JavaScript switched off.
 */
@media (prefers-reduced-motion: reduce) {
  .spl:not(.spl--motion) .stage :where(.a) { opacity: 1 !important; animation: none !important; transform: none !important; }
  .spl:not(.spl--motion) .s-door__half { display: none; }
  .spl:not(.spl--motion) .s-mask__row span i { transform: none !important; animation: none !important; }
  .spl:not(.spl--motion) .s-type__word { width: 6ch !important; animation: none !important; }
  .spl:not(.spl--motion) .s-type__caret { animation: none !important; }
  .spl:not(.spl--motion) .s-type__sub,
  .spl:not(.spl--motion) .s-zoom__mark,
  .spl:not(.spl--motion) .s-spring__word { opacity: 1 !important; transform: none !important; animation: none !important; }
  .spl:not(.spl--motion) .s-zoom__disc { transform: scale(16) !important; animation: none !important; }
  .spl:not(.spl--motion) .s-spring__mark { transform: none !important; animation: none !important; }
  .spl:not(.spl--motion) .s-skel__b { background: #2f6bd8 !important; animation: none !important; }
  .spl:not(.spl--motion) .s-skel__b::after { animation: none !important; opacity: 0 !important; }
  .spl:not(.spl--motion) .s-draw__mark path { stroke-dashoffset: 0 !important; animation: none !important; }
  .spl:not(.spl--motion) .s-load__ring .arc { stroke-dashoffset: 0 !important; animation: none !important; }
}

/* The reduced-motion notice and its opt-in. */
.spl-still {
  display: flex; flex-wrap: wrap; align-items: center; gap: .75rem;
  margin: 1.1rem 0 0; padding: .75rem .9rem;
  max-width: 46rem;
  border: 1px solid var(--line);
  border-inline-start: 3px solid #8b7cf6;
  border-radius: 10px;
  background: rgba(139, 124, 246, .08);
}
.spl-still[hidden] { display: none; }
.spl-still > span { font-size: .86rem; line-height: 1.6; color: var(--ink-2); flex: 1 1 18rem; }

/* The screen itself replays, so it should say so on hover — except while the
   animations are being held still, when clicking it would do nothing. */
.spl .stage { cursor: pointer; }
@media (prefers-reduced-motion: reduce) {
  .spl:not(.spl--motion) .stage { cursor: default; }
}

/* A control that cannot do anything should look like it. */
.spl-btn[disabled], .spl-replay[disabled] { opacity: .45; cursor: not-allowed; }

/* The site-wide focus ring is the portfolio's teal, which reads as a leak
   from the host page onto a specimen. This one borrows the sample's violet. */
.spl :focus-visible { outline-color: #8b7cf6; }
