/* Clicset home («próximamente»), / (es) and /en/ (en). D-PROD-201: CSS only (nothing inline), the app's own fonts
   self-hosted in /fonts and the colours of apps/mobile/src/ui/theme.ts (ds). Lime only on navy or as the ball.
   D-PROD-203: simple page: hero, three short points and the footer; ES · EN selector at the top right.
   D-PROD-204: the whole page fits in the screen without scrolling: body is a 100svh column (100vh fallback),
   the hero takes the free height and the sizes of the headline, the scoreboard and the ball scene follow the
   height (clamp with svh). Very low screens (under ~560 px or a phone on its side) may scroll. */

@font-face { font-family: "Barlow Condensed"; font-style: italic; font-weight: 800; font-display: swap; src: url("/fonts/BarlowCondensed_800ExtraBold_Italic.woff2") format("woff2"); }
@font-face { font-family: "Sora"; font-style: normal; font-weight: 400; font-display: swap; src: url("/fonts/Sora_400Regular.woff2") format("woff2"); }
@font-face { font-family: "Sora"; font-style: normal; font-weight: 700; font-display: swap; src: url("/fonts/Sora_700Bold.woff2") format("woff2"); }
@font-face { font-family: "Sora"; font-style: normal; font-weight: 800; font-display: swap; src: url("/fonts/Sora_800ExtraBold.woff2") format("woff2"); }

:root {
  --navy: #0B1F3A;
  --navy2: #1E3A5F;
  --navy-deep: #071528;
  --blue: #1F56D6;
  --blue-light: #7FA6FF;
  --blue700: #1846B0;
  --red: #DC2626;
  --red700: #B91C1C;
  --red-on-navy: #F87171;
  --lime: #C6F432;
  --white: #FFFFFF;
  --surface: #F1F5F9;
  --line: #E2E8F0;
  --ink: #0B1F3A;
  --ink2: #475569;
  --on-navy2: #CBD5E1;
  --display: "Barlow Condensed", "Arial Narrow", sans-serif;
  --text: "Sora", system-ui, -apple-system, "Segoe UI", sans-serif;
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
  /* One rally of the demo: 7 steps (0-0 … juego) of 2 s each. */
  --rally: 14s;
  /* D-PROD-202: delay of the score and the voice after each press of the remote. */
  --tap: 0.12s;
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--navy);
  color: var(--ink);
  font-family: var(--text);
  font-size: 1rem;
  line-height: 1.6;
  overflow-x: hidden;
}
/* D-PROD-204: header, hero (grows), three points and footer in one screen; the footer sits at the bottom. */
body.home { display: flex; flex-direction: column; min-height: 100vh; min-height: 100svh; }
body.home main { flex: 1 0 auto; display: flex; flex-direction: column; }
main { overflow-x: hidden; overflow-x: clip; }
img { max-width: 100%; }
a { color: var(--blue); text-underline-offset: 0.15em; }
:focus-visible { outline: 3px solid var(--lime); outline-offset: 3px; border-radius: 6px; }

.skip { position: absolute; left: 16px; top: -100px; z-index: 20; background: var(--lime); color: var(--navy); padding: 8px 14px; border-radius: 8px; font-weight: 700; }
.skip:focus { top: 12px; }

.shell { width: 100%; max-width: 76rem; margin: 0 auto; padding: 0 16px; }
@media (min-width: 720px) { .shell { padding: 0 32px; } }

/* Top bar */
.top { position: relative; z-index: 2; background: var(--navy); }
.top-row { display: flex; align-items: center; justify-content: space-between; min-height: 56px; }
.top-logo { display: inline-flex; padding: 4px 0; }
.top-logo img { display: block; width: 112px; height: auto; }
@media (min-width: 720px) { .top-row { min-height: 64px; } .top-logo img { width: 130px; } }
/* D-PROD-203: language selector, the active one in lime and underlined. */
.lang { display: flex; align-items: center; gap: 2px; font-weight: 700; font-size: 0.875rem; letter-spacing: 0.12em; color: var(--on-navy2); }
.lang a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 10px; color: var(--on-navy2); text-decoration: none; }
.lang a:hover { color: var(--white); }
.lang a[aria-current="page"] { color: var(--lime); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; }
.lang a:last-child { padding-right: 0; }

/* Hero */
.hero {
  position: relative;
  background: var(--navy) url("/brand/court.svg") center / cover no-repeat;
  color: var(--white);
  padding: 6px 0 28px;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 24px), 0 100%);
  overflow: hidden;
  /* D-PROD-204: takes the height left by the header, the points and the footer, content centred. */
  flex: 1 0 auto; display: flex; flex-direction: column; justify-content: center;
}
.hero::after { /* glow behind the scoreboard */
  content: ""; position: absolute; right: -10%; top: 30%; width: 70vw; height: 70vw; max-width: 900px; max-height: 900px;
  background: radial-gradient(closest-side, rgba(31, 86, 214, 0.45), rgba(31, 86, 214, 0) 70%);
  pointer-events: none;
}
.hero-grid { position: relative; z-index: 1; display: grid; gap: 14px; }
@media (min-width: 720px) { .hero-grid { gap: 24px; } }
@media (min-width: 1000px) {
  .hero { padding: 8px 0 40px; clip-path: polygon(0 0, 100% 0, 100% calc(100% - 32px), 0 100%); }
  .hero-grid { grid-template-columns: 1.05fr 1fr; align-items: center; gap: 48px; }
}

.eyebrow { display: inline-flex; align-items: center; gap: 10px; margin: 0 0 10px; line-height: 1.4; color: var(--lime); font-weight: 700; font-size: 0.75rem; letter-spacing: 0.2em; text-transform: uppercase; }
/* D-PROD-203: pre-launch page, so «Próximamente» is the first thing you read: a big lime tag. */
.launch { display: inline-flex; align-items: center; gap: 12px; margin: 0 0 10px; padding: 0.24em 0.6em 0.24em 0.48em; border-radius: 999px; background: var(--lime); color: var(--navy); font-family: var(--display); font-style: italic; font-weight: 800; text-transform: uppercase; font-size: clamp(1.4rem, min(6.4vw, 4.4svh), 2.25rem); line-height: 1; letter-spacing: 0.02em; box-shadow: 0 10px 30px -10px rgba(198, 244, 50, 0.55); animation: rise 0.7s var(--ease-out) both; }
.launch .dot { width: 12px; height: 12px; background: var(--navy); box-shadow: none; animation: blink 1.2s steps(2, jump-none) infinite; }
@keyframes blink { 50% { opacity: 0.25; } }
.launch + .eyebrow { display: flex; }
.dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--lime); box-shadow: 0 0 0 0 rgba(198, 244, 50, 0.6); animation: beacon 1.8s var(--ease-out) infinite; }
.eyebrow-ink { color: var(--blue); }

/* D-PROD-204: the headline follows the height too (two lines on phones in Spanish, three in English). */
.headline { margin: 0; font-family: var(--display); font-style: italic; font-weight: 800; text-transform: uppercase; font-size: clamp(2.5rem, min(14.5vw, 7.6svh), 6rem); line-height: 0.86; letter-spacing: -0.005em; }
.hl { display: block; animation: rise 0.7s var(--ease-out) both; }
.hl-2 { animation-delay: 0.12s; }
.headline em { font-style: italic; color: var(--lime); }
/* D-PROD-203: the English motto is longer: three set lines that fit at 375 px. */
.headline-en { font-size: clamp(2.25rem, min(12.5vw, 6.2svh), 5rem); }
@media (min-width: 1000px) {
  .headline { font-size: clamp(3.5rem, min(9.5vw, 14.5svh), 8.75rem); }
  .headline-en { font-size: clamp(3rem, min(7.5vw, 11svh), 6.25rem); }
}
.headline-en .hl { white-space: nowrap; }
.hl-3 { animation-delay: 0.18s; }

/* D-PROD-204: one short line: what it does and the stores (no separate notice: «Próximamente» already says it). */
.lead { margin: 14px 0 0; max-width: 31rem; color: var(--on-navy2); font-size: 0.9375rem; line-height: 1.5; animation: rise 0.7s var(--ease-out) 0.24s both; }
.lead-soon { color: var(--lime); font-weight: 700; white-space: nowrap; }
@media (min-width: 1000px) { .lead { margin-top: 22px; font-size: 1.0625rem; } }
/* Short phones: the line goes; «Próximamente», the headline and the demo stay. */
@media (max-width: 999px) and (max-height: 759px), (max-height: 640px) { .lead { display: none; } }

/* Stage: the scoreboard, the voice and the remote */
.stage { position: relative; padding: 38px 0 56px; max-width: 34rem; width: 100%; justify-self: center; animation: drop-in 0.9s var(--ease-bounce) 0.3s both; }
@media (min-width: 720px) { .stage { padding-top: 44px; } }

.board {
  position: relative;
  background: var(--white);
  color: var(--ink);
  border-radius: 28px;
  padding: 18px 18px 14px;
  transform: rotate(-2.5deg);
  box-shadow: 0 2px 0 rgba(255, 255, 255, 0.4) inset, 0 30px 60px -20px rgba(0, 0, 0, 0.55), 0 0 0 6px rgba(255, 255, 255, 0.06);
}
.board-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 999px; font-weight: 700; font-size: clamp(0.625rem, 2.6vw, 0.75rem); letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap; }
.chip img { display: block; }
.chip { flex: none; }
.chip-a { background: var(--navy); color: var(--white); }
.chip-b { border: 2px solid var(--red); color: #B91C1C; }
.games { display: inline-flex; align-items: center; gap: 4px; font-weight: 800; font-size: 0.875rem; color: var(--ink); font-variant-numeric: tabular-nums; }
.games-label { font-weight: 700; font-size: 0.625rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink2); margin-right: 4px; }
.games-a { display: inline-block; height: 1.2em; line-height: 1.2; overflow: hidden; color: var(--blue); }
.games-sep { color: var(--ink2); }

.points { display: grid; grid-template-columns: 1fr 1fr; align-items: center; margin-top: 4px; }
/* D-PROD-204: the points follow the height of the screen. */
.pt { display: flex; justify-content: center; height: 1em; overflow: hidden; font-weight: 800; font-size: clamp(3.75rem, min(26vw, 11.5svh), 9rem); line-height: 1; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
@media (min-width: 1000px) { .pt { font-size: clamp(5rem, min(11vw, 19svh), 10.5rem); } }
.pt-a { color: var(--blue); }
.pt-b { color: var(--red); border-left: 2px solid var(--line); }
.roll { display: flex; flex-direction: column; align-items: center; }
.roll > span { display: block; height: 1em; line-height: 1; }
.pt .roll > span { padding-top: 0.06em; }
.roll-g > span { height: 1.2em; line-height: 1.2; }

.board-foot { height: 26px; display: flex; justify-content: center; align-items: center; }
.flash { display: inline-block; padding: 4px 12px; border-radius: 999px; background: var(--navy); color: var(--lime); font-family: var(--display); font-style: italic; font-weight: 800; text-transform: uppercase; font-size: 1rem; letter-spacing: 0.03em; opacity: 0; }

/* The voice: a lime speech bubble that says the score after each point. */
.voice {
  position: absolute; z-index: 2; right: -4px; top: 0;
  display: grid; align-items: center; grid-template-columns: auto 1fr;
  min-width: 13.5rem; padding: 10px 16px 10px 12px;
  background: var(--lime); color: var(--navy);
  border-radius: 18px 18px 4px 18px;
  font-weight: 700; font-size: 0.9375rem;
  transform: rotate(2deg);
  box-shadow: 0 14px 30px -12px rgba(0, 0, 0, 0.5);
}
.voice-icon { grid-row: 1; grid-column: 1; width: 22px; height: 22px; margin-right: 10px; border-radius: 50%; background: var(--navy); position: relative; }
.voice-icon::before, .voice-icon::after { content: ""; position: absolute; inset: 6px; border-radius: 50%; border: 2px solid var(--lime); border-left-color: transparent; border-bottom-color: transparent; transform: rotate(45deg); }
.voice-icon::after { inset: 9px; background: var(--lime); border: 0; }
.say { grid-row: 1; grid-column: 2; opacity: 0; white-space: nowrap; }

/* D-PROD-205: a two-button selfie remote (the app's two-button profile, D-PROD-200): the blue button gives the
   point to the blue team and the red one to the red team, one above the other. Each point presses only the
   button of the team that wins it; its ripple and its «clic» take the team's colour. */
/* D-PROD-206: the remote stands upright (only a slight -4° tilt of the whole remote, so the buttons stay on the
   body's axis): a 64 × 132 px body, two 30 px buttons centred one above the other (blue above, red below) with
   18 px between them and 17 px of body on each side; the key ring goes through a lug on top of the body. Each
   «clic» comes out to the right of its own button, at its height, with a little arrow pointing at it. */
.remote { position: absolute; z-index: 2; left: 4px; bottom: 0; display: flex; flex-direction: column; align-items: center; transform: rotate(-4deg); transform-origin: bottom left; }
.remote-ring { position: relative; z-index: 0; display: block; width: 24px; height: 24px; border: 4px solid var(--blue-light); border-radius: 50%; margin-bottom: -8px; }
.remote-body { position: relative; z-index: 1; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 18px; width: 64px; height: 132px; border-radius: 32px; background: linear-gradient(180deg, #2C5285, #12294A 55%, var(--navy-deep)); box-shadow: 0 0 0 2px var(--navy2) inset, 0 2px 0 rgba(255, 255, 255, 0.12) inset, 0 18px 30px -10px rgba(0, 0, 0, 0.6); }
.remote-body::before { content: ""; position: absolute; left: 50%; top: -5px; width: 20px; height: 12px; margin-left: -10px; border-radius: 6px 6px 3px 3px; background: #2C5285; box-shadow: 0 0 0 2px var(--navy2) inset; }
.remote-btn { position: relative; display: block; flex: none; width: 30px; height: 30px; border-radius: 50%; }
.remote-btn-a { background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0) 60%), var(--blue); box-shadow: 0 4px 0 var(--blue700), 0 0 0 4px rgba(127, 166, 255, 0.22); }
.remote-btn-b { background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0) 60%), var(--red); box-shadow: 0 4px 0 var(--red700), 0 0 0 4px rgba(248, 113, 113, 0.22); }
.remote-btn::after { content: ""; position: absolute; inset: 0; border-radius: 50%; border: 3px solid var(--blue-light); opacity: 0; }
.remote-btn-b::after { border-color: var(--red-on-navy); }
/* Button centres: 58 px (blue) and 106 px (red) from the top of the remote; each 28 px pill is centred on its own. */
.clic { position: absolute; left: 74px; padding: 2px 10px; border-radius: 999px; font-family: var(--display); font-style: italic; font-weight: 800; font-size: 1.25rem; line-height: 1.2; text-transform: uppercase; color: var(--white); white-space: nowrap; opacity: 0; box-shadow: 0 8px 18px -8px rgba(0, 0, 0, 0.6); }
.clic::before { content: ""; position: absolute; left: -4px; top: 50%; width: 10px; height: 10px; margin-top: -5px; border-radius: 2px; background: inherit; transform: rotate(45deg); }
.clic-a { top: 44px; background: var(--blue); }
.clic-b { top: 92px; background: var(--red); }

/* D-PROD-202: the bouncing ball of the app's loader (BounceScene in src/ui/brand/Loader.tsx) on a 300 × 190
   court like the Loader's, under the scoreboard. It plays each point of the rally (one 2 s step, the same
   timeline as the remote's press): rests while the score rolls, bounces like the app (104 px, cubic ease-in
   fall, squash 1.28 × 0.7 from the bottom, cubic ease-out rise) with two damped bounces, stops, and only then
   the remote is pressed (the next step). Times in the keyframes `bote`, `bote-shadow` and `bote-spin`. */
/* D-PROD-204: on shorter screens the whole scene is scaled down (--bs), with the same times and sequence. */
.stage { --bs: 1; padding-bottom: calc(176px * var(--bs)); }
.bounce { position: absolute; right: 0; bottom: 0; width: 300px; height: 190px; transform: scale(var(--bs)); transform-origin: bottom right; }
@media (max-height: 700px) { .stage { --bs: 0.8; } }
@media (max-width: 999px) and (max-height: 960px) { .stage { --bs: 0.8; } }
@media (max-width: 999px) and (max-height: 780px) { .stage { --bs: 0.66; } }
@media (max-width: 999px) and (max-height: 680px) { .stage { --bs: 0.6; } }
.bounce::before { /* the court lines fade at the sides so the scene blends into the hero's court */
  content: ""; position: absolute; inset: 0; background: url("/brand/bounce-court.svg") center / 300px 190px no-repeat;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent); mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
}
.bounce-shadow { position: absolute; left: 124px; top: 162px; width: 52px; height: 12px; border-radius: 6px; background: var(--lime); opacity: 0.5; transform: scale(1.15); }
.bounce-ball { position: absolute; left: 131px; top: 130px; width: 38px; height: 38px; transform-origin: bottom; }
.bounce-ball img { display: block; width: 38px; height: 38px; }

/* D-PROD-203: three short points (selfie remote, voice, sports) instead of the long sections.
   D-PROD-204: a compact row just above the footer; on phones they go (the hero already says it). */
.feats { display: none; padding: 6px 0 18px; color: var(--white); }
@media (min-width: 720px) { .feats { display: block; } }
.feat-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin: 0; padding: 0; list-style: none; }
.feat { position: relative; padding: 0 0 0 34px; }
.feat::before { content: ""; position: absolute; left: 0; top: 1px; width: 22px; height: 22px; background: url("/brand/ball-on-navy.svg") center / contain no-repeat; }
.feat h2 { margin: 0 0 2px; font-family: var(--display); font-style: italic; font-weight: 800; text-transform: uppercase; font-size: 1.25rem; line-height: 1.1; color: var(--white); }
.feat p { margin: 0; color: var(--on-navy2); font-size: 0.8125rem; line-height: 1.45; }
/* Tablets: only the three titles, so the row stays one line high. */
@media (max-width: 999px) { .feat h2 { font-size: 1.125rem; } .feat p { display: none; } }

footer { background: var(--navy); color: var(--on-navy2); padding: 12px 0 14px; font-size: 0.8125rem; line-height: 1.5; border-top: 1px solid rgba(255, 255, 255, 0.08); }
.foot-row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 24px; }
footer a { color: var(--white); }
footer a:hover { color: var(--lime); }
footer p { margin: 0; }

/* ── The rally. 7 steps of 2 s: 0-0, 15-0, 15-15, 30-15, 30-30, 40-30, juego (3-1 in games). ── */
.roll-a, .roll-b, .roll-g, .say, .flash, .remote-btn, .remote-btn::after, .clic { animation-duration: var(--rally); animation-iteration-count: infinite; }
.roll-a { animation-name: roll-a; animation-timing-function: var(--ease-bounce); }
.roll-b { animation-name: roll-b; animation-timing-function: var(--ease-bounce); }
.roll-g { animation-name: roll-g; animation-timing-function: var(--ease-bounce); }
.flash { animation-name: flash; }
.say { animation-name: say; animation-timing-function: linear; }
.say-1 { animation-delay: calc(2s + var(--tap)); }
.say-2 { animation-delay: calc(4s + var(--tap)); }
.say-3 { animation-delay: calc(6s + var(--tap)); }
.say-4 { animation-delay: calc(8s + var(--tap)); }
.say-5 { animation-delay: calc(10s + var(--tap)); }
.say-6 { animation-delay: calc(12s + var(--tap)); }
/* D-PROD-202: the ball's 2 s step is the step of the rally, so it is always still when a button is pressed. */
.bounce-ball, .bounce-shadow, .bounce-ball img { animation-duration: 2s; animation-iteration-count: infinite; }
.bounce-ball { animation-name: bote; }
.bounce-shadow { animation-name: bote-shadow; }
.bounce-ball img { animation-name: bote-spin; }
.remote-btn-a { animation-name: press-a; }
.remote-btn-b { animation-name: press-b; }
.remote-btn-a::after { animation-name: ripple-a; }
.remote-btn-b::after { animation-name: ripple-b; }
.clic-a { animation-name: clic-a; }
.clic-b { animation-name: clic-b; }
.say-0 { animation-delay: var(--tap); }
/* D-PROD-202: the score and the voice change just after the press (its deepest point is at 0.10 s). */
.roll-a, .roll-b, .roll-g, .flash { animation-delay: var(--tap); }

@keyframes roll-a {
  0%, 14.29% { transform: translateY(0); }
  17.5%, 42.86% { transform: translateY(-1em); }
  46%, 71.43% { transform: translateY(-2em); }
  74.6%, 85.71% { transform: translateY(-3em); }
  88.9%, 98.5% { transform: translateY(-4em); }
  100% { transform: translateY(0); }
}
@keyframes roll-b {
  0%, 28.57% { transform: translateY(0); }
  31.8%, 57.14% { transform: translateY(-1em); }
  60.3%, 85.71% { transform: translateY(-2em); }
  88.9%, 98.5% { transform: translateY(-4em); }
  100% { transform: translateY(0); }
}
@keyframes roll-g {
  0%, 85.71% { transform: translateY(0); }
  88.9%, 98.5% { transform: translateY(-1.2em); }
  100% { transform: translateY(0); }
}
@keyframes flash {
  0%, 86% { opacity: 0; transform: scale(0.6); }
  89% { opacity: 1; transform: scale(1.08); }
  91%, 98% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; }
}
/* Each line is on screen for one step (1/7 of the rally), starting at its own delay. */
@keyframes say {
  0% { opacity: 0; transform: translateY(6px); }
  2% { opacity: 1; transform: translateY(0); }
  13% { opacity: 1; transform: translateY(0); }
  14.28%, 100% { opacity: 0; transform: translateY(-4px); }
}
/* D-PROD-205: each point presses only its team's button, at 0.04-0.20 s of its step (deepest at 0.10 s), the
   same instant as before: blue at 2, 6, 10 and 12 s (15-0, 30-15, 40-30, juego), red at 4 and 8 s (15-15,
   30-30). The 0-0 step («¿Jugamos?») is not a point: no button. Ripple 0.06-0.60 s, «clic» 0.06-0.64 s. */
@keyframes press-a {
  0%, 14.571%, 15.714%, 43.143%, 44.286%, 71.714%, 72.857%, 86%, 87.143%, 100% { transform: translateY(0); box-shadow: 0 4px 0 var(--blue700), 0 0 0 4px rgba(127, 166, 255, 0.22); }
  15%, 43.571%, 72.143%, 86.429% { transform: translateY(3px); box-shadow: 0 1px 0 var(--blue700), 0 0 0 8px rgba(127, 166, 255, 0.4); }
}
@keyframes ripple-a {
  0%, 14.714%, 43.286%, 71.857%, 86.143% { opacity: 0; transform: scale(1); }
  15%, 43.571%, 72.143%, 86.429% { opacity: 0.9; transform: scale(1); }
  18.571%, 47.143%, 75.714%, 90%, 100% { opacity: 0; transform: scale(2.6); }
}
@keyframes clic-a {
  0%, 14.714%, 43.286%, 71.857%, 86.143% { opacity: 0; transform: translateX(-8px) scale(0.85); }
  15.143%, 17.714%, 43.714%, 46.286%, 72.286%, 74.857%, 86.571%, 89.143% { opacity: 1; transform: translateX(0) scale(1); }
  18.857%, 47.429%, 76%, 90.286%, 100% { opacity: 0; transform: translateX(6px) scale(1); }
}
@keyframes press-b {
  0%, 28.857%, 30%, 57.429%, 58.571%, 100% { transform: translateY(0); box-shadow: 0 4px 0 var(--red700), 0 0 0 4px rgba(248, 113, 113, 0.22); }
  29.286%, 57.857% { transform: translateY(3px); box-shadow: 0 1px 0 var(--red700), 0 0 0 8px rgba(248, 113, 113, 0.4); }
}
@keyframes ripple-b {
  0%, 29%, 57.571% { opacity: 0; transform: scale(1); }
  29.286%, 57.857% { opacity: 0.9; transform: scale(1); }
  32.857%, 61.429%, 100% { opacity: 0; transform: scale(2.6); }
}
@keyframes clic-b {
  0%, 29%, 57.571% { opacity: 0; transform: translateX(-8px) scale(0.85); }
  29.429%, 32%, 58%, 60.571% { opacity: 1; transform: translateX(0) scale(1); }
  33.143%, 61.714%, 100% { opacity: 0; transform: translateX(6px) scale(1); }
}
/* D-PROD-202: one point in 2 s (the step). 0-0.30 s still (press at 0.04-0.20 s, score and voice change);
   0.30-0.41 squash; 0.41-0.83 rise 104 px (cubic ease-out); 0.83-1.25 fall (cubic ease-in); 1.25-1.33 smaller
   squash; 1.33-1.50 rise 18 px; 1.50-1.67 fall; 1.67-1.71 last squash; 1.71-2.04 still until the next press. */
@keyframes bote {
  0%, 15% { transform: translateY(0) scale(1, 1); animation-timing-function: linear; }
  17.75% { transform: translateY(3px) scale(1.28, 0.7); animation-timing-function: linear; }
  20.5% { transform: translateY(0) scale(1, 1); animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1); }
  41.5% { transform: translateY(-104px) scale(1, 1); animation-timing-function: cubic-bezier(0.32, 0, 0.67, 0); }
  62.5% { transform: translateY(0) scale(1, 1); animation-timing-function: linear; }
  64.5% { transform: translateY(2px) scale(1.16, 0.82); animation-timing-function: linear; }
  66.5% { transform: translateY(0) scale(1, 1); animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1); }
  75% { transform: translateY(-18px) scale(1, 1); animation-timing-function: cubic-bezier(0.32, 0, 0.67, 0); }
  83.5% { transform: translateY(0) scale(1, 1); animation-timing-function: linear; }
  84.5% { transform: translateY(1px) scale(1.06, 0.92); animation-timing-function: linear; }
  85.5%, 100% { transform: translateY(0) scale(1, 1); }
}
/* The shadow follows the height with the same easings: 1.15 and 0.5 on the court, 0.35 and 0.15 at 104 px. */
@keyframes bote-shadow {
  0%, 20.5% { opacity: 0.5; transform: scale(1.15); animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1); }
  41.5% { opacity: 0.15; transform: scale(0.35); animation-timing-function: cubic-bezier(0.32, 0, 0.67, 0); }
  62.5%, 66.5% { opacity: 0.5; transform: scale(1.15); animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1); }
  75% { opacity: 0.44; transform: scale(1.01); animation-timing-function: cubic-bezier(0.32, 0, 0.67, 0); }
  83.5%, 100% { opacity: 0.5; transform: scale(1.15); }
}
/* One turn while it is in the air, slowing down as the bounces die out. */
@keyframes bote-spin {
  0%, 15% { transform: rotate(0); animation-timing-function: cubic-bezier(0.3, 0.6, 0.5, 1); }
  85.5%, 100% { transform: rotate(360deg); }
}
@keyframes beacon {
  0% { box-shadow: 0 0 0 0 rgba(198, 244, 50, 0.6); }
  80%, 100% { box-shadow: 0 0 0 12px rgba(198, 244, 50, 0); }
}
@keyframes rise { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@keyframes drop-in { from { opacity: 0; transform: translateY(-40px) rotate(4deg); } to { opacity: 1; transform: none; } }

/* Phones: the bubble and the remote stay inside the screen. */
@media (max-width: 480px) {
  /* D-PROD-203: at 375 px «Equipo azul» was cut and stuck to «Juegos»: the chips never shrink and the label goes. */
  .games-label { display: none; }
  .board-top { gap: 6px; }
  .voice { min-width: 0; right: 0; padding: 8px 14px 8px 10px; font-size: 0.8125rem; }
  .voice-icon { width: 20px; height: 20px; margin-right: 8px; }
  .voice-icon::before { inset: 5px; }
  .voice-icon::after { inset: 8px; }
  .remote { left: 10px; transform: rotate(-4deg) scale(0.8); }
  /* D-PROD-204: the footer in two lines on a 375 px phone. */
  footer { font-size: 0.75rem; }
  .board { padding: 12px 12px 8px; border-radius: 22px; }
  .board-foot { height: 22px; }
  .flash { font-size: 0.875rem; padding: 2px 10px; }
}
/* D-PROD-204: short phones: a smaller remote, so its ring stays clear of the scoreboard. */
@media (max-width: 480px) and (max-height: 780px) { .remote { transform: rotate(-4deg) scale(0.6); } }

/* Reduced motion: no rally; the board stays at 40-30 and the bubble says it. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .roll-a { transform: translateY(-3em); }
  .roll-b { transform: translateY(-2em); }
  .say-5 { opacity: 1; }
}

@media print {
  .top, .remote, .voice, .bounce, .skip { display: none; }
  .hero, .feats, footer { background: var(--white); color: var(--ink); clip-path: none; }
  .feats { display: block; }
  .feat h2 { color: var(--ink); }
}
