/* Loole game menu
   Layout: one phone-width column under a sticky player HUD (level, XP, bolts), with four
   views (Play, Map, Missions, Team) switched from a floating pipe dock at the bottom.
   Widens to a 4-up pipe grid on desktop.
   Style: cel-shaded cartoon, like the mascot. Flat colour with one white shine stripe and one
   hard shadow band (no soft gradients), black outlines and hard black drop shadows.
   Brand colours only: red and blue are the two teams; white marks progress and rewards
   (stars, XP, Claim). No third hue.
   Single deliberate dark look on a deep navy night ground. */
:root {
  --ink: #0B1026;          /* page ground: deep navy */
  --panel: #18204A;        /* cards */
  --panel-hi: #232C62;     /* rows inside cards, locked things */
  --track: #0E1433;        /* empty bars */
  --red: #E8232B;
  --red-dark: #B3141C;
  --blue: #2B6CF0;
  --blue-dark: #1A45B8;
  --blue-hi: #5A8FFF;      /* blue lines on dark art */
  --white: #F7F8FC;        /* cool white: text, progress, rewards */
  --white-dark: #C9D0E6;   /* cel shadow band on white things */
  --muted: #A9B3D9;
  --line: #000;            /* cartoon outline */

  /* team colour: set on <body data-team> */
  --team: var(--red);
  --team-dark: var(--red-dark);

  /* cel shading: hard-edged bands, no soft gradients */
  --cel-hi: linear-gradient(90deg, rgba(255, 255, 255, 0) 0 13%, rgba(255, 255, 255, .55) 13% 20%, rgba(255, 255, 255, 0) 20%);
  --cel-red: var(--cel-hi), linear-gradient(90deg, var(--red) 0 66%, var(--red-dark) 66%);
  --cel-blue: var(--cel-hi), linear-gradient(90deg, var(--blue) 0 66%, var(--blue-dark) 66%);
  --cel-white: linear-gradient(180deg, #FFFFFF 0 7px, var(--white) 7px 68%, var(--white-dark) 68%);
  --cel-white-x: linear-gradient(90deg, var(--white) 0 62%, var(--white-dark) 62%);
  --cel-red-x: linear-gradient(90deg, var(--red) 0 62%, var(--red-dark) 62%);
  --cel-blue-y: linear-gradient(180deg, #5B8DFF 0 5px, var(--blue) 5px 68%, var(--blue-dark) 68%);
  --pipe-drop: rgba(0, 0, 0, .6);

  --font-display: "Lilita One", "Arial Rounded MT Bold", "Trebuchet MS", system-ui, sans-serif;
  --font-body: "Fredoka", "Nunito", "Segoe UI", system-ui, sans-serif;

  --max: 520px;
  --gutter-l: max(16px, env(safe-area-inset-left, 0px));
  --gutter-r: max(16px, env(safe-area-inset-right, 0px));
  --dock-h: 60px;
  --dock-gap: 12px;
  --outline-text: 0 2px 0 var(--line), 1.5px 0 0 var(--line), -1.5px 0 0 var(--line), 0 -1.5px 0 var(--line), 1.5px 2px 0 var(--line), -1.5px 2px 0 var(--line);

  color-scheme: dark;
}
@media (min-width: 860px) {
  :root { --max: 980px; }
}
[data-team="blue"] { --team: var(--blue); --team-dark: var(--blue-dark); }

*, *::before, *::after {
  box-sizing: border-box;
  /* a game screen: nothing is text-selectable */
  -webkit-user-select: none;
  user-select: none;
}
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--ink);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 15px;
  line-height: 1.4;
  padding-bottom: calc(var(--dock-h) + var(--dock-gap) + env(safe-area-inset-bottom, 0px) + 40px);
  overflow-x: hidden;
  -webkit-tap-highlight-color: transparent;
}
/* paints the phone's status-bar band so content never scrolls under it */
body::before {
  content: "";
  position: fixed;
  inset: 0 0 auto;
  height: env(safe-area-inset-top, 0px);
  z-index: 30;
  background: var(--ink);
}
img, svg { max-width: 100%; }
img { display: block; height: auto; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; }
:focus-visible { outline: 3px solid var(--white); outline-offset: 4px; border-radius: 12px; }
h1, h2, p { margin: 0; }
.defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- animated background ---------- */
.bg { position: fixed; inset: 0; z-index: -1; overflow: hidden; background: var(--ink); pointer-events: none; }
.bg__rot { position: absolute; inset: -35%; transform: rotate(-14deg); }
.bg__pattern {
  position: absolute;
  inset: -160px;
  /* pipes, nuts, stars, water drops: all plain white */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160' viewBox='0 0 160 160'%3E%3Cg fill='none' stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5'%3E%3Cg transform='translate(30 42) rotate(-16)' stroke='rgb(247,248,252)' stroke-opacity='.17'%3E%3Crect x='-12' y='-13' width='24' height='8' rx='2.5'/%3E%3Cpath d='M-9 -5V11.5a2.5 2.5 0 0 0 2.5 2.5h13a2.5 2.5 0 0 0 2.5 -2.5V-5'/%3E%3Cpath d='M-5 -1.5V10.5' stroke-opacity='.08'/%3E%3C/g%3E%3Cg transform='translate(120 42) rotate(12)' stroke='rgb(247,248,252)' stroke-opacity='.17'%3E%3Cpolygon points='13.00,0.00 6.50,11.26 -6.50,11.26 -13.00,0.00 -6.50,-11.26 6.50,-11.26'/%3E%3Ccircle r='5'/%3E%3C/g%3E%3Cpath d='M38.0 103.0L40.8 110.1L48.5 110.6L42.6 115.5L44.5 122.9L38.0 118.8L31.5 122.9L33.4 115.5L27.5 110.6L35.2 110.1Z' stroke='rgb(247,248,252)' stroke-opacity='.16'/%3E%3Cpath transform='translate(118 112)' d='M0 -12C6 -4 9 1 9 5A9 9 0 0 1 -9 5C-9 1 -6 -4 0 -12Z' stroke='rgb(247,248,252)' stroke-opacity='.16'/%3E%3Cpath transform='translate(80 80)' d='M0 -7V7M-7 0H7' stroke='rgb(247,248,252)' stroke-opacity='.14'/%3E%3C/g%3E%3Cg fill='rgb(247,248,252)' fill-opacity='.12'%3E%3Ccircle cx='150' cy='150' r='1.6'/%3E%3Ccircle cx='72' cy='14' r='1.6'/%3E%3Ccircle cx='8' cy='78' r='1.8'/%3E%3Ccircle cx='86' cy='136' r='1.4'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 160px 160px;
  animation: drift 26s linear infinite;
  will-change: transform;
}
.bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(80% 45% at 0% 0%, rgba(232, 35, 43, .2), rgba(232, 35, 43, 0) 62%),
    radial-gradient(80% 45% at 100% 0%, rgba(43, 108, 240, .26), rgba(43, 108, 240, 0) 62%),
    radial-gradient(140% 100% at 50% 45%, rgba(11, 16, 38, 0) 40%, rgba(11, 16, 38, .85) 100%);
}
@keyframes drift { to { transform: translate3d(160px, -160px, 0); } }

/* ---------- player HUD ---------- */
.topbar {
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: 20;
  background: linear-gradient(var(--ink) 80%, rgba(11, 16, 38, 0));
}
.topbar__inner {
  max-width: var(--max);
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding-block: 12px 18px;
  padding-left: var(--gutter-l);
  padding-right: var(--gutter-r);
}
.player {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
  text-decoration: none;
}
.player__avatar {
  position: relative;
  flex: none;
  width: 48px;
  height: 48px;
}
.player__face, .face {
  position: relative;
  display: block;
  border-radius: 50%;
  border: 3px solid var(--line);
  background: var(--panel-hi);
  overflow: hidden;
}
.player__face { width: 100%; height: 100%; box-shadow: 0 0 0 2.5px var(--team), 0 4px 0 2.5px var(--line); }
/* Meppo's face fills the circle */
.player__face, .face { --mpx: 2.5; }
.player__face .meppo, .face .meppo { position: absolute; left: calc(50% - 15px * var(--mpx)); top: calc(50% - 15px * var(--mpx)); }
.player__lv {
  position: absolute;
  right: -8px;
  bottom: -6px;
  display: grid;
  place-items: center;
  min-width: 24px;
  height: 24px;
  padding: 0 5px;
  border: 2.5px solid var(--line);
  border-radius: 999px;
  background: var(--cel-white);
  color: var(--line);
  font-family: var(--font-display);
  font-size: .82rem;
  line-height: 1;
}
.player__info { display: grid; gap: 4px; width: min(150px, 100%); min-width: 0; }
.player__title {
  font-family: var(--font-display);
  font-size: 1rem;
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 2px 0 var(--line);
}
.player__xp { font-size: .7rem; font-weight: 600; line-height: 1; color: var(--muted); font-variant-numeric: tabular-nums; }
.xp, .bar {
  display: block;
  height: 11px;
  border: 2px solid var(--line);
  border-radius: 999px;
  background: var(--track);
  overflow: hidden;
}
.xp__fill, .bar__fill {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(180deg, var(--white) 0 62%, var(--white-dark) 62%);
  box-shadow: 2px 0 0 var(--line);
  transition: width .6s cubic-bezier(.34, 1.3, .64, 1);
}
.bolts {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  padding: 3px 12px 3px 4px;
  border: 3px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  box-shadow: 0 4px 0 var(--line);
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
}
.bolts svg { width: 26px; height: 26px; }
.is-bumped { animation: bump .5s cubic-bezier(.34, 1.56, .64, 1); }

/* round buttons are pipe openings seen from above */
.mouth {
  display: grid;
  place-items: center;
  flex: none;
  border-radius: 50%;
  border: 3px solid var(--line);
  color: var(--white);
  background: radial-gradient(circle closest-side, #0B0F22 0 60%, var(--line) 61% 67%, rgba(0, 0, 0, 0) 68%), linear-gradient(90deg, var(--blue) 0 62%, var(--blue-dark) 62%);
  box-shadow: 0 4px 0 var(--line);
  transition: transform .12s ease, box-shadow .12s ease;
}
.mouth--sm { width: 44px; height: 44px; }
.mouth--sm svg { width: 17px; height: 17px; }
.mouth--sm:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--line); }

/* ---------- layout ---------- */
.app {
  max-width: var(--max);
  margin: 0 auto;
  padding-left: var(--gutter-l);
  padding-right: var(--gutter-r);
}
.view { display: grid; gap: 26px; }
@media (min-width: 860px) {
  .view:not([data-view="home"]):not(.view--wide) { width: 100%; max-width: 560px; margin-inline: auto; }
  .view[data-view="home"] .missions { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.section__head, .card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.card__head { margin-bottom: 12px; }
h1, h2 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: .01em;
  text-wrap: balance;
  text-shadow: var(--outline-text);
}
h1 { font-size: 1.85rem; }
h2 { font-size: 1.35rem; }
.section__meta {
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.card {
  padding: 14px;
  border: 3px solid var(--line);
  border-radius: 18px;
  background: var(--panel);
  box-shadow: 0 5px 0 var(--line);
}

/* ---------- artist collab banner: top of Play, and the Collab page header ---------- */
.collab-banner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 104px;
  grid-template-areas: "text art" "actions art";
  column-gap: 6px;
  row-gap: 14px;
  padding: 16px 0 16px 16px;
  border: 3px solid var(--line);
  border-radius: 20px;
  overflow: hidden;
  background:
    radial-gradient(circle, rgba(255, 255, 255, .16) 1.1px, rgba(255, 255, 255, 0) 1.7px) 0 0 / 11px 11px,
    linear-gradient(118deg, var(--red) 0 58%, var(--line) 58% 59.3%, #120C0C 59.3%);
  box-shadow: 0 6px 0 var(--line);
}
.collab-banner--page { grid-template-areas: "text art"; }
.collab-banner__text { grid-area: text; display: grid; gap: 7px; align-content: start; min-width: 0; }
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-self: start;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--line);
  color: var(--white);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.live-dot { width: 7px; height: 7px; border-radius: 50%; background: #FF4A51; animation: blink 1.1s steps(2, jump-none) infinite; }
.collab-banner__title { font-size: 1.85rem; line-height: 1.02; }
.collab-banner--page .collab-banner__title { font-size: 2.1rem; }
.nowrap { white-space: nowrap; }
.collab-banner__sub { font-size: .86rem; font-weight: 700; line-height: 1.3; text-shadow: 0 1px 0 rgba(0, 0, 0, .7); }
.collab-banner__actions { grid-area: actions; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 22px; }
/* the event's Meppo dances on a pipe that comes up from the banner's floor,
   always in the full Khalse outfit, whatever your profile wears */
.collab-banner__art { grid-area: art; position: relative; align-self: end; height: 136px; margin-bottom: -16px; }
.collab-banner__mascot {
  --mpx: 4;
  --m-head: url(assets/meppo/acc-kbeanie.png);
  --m-eyes: url(assets/meppo/acc-redshades.png);
  --m-mouth: none;
  --m-neck: url(assets/meppo/acc-skullchain.png);
  position: absolute;
  z-index: 1;
  left: calc(50% - 8px);          /* room for the cap's brim when he turns right and leans */
  bottom: -52px;
  transform: translateX(-50%);
}
a.pipe-btn { text-decoration: none; }

/* ---------- team battle strip ---------- */
.team-strip {
  display: grid;
  grid-template-columns: 50px minmax(0, 1fr) 50px;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 3px solid var(--line);
  border-radius: 18px;
  background: var(--panel);
  box-shadow: 0 5px 0 var(--line);
  text-decoration: none;
  transition: transform .12s ease, box-shadow .12s ease;
}
.team-strip:active { transform: translateY(3px); box-shadow: 0 2px 0 var(--line); }
.face { width: 50px; height: 50px; }
.face--red { --team: var(--red); --team-dark: var(--red-dark); }
.face--blue { --team: var(--blue); --team-dark: var(--blue-dark); }
/* the two teams look at each other */
.team-strip .face--red .meppo { left: calc(50% - 17px * var(--mpx)); transform: scaleX(-1); }
.face.is-you { box-shadow: 0 0 0 3px var(--white); }
.team-strip__mid { display: grid; gap: 4px; min-width: 0; }
.team-strip__row { display: flex; justify-content: space-between; gap: 8px; font-size: .78rem; font-weight: 600; color: var(--muted); }
.team-strip__title { font-family: var(--font-display); font-size: 1rem; font-weight: 400; color: var(--white); text-shadow: 0 2px 0 var(--line); }
.team-strip__left { align-self: center; font-variant-numeric: tabular-nums; }
.team-strip__nums { font-variant-numeric: tabular-nums; }
.team-strip__nums > span:first-child { color: #FF8A8F; }
.team-strip__nums > span:last-child { color: #8FB4FF; }
.tug {
  position: relative;
  display: block;
  height: 14px;
  border: 2.5px solid var(--line);
  border-radius: 999px;
  background: linear-gradient(180deg, #5B8DFF 0 3px, var(--blue) 3px 70%, var(--blue-dark) 70%);
  overflow: hidden;
}
.tug__red {
  display: block;
  height: 100%;
  width: 50%;
  background: linear-gradient(180deg, #FF6B71 0 3px, var(--red) 3px 70%, var(--red-dark) 70%);
  box-shadow: 2.5px 0 0 var(--line);
  transition: width .6s ease;
}
.tug--lg { height: 20px; }

/* ---------- the three game categories on the Play page ---------- */
/* phones: two pipes, then the third centred under them at the same size; desktop: one row */
.lobby { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px 16px; }
.lobby > .pipe:nth-of-type(2) { --pipe: var(--cel-blue); }
.lobby > .pipe:nth-of-type(3) { grid-column: 1 / -1; width: min(calc((100% - 16px) / 2), 184px); }
@media (min-width: 860px) {
  .lobby { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px 24px; max-width: 680px; margin-inline: auto; width: 100%; }
  .lobby > .pipe:nth-of-type(3) { grid-column: auto; width: min(100%, 184px); }
}

/* ---------- a category page: back button and title, a line about where the games run, the games ---------- */
.cat-head { display: flex; align-items: center; gap: 14px; }
.cat-head h1 { flex: 1; min-width: 0; }
.cat-intro { max-width: 62ch; color: var(--muted); font-weight: 600; line-height: 1.45; }
.cat-intro strong { color: var(--white); }
.cat-note { text-align: center; color: var(--muted); font-weight: 600; }
.game-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px 16px; }
/* red and blue in a checkerboard: 2 columns on phones */
.game-grid > .pipe:nth-child(4n+2), .game-grid > .pipe:nth-child(4n+3) { --pipe: var(--cel-blue); }
.game-grid--single { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 860px) {
  .game-grid { grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr)); gap: 28px 24px; }
  .game-grid--3 { --cols: 3; max-width: 680px; margin-inline: auto; width: 100%; }
  .game-grid--5 { --cols: 5; }
  .game-grid--single { --cols: 1; }
  /* odd column counts make a checkerboard out of plain alternation */
  .game-grid > .pipe:nth-child(n) { --pipe: var(--cel-red); }
  .game-grid > .pipe:nth-child(even) { --pipe: var(--cel-blue); }
}
.soon-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.chip { padding: 5px 12px; border: 2px solid var(--line); border-radius: 999px; background: var(--panel-hi); color: var(--muted); font-size: .82rem; font-weight: 700; }

/* ---------- pipe buttons ---------- */
/* Pipes are a fixed shape. Every part is sized in cqi (1% of the pipe's own width),
   so the pipe scales as one drawing and never stretches with its grid column.
   Proportions are taken from the 171px phone pipe. */
.pipe {
  --pipe: var(--cel-red);
  container-type: inline-size;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-self: center;
  width: min(100%, 184px);
  text-align: center;
  filter: drop-shadow(0 7px 0 var(--pipe-drop));
  transition: transform .12s ease, filter .12s ease;
  animation: pop .6s cubic-bezier(.34, 1.56, .64, 1) backwards;
  animation-delay: calc(var(--i, 0) * 70ms + 200ms);
}
a.pipe { color: inherit; text-decoration: none; }
.pipe:focus-visible { outline-offset: 6px; border-radius: 18px; }
/* the game rises out of the pipe; its bottom edge is tucked behind the rim */
.pipe__art {
  position: relative;
  z-index: 1;
  display: block;
  width: 82%;
  aspect-ratio: 160 / 124; /* the bottom 14 units of each drawing sit behind the rim */
  margin-bottom: -7cqi;
  border: 3px solid var(--line);
  border-bottom: 0;
  border-radius: 9.4cqi 9.4cqi 0 0;
  overflow: hidden;
  background: var(--panel);
  transition: transform .22s cubic-bezier(.34, 1.56, .64, 1);
}
.pipe__art svg { display: block; width: 100%; height: 100%; }
.pipe__rim {
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  aspect-ratio: 171 / 30;
  border: 3px solid var(--line);
  border-radius: 5.85cqi;
  background: var(--pipe);
}
.pipe__rim::before {
  content: "";
  position: absolute;
  left: 4.7cqi;
  right: 4.7cqi;
  top: 1.75cqi;
  height: 2.35cqi;
  border-radius: 4px;
  background: rgba(247, 248, 252, .42);
}
.pipe__body {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 82%;
  height: 38cqi;
  padding: 0 3.5cqi 1.75cqi;
  border: 3px solid var(--line);
  border-top: 0;
  border-radius: 0 0 7cqi 7cqi;
  background: linear-gradient(180deg, rgba(0, 0, 0, .3) 0 4cqi, rgba(0, 0, 0, 0) 4cqi), var(--pipe);
}
.pipe__name {
  font-family: var(--font-display);
  font-size: 12.4cqi;
  line-height: 1.05;
  color: var(--white);
  text-shadow: var(--outline-text);
  overflow-wrap: anywhere;
}

@media (hover: hover) {
  .pipe:hover .pipe__art { transform: translateY(-3cqi); }
}
/* press: the pipe dips and the game sinks back inside */
.pipe:active { transform: translateY(4px); filter: drop-shadow(0 3px 0 var(--pipe-drop)); }
.pipe:active .pipe__art { transform: translateY(6cqi); }

/* small badge on a category pipe: how many games it has */
.pill {
  position: absolute;
  top: 4cqi;
  right: 4cqi;
  display: inline-flex;
  align-items: center;
  gap: .8cqi;
  padding: .9cqi 3cqi;
  border: 2px solid var(--line);
  border-radius: 999px;
  background: var(--ink);
  color: var(--white);
  font-size: 6.2cqi;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1.2;
}
.star-off { --star: #3A4580; }

/* ---------- game art motion ---------- */
.plinko-ball { transform: translate(110px, 98px); animation: plinko 3.4s infinite; }
.plinko-hit { animation: bin-hit 3.4s infinite; }
@keyframes plinko {
  0%   { transform: translate(80px, -8px); opacity: 0; animation-timing-function: ease-in; }
  6%   { opacity: 1; }
  14%  { transform: translate(80px, 12px); animation-timing-function: ease-out; }
  26%  { transform: translate(70px, 28px); animation-timing-function: ease-out; }
  38%  { transform: translate(80px, 44px); animation-timing-function: ease-out; }
  50%  { transform: translate(90px, 60px); animation-timing-function: ease-out; }
  62%  { transform: translate(100px, 76px); animation-timing-function: ease-in; }
  74%  { transform: translate(110px, 92px); opacity: 1; }
  90%  { transform: translate(110px, 92px); opacity: 1; }
  100% { transform: translate(110px, 92px); opacity: 0; }
}
@keyframes bin-hit {
  0%, 73%, 100% { fill: #F7F8FC; }
  76%, 90% { fill: #FF8A8F; }
}

/* Diamond: one tile flips open to show a diamond, two sparkles twinkle */
.dm-cover, .dm-found, .dm-spark { transform-box: fill-box; transform-origin: center; }
.dm-cover { animation: dm-flip 3.2s ease-in-out infinite; }
.dm-found { animation: dm-pop 3.2s ease-in-out infinite; }
.dm-spark { animation: dm-twinkle 1.8s ease-in-out infinite; }
.dm-spark--b { animation-delay: -.9s; }
@keyframes dm-flip { 0%, 20% { transform: scaleX(1); } 30%, 80% { transform: scaleX(0); } 90%, 100% { transform: scaleX(1); } }
@keyframes dm-pop { 0%, 26% { transform: scale(.4); } 36% { transform: scale(1.18); } 42%, 100% { transform: scale(1); } }
@keyframes dm-twinkle { 0%, 100% { opacity: .15; transform: scale(.4) rotate(0); } 50% { opacity: 1; transform: scale(1) rotate(45deg); } }

/* FIFA: the ball rolls into the goal, the net flashes, GOAL! pops */
.fifa-ball { transform: translate(46px, 80px); animation: fifa-ball 3.6s infinite; }
@keyframes fifa-ball {
  0%   { transform: translate(46px, 80px) rotate(0deg); opacity: 0; }
  6%   { opacity: 1; }
  38%  { transform: translate(96px, 48px) rotate(300deg); animation-timing-function: ease-in; }
  56%  { transform: translate(152px, 58px) rotate(620deg); }
  86%  { transform: translate(152px, 58px) rotate(620deg); opacity: 1; }
  100% { transform: translate(152px, 58px) rotate(620deg); opacity: 0; }
}
.fifa-flash { opacity: 0; animation: fifa-flash 3.6s infinite; }
@keyframes fifa-flash { 0%, 55% { opacity: 0; } 58% { opacity: .5; } 72%, 100% { opacity: 0; } }
.fifa-goal {
  font-family: var(--font-display);
  font-size: 18px;
  fill: var(--white);
  stroke: var(--line);
  stroke-width: 4px;
  paint-order: stroke;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: fifa-goal 3.6s infinite;
}
@keyframes fifa-goal { 0%, 55% { opacity: 0; transform: scale(.4); } 62% { opacity: 1; transform: scale(1.15); } 68%, 86% { opacity: 1; transform: scale(1); } 94%, 100% { opacity: 0; transform: scale(1); } }

.crash-line { stroke: var(--blue-hi); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 6; }
.crash-flame { transform-box: fill-box; transform-origin: 100% 50%; animation: flicker .12s ease-in-out infinite alternate; }
.crash-alt {
  font-family: var(--font-display);
  font-size: 23px;
  fill: var(--white);
  stroke: var(--line);
  stroke-width: 4px;
  paint-order: stroke;
  font-variant-numeric: tabular-nums;
}
.crash-status { font-family: var(--font-display); font-size: 12px; letter-spacing: .08em; fill: var(--white); stroke: var(--line); stroke-width: 3px; paint-order: stroke; }
.is-crashed .crash-alt { fill: #FF8A8F; }
.boom { transform-box: fill-box; transform-origin: center; }
.is-crashed .boom { animation: boom .45s cubic-bezier(.34, 1.56, .64, 1) backwards; }

/* HiLo: the face-up card flips, the arrows pulse in turn */
.hilo-card { transform-box: fill-box; transform-origin: center; animation: hilo-flip 3s ease-in-out infinite; }
@keyframes hilo-flip { 0%, 62%, 100% { transform: scaleX(1); } 72% { transform: scaleX(.05); } 82% { transform: scaleX(1); } }
.hilo-big { font-family: var(--font-display); font-size: 36px; fill: var(--red); }
.hilo-small { font-family: var(--font-display); font-size: 12px; fill: var(--red); }
.hilo-up, .hilo-down { transform-box: fill-box; transform-origin: center; animation: hilo-pulse 1.5s ease-in-out infinite; }
.hilo-down { animation-delay: -.75s; }
@keyframes hilo-pulse { 50% { transform: scale(1.14); } }

/* Roulette: the wheel turns one way, the ball runs the other */
.rl-wheel { transform-origin: 80px 62px; animation: spin 7s linear infinite; }
.rl-ball { transform-origin: 80px 62px; animation: spin 2.2s linear infinite reverse; }

/* console game icons float gently, alternating */
.gi-float { transform-box: fill-box; transform-origin: center; animation: gi-float 3.2s ease-in-out infinite; }
.game-grid > .pipe:nth-child(odd) .gi-float { animation-delay: -1.6s; }
@keyframes gi-float { 50% { transform: translateY(-5px) rotate(-3deg); } }

.ck-d circle { fill: #1F1416; stroke: #000; stroke-width: 1.3; }
.ck-l circle { fill: #F7F8FC; stroke: #000; stroke-width: 1.3; }
.nard-die { transform-box: fill-box; transform-origin: center; animation: tumble 2.8s ease-in-out infinite; }
.nard-die--b { animation-delay: -.35s; }

.bridge-die { animation: bob 2.5s ease-in-out infinite; animation-delay: var(--d, 0s); }
.lava { animation: lava 3s linear infinite; }
.pawn { transform: translate(80px, 56px); animation: hop 6s infinite; }
@keyframes hop {
  0%   { transform: translate(16px, 67px); opacity: 0; }
  4%   { transform: translate(16px, 67px); opacity: 1; animation-timing-function: ease-out; }
  9%   { transform: translate(29px, 46px); animation-timing-function: ease-in; }
  14%  { transform: translate(42px, 56px); animation-timing-function: ease-out; }
  21%  { transform: translate(51.5px, 42px); animation-timing-function: ease-in; }
  28%  { transform: translate(61px, 56px); animation-timing-function: ease-out; }
  35%  { transform: translate(70.5px, 42px); animation-timing-function: ease-in; }
  42%  { transform: translate(80px, 56px); animation-timing-function: ease-out; }
  49%  { transform: translate(89.5px, 42px); animation-timing-function: ease-in; }
  56%  { transform: translate(99px, 56px); animation-timing-function: ease-out; }
  63%  { transform: translate(108.5px, 42px); animation-timing-function: ease-in; }
  70%  { transform: translate(118px, 56px); animation-timing-function: ease-out; }
  77%  { transform: translate(131px, 46px); animation-timing-function: ease-in; }
  84%  { transform: translate(144px, 67px); opacity: 1; }
  95%  { transform: translate(144px, 67px); opacity: 1; }
  100% { transform: translate(144px, 67px); opacity: 0; }
}

/* ---------- missions ---------- */
.missions { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.mission {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border: 2.5px solid var(--line);
  border-radius: 14px;
  background: var(--panel-hi);
}
.mission.is-ready { box-shadow: inset 0 0 0 2px var(--white); }
.mission.is-claimed { background: var(--track); }
.mission.is-claimed .mission__icon, .mission.is-claimed .mission__main { opacity: .55; }
.mission__icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 2.5px solid var(--line);
  border-radius: 50%;
  background: var(--ink);
}
.mission__icon svg { width: 24px; height: 24px; }
.mission__main { display: grid; gap: 6px; min-width: 0; }
.mission__text { font-weight: 600; font-size: .92rem; line-height: 1.25; }
.mission__end {
  display: grid;
  justify-items: end;
  gap: 1px;
  min-width: 62px;
  text-align: right;
}
.mission__count { font-family: var(--font-display); font-size: 1rem; font-variant-numeric: tabular-nums; }
.mission__reward { font-size: .72rem; font-weight: 700; color: var(--muted); white-space: nowrap; }
.mission__done { display: inline-flex; align-items: center; gap: 4px; font-weight: 700; font-size: .85rem; color: var(--muted); }
.mission__done svg { width: 16px; height: 16px; }
.mission.is-ready .mission__end { padding-right: 12px; }

/* horizontal pipe: the body is the button, the flange at the right is the pipe end */
.pipe-btn {
  --btn: var(--cel-white);
  position: relative;
  z-index: 1;
  display: inline-grid;
  place-items: center;
  min-width: 96px;
  height: 44px;
  padding: 0 16px 0 14px;
  border: 3px solid var(--line);
  border-right: 0;
  border-radius: 12px 0 0 12px;
  background: var(--btn);
  color: var(--line);
  font-family: var(--font-display);
  font-size: 1.1rem;
  letter-spacing: .02em;
  white-space: nowrap;
  box-shadow: 0 4px 0 var(--line);
  transition: transform .12s ease, box-shadow .12s ease;
}
.pipe-btn::after {
  content: "";
  position: absolute;
  top: -7px;
  bottom: -7px;
  right: -12px;
  width: 15px;
  border: 3px solid var(--line);
  border-radius: 6px;
  background: inherit;
  box-shadow: 0 4px 0 var(--line);
}
.pipe-btn:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--line); }
.pipe-btn:active::after { box-shadow: 0 1px 0 var(--line); }
.pipe-btn--sm { min-width: 74px; height: 36px; font-size: 1rem; padding: 0 12px 0 11px; }
.pipe-btn--sm::after { top: -6px; bottom: -6px; right: -11px; width: 13px; }
/* the rival team's colour, as cel bands across the height */
.pipe-btn--rival {
  --btn: linear-gradient(180deg, #5B8DFF 0 7px, var(--blue) 7px 68%, var(--blue-dark) 68%);
  color: var(--white);
  text-shadow: 0 2px 0 var(--line);
}
[data-team="blue"] .pipe-btn--rival { --btn: linear-gradient(180deg, #FF6B71 0 7px, var(--red) 7px 68%, var(--red-dark) 68%); }
.text-btn { font-weight: 700; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; padding: 8px 4px; }

/* ---------- map ---------- */
.map { position: relative; min-height: 400px; }
.map__path { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
.road-edge { fill: none; stroke: var(--line); stroke-width: 18; stroke-linecap: round; }
.road { fill: none; stroke: var(--panel-hi); stroke-width: 12; stroke-linecap: round; }
.road-dash { fill: none; stroke: var(--muted); stroke-opacity: .5; stroke-width: 2.5; stroke-dasharray: 2 12; stroke-linecap: round; }
.road-done { fill: none; stroke: var(--white); stroke-width: 12; stroke-linecap: round; }
.zone {
  position: absolute;
  left: 50%;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 16px;
  border: 3px solid var(--line);
  border-radius: 12px;
  background: var(--cel-red);
  box-shadow: 0 4px 0 var(--line);
  font-family: var(--font-display);
  font-size: 1.1rem;
  white-space: nowrap;
  text-shadow: 0 2px 0 var(--line);
  transform: translate(-50%, -50%);
}
.zone--blue { background: var(--cel-blue); }
.stage {
  --stage: var(--cel-red);
  position: absolute;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border: 3px solid var(--line);
  border-radius: 50%;
  background: var(--stage);
  box-shadow: 0 5px 0 var(--line);
  font-family: var(--font-display);
  font-size: 1.3rem;
  text-shadow: var(--outline-text);
  transform: translate(-50%, -50%);
  transition: box-shadow .12s ease;
}
.stage--blue { --stage: var(--cel-blue); }
.stage:active { box-shadow: 0 2px 0 var(--line); translate: 0 3px; }
.stage__stars { position: absolute; top: calc(100% + 6px); left: 50%; display: flex; gap: 1px; width: max-content; transform: translateX(-50%); }
.stage__stars svg { flex: none; width: 16px; height: 16px; }
.stage.is-locked { background: var(--panel-hi); color: var(--muted); }
.stage.is-locked svg { width: 24px; height: 24px; }
.stage.is-current {
  width: 66px;
  height: 66px;
  background: var(--cel-white-x);
  color: var(--line);
  font-size: 1.5rem;
  text-shadow: none;
}
.stage.is-current::after {
  content: "";
  position: absolute;
  inset: -10px;
  border: 3px solid var(--white);
  border-radius: 50%;
  animation: ring 1.6s ease-out infinite;
}
/* Meppo waits on top of your next stage */
.map__me {
  --mpx: 2;
  position: absolute;
  z-index: 1;
  transform: translate(-50%, calc(-100% - 8px));
}
.map__end { position: absolute; left: 0; right: 0; text-align: center; font-weight: 600; color: var(--muted); }

/* ---------- team view ---------- */
.faceoff {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 8px 6px;
  text-align: center;
}
.faceoff__side { display: grid; justify-items: center; gap: 4px; min-width: 0; }
/* each team's Meppo stands on its own pipe; they face each other */
.faceoff__stage { position: relative; display: block; width: 84px; height: 96px; overflow: hidden; border-bottom: 3px solid var(--line); }
.faceoff__stage .m-stand { --mpx: 2.5; position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%); }
.faceoff__stage.face--red .meppo { transform: scaleX(-1); }
.faceoff__name { font-family: var(--font-display); font-size: 1.15rem; text-shadow: 0 2px 0 var(--line); }
.faceoff__score { font-family: var(--font-display); font-size: 1.5rem; font-variant-numeric: tabular-nums; text-shadow: var(--outline-text); }
.faceoff__side:first-child .faceoff__score { color: #FF8A8F; }
.faceoff__side:nth-child(3) .faceoff__score { color: #8FB4FF; }
.vs {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border: 3px solid var(--line);
  border-radius: 50%;
  background: linear-gradient(135deg, var(--red) 0 50%, var(--blue) 50%);
  color: var(--white);
  font-family: var(--font-display);
  font-size: 1.2rem;
  text-shadow: var(--outline-text);
  box-shadow: 0 4px 0 var(--line);
  transform: rotate(-8deg);
}
.faceoff__bar { grid-column: 1 / -1; display: grid; gap: 4px; margin-top: 6px; }
.faceoff__pcts { display: flex; justify-content: space-between; font-family: var(--font-display); font-size: 1rem; }
.faceoff__pcts span:first-child { color: #FF8A8F; }
.faceoff__pcts span:last-child { color: #8FB4FF; }
.team-me { display: grid; gap: 16px; justify-items: start; padding-right: 26px; }
.team-me__row { display: flex; align-items: center; gap: 14px; }
.face--mine { --mpx: 3; flex: none; width: 58px; height: 58px; box-shadow: 0 0 0 3px var(--team); }
.team-me__title { font-size: 1.2rem; }
.team-me__text { margin-top: 2px; color: var(--muted); }
.team-me__text strong { color: var(--white); font-variant-numeric: tabular-nums; }
.confirm { display: grid; gap: 12px; width: 100%; padding: 12px; border: 2.5px solid var(--line); border-radius: 14px; background: var(--panel-hi); }
.confirm__actions { display: flex; align-items: center; gap: 22px; }
.rules { margin: 10px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.rules li { position: relative; padding-left: 26px; color: var(--muted); }
.rules li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .15em;
  width: 16px;
  height: 16px;
  background: var(--white);
  clip-path: polygon(50% 0, 63% 35%, 100% 38%, 71% 61%, 80% 100%, 50% 78%, 20% 100%, 29% 61%, 0 38%, 37% 35%);
}

/* ---------- dock: one floating pipe with end caps ---------- */
.dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 25;
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + var(--dock-gap));
  padding-left: calc(var(--gutter-l) + 12px);
  padding-right: calc(var(--gutter-r) + 12px);
  pointer-events: none;
}
.dock__pipe {
  position: relative;
  max-width: 460px;
  height: var(--dock-h);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  border: 3px solid var(--line);
  border-left: 0;
  border-right: 0;
  background: var(--cel-blue-y);
  filter: drop-shadow(0 5px 0 var(--pipe-drop));
  pointer-events: auto;
}
/* flanges: the pipe's two end caps */
.dock__pipe::before, .dock__pipe::after {
  content: "";
  position: absolute;
  top: -10px;
  bottom: -10px;
  width: 18px;
  border: 3px solid var(--line);
  border-radius: 7px;
  background: linear-gradient(180deg, #5B8DFF 0 7px, var(--blue) 7px 68%, var(--blue-dark) 68%);
}
.dock__pipe::before { left: -12px; }
.dock__pipe::after { right: -12px; }
.dock__tab {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 1px;
  padding-bottom: 6px;
  color: var(--white);
  text-decoration: none;
}
.dock__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: -6px;
  border: 3px solid transparent;
  border-radius: 50%;
  transition: transform .3s cubic-bezier(.34, 1.56, .64, 1), background-color .2s;
}
.dock__icon svg { width: 25px; height: 25px; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .55)); }
.dock__label { font-size: .72rem; font-weight: 700; letter-spacing: .02em; color: rgba(247, 248, 252, .82); text-shadow: 0 1px 0 rgba(0, 0, 0, .7); }
/* active tab: the icon pops up out of the blue pipe into a red opening */
.dock__tab.is-active .dock__icon {
  transform: translateY(-22px);
  border-color: var(--line);
  background: var(--cel-red-x);
  color: var(--white);
  box-shadow: 0 4px 0 var(--line);
}
.dock__tab.is-active .dock__label { color: var(--white); }
.dock__tab:active .dock__icon { translate: 0 2px; }
/* while the mascot talks, the raised icon ducks back into the pipe to make room */
.is-talking .dock__tab.is-active .dock__icon { transform: translateY(-3px) scale(.8); }
.is-talking .dock__tab.is-active .dock__badge { top: 2px; left: calc(50% + 8px); }
.dock__badge {
  position: absolute;
  top: 2px;
  left: calc(50% + 8px);
  display: grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border: 2.5px solid var(--line);
  border-radius: 999px;
  background: var(--red);
  color: var(--white);
  font-family: var(--font-display);
  font-size: .78rem;
  line-height: 1;
  animation: badge 1.6s ease-in-out infinite;
}
.dock__tab.is-active .dock__badge { top: -18px; left: calc(50% + 12px); }
@media (min-width: 860px) {
  .dock__pipe { max-width: 540px; }
}
.dock__badge--dot { min-width: 14px; width: 14px; height: 14px; padding: 0; top: 7px; left: calc(50% + 9px); }

/* ---------- the mascot that talks ---------- */
.buddy {
  position: fixed;
  z-index: 24; /* just under the dock, so the mascot rises out from behind it */
  left: calc(var(--gutter-l) + 14px);
  right: var(--gutter-r);
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--dock-gap) + 50px);
  display: flex;
  align-items: flex-end;
  gap: 10px;
  pointer-events: none;
  /* nothing below this box shows, so the dropping mascot vanishes behind the bar */
  clip-path: inset(-400px -400px 0 -400px);
}
/* Meppo pops up out of a pipe behind the bottom bar */
.buddy__mascot {
  --mpx: 2;
  flex: none;
  transform: translateY(105%);
  transition: transform .45s cubic-bezier(.34, 1.56, .64, 1);
}
.buddy__bubble {
  position: relative;
  max-width: 280px;
  margin-bottom: 70px;
  padding: 10px 14px;
  border: 3px solid var(--line);
  border-radius: 16px;
  background: var(--white);
  color: var(--line);
  font-weight: 600;
  line-height: 1.3;
  box-shadow: 0 4px 0 var(--line);
  transform: scale(.4);
  transform-origin: 0 100%;
  opacity: 0;
  transition: transform .3s cubic-bezier(.34, 1.56, .64, 1) .12s, opacity .15s .12s;
}
.buddy__bubble::before {
  content: "";
  position: absolute;
  left: -14px;
  bottom: 10px;
  border: 8px solid transparent;
  border-right: 12px solid var(--line);
  border-left: 0;
}
.buddy.is-up .buddy__mascot { transform: translateY(0); }
.buddy.is-up .buddy__bubble { transform: scale(1); opacity: 1; }
.confetti {
  position: fixed;
  z-index: 23; /* behind the mascot and its speech bubble */
  width: 9px;
  height: 12px;
  border: 1.5px solid var(--line);
  border-radius: 2px;
  pointer-events: none;
  animation: confetti 1.1s cubic-bezier(.2, .6, .4, 1) forwards;
}

/* ---------- loading screen ---------- */
body.is-loading, body.is-show { overflow: hidden; }
.splash {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  overflow: hidden;
  padding-block: 24px;
  padding-left: var(--gutter-l);
  padding-right: var(--gutter-r);
  background: radial-gradient(70% 55% at 50% 42%, #1E2A63 0%, var(--ink) 72%);
  transition: opacity .45s ease, transform .45s ease;
}
.splash.is-leaving { opacity: 0; transform: scale(1.08); pointer-events: none; }
.splash__rays {
  position: absolute;
  left: 50%;
  top: 42%;
  width: 760px;
  aspect-ratio: 1 / 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg, rgba(247, 248, 252, .07) 0deg 9deg, rgba(247, 248, 252, 0) 9deg 18deg);
  -webkit-mask: radial-gradient(circle closest-side, #000 20%, rgba(0, 0, 0, 0) 100%);
  mask: radial-gradient(circle closest-side, #000 20%, rgba(0, 0, 0, 0) 100%);
  animation: spin 40s linear infinite;
  pointer-events: none;
}
.splash__inner { position: relative; display: grid; justify-items: center; gap: 22px; width: min(100%, 320px); }
.splash__title {
  font-family: var(--font-display);
  font-size: 3.6rem;
  line-height: 1;
  text-shadow: var(--outline-text), 0 6px 0 var(--line);
  animation: logo-in .8s cubic-bezier(.34, 1.56, .64, 1) backwards;
}
/* Meppo peeks out of a pipe while the game loads (the event reel's intro), then hops out onto it.
   The peek window ends at the rim, so nothing of him shows beside the pipe. */
.splash__stage {
  --mpx: 4;
  /* like the reel: he peeks out plain, and hops out in the full Khalse outfit */
  --m-head: none; --m-eyes: none; --m-mouth: none; --m-neck: none;
  position: relative;
  width: calc(32px * var(--mpx));
  height: calc(46px * var(--mpx));
  clip-path: inset(-200px -200px 0 -200px);            /* only the bottom edge cuts the pipe off */
}
.splash.is-ready .splash__stage { --m-head: url(assets/meppo/acc-kbeanie.png); --m-eyes: url(assets/meppo/acc-redshades.png); --m-neck: url(assets/meppo/acc-skullchain.png); }
.splash__pipe { position: absolute; left: 50%; top: calc(31px * var(--mpx)); margin-top: 0; translate: -50% 0; animation: pipe-rise .6s cubic-bezier(.2, .9, .3, 1.15) backwards; }
.splash__peek { position: absolute; left: 0; right: 0; top: 0; height: calc(31px * var(--mpx)); overflow: hidden; }
.splash__meppo { position: absolute; left: 50%; top: 0; translate: -50% 0; transform: translateY(calc(32px * var(--mpx))); animation: meppo-peek 2.8s ease-in-out .7s infinite; }
.splash.is-ready .splash__meppo { animation: meppo-hop .45s cubic-bezier(.34, 1.56, .64, 1) forwards; }
@keyframes pipe-rise { from { transform: translateY(100%); } }
@keyframes meppo-peek {
  0%, 100% { transform: translateY(calc(32px * var(--mpx))); }               /* inside the pipe */
  14%, 34% { transform: translateY(calc(13px * var(--mpx))); }               /* eyes over the rim */
  38%, 56% { transform: translateY(calc(13px * var(--mpx))) scaleX(-1); }    /* looks the other way */
  60%, 74% { transform: translateY(calc(13px * var(--mpx))); }
  88% { transform: translateY(calc(32px * var(--mpx))); }
}
@keyframes meppo-hop { from { transform: translateY(calc(32px * var(--mpx))); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) {
  .splash__pipe, .splash__meppo, .splash.is-ready .splash__meppo { animation: none; }
  .splash__meppo { transform: none; }
}
/* the loading bar is a pipe: red cap, white flow, blue cap */
.loader {
  position: relative;
  width: calc(100% - 26px);
  height: 24px;
  border: 3px solid var(--line);
  border-left: 0;
  border-right: 0;
  background: var(--track);
}
.loader::before, .loader::after {
  content: "";
  position: absolute;
  z-index: 1;
  top: -8px;
  bottom: -8px;
  width: 16px;
  border: 3px solid var(--line);
  border-radius: 6px;
}
.loader::before { left: -13px; background: var(--cel-red-x); }
.loader::after { right: -13px; background: linear-gradient(90deg, var(--blue) 0 62%, var(--blue-dark) 62%); }
.loader__fill { display: block; height: 100%; width: 0; background: linear-gradient(180deg, #FFF 0 32%, var(--white) 32% 66%, var(--white-dark) 66%); transition: width .35s ease; }
.splash__start { min-width: 190px; height: 54px; font-size: 1.35rem; animation: start-pulse 1.5s ease-in-out infinite; }
.splash__tip { min-height: 2.8em; max-width: 30ch; text-align: center; color: var(--muted); font-weight: 600; }

/* ---------- music and death mode buttons ---------- */
.music-btn[aria-pressed="true"] .music-btn__off, .music-btn[aria-pressed="false"] .music-btn__on { display: none; }
.music-btn[aria-pressed="false"] {
  color: var(--muted);
  background: radial-gradient(circle closest-side, #0B0F22 0 60%, var(--line) 61% 67%, rgba(0, 0, 0, 0) 68%), linear-gradient(90deg, var(--panel-hi) 0 62%, var(--track) 62%);
}
/* the death mode button is a pipe too: black with a skull, bone white while death mode is on */
.death-btn {
  --btn: linear-gradient(180deg, #5A5D70 0 7px, #2B2D3A 7px 68%, #15161E 68%);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 14px 0 6px;
  color: var(--white);
  text-shadow: 0 2px 0 var(--line);
}
.death-btn svg { flex: none; width: 26px; height: 26px; }
.death-btn[aria-pressed="true"] { --btn: linear-gradient(180deg, #FFF 0 7px, #EDE6D6 7px 68%, #C9BFA8 68%); color: var(--line); text-shadow: none; }

/* ---------- collab page ---------- */
.label { font-size: .7rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.np { display: grid; gap: 14px; padding-right: 26px; }
.np__row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px; }
.np__play { width: 58px; height: 58px; }
.np__play svg { width: 22px; height: 22px; }
.np__play[data-playing="true"] .np__icon-play, .np__play[data-playing="false"] .np__icon-pause { display: none; }
.np__play:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--line); }
.np__info { display: grid; gap: 2px; min-width: 0; }
.np__title { font-size: 1.45rem; }
.np__credit { font-size: .84rem; font-weight: 600; color: var(--muted); }
.np__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; }
.eq { display: flex; align-items: flex-end; gap: 3px; height: 32px; }
.eq span { width: 7px; height: 100%; border: 1.5px solid var(--line); border-radius: 3px; background: var(--white); transform-origin: 50% 100%; transform: scaleY(.15); }

/* the album: the cover, and the places to stream it */
.album {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr);
  align-items: center;
  gap: 14px 16px;
  overflow: hidden;
  background: radial-gradient(120% 90% at 0% 0%, rgba(232, 35, 43, .3), rgba(232, 35, 43, 0) 58%), var(--panel);
}
.album__art { position: relative; width: 150px; height: 124px; display: grid; place-items: center; }
.album__cover {
  position: relative;
  z-index: 1;
  width: 124px;
  height: 124px;
  object-fit: cover;
  border: 3px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 5px 0 var(--line);
}
.album__info { display: grid; gap: 4px; min-width: 0; }
.album__title { font-size: 1.6rem; text-shadow: var(--outline-text); }
.album__meta { font-weight: 700; }
.album__note { font-size: .8rem; color: var(--muted); }
.album__note strong { color: var(--white); }
.album__stream { grid-column: 1 / -1; display: grid; gap: 12px; padding-top: 4px; }
.streams { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 8px; }
@media (min-width: 860px) { .streams { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.stream {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 7px;
  padding: 2px;
  border-radius: 12px;
  color: var(--white);
  font-size: .78rem;
  font-weight: 700;
  line-height: 1.15;
  text-align: center;
  text-decoration: none;
}
/* brand tile, cel-shaded like the pipes */
.stream__logo {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border: 3px solid var(--line);
  border-radius: 17px;
  background:
    linear-gradient(90deg, rgba(255, 255, 255, 0) 0 14%, rgba(255, 255, 255, .35) 14% 22%, rgba(255, 255, 255, 0) 22%),
    linear-gradient(90deg, var(--brand) 0 66%, color-mix(in srgb, var(--brand), #000 22%) 66%);
  color: var(--logo-ink, #FFF);
  box-shadow: 0 4px 0 var(--line);
  transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), box-shadow .18s ease;
}
.stream__logo svg { width: 28px; height: 28px; }
@media (hover: hover) { .stream:hover .stream__logo { transform: translateY(-3px) rotate(-5deg); } }
.stream:active .stream__logo { transform: translateY(3px); box-shadow: 0 1px 0 var(--line); }

.outfit { display: grid; grid-template-columns: 116px minmax(0, 1fr); align-items: center; gap: 16px; }
/* the preview always shows every piece */
.outfit__preview {
  --m-head: url(assets/meppo/acc-kbeanie.png);
  --m-eyes: url(assets/meppo/acc-redshades.png);
  --m-mouth: none;
  --m-neck: url(assets/meppo/acc-skullchain.png);
  position: relative;
  height: 146px;
  border: 2.5px solid var(--line);
  border-radius: 14px;
  background: radial-gradient(circle at 50% 35%, #2C3878, var(--track) 72%);
  overflow: hidden;
}
.outfit__preview .m-stand { --mpx: 3; position: absolute; left: 50%; bottom: -24px; transform: translateX(-50%); }
.outfit__info { display: grid; gap: 8px; justify-items: start; min-width: 0; }
.outfit__text { font-size: .88rem; color: var(--muted); }
.outfit__parts { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.part { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px 3px 4px; border: 2px solid var(--line); border-radius: 999px; background: var(--panel-hi); font-size: .78rem; font-weight: 700; }
.part svg { width: 20px; height: 20px; }
.part:not(.is-owned) { color: var(--muted); }
.part:not(.is-owned) svg { opacity: .4; }
.part.is-owned { background: var(--white); color: var(--line); }
.switch { position: relative; display: inline-flex; align-items: center; gap: 10px; font-weight: 700; cursor: pointer; }
.switch input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.switch__track { position: relative; width: 50px; height: 28px; border: 2.5px solid var(--line); border-radius: 999px; background: var(--track); transition: background-color .2s; }
.switch__track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 19px;
  height: 19px;
  border: 2px solid var(--line);
  border-radius: 50%;
  background: var(--white);
  transition: transform .22s cubic-bezier(.34, 1.56, .64, 1);
}
.switch input:checked + .switch__track { background: var(--red); }
.switch input:checked + .switch__track::after { transform: translateX(21px); }
.switch input:focus-visible + .switch__track { outline: 3px solid var(--white); outline-offset: 3px; }

/* event pass: reward nodes evenly spaced along one bar */
.pass { position: relative; margin: 0 24px; padding-bottom: 64px; }
.pass__bar { height: 16px; margin-top: 22px; border: 2.5px solid var(--line); border-radius: 999px; background: var(--track); overflow: hidden; }
.pass__fill {
  display: block;
  height: 100%;
  background: linear-gradient(180deg, var(--white) 0 60%, var(--white-dark) 60%);
  box-shadow: 2.5px 0 0 var(--line);
  transition: width .6s cubic-bezier(.34, 1.3, .64, 1);
}
.pass__nodes { list-style: none; margin: 0; padding: 0; }
.pass__node {
  position: absolute;
  top: 30px;
  display: grid;
  justify-items: center;
  gap: 1px;
  width: 64px;
  text-align: center;
  transform: translate(-50%, -21px);
}
.pass__icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 3px solid var(--line);
  border-radius: 50%;
  background: var(--panel-hi);
  box-shadow: 0 3px 0 var(--line);
}
.pass__icon > svg { width: 24px; height: 24px; }
.pass__node:not(.is-owned) .pass__icon > svg { opacity: .45; }
.pass__node.is-owned .pass__icon { background: var(--white); }
.pass__lock {
  position: absolute;
  right: -7px;
  bottom: -5px;
  display: grid;
  place-items: center;
  width: 19px;
  height: 19px;
  border: 2px solid var(--line);
  border-radius: 50%;
  background: var(--panel);
}
.pass__lock svg { width: 12px; height: 12px; }
.pass__label { margin-top: 5px; font-size: .72rem; font-weight: 700; line-height: 1.1; }
.pass__ep { font-size: .64rem; font-weight: 600; color: var(--muted); }

/* ---------- the live show ---------- */
.show {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 10px;
  padding-top: calc(env(safe-area-inset-top, 0px) + 16px);
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 22px);
  padding-left: var(--gutter-l);
  padding-right: var(--gutter-r);
  background: radial-gradient(100% 60% at 50% 100%, #1C2A66 0%, #070A18 70%);
  overflow: hidden;
}
.show__lights span {
  position: absolute;
  top: -10%;
  width: 60vmax;
  height: 130vmax;
  clip-path: polygon(46% 0, 54% 0, 100% 100%, 0 100%);
  transform-origin: 50% 0;
  mix-blend-mode: screen;
  animation: sweep 4.6s ease-in-out infinite alternate;
}
.show__lights span:first-child { left: -22vmax; background: linear-gradient(180deg, rgba(232, 35, 43, .5), rgba(232, 35, 43, 0) 72%); --from: -26deg; --to: 16deg; }
.show__lights span:last-child { right: -22vmax; background: linear-gradient(180deg, rgba(43, 108, 240, .55), rgba(43, 108, 240, 0) 72%); --from: 26deg; --to: -16deg; animation-delay: -2.3s; }
.show__head { position: relative; z-index: 1; display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.show__title { margin-top: 8px; font-size: 2.2rem; }
.show__credit { font-weight: 600; color: var(--muted); }
.show__stage { position: relative; display: grid; justify-items: center; align-content: end; }
/* Meppo dances on a pipe that comes up from the bottom of the screen, behind the death mode button */
.show__mascot { --mpx: 6; margin-bottom: -250px; }
.show__foot { position: relative; z-index: 1; display: flex; justify-content: center; }

/* ---------- now playing: track and beat producer ---------- */
.credit {
  position: fixed;
  z-index: 22;
  top: calc(env(safe-area-inset-top, 0px) + 80px);
  left: 0;
  right: 0;
  display: flex;
  width: max-content; /* centred with auto margins, so it can use the full width */
  margin-inline: auto;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 32px);
  padding: 6px 16px 6px 6px;
  border: 3px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  color: var(--line);
  box-shadow: 0 4px 0 var(--line);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-14px) scale(.9);
  transition: transform .35s cubic-bezier(.34, 1.56, .64, 1), opacity .25s ease, visibility 0s .35s;
  pointer-events: none;
}
.credit.is-in { opacity: 1; visibility: visible; transform: none; transition: transform .35s cubic-bezier(.34, 1.56, .64, 1), opacity .25s ease; }
.credit__disc {
  flex: none;
  width: 36px;
  height: 36px;
  border: 2px solid var(--line);
  border-radius: 50%;
  background: radial-gradient(circle, var(--red) 0 22%, var(--line) 23% 28%, rgba(0, 0, 0, 0) 29%), repeating-radial-gradient(circle, #111 0 2px, #2A2A2A 2px 3.5px);
  animation: record-spin 2.4s linear infinite;
}
.credit__text { display: grid; min-width: 0; line-height: 1.2; }
.credit__title { overflow: hidden; font-family: var(--font-display); font-size: 1rem; white-space: nowrap; text-overflow: ellipsis; }
.credit__artist { font-family: var(--font-body); font-size: .76rem; font-weight: 600; color: #4A5170; }
.credit__beat { font-size: .8rem; font-weight: 600; }
.credit__beat strong { color: var(--red); }

/* ---------- death mode: every Meppo is his skeleton, and the page sits on the album cover ---------- */
html.is-death .meppo { --m-body: url(assets/meppo/meppo-skull.png); }
.bg::before { content: ""; position: absolute; inset: 0; z-index: 1; background: #0E0909 url(assets/cover-bg.jpg) center / cover; opacity: 0; transition: opacity .6s ease; }
html.is-death .bg::before { opacity: 1; }

/* ---------- Meppo, the mascot: pixel sprites played frame by frame ---------- */
/* Each strip in assets/meppo holds 13 frames of 32 x 32: 0-4 idle, 5-12 dance.
   Row 0 is the red team, row 1 the blue team. Wardrobe items are strips drawn on the
   same frames, so they move with him. All of his motion is in the frames, and app.js
   picks the frame (--f) from the background music's beat. */
:root {
  --mpx: 2;                                   /* one sprite pixel, in CSS px */
  --m-row: 0;
  --m-rim: url(assets/meppo/pipe-rim-red.png);
  --m-pipe: url(assets/meppo/pipe-body-red.png);
}
[data-team="blue"], .face--blue, .is-blue { --m-row: 1; --m-rim: url(assets/meppo/pipe-rim-blue.png); --m-pipe: url(assets/meppo/pipe-body-blue.png); }
.face--red, .is-red { --m-row: 0; --m-rim: url(assets/meppo/pipe-rim-red.png); --m-pipe: url(assets/meppo/pipe-body-red.png); }
/* the Khalse outfit from the event pass */
[data-outfit~="kbeanie"] { --m-head: url(assets/meppo/acc-kbeanie.png); }
[data-outfit~="redshades"] { --m-eyes: url(assets/meppo/acc-redshades.png); }
[data-outfit~="skullchain"] { --m-neck: url(assets/meppo/acc-skullchain.png); }
/* only your own team's Meppo wears it */
[data-face]:not(.is-you) { --m-head: none; --m-eyes: none; --m-mouth: none; --m-neck: none; }
.meppo {
  --m-body: url(assets/meppo/meppo-cheeky.png);
  display: block;
  flex: none;
  width: calc(32px * var(--mpx));
  height: calc(32px * var(--mpx));
  background-image: var(--m-head, none), var(--m-eyes, none), var(--m-mouth, none), var(--m-neck, none), var(--m-body);
  background-repeat: no-repeat;
  background-size: calc(416px * var(--mpx)) calc(64px * var(--mpx));
  background-position: calc(var(--f, 0) * -32px * var(--mpx)) calc(-32px * var(--mpx) * var(--m-row));
  image-rendering: pixelated;
}
.meppo[data-mood="excited"] { --m-body: url(assets/meppo/meppo-excited.png); }
.meppo[data-mood="wow"] { --m-body: url(assets/meppo/meppo-wow.png); }
.meppo[data-mood="sad"] { --m-body: url(assets/meppo/meppo-sad.png); }
.meppo[data-mood="wink"] { --m-body: url(assets/meppo/meppo-wink.png); }
.meppo[data-mood="fired"] { --m-body: url(assets/meppo/meppo-fired.png); }
.meppo[data-mood="skull"] { --m-body: url(assets/meppo/meppo-skull.png); }
/* the pipe he stands on, drawn in his pixels like the site's pipes */
.m-stand { display: flex; flex-direction: column; align-items: center; }
.px-pipe {
  --h: 14;                                    /* height in sprite pixels */
  display: block;
  flex: none;
  width: calc(18px * var(--mpx));
  height: calc(var(--h) * var(--mpx) * 1px);
  margin-top: calc(-1px * var(--mpx));       /* his feet stand on the rim */
  background:
    var(--m-rim) 50% 0 / calc(18px * var(--mpx)) calc(6px * var(--mpx)) no-repeat,
    var(--m-pipe) 50% 0 / calc(14px * var(--mpx)) calc(1px * var(--mpx)) repeat-y;
  image-rendering: pixelated;
}
.player__avatar::before {
  content: "";
  position: absolute;
  inset: -6px;
  border: 2.5px solid var(--line);
  border-radius: 50%;
  background: conic-gradient(var(--red) 0 50%, var(--blue) 50% 100%);
  opacity: 0;
  transition: opacity .3s ease;
}
[data-frame="collab"] .player__avatar::before { opacity: 1; }
[data-frame="collab"] .player__face { box-shadow: 0 4px 0 2.5px var(--line); }

/* ---------- top 10: the top three standing, then the list, then you ---------- */
.is-red { --team: var(--red); --team-dark: var(--red-dark); --pipe: var(--cel-red); }
.is-blue { --team: var(--blue); --team-dark: var(--blue-dark); --pipe: var(--cel-blue); }
.top10 .card__head { grid-column: 1 / -1; }
@media (min-width: 860px) {
  .top10 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); column-gap: 24px; align-items: end; }
}
.podium {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: end;
  gap: 8px;
}
.podium__spot { display: grid; justify-items: center; gap: 2px; min-width: 0; text-align: center; }
.podium__spot--1 { order: 2; }
.podium__spot--2 { order: 1; }
.podium__spot--3 { order: 3; }
/* each player stands on a pipe with their rank on it; #1's pipe is the tallest and they dance */
.podium__stage { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; width: 100%; padding-bottom: 18px; }
.podium__stage .m-stand { --mpx: 2.5; position: relative; z-index: 1; }
.podium__spot--1 .podium__stage .m-stand { --mpx: 3; }
.podium__rank {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: 0;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-left: -17px;
  border: 3px solid var(--line);
  border-radius: 50%;
  background: var(--white);
  color: var(--line);
  font-family: var(--font-display);
  font-size: 1.15rem;
  box-shadow: 0 3px 0 var(--line);
}
.podium__name { max-width: 100%; margin-top: 8px; overflow: hidden; font-weight: 700; font-size: .86rem; white-space: nowrap; text-overflow: ellipsis; }
.podium__pts { font-family: var(--font-display); font-size: .95rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.ranks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.rank-row {
  display: grid;
  grid-template-columns: 30px 38px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 6px 12px 6px 6px;
  border: 2.5px solid var(--line);
  border-radius: 14px;
  background: var(--panel-hi);
}
.rank-row--you { background: var(--track); box-shadow: inset 0 0 0 2px var(--white); }
.rank-row__pos { font-family: var(--font-display); font-size: 1.1rem; text-align: center; color: var(--muted); font-variant-numeric: tabular-nums; }
.rank-row--you .rank-row__pos { font-size: .95rem; color: var(--white); }
.face--sm { --mpx: 2; width: 38px; height: 38px; border-width: 2.5px; }
.rank-row__who { display: grid; min-width: 0; line-height: 1.15; }
.rank-row__name { overflow: hidden; font-weight: 700; white-space: nowrap; text-overflow: ellipsis; }
.rank-row__lv { font-size: .72rem; font-weight: 600; color: var(--muted); }
.rank-row__pts { font-family: var(--font-display); font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.ranks__gap { text-align: center; font-weight: 700; line-height: .6; letter-spacing: .4em; color: var(--muted); }

/* ---------- reaction stickers: the mascot with a word, cut out like a sticker ---------- */
.sticker-pop {
  position: fixed;
  z-index: 60;
  left: 50%;
  top: 44%;
  display: grid;
  justify-items: center;
  pointer-events: none;
  transform: translate(-50%, -50%);
}
.sticker-pop__art {
  --mpx: 4;
  filter: drop-shadow(3px 0 0 #FFF) drop-shadow(-3px 0 0 #FFF) drop-shadow(0 3px 0 #FFF) drop-shadow(0 -3px 0 #FFF) drop-shadow(0 8px 0 rgba(0, 0, 0, .45));
}
.sticker-pop__word {
  position: absolute;
  top: -34px;
  left: 50%;
  padding: 4px 16px;
  border: 3.5px solid var(--line);
  border-radius: 14px;
  background: var(--white);
  color: var(--line);
  font-family: var(--font-display);
  font-size: 1.9rem;
  white-space: nowrap;
  box-shadow: 0 4px 0 var(--line);
  transform: translateX(-50%) rotate(-7deg);
}
.sticker-pop.is-on { animation: sticker-pop 1.8s cubic-bezier(.34, 1.56, .64, 1) forwards; }

/* ---------- keyframes ---------- */
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes logo-in { from { transform: scale(.75) rotate(-5deg); } }
@keyframes pop { from { transform: translateY(14px) scale(.92); } }
@keyframes bump { 40% { transform: scale(1.1); } }
@keyframes bob { 50% { transform: translateY(2.5px); } }
@keyframes lava { to { transform: translateX(-25px); } }
@keyframes flicker { to { transform: scaleX(.6); } }
@keyframes boom { from { transform: scale(.2) rotate(-30deg); } }
@keyframes tumble { 0%, 60%, 100% { transform: rotate(0); } 70% { transform: rotate(-16deg) translateY(-3px); } 82% { transform: rotate(10deg); } }
@keyframes ring { from { transform: scale(.85); opacity: 1; } to { transform: scale(1.3); opacity: 0; } }
@keyframes badge { 50% { transform: scale(1.15); } }
@keyframes confetti {
  0% { transform: translate(0, 0) rotate(0); opacity: 1; }
  70% { opacity: 1; }
  100% { transform: translate(var(--dx), calc(var(--dy) + 140px)) rotate(var(--rot)); opacity: 0; }
}

@keyframes blink { 50% { opacity: .25; } }
@keyframes record-spin { to { transform: rotate(360deg); } }
@keyframes sweep { from { transform: rotate(var(--from)); } to { transform: rotate(var(--to)); } }
@keyframes sticker-pop {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.3) rotate(-14deg); }
  18% { opacity: 1; transform: translate(-50%, -50%) scale(1.08) rotate(4deg); }
  28% { transform: translate(-50%, -50%) scale(1) rotate(0); }
  80% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -85%) scale(.92); }
}
@keyframes start-pulse { 50% { transform: scale(1.05); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .pipe:active .pipe__art { transform: none; }
}
