:root {
  --bg: #170b30;
  --panel: #2a1560;
  --panel-2: #1c0e3d;
  --line: #4a2f8f;
  --pink: #ff4fa3;
  --lime: #b6ff3c;
  --yellow: #ffd23f;
  --ink: #ffffff;
  --muted: #c3b3f2;
  --r: 18px;
}
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body {
  background:
    radial-gradient(1100px 700px at 85% -10%, #3d1c82 0, transparent 60%),
    radial-gradient(900px 600px at -10% 110%, #5c1457 0, transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--ink);
  font-family: 'Rubik', system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
h1, h2, .logo, .code, .stamp, .vs, .step {
  font-family: 'Bungee', 'Arial Black', sans-serif;
  letter-spacing: 0.02em;
  margin: 0;
}
p { margin: 0; }
button { font-family: inherit; cursor: pointer; }
.muted { color: var(--muted); }
.center { text-align: center; }
.logo { color: var(--lime); text-shadow: 0.06em 0.06em 0 var(--pink); line-height: 0.95; }

/* ---------- shared pieces ---------- */
.btn {
  font: 700 18px 'Rubik', sans-serif;
  background: var(--lime);
  color: #170b30;
  border: 0;
  border-radius: 14px;
  padding: 14px 18px;
  box-shadow: 0 5px 0 #6f9f17;
  touch-action: manipulation;
}
.btn:active { transform: translateY(4px); box-shadow: 0 1px 0 #6f9f17; }
.btn.big { width: 100%; font-size: 20px; margin-top: 16px; }
.btn.ghost { background: transparent; color: var(--ink); border: 2px solid var(--line); box-shadow: none; }
.btn:disabled { opacity: 0.35; }

.product {
  position: relative;
  margin: 0;
  background: #fff;
  color: #170b30;
  border-radius: 16px;
  padding: 10px;
  box-shadow: 0 10px 0 rgba(0, 0, 0, 0.28);
}
.product img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 10px; background: #ddd; }
.product figcaption { font-weight: 800; text-align: center; padding: 10px 6px 4px; line-height: 1.15; overflow-wrap: anywhere; }

.board { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.board li { display: flex; align-items: center; gap: 10px; background: var(--panel-2); border-radius: 12px; padding: 10px 14px; font-weight: 600; }
.board .rank { font-family: 'Bungee', sans-serif; color: var(--muted); width: 1.4em; }
.board .dot { width: 14px; height: 14px; border-radius: 50%; flex: none; }
.board .nm { flex: 1; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board .amt { font-family: 'Bungee', sans-serif; color: var(--lime); }
.board li.me { outline: 2px solid var(--pink); }

.spinner { width: 54px; height: 54px; margin: 18px auto; border-radius: 50%; border: 6px solid var(--line); border-top-color: var(--lime); animation: spin 0.9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- phone ---------- */
body.phone { padding-bottom: env(safe-area-inset-bottom); }
.phone #bar {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; padding-top: calc(10px + env(safe-area-inset-top));
  background: rgba(23, 11, 48, 0.92); border-bottom: 2px solid var(--line);
  font-weight: 700;
}
.phone #bar[hidden] { display: none; }
.phone #bar .who { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.phone #bar .cash { font-family: 'Bungee', sans-serif; color: var(--lime); }
.timer { font-family: 'Bungee', sans-serif; min-width: 2.2em; text-align: center; color: var(--yellow); }
.timer.low { color: var(--pink); animation: pulse 0.5s ease-in-out infinite alternate; }
@keyframes pulse { to { transform: scale(1.18); } }
.iconbtn { background: var(--panel); color: var(--ink); border: 2px solid var(--line); border-radius: 10px; font-size: 18px; line-height: 1; padding: 7px 10px; }
.iconbtn.armed { background: var(--pink); border-color: var(--pink); }

.phone main { max-width: 540px; margin: 0 auto; padding: 16px; }
.card { background: var(--panel); border: 2px solid var(--line); border-radius: var(--r); padding: 18px; }
.card h2 { font-size: 24px; color: var(--yellow); margin-bottom: 8px; }
.card .lead { color: var(--muted); font-size: 17px; line-height: 1.35; margin-bottom: 14px; }
.card .lead b { color: var(--ink); }
.join .logo { font-size: 64px; margin: 10px 0 18px; }
textarea, input, select {
  width: 100%; font: 500 17px 'Rubik', sans-serif; color: var(--ink);
  background: var(--panel-2); border: 2px solid var(--line); border-radius: 12px; padding: 13px 14px;
  margin-bottom: 10px; appearance: none; -webkit-appearance: none;
}
textarea { resize: none; }
textarea:focus, input:focus, select:focus { outline: none; border-color: var(--lime); }
#jCode { font-family: 'Bungee', sans-serif; font-size: 30px; text-align: center; letter-spacing: 0.25em; text-transform: uppercase; }
.row { display: flex; gap: 10px; align-items: stretch; }
.row > input, .row > select { margin-bottom: 0; flex: 1; min-width: 0; }
.row > .btn { flex: none; }
.chips { list-style: none; padding: 0; margin: 14px 0 0; display: flex; flex-wrap: wrap; gap: 8px; }
.chips li { background: var(--panel-2); border: 2px solid var(--line); border-radius: 999px; padding: 6px 12px; font-size: 15px; }
.roster { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin: 6px 0 4px; }
.chip { display: inline-flex; align-items: center; gap: 8px; background: var(--panel-2); border: 2px solid var(--line); border-radius: 999px; padding: 6px 14px 6px 8px; font-weight: 700; }
.chip .dot { width: 16px; height: 16px; border-radius: 50%; }
.chip.off { opacity: 0.4; }
.chip.done { border-color: var(--lime); }
.chip .tick { color: var(--lime); }

.picks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 12px; }
.pick { padding: 0; border: 4px solid transparent; border-radius: 14px; background: none; overflow: hidden; }
.pick img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 9px; }
.pick.on { border-color: var(--lime); }
.caps { display: grid; gap: 8px; }
.cap { text-align: left; font: 600 17px 'Rubik', sans-serif; color: var(--ink); background: var(--panel-2); border: 3px solid var(--line); border-radius: 12px; padding: 12px 14px; }
.cap.on { border-color: var(--lime); background: #24361a; }
.votes { display: grid; gap: 14px; }
button.vote { display: flex; align-items: center; gap: 12px; text-align: left; background: #fff; color: #170b30; border: 0; border-radius: 16px; padding: 10px; box-shadow: 0 6px 0 rgba(0, 0, 0, 0.3); font: 800 18px 'Rubik', sans-serif; }
button.vote:active { transform: translateY(4px); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.3); }
button.vote img { width: 104px; height: 104px; object-fit: cover; border-radius: 10px; flex: none; }
button.vote span { overflow-wrap: anywhere; }
.phone .product { max-width: 300px; margin: 12px auto; transform: rotate(-1.5deg); }
.phone .product figcaption { font-size: 18px; }
.gain { font-family: 'Bungee', sans-serif; color: var(--lime); font-size: 26px; margin-top: 8px; }

#toast {
  position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 30px); opacity: 0;
  background: #fff; color: #170b30; font-weight: 700; padding: 12px 18px; border-radius: 12px;
  transition: 0.2s; pointer-events: none; max-width: 90vw; text-align: center; z-index: 20;
}
#toast.show { transform: translate(-50%, 0); opacity: 1; }

/* ---------- TV ---------- */
body.tv { height: 100vh; overflow: hidden; display: grid; grid-template-rows: auto 1fr auto; }
.tv #top { display: flex; align-items: center; gap: 2vw; padding: 1.4vh 2.4vw; font-size: 2.2vh; font-weight: 600; }
.tv #top .brand { font-family: 'Bungee', sans-serif; font-size: 3.2vh; color: var(--lime); text-shadow: 0.06em 0.06em 0 var(--pink); }
.tv #top .joinmini { color: var(--muted); flex: 1; }
.tv #top .joinmini b { color: var(--ink); }
.tv #top .joinmini .codemini { font-family: 'Bungee', sans-serif; color: var(--yellow); font-size: 2.8vh; letter-spacing: 0.1em; }
.tv .timer { font-size: 5vh; min-width: 2.4em; }
.tv .iconbtn { font-size: 2.4vh; padding: 0.8vh 1vw; }
.tv #stage { min-height: 0; display: grid; place-items: center; padding: 0 3vw; }
.tv #foot { padding: 1.4vh 2.4vw 2.2vh; }
.tv .roster { gap: 1vw; }
.tv .chip { font-size: 2.3vh; padding: 0.7vh 1.2vw 0.7vh 0.7vw; }
.tv .chip .dot { width: 2.2vh; height: 2.2vh; }
.tv .chip .amt { font-family: 'Bungee', sans-serif; color: var(--lime); }

.lobby { display: grid; grid-template-columns: 1.05fr 1fr; gap: 5vw; align-items: center; width: 100%; max-width: 1500px; }
.logo.huge { font-size: 17vh; }
.tag { font-size: 3.4vh; color: var(--muted); margin: 3vh 0; max-width: 22em; line-height: 1.25; }
.joinbox { background: var(--panel); border: 0.5vh solid var(--line); border-radius: 3vh; padding: 3.5vh 2.6vw; display: flex; gap: 2.4vw; align-items: center; }
.joinbox .jb-label { color: var(--muted); font-size: 2.4vh; text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700; }
.joinbox .jb-url { font-size: 2.3vh; font-weight: 700; margin: 0.6vh 0 2.4vh; overflow-wrap: anywhere; }
.joinbox .code { font-size: 10vh; white-space: nowrap; color: var(--yellow); letter-spacing: 0.08em; line-height: 1; }
.joinbox .qr { width: 30vh; height: 30vh; border-radius: 2vh; background: #fff; padding: 1vh; flex: none; }
.joinbox > div { flex: 1; min-width: 0; }
.tv .btn { font-size: 3vh; padding: 1.6vh 2.4vw; border-radius: 1.8vh; }
.botrow { display: flex; gap: 1vw; margin-top: 2vh; }
.tv .botrow .btn { font-size: 2.2vh; padding: 1vh 1.4vw; }
.warn { color: var(--pink); font-weight: 700; font-size: 2.4vh; margin-top: 1.6vh; }
.tv .hint { color: var(--muted); font-size: 2.6vh; margin-top: 1.6vh; }

.phase { text-align: center; max-width: 80vw; }
.step { color: var(--pink); font-size: 3vh; text-transform: uppercase; }
.phase h1 { font-size: 11vh; color: var(--lime); text-shadow: 0.05em 0.05em 0 var(--pink); line-height: 1; margin: 1.4vh 0 2.6vh; }
.phase .how { font-size: 4vh; color: var(--ink); line-height: 1.25; }
.phase .stat { font-size: 3.2vh; color: var(--yellow); margin-top: 3.4vh; font-weight: 700; min-height: 1.3em; }
.meter { width: 50vw; height: 3vh; margin: 3vh auto 0; border-radius: 2vh; background: var(--panel-2); border: 0.4vh solid var(--line); overflow: hidden; }
.meter i { display: block; height: 100%; background: var(--lime); transition: width 0.4s; }

.battle { width: 100%; text-align: center; }
.shelf { display: grid; grid-template-columns: 1fr auto 1fr; gap: 3vw; align-items: start; justify-items: center; margin-top: 1.6vh; }
.vs { font-size: 7vh; color: var(--pink); align-self: center; }
.slot { width: min(36vw, 58vh); transition: transform 0.4s, filter 0.4s; }
.battle.result .slot { width: min(30vw, 44vh); }
.tv .product { padding: 1.4vh; border-radius: 2.4vh; box-shadow: 0 1.6vh 0 rgba(0, 0, 0, 0.3); }
.tv .product img { border-radius: 1.6vh; }
.tv .product figcaption { font-size: 3.4vh; padding: 1.4vh 1vw 0.6vh; }
.battle.result .product figcaption { font-size: 2.8vh; }
.slot:first-child .product { transform: rotate(-1.5deg); }
.slot:last-child .product { transform: rotate(1.5deg); }
.slot.lose { filter: grayscale(0.85) brightness(0.62); transform: scale(0.92); }
.slot.win .product { outline: 0.9vh solid var(--lime); }
.stamp { position: absolute; top: 4%; right: -4%; transform: rotate(12deg); background: var(--lime); color: #170b30; font-size: 4vh; padding: 0.6vh 1.4vw; border-radius: 1vh; box-shadow: 0 0.6vh 0 rgba(0, 0, 0, 0.3); }
.slot.lose .stamp { background: var(--pink); color: #fff; }
.credits { margin-top: 2.2vh; font-size: 2.2vh; line-height: 1.4; color: var(--muted); }
.credits b { color: var(--ink); font-size: 2.8vh; }
.credits i { color: var(--yellow); font-style: normal; }
.credits .voters { color: var(--lime); font-weight: 700; }
.manager { margin-top: 2vh; font-size: 3.2vh; min-height: 2.6em; font-weight: 600; max-width: 80vw; margin-inline: auto; line-height: 1.25; }
.manager b { color: var(--yellow); }
.mgr { font-family: 'Bungee', sans-serif; color: var(--pink); margin-right: 0.4em; }

.scores { display: grid; grid-template-columns: auto 1fr; gap: 5vw; align-items: center; width: 100%; max-width: 1400px; }
.scores .champ { width: min(32vw, 46vh); text-align: center; }
.scores .champ .credits b { font-size: 2.6vh; }
.scores h1 { font-size: 7vh; color: var(--lime); text-shadow: 0.05em 0.05em 0 var(--pink); }
.tv .board { gap: 1.1vh; margin-top: 2.4vh; }
.tv .board li { font-size: 3.2vh; padding: 1.3vh 1.6vw; border-radius: 1.6vh; }
.tv .board .dot { width: 2.4vh; height: 2.4vh; }
.tv .board li:first-child { outline: 0.5vh solid var(--yellow); }

/* ---------- motion ---------- */
/* Everything below is movement only. Delete this block and the game still works. */

/* Slow drifting colour behind every screen. */
body::before {
  content: '';
  position: fixed;
  inset: -25%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(38% 34% at 28% 30%, rgba(255, 79, 163, 0.2), transparent 70%),
    radial-gradient(34% 30% at 74% 68%, rgba(79, 216, 255, 0.16), transparent 70%),
    radial-gradient(26% 24% at 60% 22%, rgba(182, 255, 60, 0.1), transparent 70%);
  animation: drift 28s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes drift {
  0% { transform: translate3d(-4%, -3%, 0) rotate(0deg) scale(1); }
  50% { transform: translate3d(5%, 4%, 0) rotate(8deg) scale(1.08); }
  100% { transform: translate3d(-2%, 6%, 0) rotate(-6deg) scale(1.02); }
}

@keyframes bob { 0%, 100% { transform: translateY(0) rotate(-1.2deg); } 50% { transform: translateY(-1.5%) rotate(1.2deg); } }
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1.1vh); } }
@keyframes sway { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-1.2vh) rotate(0.8deg); } }
@keyframes riseIn { from { opacity: 0; transform: translateY(18px) scale(0.97); } to { opacity: 1; transform: none; } }
@keyframes popIn { 0% { opacity: 0; transform: scale(0.4); } 70% { opacity: 1; transform: scale(1.12); } 100% { opacity: 1; transform: scale(1); } }
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.025); } }
@keyframes glow { 0% { box-shadow: 0 5px 0 #6f9f17, 0 0 0 0 rgba(182, 255, 60, 0.55); } 100% { box-shadow: 0 5px 0 #6f9f17, 0 0 0 14px rgba(182, 255, 60, 0); } }
@keyframes dotHop { 0%, 60%, 100% { transform: translateY(0); opacity: 0.45; } 30% { transform: translateY(-70%); opacity: 1; } }
@keyframes press { 0% { transform: scale(0.94); } 60% { transform: scale(1.04); } 100% { transform: scale(1); } }
@keyframes rowIn { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }

/* Shared: the logo rocks, waiting dots hop, score rows slide in one after another. */
.logo { display: inline-block; transform-origin: 40% 60%; animation: bob 5s ease-in-out infinite; }
.dots { display: flex; gap: 8px; justify-content: center; margin-top: 8px; }
.dots i { width: 10px; height: 10px; border-radius: 50%; background: var(--lime); animation: dotHop 1.1s ease-in-out infinite; }
.dots i:nth-child(2) { animation-delay: 0.15s; }
.dots i:nth-child(3) { animation-delay: 0.3s; }
.board li { animation: rowIn 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.1) backwards; }
.board li:nth-child(2) { animation-delay: 0.07s; }
.board li:nth-child(3) { animation-delay: 0.14s; }
.board li:nth-child(4) { animation-delay: 0.21s; }
.board li:nth-child(5) { animation-delay: 0.28s; }
.board li:nth-child(6) { animation-delay: 0.35s; }
.board li:nth-child(7) { animation-delay: 0.42s; }
.board li:nth-child(8) { animation-delay: 0.49s; }

/* TV: every new screen rises in; headlines breathe. */
.tv #stage > * { animation: riseIn 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.15) both; }
.tv #stage > .battle.result { animation: none; } /* the reveal should not blink */
.phase h1, .scores h1 { animation: breathe 3.4s ease-in-out 0.6s infinite; }
.phase .step { animation: riseIn 0.4s ease 0.1s backwards; }
.phase .how { animation: riseIn 0.5s ease 0.25s backwards; }
.phase .stat { animation: riseIn 0.5s ease 0.4s backwards; }
.meter i { background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.3) 25%, transparent 25% 50%, rgba(255, 255, 255, 0.3) 50% 75%, transparent 75%); background-size: 4vh 4vh; animation: stripes 0.9s linear infinite; }
@keyframes stripes { to { background-position: 4vh 0; } }

/* TV lobby: the join box floats, the code letters pop in and take turns hopping. */
.joinbox { animation: floaty 6s ease-in-out infinite; }
.code span { display: inline-block; animation: popIn 0.5s cubic-bezier(0.2, 1.5, 0.4, 1) both, hop 3s ease-in-out infinite; animation-delay: calc(var(--i) * 0.09s + 0.2s), calc(var(--i) * 0.2s + 1.2s); }
@keyframes hop { 0%, 70%, 100% { transform: translateY(0); } 35% { transform: translateY(-9%); } }
.tv [data-act='start'] { animation: glow 1.5s ease-out infinite; }
.chip.pop { animation: popIn 0.45s cubic-bezier(0.2, 1.5, 0.4, 1) both; }
.chip.justdone { animation: press 0.5s ease; }

/* TV face-off: products slide in from the sides and sway, VS slams and throbs. */
.battle.vote .slot:first-child { animation: fromLeft 0.6s cubic-bezier(0.2, 1.2, 0.4, 1) both, sway 4.4s ease-in-out 0.7s infinite; }
.battle.vote .slot:last-child { animation: fromRight 0.6s cubic-bezier(0.2, 1.2, 0.4, 1) 0.12s both, sway 4.4s ease-in-out 2.6s infinite; }
@keyframes fromLeft { from { opacity: 0; transform: translateX(-30vw) rotate(-12deg); } to { opacity: 1; transform: none; } }
@keyframes fromRight { from { opacity: 0; transform: translateX(30vw) rotate(12deg); } to { opacity: 1; transform: none; } }
.vs { animation: slam 0.5s cubic-bezier(0.3, 1.7, 0.5, 1) 0.45s both, throb 1.1s ease-in-out 1s infinite; }
@keyframes slam { from { opacity: 0; transform: scale(3.2) rotate(-18deg); } to { opacity: 1; transform: none; } }
@keyframes throb { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.14); } }
.manager b { display: inline-block; animation: popIn 0.35s ease both; }

/* TV reveal: the winner pops, the loser slumps, the stamp slams down, credits follow. */
.battle.result .vs { animation: none; opacity: 0.35; }
.battle.result .slot.win { animation: winPop 0.7s cubic-bezier(0.2, 1.5, 0.4, 1) both, sway 4.4s ease-in-out 0.9s infinite; }
.battle.result .slot.lose { animation: slump 0.8s ease-in 0.15s both; }
@keyframes winPop { 0% { transform: scale(0.92); } 60% { transform: scale(1.07); } 100% { transform: scale(1); } }
@keyframes slump { from { filter: none; transform: none; } to { filter: grayscale(0.85) brightness(0.62); transform: translateY(2.5vh) rotate(-3deg) scale(0.9); } }
.stamp { animation: stampIn 0.45s cubic-bezier(0.3, 1.8, 0.5, 1) 0.4s both; }
@keyframes stampIn { from { opacity: 0; transform: rotate(40deg) scale(3); } to { opacity: 1; transform: rotate(12deg) scale(1); } }
.battle.result .credits { animation: riseIn 0.5s ease 0.7s backwards; }
.roastline { display: inline-block; animation: riseIn 0.5s ease both; }
.manager .dots { display: inline-flex; margin: 0 0 0 0.5em; gap: 0.3em; vertical-align: middle; }
.manager .dots i { width: 0.35em; height: 0.35em; background: var(--muted); }

/* TV scores and the final screen. */
.scores .champ .product { animation: sway 4.6s ease-in-out infinite; }
.confetti { position: fixed; inset: 0; z-index: 3; overflow: hidden; pointer-events: none; }
.confetti i { position: absolute; top: -4vh; left: var(--x); width: 1.1vh; height: 2.2vh; border-radius: 0.2vh; background: var(--c); opacity: 0.9; animation: fall var(--d) linear var(--w) infinite; }
@keyframes fall { to { transform: translate3d(var(--sx), 112vh, 0) rotate(720deg); } }

/* Phone: each screen rises in, the main button glows, picks and votes answer a tap. */
.phone #app > section { animation: riseIn 0.38s cubic-bezier(0.2, 0.9, 0.3, 1.15) both; }
.phone .btn.big:not(.ghost):not(:disabled) { animation: glow 2s ease-out infinite; }
.phone .btn.big:not(.ghost):not(:disabled):active { animation: none; }
.pick.on, .cap.on { animation: press 0.25s ease; }
.phone .product { animation: prodIn 0.4s cubic-bezier(0.2, 1.4, 0.4, 1) backwards; }
@keyframes prodIn { from { opacity: 0; transform: scale(0.7) rotate(-9deg); } to { opacity: 1; transform: rotate(-1.5deg); } }
button.vote { animation: riseIn 0.4s ease backwards; }
button.vote:nth-child(2) { animation-delay: 0.1s; }
.gain { animation: popIn 0.6s cubic-bezier(0.2, 1.6, 0.4, 1) 0.25s both; }
.chips li:last-child { animation: popIn 0.3s ease both; }

/* ---------- fit ---------- */
/* Long prompts and labels must not push the face-off into the player strip. */
.slot { width: min(36vw, 52vh); }
.battle.result .slot { width: min(30vw, 33vh); }
.battle.result .shelf { margin-top: 1.6vh; }
.tv .product figcaption.long { font-size: 2.5vh; }
.battle.result .product figcaption.long { font-size: 2.2vh; }
.battle.result .credits { position: relative; left: 50%; width: 42vw; margin-left: -21vw; margin-top: 1.2vh; font-size: 2vh; }
.battle.result .credits b { font-size: 2.4vh; }
.credits .pic { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.manager { min-height: 1.3em; }
.battle.result .manager { margin-top: 1vh; font-size: 2.8vh; }

/* ---------- reveal ---------- */
/* Bigger pictures on the TV, and a staged reveal. Each face-off opens with both products covered;
   --img and --txt (set per product by host.js from the server's timings) say when its picture is
   uncovered and when its label lands. Voting opens when the reveal is over. */
.tv.faceoff #foot { display: none; } /* scores come back on the round's score screen */
.slot { width: min(42vw, 64vh); }
.battle.result .slot { width: min(36vw, 52vh); }
.battle.result .credits .pic { -webkit-line-clamp: 2; }
.battle.result .manager { font-size: 2.6vh; }
.shot { position: relative; overflow: hidden; border-radius: 1.6vh; }
.cover { position: absolute; inset: 0; display: none; place-items: center; border-radius: inherit; background: repeating-linear-gradient(135deg, #2a1560 0 3vh, #3b2085 3vh 6vh); }
.cover span { font-family: 'Bungee', sans-serif; font-size: 24vh; line-height: 1; color: var(--yellow); text-shadow: 0.05em 0.05em 0 var(--pink); animation: throb 0.9s ease-in-out infinite; }
.shelf-tag { position: absolute; top: 3%; left: -4%; transform: rotate(-8deg); background: var(--yellow); color: #170b30; font: 800 2.2vh 'Rubik', sans-serif; text-transform: uppercase; padding: 0.5vh 1vw; border-radius: 1vh; box-shadow: 0 0.6vh 0 rgba(0, 0, 0, 0.3); }

.battle.intro .slot:first-child { animation: fromLeft 0.6s cubic-bezier(0.2, 1.2, 0.4, 1) both; }
.battle.intro .slot:last-child { animation: fromRight 0.6s cubic-bezier(0.2, 1.2, 0.4, 1) 0.12s both; }
.battle.intro .cover { display: grid; animation: lift 0.5s cubic-bezier(0.6, 0, 0.3, 1) var(--img) forwards; }
@keyframes lift { to { transform: translateY(-103%); } }
.battle.intro .shot img { animation: flash 0.7s ease-out var(--img) backwards; }
@keyframes flash { from { transform: scale(1.3); filter: brightness(2.4) saturate(0.2); } to { transform: none; filter: none; } }
.battle.intro figcaption { animation: labelIn 0.45s cubic-bezier(0.3, 1.7, 0.5, 1) var(--txt) both; }
@keyframes labelIn { from { opacity: 0; transform: scale(1.6) rotate(-5deg); } to { opacity: 1; transform: none; } }
.battle.intro .vs { animation: none; opacity: 0; }

/* The vote follows the reveal on the same cards, so nothing slides in again. VS arrives with the vote. */
.tv #stage > .battle.vote { animation: none; }
.battle.vote .slot:first-child { animation: sway 4.4s ease-in-out infinite; }
.battle.vote .slot:last-child { animation: sway 4.4s ease-in-out 2.2s infinite; }
.battle.vote .vs { animation: slam 0.5s cubic-bezier(0.3, 1.7, 0.5, 1) both, throb 1.1s ease-in-out 0.6s infinite; }

/* The result holds for 1.4s (RESULT_HOLD in host.js): both products shake, then the winner is shown. */
.battle.result .shelf { animation: jitter 0.12s linear 0s 11; }
@keyframes jitter { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-0.35vw); } 75% { transform: translateX(0.35vw); } }
.battle.result .slot.win .product { outline-color: transparent; animation: ring 0.25s ease 1.4s forwards; }
@keyframes ring { to { outline-color: var(--lime); } }
.battle.result .slot.win { animation: winPop 0.7s cubic-bezier(0.2, 1.5, 0.4, 1) 1.4s, sway 4.4s ease-in-out 2.3s infinite; }
.battle.result .slot.lose { animation: slump 0.8s ease-in 1.5s both; }
.battle.result .stamp { animation-delay: 1.8s; }
.battle.result .credits { animation: riseIn 0.5s ease 2.2s backwards; }

/* Phone: the two versions of an order, bigger vote pictures, and a result that waits for the TV. */
.options { display: grid; gap: 12px; justify-items: center; }
.option { width: min(100%, 31vh); padding: 0; border: 4px solid transparent; border-radius: 16px; background: none; overflow: hidden; animation: riseIn 0.4s ease backwards; }
.option:nth-child(2) { animation-delay: 0.12s; }
.option img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 11px; }
.option:active { border-color: var(--lime); transform: scale(0.97); }
button.vote { flex-direction: column; text-align: center; gap: 8px; }
button.vote img { width: min(100%, 30vh); height: auto; aspect-ratio: 1; }
.phone #app > section.late { animation-delay: 1.9s; }

/* Anyone who has asked their device for less motion gets a still game. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* Keep the "Employee of the round" line clear of the swaying product under it. */
.scores .champ .step { margin-bottom: 2.2vh; }

/* ---------- phone, second pass: everything above the fold ---------- */
/* The phone screen never scrolls. player.js keeps --vvh equal to the height you can actually see
   (it shrinks when the keyboard opens) and adds "typing" to <body> while the keyboard is up.
   Every screen is a column that fits inside that height; pictures take whatever room is left. */
html:has(body.phone) { height: 100%; overflow: hidden; overscroll-behavior: none; }
body.phone { position: fixed; top: 0; left: 0; right: 0; height: var(--vvh, 100dvh); display: flex; flex-direction: column; overflow: hidden; padding-bottom: 0; }
.phone #bar { position: static; flex: none; gap: 8px; padding: calc(7px + env(safe-area-inset-top)) 12px 7px; font-size: 15px; background: color-mix(in srgb, var(--bg) 92%, transparent); }
.phone #bar .iconbtn { padding: 5px 9px; font-size: 16px; }
.phone main { flex: 1 1 0; min-height: 0; width: 100%; max-width: 540px; margin: 0 auto; padding: 10px 12px calc(10px + env(safe-area-inset-bottom)); display: flex; flex-direction: column; }
.phone #app > section.card { display: flex; flex-direction: column; gap: 10px; min-height: 0; max-height: 100%; padding: 14px; overflow: hidden; }
.phone #app > section.card.fill { flex: 1 1 0; }
:where(.phone .card) > * { flex: none; } /* zero-weight on purpose: any screen's own rule can make a child stretch */
.phone .card h2 { font-size: 20px; line-height: 1.1; margin: 0; }
.phone .card .lead { font-size: 15.5px; line-height: 1.3; margin: 0; }
.phone .card .lead.clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.phone .head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.phone .card.center .head { justify-content: center; }
.phone .head .count { font-size: 13px; color: var(--muted); white-space: nowrap; }
.phone textarea, .phone input { margin: 0; padding: 11px 12px; }
.phone textarea { height: 84px; }
.phone .btn { padding: 12px 14px; font-size: 17px; }
.phone .btn.big { margin: 0; padding: 13px 14px; font-size: 18px; }
.phone .btn.small { align-self: center; padding: 9px 12px; font-size: 15px; }
.phone .row { gap: 8px; }
.phone .row .grow { flex: 1; }
.phone .stack { display: flex; flex-direction: column; gap: 10px; }
.phone .muted { font-size: 14.5px; }
.phone .mini { font-size: 11.5px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.phone .spinner { margin: 6px auto; }
.phone .dots { margin: 0; }
.phone .gain { font-size: 22px; margin: 0; }
.phone #toast { top: calc(var(--vvh, 100vh) - 64px); bottom: auto; }

/* A picture that takes whatever room is left and stays square. */
.fit { flex: 1 1 0; min-width: 0; min-height: 0; container-type: size; display: grid; place-items: center; }
.fit > img { display: block; width: min(100cqw, 100cqh); height: min(100cqw, 100cqh); object-fit: cover; border-radius: 12px; }
.slotfit { flex: 1 1 0; min-height: 0; display: flex; }
/* A product card (picture plus label) that grows to fill the room it is given and keeps its shape:
   as wide as the space allows, but never so wide that the label under the picture would not fit. */
.hug { display: block; width: min(100cqw, calc(100cqh - 46px)); padding: 7px 7px 0; background: #fff; color: #170b30; border-radius: 14px; box-shadow: 0 5px 0 rgba(0, 0, 0, 0.28); }
.phone .hug img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; border-radius: 9px; }
.hug .lbl { display: flex; align-items: center; justify-content: center; height: 40px; padding: 0 4px; font: 800 15px/1.15 'Rubik', sans-serif; text-align: center; }
.hug .lbl span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }

/* Join */
.phone .join .logo { margin: 0; font-size: min(64px, calc(var(--vvh, 100vh) * 0.085)); }
.phone #jCode { font-size: 26px; }
/* Lobby */
.phone .roster { margin: 0; gap: 6px; }
.phone .chip { gap: 6px; padding: 4px 10px 4px 6px; font-size: 14px; border-width: 1.5px; }
.phone .chip .dot { width: 12px; height: 12px; }
.themes { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.themechip { font: 600 14px 'Rubik', sans-serif; color: var(--ink); background: var(--panel-2); border: 2px solid var(--line); border-radius: 999px; padding: 7px 11px; }
.themechip.on { border-color: var(--lime); }
/* Keep one of two */
.phone .options { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
.phone .option { flex: 1 1 0; min-height: 0; width: auto; display: flex; padding: 0; border: 0; border-radius: 0; background: none; overflow: visible; }
.phone .option .fit > img { border: 4px solid transparent; border-radius: 14px; }
.phone .option:active .fit > img { border-color: var(--lime); }
/* Labels */
.phone .chips { flex: 0 1 auto; min-height: 0; overflow-y: auto; margin: 0; gap: 6px; }
.phone .chips li { padding: 4px 10px; font-size: 13.5px; border-width: 1.5px; }
/* Build */
.phone .picks { display: flex; justify-content: center; gap: 8px; margin: 0; }
.phone .pick { flex: none; width: 60px; height: 60px; border-width: 3px; border-radius: 12px; }
.phone .pick img { width: 100%; height: 100%; border-radius: 8px; }
.phone .caps { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.phone .cap { display: flex; align-items: center; min-height: 46px; padding: 7px 9px; font-size: 13.5px; line-height: 1.2; border-width: 2px; border-radius: 10px; }
.phone .cap span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.phone .cap:last-child:nth-child(odd) { grid-column: 1 / -1; min-height: 0; }
/* Vote */
.phone .votes { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
.phone button.vote { flex: 1 1 0; min-height: 0; display: flex; flex-direction: row; align-items: stretch; padding: 0; border: 0; background: none; box-shadow: none; color: inherit; }
.phone button.vote:active { transform: none; box-shadow: none; }
.phone button.vote:active .hug { transform: translateY(3px); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.28); }
/* Scores */
.phone .board { margin: 0; gap: 5px; }
.phone .board li { gap: 8px; padding: 7px 12px; font-size: 15px; }

/* Keyboard up: drop the extras so the field and its button are what is left on screen. */
.phone.typing main { padding-top: 6px; padding-bottom: 6px; }
.phone.typing #app > section.card { gap: 8px; padding: 10px 12px; }
.phone.typing .lead, .phone.typing .chips, .phone.typing .mini, .phone.typing .dots { display: none; }
.phone.typing .join .logo { font-size: 24px; }
.phone.typing .join .logo br { display: none; }

/* ---------- TV: host code, theme slot machine ---------- */
.gate { display: grid; gap: 2.4vh; justify-items: center; text-align: center; max-width: 70vw; }
.gate .logo { font-size: 14vh; }
.gate .how { font-size: 3.2vh; }
.gate input { width: min(60vw, 560px); margin: 0; padding: 1.6vh 1vw; font-size: 3.2vh; text-align: center; }
.roll { text-align: center; }
.roll .step { font-size: 4.4vh; }
.roll .how { font-size: 3.8vh; color: var(--muted); min-height: 1.3em; }
.reel { width: min(84vw, 160vh); height: 24vh; margin: 3.5vh auto; overflow: hidden; border-radius: 3vh; background: var(--panel); border: 0.7vh solid var(--line); box-shadow: inset 0 4vh 4vh -3vh rgba(0, 0, 0, 0.7), inset 0 -4vh 4vh -3vh rgba(0, 0, 0, 0.7); }
.strip { animation: reel var(--dur) cubic-bezier(0.12, 0.72, 0.1, 1) forwards; will-change: transform; }
@keyframes reel { to { transform: translateY(calc(var(--n) * -24vh)); } }
.reel-item { height: 24vh; display: flex; align-items: center; justify-content: center; gap: 2vw; font-size: 14vh; line-height: 1; white-space: nowrap; color: var(--lime); text-shadow: 0.05em 0.05em 0 var(--pink); }
.reel-item span { font-size: 11vh; text-shadow: none; }
.roll.landed .reel { border-color: var(--lime); animation: landed 0.7s cubic-bezier(0.3, 1.7, 0.5, 1); }
@keyframes landed { 0% { transform: scale(1); } 40% { transform: scale(1.09); } 100% { transform: scale(1); } }

/* ---------- themes ---------- */
/* host.js and player.js set data-theme on <html>. A theme only swaps colours, the headline font and
   the backdrop; every screen keeps its layout. "base" is the plain look and needs no rules here. */
h1, h2, .logo, .code, .stamp, .vs, .step, .brand, .mgr, .timer, .gain, .count, .cover span, .board .rank, .board .amt, .shelf-tag, .reel-item, .cash, .chip .amt, .codemini, #jCode {
  font-family: var(--display, 'Bungee'), 'Arial Black', sans-serif !important;
}
.btn { box-shadow: 0 5px 0 var(--btn-shadow, #6f9f17); }
.btn:active { box-shadow: 0 1px 0 var(--btn-shadow, #6f9f17); }
.btn.ghost, .btn.ghost:active { box-shadow: none; }
@keyframes glow { 0% { box-shadow: 0 5px 0 var(--btn-shadow, #6f9f17), 0 0 0 0 var(--glow, rgba(182, 255, 60, 0.55)); } 100% { box-shadow: 0 5px 0 var(--btn-shadow, #6f9f17), 0 0 0 14px transparent; } }
.cap.on, .themechip.on { background: color-mix(in srgb, var(--lime) 20%, var(--panel-2)); }
.cover { background: repeating-linear-gradient(135deg, var(--panel) 0 3vh, var(--line) 3vh 6vh); }
body::before {
  background:
    radial-gradient(38% 34% at 28% 30%, var(--blob-1, rgba(255, 79, 163, 0.2)), transparent 70%),
    radial-gradient(34% 30% at 74% 68%, var(--blob-2, rgba(79, 216, 255, 0.16)), transparent 70%),
    radial-gradient(26% 24% at 60% 22%, var(--blob-3, rgba(182, 255, 60, 0.1)), transparent 70%);
}
html[data-theme]:not([data-theme='base']) body {
  background:
    radial-gradient(1100px 700px at 85% -10%, var(--wash-1) 0, transparent 60%),
    radial-gradient(900px 600px at -10% 110%, var(--wash-2) 0, transparent 55%),
    var(--bg);
}

/* Pirate: deep sea, gold and crimson. */
html[data-theme='pirate'] {
  --bg: #071a22; --panel: #123440; --panel-2: #0a242e; --line: #2e6274;
  --lime: #f4c542; --pink: #e2504c; --yellow: #f6e7b4; --muted: #a8c6cf;
  --btn-shadow: #9c7a12; --glow: rgba(244, 197, 66, 0.5); --display: 'Pirata One';
  --wash-1: #0f4a5c; --wash-2: #5c1a1a;
  --blob-1: rgba(244, 197, 66, 0.14); --blob-2: rgba(40, 170, 190, 0.2); --blob-3: rgba(226, 80, 76, 0.12);
}
/* Western: leather, sand and rust. */
html[data-theme='western'] {
  --bg: #1f0f06; --panel: #4a2812; --panel-2: #2f1808; --line: #84502a;
  --lime: #f2b84b; --pink: #d9552b; --yellow: #ffe3ad; --muted: #dcbc9c;
  --btn-shadow: #9a6a16; --glow: rgba(242, 184, 75, 0.5); --display: 'Rye';
  --wash-1: #6b3410; --wash-2: #5a1d0c;
  --blob-1: rgba(242, 184, 75, 0.18); --blob-2: rgba(217, 85, 43, 0.16); --blob-3: rgba(255, 227, 173, 0.08);
}
/* Space: near-black, cyan and violet, with stars. */
html[data-theme='space'] {
  --bg: #04050f; --panel: #10163a; --panel-2: #080c22; --line: #2b3a7c;
  --lime: #5ef2ff; --pink: #b46bff; --yellow: #ffe66b; --muted: #9db0ea;
  --btn-shadow: #1b8e9b; --glow: rgba(94, 242, 255, 0.5); --display: 'Orbitron';
  --wash-1: #1b1f6b; --wash-2: #3a0f66;
  --blob-1: rgba(180, 107, 255, 0.22); --blob-2: rgba(94, 242, 255, 0.16); --blob-3: rgba(255, 255, 255, 0.05);
}
html[data-theme='space'] body {
  background:
    radial-gradient(1.6px 1.6px at 40px 60px, #fff 50%, transparent 51%) 0 0 / 230px 230px,
    radial-gradient(1.2px 1.2px at 150px 20px, #cfe 50%, transparent 51%) 0 0 / 190px 190px,
    radial-gradient(1px 1px at 90px 130px, #fff 50%, transparent 51%) 0 0 / 140px 140px,
    radial-gradient(1100px 700px at 85% -10%, var(--wash-1) 0, transparent 60%),
    radial-gradient(900px 600px at -10% 110%, var(--wash-2) 0, transparent 55%),
    var(--bg);
}
