/* ===== Reset & base ===== */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
  height: 100%; width: 100%;
  overflow: hidden;
  font-family: 'Segoe UI', system-ui, sans-serif;
  touch-action: none;              /* the pitch handles its own gestures */
  overscroll-behavior: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  background: #0d1b12;
  color: #f2f7f3;
}
img { -webkit-user-drag: none; user-select: none; }

/* ===== Screens ===== */
.screen { position: fixed; inset: 0; }
.screen--hidden { display: none; }

/* ===== Buttons ===== */
.btn {
  font: inherit;
  font-weight: 600;
  color: #10231a;
  background: #ffd166;
  border: none;
  border-radius: 999px;
  padding: 0.6em 1.4em;
  cursor: pointer;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.25);
  transition: transform 0.08s ease-out, filter 0.15s;
}
.btn:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); }
.btn:hover { filter: brightness(1.06); }
.btn--big { font-size: 1.3rem; padding: 0.7em 2em; }
.btn--small { font-size: 0.85rem; padding: 0.45em 1em; }
.btn--ghost {
  background: rgba(255, 255, 255, 0.14);
  color: #f2f7f3;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.2);
}

/* ===== Portrait nag ===== */
.rotate-nag {
  position: fixed; inset: 0;
  display: none;
  flex-direction: column;
  align-items: center; justify-content: center;
  gap: 0.6em;
  background: #0d1b12;
  z-index: 500;
}
.rotate-nag__icon { font-size: 4rem; animation: nag-turn 2s ease-in-out infinite; }
.rotate-nag__text { font-size: 1.1rem; opacity: 0.75; }
@keyframes nag-turn {
  0%, 40% { transform: rotate(0deg); }
  60%, 100% { transform: rotate(90deg); }
}
/* Landscape is the only supported orientation - a pitch is wide. */
@media (orientation: portrait) and (max-width: 900px) {
  .rotate-nag { display: flex; }
}

/* ===== Splash ===== */
.splash {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(ellipse at center, #1e5631 0%, #0d1b12 100%);
  z-index: 200;
  transition: opacity 0.35s ease-out;
}
.splash--hidden { opacity: 0; pointer-events: none; }
.splash__content { text-align: center; padding: 1em; }
.splash__icon { font-size: 4.5rem; animation: ball-bob 2.2s ease-in-out infinite; }
.splash__title {
  font-size: 3rem; font-weight: 800; letter-spacing: -0.02em;
  margin-top: 0.1em;
  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.3);
}
.splash__intro {
  margin: 1em auto 1.4em;
  display: flex; flex-direction: column; gap: 0.35em;
  width: max-content; max-width: 100%;
}
.splash__rule { font-size: 1rem; color: #bfe0cb; text-align: left; }
.splash__buttons { display: flex; gap: 0.8em; justify-content: center; flex-wrap: wrap; }
@keyframes ball-bob {
  0%, 100% { transform: translateY(0) rotate(-6deg); }
  50%      { transform: translateY(-12px) rotate(6deg); }
}

/* ===== Top bar ===== */
#top-bar {
  position: fixed; top: 0; left: 0; right: 0;
  height: 44px;
  padding: 0 10px;
  padding-top: env(safe-area-inset-top, 0px);
  display: flex; align-items: center; gap: 10px;
  background: rgba(8, 20, 13, 0.82);
  z-index: 60;
}
.score { display: flex; align-items: center; gap: 6px; }
.score--away { margin-left: auto; }
.score__num { font-size: 1.4rem; font-weight: 800; min-width: 1ch; }
/* The kid reads the mood, not the number - the face is the score display. */
.score__face {
  width: 34px; height: 34px;
  border-radius: 50%;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.12);
  border: 2px solid var(--team-colour, #fff);
  flex: none;
}
.score__face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.score__face--pop { animation: face-pop 0.5s ease-out; }
@keyframes face-pop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.45) rotate(-8deg); }
  100% { transform: scale(1); }
}
#clock {
  position: absolute; left: 50%; transform: translateX(-50%);
  font-size: 1.05rem; font-variant-numeric: tabular-nums; opacity: 0.85;
}
.top-bar__actions { display: flex; gap: 2px; }
.top-bar__actions button {
  background: none; border: none; color: #f2f7f3;
  font-size: 1.15rem; cursor: pointer; padding: 4px 7px; border-radius: 6px;
}
.top-bar__actions button:hover { background: rgba(255, 255, 255, 0.1); }

/* ===== Banner (KICK OFF / GOAL! / FULL TIME) ===== */
.banner {
  position: fixed; top: 38%; left: 0; right: 0;
  text-align: center;
  z-index: 90;
  pointer-events: none;
}
.banner span {
  display: inline-block;
  font-size: clamp(2rem, 9vw, 5rem);
  font-weight: 900;
  letter-spacing: -0.02em;
  color: #fff;
  padding: 0.1em 0.5em;
  border-radius: 0.3em;
  background: rgba(10, 30, 18, 0.55);
  text-shadow: 0 4px 0 rgba(0, 0, 0, 0.35);
  animation: banner-in 0.45s cubic-bezier(0.2, 1.6, 0.4, 1);
}
.banner--hidden { display: none; }
@keyframes banner-in {
  0%   { transform: scale(0.2) rotate(-12deg); opacity: 0; }
  70%  { transform: scale(1.12) rotate(3deg); opacity: 1; }
  100% { transform: scale(1) rotate(0deg); }
}

/* ===== GOAL! =====
   A goal gets the comic book treatment - the word on a starburst, the way BOOM
   is drawn - rather than the same calm plate as "kick off". The outline is
   eight offset shadows instead of -webkit-text-stroke, because a centred
   stroke eats into the letterform at this weight, and they are in em so the
   whole thing scales with the clamped font size. */
.banner--boom span {
  position: relative;
  background: none;
  padding: 0.12em 0.34em;
  color: #ffd166;
  font-style: italic;
  font-size: clamp(2.4rem, 12vw, 6.4rem);
  letter-spacing: 0.01em;
  transform: rotate(-5deg);
  text-shadow:
    -0.045em -0.045em 0 #10231a, 0.045em -0.045em 0 #10231a,
    -0.045em 0.045em 0 #10231a, 0.045em 0.045em 0 #10231a,
    0 -0.05em 0 #10231a, 0 0.05em 0 #10231a,
    -0.05em 0 0 #10231a, 0.05em 0 0 #10231a,
    0 0.1em 0 #e8622c, 0 0.15em 0.02em rgba(0, 0, 0, 0.45);
  animation:
    boom-in 0.42s cubic-bezier(0.2, 1.9, 0.35, 1),
    boom-shake 0.5s 0.42s ease-in-out;
}
.banner--boom span::before {
  content: '';
  position: absolute;
  inset: -0.34em -0.5em;
  z-index: -1;
  background: radial-gradient(circle at 50% 45%, #ffe29a 0%, #f4913d 45%, #e8622c 100%);
  clip-path: polygon(50.0% 0.0%, 56.9% 19.8%, 71.7% 5.0%, 69.3% 25.8%, 89.1% 18.8%, 77.9% 36.5%, 98.7% 38.9%, 81.0% 50.0%, 98.7% 61.1%, 77.9% 63.5%, 89.1% 81.2%, 69.3% 74.2%, 71.7% 95.0%, 56.9% 80.2%, 50.0% 100.0%, 43.1% 80.2%, 28.3% 95.0%, 30.7% 74.2%, 10.9% 81.2%, 22.1% 63.5%, 1.3% 61.1%, 19.0% 50.0%, 1.3% 38.9%, 22.1% 36.5%, 10.9% 18.8%, 30.7% 25.8%, 28.3% 5.0%, 43.1% 19.8%);
  animation: boom-star 0.42s cubic-bezier(0.2, 1.9, 0.35, 1), boom-spin 9s linear 0.42s infinite;
}
@keyframes boom-in {
  0%   { transform: scale(0.15) rotate(-24deg); opacity: 0; }
  65%  { transform: scale(1.18) rotate(2deg); opacity: 1; }
  100% { transform: scale(1) rotate(-5deg); }
}
@keyframes boom-star {
  0%   { transform: scale(0.1) rotate(-40deg); opacity: 0; }
  60%  { transform: scale(1.14) rotate(6deg); opacity: 1; }
  100% { transform: scale(1) rotate(0deg); }
}
@keyframes boom-shake {
  0%, 100% { transform: scale(1) rotate(-5deg); }
  25%      { transform: scale(1.03) rotate(-2.5deg); }
  60%      { transform: scale(1.01) rotate(-7deg); }
}
@keyframes boom-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
/* ===== kick off =====
   The other half of the comic vocabulary: a caption plate rather than an
   impact. Cream newsprint, a hard ink border offset into a shadow the way a
   comic panel is inked, and speed lines either side so it arrives rather than
   simply appearing. Dark text here because the plate itself is light. */
.banner--panel span {
  position: relative;
  background: #fbf0d3;
  color: #16241a;
  border: 0.055em solid #10231a;
  border-radius: 0.05em;
  box-shadow: 0.085em 0.085em 0 #10231a, 0.17em 0.17em 0 rgba(0, 0, 0, 0.3);
  font-size: clamp(1.5rem, 6.2vw, 3.4rem);
  font-style: italic;
  font-weight: 900;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-shadow: none;
  padding: 0.12em 0.45em;
  transform: rotate(-2deg);
  animation: panel-in 0.42s cubic-bezier(0.2, 1.5, 0.4, 1);
}
.banner--panel span::before,
.banner--panel span::after {
  content: '';
  position: absolute;
  top: 16%; bottom: 16%;
  width: 0.85em;
  background:
    linear-gradient(#10231a, #10231a) left 22% / 100% 0.075em no-repeat,
    linear-gradient(#10231a, #10231a) left 50% / 78% 0.075em no-repeat,
    linear-gradient(#10231a, #10231a) left 78% / 55% 0.075em no-repeat;
}
.banner--panel span::before { right: 100%; margin-right: 0.3em; transform: scaleX(-1); }
.banner--panel span::after { left: 100%; margin-left: 0.3em; }
@keyframes panel-in {
  0%   { transform: translateX(-0.7em) rotate(-9deg) scale(0.78); opacity: 0; }
  65%  { transform: translateX(0.06em) rotate(1.5deg) scale(1.05); opacity: 1; }
  100% { transform: translateX(0) rotate(-2deg) scale(1); }
}

/* Anyone who would rather the screen sat still keeps the words and loses the
   spin and the wobble. */
@media (prefers-reduced-motion: reduce) {
  .banner--boom span,
  .banner--boom span::before,
  .banner--panel span { animation: none; }
}

/* ===== Overlays ===== */
.overlay {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6, 16, 10, 0.72);
  z-index: 120;
}
.overlay--hidden { display: none; }

.fulltime__card {
  text-align: center;
  background: #14301f;
  border-radius: 18px;
  padding: 1.4em 2em;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
  max-width: 90vw;
}
.fulltime__title { font-size: 2rem; font-weight: 800; }
.fulltime__score { font-size: 1.2rem; opacity: 0.8; margin: 0.3em 0 1em; }
.fulltime__buttons { display: flex; gap: 0.6em; justify-content: center; flex-wrap: wrap; }

/* ===== Viewport and pitch =====
   #viewport clips; #pitch carries the zoom punch and screen shake; the three
   layers inside it each pan by -camX * zoom (the crowd at a third of that). */
#viewport {
  position: fixed;
  top: 44px; left: 0; right: 0; bottom: 0;
  top: calc(44px + env(safe-area-inset-top, 0px));
  overflow: hidden;
  background: #0d1b12;
}
#pitch { position: absolute; inset: 0; will-change: transform; }
#crowd, #pitch-markings, #world, #fx {
  position: absolute; left: 0; top: 0;
  will-change: transform;
}
#world, #fx { width: 100%; height: 100%; }
#fx { pointer-events: none; }

/* ===== Scene: grass ===== */
.scene-grass { background: linear-gradient(#0f3f24 0%, #0b2a18 55%, #071a0f 100%); }
.scene-grass .pm__surface {
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.045) 0 64px, rgba(0,0,0,0.045) 64px 128px),
    linear-gradient(#2f7d4a 0%, #3f9459 45%, #4aa463 100%);
}
.scene-grass .crowd {
  background:
    radial-gradient(circle at 12px 10px, #ffd166 0 4px, transparent 5px),
    radial-gradient(circle at 34px 16px, #ef476f 0 4px, transparent 5px),
    radial-gradient(circle at 56px 8px, #06d6a0 0 4px, transparent 5px),
    radial-gradient(circle at 78px 18px, #118ab2 0 4px, transparent 5px),
    linear-gradient(#20313f, #16232d);
  background-size: 96px 28px, 96px 28px, 96px 28px, 96px 28px, 100% 100%;
}
.scene-grass .pm__wall { background: linear-gradient(#f4f6f8, #c6ced6); }
.scene-grass .pm__endwall { background: linear-gradient(90deg, #f4f6f8, #c6ced6); }

/* ===== Pitch markings ===== */
#pitch-markings { pointer-events: none; }
.pm__surface, .pm__line, .pm__circle, .pm__box, .pm__spot,
.pm__wall, .pm__endwall, .pm__goal {
  position: absolute;
}
/* Shared by every scene; the scene blocks only paint. */
.pm__surface { box-shadow: inset 0 24px 40px rgba(0, 0, 0, 0.28); }
.pm__halfway { width: 3px; background: rgba(255, 255, 255, 0.5); margin-left: -1.5px; }
.pm__circle { border: 3px solid rgba(255, 255, 255, 0.45); border-radius: 50%; }
.pm__spot { width: 6px; height: 6px; border-radius: 50%; background: rgba(255, 255, 255, 0.6); }
.pm__box { border: 3px solid rgba(255, 255, 255, 0.4); }
/* Walls: the pitch is fully enclosed, so the ball never goes out. */
.pm__wall { height: 7px; border-radius: 3px; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4); }
.pm__wall--far { transform: translateY(-7px); }
.pm__endwall { width: 6px; border-radius: 3px; }
.pm__goal {
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.75) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.75) 0 1px, transparent 1px 9px),
    rgba(10, 20, 14, 0.45);
  border: 3px solid #fff;
  box-shadow: 0 0 14px rgba(255, 255, 255, 0.3);
}
.crowd { pointer-events: none; }
/* The crowd bounces along with the match. */
.crowd--cheer { animation: crowd-bounce 0.28s ease-in-out 8; }
@keyframes crowd-bounce {
  0%, 100% { background-position-y: 0, 0, 0, 0, 0; }
  50%      { background-position-y: -5px, 3px, -4px, 4px, 0; }
}

/* ===== Ball ===== */
.ball {
  position: absolute; left: 0; top: 0;
  will-change: transform;
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
}
.ball__shadow {
  position: absolute; left: 0; top: 0;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.3);
  filter: blur(2px);
  will-change: transform;
  pointer-events: none;
}

/* ===== Juice ===== */
/* Ball trail: a fading clone dropped every few frames on a hard shot. */
.ball-trail {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.55);
  animation: trail-fade 0.26s linear forwards;
  pointer-events: none;
}
@keyframes trail-fade {
  from { opacity: 0.5; transform: scale(0.9); }
  to   { opacity: 0; transform: scale(0.4); }
}

/* Fireworks: --dx/--dy carry each spark's direction. */
.spark {
  position: absolute;
  width: 7px; height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  animation: spark-fly 0.9s cubic-bezier(0.1, 0.7, 0.3, 1) forwards;
  pointer-events: none;
}
@keyframes spark-fly {
  0%   { transform: translate(0, 0) scale(0.4); opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translate(var(--dx), calc(var(--dy) + 30px)) scale(0.9); opacity: 0; }
}

/* ===== Editor ===== */
#editor-bar {
  position: fixed; top: 0; left: 0; right: 0;
  height: 44px;
  padding: 0 10px;
  padding-top: env(safe-area-inset-top, 0px);
  display: flex; align-items: center; gap: 10px;
  background: rgba(8, 20, 13, 0.9);
  z-index: 60;
}
#editor-bar #editor-back {
  background: none; border: none; color: #f2f7f3;
  font-size: 1.4rem; cursor: pointer; padding: 2px 8px; border-radius: 6px;
}
#editor-title { font-weight: 600; opacity: 0.85; }
#editor-bar #editor-play { margin-left: auto; }

#editor-body {
  position: absolute;
  top: calc(44px + env(safe-area-inset-top, 0px)); left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column;
  gap: 8px;
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(#123021, #0a1a11);
  /* Scroll rather than clip: the key legend at the bottom is the first thing
     to be cut off on a short landscape screen. */
  overflow-x: hidden;
  overflow-y: auto;
}

/* Roster strip */
.ed__roster {
  display: flex; gap: 8px;
  overflow-x: auto; overflow-y: hidden;
  flex: none;
  padding-bottom: 4px;
  scrollbar-width: thin;
}
.ed__card {
  flex: none;
  width: 54px; height: 54px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.08);
  color: #f2f7f3;
  font-size: 1.5rem;
  cursor: pointer;
  overflow: hidden;
  padding: 0;
  display: flex; align-items: center; justify-content: center;
}
.ed__card img { width: 100%; height: 100%; object-fit: contain; }
.ed__card--on { border-color: #ffd166; box-shadow: 0 0 0 3px rgba(255, 209, 102, 0.3); }
.ed__card--add { border-style: dashed; }
.ed__card--del { border-color: rgba(239, 71, 111, 0.5); font-size: 1.2rem; }

/* Preview and slots */
/* min-height stops a short landscape screen crushing the preview to nothing.
   Below that the editor body scrolls instead, which is the right trade on a
   phone - the character you are building must stay visible. */
/* The preview with the parts in a row beneath it, rather than a tall thin
   column of parts beside it. The column left the width either side of the
   stage empty and scrolled by itself, which is a poor place to keep anything
   you are meant to find. */
.ed__main {
  flex: 1; min-height: 170px;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.ed__stage {
  flex: 1 1 auto;
  width: 100%; max-width: 560px; min-height: 120px;
  position: relative;
  border-radius: 14px;
  background:
    radial-gradient(ellipse at 50% 92%, rgba(0, 0, 0, 0.35) 0%, transparent 60%),
    linear-gradient(#2f7d4a, #1d5230);
  overflow: hidden;
  cursor: pointer;
}
/* The rig stands on the floor of the stage and scales up from its feet.
   The scale itself is set by Editor._sizePreview from the stage's measured
   height, because a fixed one clips the head on a short screen. */
.ed__stage .ch {
  left: 50%; top: auto; bottom: 8%;
  margin-left: -50px;
  transform-origin: 50% 100%;
}
.ed__slots {
  flex: none;
  width: 100%; max-width: 560px;
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 8px;
}
.ed__slots .ed__chip { width: 74px; }
.ed__chip { position: relative; display: flex; flex-direction: column; gap: 2px; }
.ed__chip-word {
  font-size: 0.66rem; text-align: center; color: #cfe6d8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ed__chip--set .ed__chip-word { color: #f2f7f3; }
.ed__chip-btn {
  width: 100%; aspect-ratio: 1;
  border-radius: 14px;
  border: 2px dashed rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.07);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
}
.ed__chip-icon { font-size: 1.5rem; }
.ed__chip--set .ed__chip-btn { border-style: solid; border-color: #ffd166; background: rgba(255, 209, 102, 0.14); }
.ed__chip-clear {
  position: absolute; top: -5px; right: -5px;
  width: 21px; height: 21px;
  border-radius: 50%;
  border: none;
  background: #ef476f; color: #fff;
  font-size: 0.7rem; line-height: 1; cursor: pointer;
  padding: 0;
}
/* Teams, ball and settings.
   The groups sit next to each other and wrap, rather than stacking five deep.
   Stacked, they left most of the width empty and pushed the key legend off a
   short screen; packed, a wide screen shows the lot at once and a narrow one
   falls back to a column by itself. */
.ed__teams {
  flex: none;
  display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: 6px 20px;
}
.ed__group { display: flex; flex-direction: column; gap: 4px; }
/* The team strips and the key legend want the whole line to themselves. */
.ed__group--full { flex-basis: 100%; }
.ed__team { display: flex; align-items: center; gap: 5px; }
.ed__swatch {
  width: 17px; height: 17px; border-radius: 50%;
  border: 2px solid transparent; cursor: pointer; padding: 0;
}
.ed__swatch--on { border-color: #fff; transform: scale(1.2); }
.ed__slotcell {
  width: 42px; height: 42px;
  border-radius: 10px;
  border: 2px solid var(--team-colour, #fff);
  background: rgba(255, 255, 255, 0.08);
  color: #f2f7f3; font-size: 1.1rem; cursor: pointer;
  overflow: hidden; padding: 0;
  display: flex; align-items: center; justify-content: center;
}
.ed__slotcell img { width: 100%; height: 100%; object-fit: contain; }
.ed__slotcell--gk { border-radius: 50%; margin-right: 6px; }
.ed__extras { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ed__ball {
  width: 42px; height: 42px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.08);
  cursor: pointer; padding: 3px;
}
.ed__ball img { width: 100%; height: 100%; object-fit: contain; }
.ed__toggle {
  min-width: 42px; height: 42px;
  border-radius: 10px; border: 2px solid rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.07);
  /* A button does not inherit the page colour: without this the browser's own
     black lands on a near-black panel. It went unnoticed while these held
     nothing but emoji, which carry their own colour. */
  color: #f2f7f3;
  font-size: 1.2rem; cursor: pointer; padding: 0 8px;
}
.ed__toggle--on { border-color: #ffd166; background: rgba(255, 209, 102, 0.18); }
/* A named toggle stacks the word under the picture. The icon alone was a
   riddle for anyone who can read, and the word alone is slower to scan than
   the picture, so both. */
.ed__toggle--named {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; height: auto; min-height: 42px; padding: 4px 9px; line-height: 1.05;
}
.ed__toggle-icon { font-size: 1.1rem; line-height: 1; }
.ed__toggle-word { font-size: 0.76rem; letter-spacing: 0.01em; opacity: 0.9; }
.ed__toggle--on .ed__toggle-word { opacity: 1; }
/* Section headings. Lower case: that is the letterform a new reader meets
   first, and it matches the rest of the game's voice. */
.ed__label {
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: lowercase;
  color: #b7e8ca; margin: 5px 0 0;
}
.ed__label:first-child { margin-top: 0; }
.ed__warn {
  font-size: 0.75rem; color: #ffb3c1; opacity: 0.9;
}

/* Adjust overlay */
.adjust__card {
  background: #14301f;
  border-radius: 18px;
  padding: 14px;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
.adjust__frame {
  position: relative;
  height: min(52vh, 300px);
  border-radius: 12px;
  overflow: hidden;
  background:
    repeating-conic-gradient(#2a2a2a 0% 25%, #343434 0% 50%) 50% / 18px 18px;
  border: 3px solid #ffd166;
  touch-action: none;
  cursor: grab;
}
.adjust__frame canvas { display: block; width: 100%; height: 100%; }
.adjust__tools { display: flex; gap: 8px; align-items: center; }
.btn--on { background: #ffd166; color: #10231a; }

/* Portrait phones: stack the preview above the slots so neither gets squeezed. */
@media (max-height: 430px) {
  .ed__slots .ed__chip { width: 58px; }
  .ed__chip-word { font-size: 0.6rem; }
  .ed__slotcell, .ed__ball, .ed__toggle { width: 34px; height: 34px; }
  .ed__toggle--named { width: auto; height: auto; min-height: 34px; padding: 2px 7px; }
  .ed__toggle-word { font-size: 0.66rem; }
  .ed__label { font-size: 0.72rem; margin: 2px 0 -1px; }
}

/* ===== Keyboard legend =====
   Shown on the splash and under the editor's two-player toggle. Both are built
   from Input.legendHtml, so neither can disagree with the actual bindings. */
kbd {
  display: inline-block;
  font: inherit;
  font-size: 0.85em;
  line-height: 1;
  padding: 0.25em 0.45em;
  margin: 0 0.1em;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-bottom-width: 2px;
  white-space: nowrap;
}
/* Which player a row belongs to. Colours match the two default team kits. */
.who {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.4em; height: 1.4em;
  margin-right: 0.4em;
  border-radius: 50%;
  background: var(--team-colour, #e63946);
  font-size: 0.8em; font-weight: 700;
  flex: none;
}
.who--2 { background: #457b9d; }

.splash__keys {
  margin: 0 0 1.2em;
  display: flex; flex-direction: column; gap: 0.4em;
  font-size: 0.82rem;
  color: #a9c9b6;
}
.splash__keyrow { display: flex; align-items: center; justify-content: center; gap: 0.15em; flex-wrap: wrap; }

.ed__keys {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 0.72rem;
  color: #a9c9b6;
}
.ed__keyrow { display: flex; align-items: center; gap: 0.15em; flex-wrap: wrap; }
/* Dimmed until two-player is switched on. */
.ed__keyrow--off { opacity: 0.35; }

@media (max-height: 430px) {
  .ed__keys { font-size: 0.66rem; }
}

/* ===== Team place picker =====
   Opened by tapping a place in a team row. Every face is drawn in that team's
   kit colour, so you can see how a character will look before choosing them. */
.picker__card {
  background: #14301f;
  border-radius: 18px;
  padding: 12px 14px 14px;
  max-width: min(92vw, 560px);
  max-height: 86vh;
  display: flex; flex-direction: column; gap: 10px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
.picker__head { display: flex; align-items: center; gap: 8px; }
/* The kit colour and the role say which place you are filling, without words. */
.picker__kit {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.85);
  flex: none;
}
.picker__role { font-size: 1.3rem; }
.picker__close {
  margin-left: auto;
  background: none; border: none; color: #f2f7f3;
  font-size: 1.1rem; cursor: pointer; padding: 4px 8px; border-radius: 6px;
}
.picker__close:hover { background: rgba(255, 255, 255, 0.1); }
.picker__grid {
  display: flex; flex-wrap: wrap; gap: 10px;
  justify-content: center;
  overflow-y: auto;
}
.picker__face {
  width: 68px; height: 68px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.08);
  color: #f2f7f3;
  font-size: 1.7rem;
  cursor: pointer;
  overflow: hidden; padding: 0;
  flex: none;
  display: flex; align-items: center; justify-content: center;
}
.picker__face img { width: 100%; height: 100%; object-fit: contain; }
.picker__face--on { border-color: #ffd166; box-shadow: 0 0 0 3px rgba(255, 209, 102, 0.3); }
.picker__face--add { border-style: dashed; }
.picker__face--none { border-style: dashed; opacity: 0.75; }
@media (max-height: 430px) {
  .picker__face { width: 54px; height: 54px; font-size: 1.3rem; }
}

/* ===== Scene: moon =====
   Regolith, craters, a starfield instead of a crowd, and Earth on the horizon. */
.scene-moon { background: linear-gradient(#05060f 0%, #0a0c1a 60%, #141626 100%); }
.scene-moon .pm__surface {
  /*
   * Craters, not dots. Each one is a bright raised rim, a bowl of shadow
   * offset down and right, and a lit crescent on the upper-left wall, so the
   * light reads as coming from one direction and the surface looks dented.
   *
   * The tile sizes are deliberately not multiples of each other, and each
   * layer starts at its own offset. Tiles that share a size line up into rows
   * and the ground stops looking like ground and starts looking perforated.
   */
  background:
    /* large crater */
    radial-gradient(circle at 196px 146px, rgba(255,255,255,0.14) 0 34px, transparent 36px),
    radial-gradient(circle at 210px 160px, rgba(0,0,0,0.34) 0 40px, transparent 43px),
    radial-gradient(circle at 200px 150px, transparent 0 43px, rgba(255,255,255,0.19) 45px 54px, transparent 57px),
    /* medium crater */
    radial-gradient(circle at 86px 76px, rgba(255,255,255,0.12) 0 16px, transparent 18px),
    radial-gradient(circle at 96px 86px, rgba(0,0,0,0.30) 0 20px, transparent 22px),
    radial-gradient(circle at 90px 80px, transparent 0 22px, rgba(255,255,255,0.17) 23px 29px, transparent 31px),
    /* small crater A */
    radial-gradient(circle at 46px 36px, rgba(0,0,0,0.26) 0 10px, transparent 12px),
    radial-gradient(circle at 43px 33px, transparent 0 11px, rgba(255,255,255,0.15) 12px 15px, transparent 16px),
    /* small crater B */
    radial-gradient(circle at 141px 108px, rgba(0,0,0,0.24) 0 8px, transparent 10px),
    radial-gradient(circle at 138px 105px, transparent 0 9px, rgba(255,255,255,0.14) 10px 13px, transparent 14px),
    /* pits */
    radial-gradient(circle at 52px 41px, rgba(0,0,0,0.18) 0 4px, transparent 6px),
    /* mottling, so the flat ground is not flat */
    radial-gradient(circle at 34% 44%, rgba(255,255,255,0.05) 0 24px, transparent 28px),
    radial-gradient(circle at 74% 18%, rgba(0,0,0,0.06) 0 20px, transparent 24px),
    linear-gradient(#7a7d86 0%, #8e9199 45%, #a3a6ad 100%);
  background-size:
    613px 421px, 613px 421px, 613px 421px,
    337px 251px, 337px 251px, 337px 251px,
    239px 173px, 239px 173px,
    197px 149px, 197px 149px,
    151px 113px,
    109px 89px, 163px 127px,
    100% 100%;
  background-position:
    40px 18px, 40px 18px, 40px 18px,
    150px 90px, 150px 90px, 150px 90px,
    20px 60px, 20px 60px,
    110px 30px, 110px 30px,
    70px 12px,
    0 0, 55px 40px,
    0 0;
}
.scene-moon .crowd {
  background:
    radial-gradient(circle at 78% 62%, #4f7fc4 0 26px, #2f5a99 27px 30px, transparent 31px),
    radial-gradient(circle at 14px 10px, #fff 0 1.4px, transparent 2px),
    radial-gradient(circle at 52px 22px, #ffe9a8 0 1.6px, transparent 2px),
    radial-gradient(circle at 80px 7px, #fff 0 1.2px, transparent 2px),
    linear-gradient(#05060f, #0b0d1c);
  background-size: 100% 100%, 96px 34px, 96px 34px, 96px 34px, 100% 100%;
}
.scene-moon .pm__wall { background: linear-gradient(#e8ecf5, #9aa3b8); box-shadow: 0 0 10px rgba(180, 210, 255, 0.4); }
.scene-moon .pm__endwall { background: linear-gradient(90deg, #e8ecf5, #9aa3b8); }
.scene-moon .pm__line, .scene-moon .pm__circle, .scene-moon .pm__box { border-color: rgba(190, 220, 255, 0.5); }
.scene-moon .pm__halfway { background: rgba(190, 220, 255, 0.5); }

/* ===== Scene: pool =====
   Water, lane ropes, tiled walls, and umbrellas along the deck.
   A pool, not an ocean: this game is a walled pitch, and a pool has walls. */
.scene-pool { background: linear-gradient(#cfd8dc 0%, #a9b6bd 60%, #8c9aa2 100%); }
.scene-pool .pm__surface {
  overflow: hidden;   /* contains the caustics overlay below */
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.10) 0 3px, transparent 3px 13px),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.14) 0 2px, transparent 2px 46px),
    linear-gradient(#0f77a8 0%, #17a0c9 45%, #2fc0dd 100%);
}
/*
 * Caustics: the light mesh on the bottom of a pool. Drifts on a transform so
 * it stays on the compositor, and runs `alternate` rather than looping, which
 * is seamless by construction - three overlapping patterns at different
 * periods have no common length to loop cleanly over.
 */
.scene-pool .pm__surface::after {
  content: '';
  position: absolute;
  inset: -14%;
  pointer-events: none;
  background:
    repeating-linear-gradient(64deg, rgba(255,255,255,0.09) 0 3px, transparent 3px 27px),
    repeating-linear-gradient(-58deg, rgba(255,255,255,0.07) 0 3px, transparent 3px 33px),
    repeating-linear-gradient(9deg, rgba(255,255,255,0.05) 0 2px, transparent 2px 43px);
  animation: caustics 15s ease-in-out infinite alternate;
}
@keyframes caustics {
  from { transform: translate3d(-22px, -14px, 0); }
  to   { transform: translate3d(22px, 14px, 0); }
}
/*
 * The waterline. A band of pool colour across each character's lower legs,
 * which is the single cheapest thing that says "standing in water" - far more
 * than any amount of surface detail does.
 */
.scene-pool .ch::after {
  content: '';
  position: absolute;
  left: -8px; right: -8px; bottom: -3px;
  height: 48px;
  background: linear-gradient(rgba(23,160,201,0) 0%, rgba(23,160,201,0.52) 38%, rgba(47,192,221,0.72) 100%);
  border-radius: 46% 54% 8% 8% / 22px 18px 4px 4px;
  z-index: 7;
  pointer-events: none;
}
/* What is under the surface goes soft. The blur is in the character's own
   coordinate space, so it scales with depth along with everything else. */
.scene-pool .ch__leg-l,
.scene-pool .ch__leg-r {
  filter: blur(1.6px) saturate(0.8);
  opacity: 0.72;
}
.scene-pool .ch__shadow { opacity: 0.35; filter: blur(4px); }
.scene-pool .ball__shadow { opacity: 0.4; }

/* The match ball has to stay findable among a floor of coloured balls. */
.scene-ballpit .ball {
  filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.95)) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.45));
}
.scene-pool .crowd {
  background:
    radial-gradient(circle at 24px 26px, #ef476f 0 15px, transparent 16px),
    radial-gradient(circle at 68px 26px, #ffd166 0 15px, transparent 16px),
    radial-gradient(circle at 112px 26px, #06d6a0 0 15px, transparent 16px),
    linear-gradient(#e8edef 0%, #cbd5d9 100%);
  background-size: 144px 40px, 144px 40px, 144px 40px, 100% 100%;
  background-position-y: bottom, bottom, bottom, 0;
}
.scene-pool .pm__wall {
  background:
    repeating-linear-gradient(90deg, #f7fbfc 0 22px, #dbe6ea 22px 24px);
}
.scene-pool .pm__endwall { background: linear-gradient(90deg, #f7fbfc, #cfdde2); }
.scene-pool .pm__line, .scene-pool .pm__circle, .scene-pool .pm__box { border-color: rgba(255, 255, 255, 0.55); }
.scene-pool .pm__halfway { background: rgba(255, 255, 255, 0.55); }

/* ===== Scene: ball pool =====
   A floor of coloured balls, padded foam walls, soft-play netting overhead. */
.scene-ballpit { background: linear-gradient(#2b1d3a 0%, #3d2a52 60%, #4a3363 100%); }
/* The painted floor is deliberately muted. Once real loose balls sit on top of
   it, a floor at full strength competes with them and the match ball gets lost
   in the noise. It is a bed for them to lie in, not a second set of balls. */
.scene-ballpit .pm__surface {
  background:
    radial-gradient(circle at 16px 16px, rgba(239,71,111,0.40) 0 13px, transparent 14px),
    radial-gradient(circle at 48px 30px, rgba(255,209,102,0.38) 0 13px, transparent 14px),
    radial-gradient(circle at 80px 14px, rgba(6,214,160,0.36) 0 13px, transparent 14px),
    radial-gradient(circle at 32px 52px, rgba(76,201,240,0.36) 0 13px, transparent 14px),
    radial-gradient(circle at 96px 46px, rgba(179,136,235,0.40) 0 13px, transparent 14px),
    linear-gradient(#4a3466, #3a2752);
  background-size: 112px 68px, 112px 68px, 112px 68px, 112px 68px, 112px 68px, 100% 100%;
}
.scene-ballpit .crowd {
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,0.16) 0 2px, transparent 2px 14px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,0.16) 0 2px, transparent 2px 14px),
    linear-gradient(#241832, #33224a);
}
/* Padded foam, so the springy walls look springy. */
.scene-ballpit .pm__wall {
  height: 11px;
  border-radius: 6px;
  background: repeating-linear-gradient(90deg, #ffd166 0 34px, #ef476f 34px 68px);
}
.scene-ballpit .pm__wall--far { transform: translateY(-11px); }
.scene-ballpit .pm__endwall {
  width: 10px;
  border-radius: 5px;
  background: repeating-linear-gradient(0deg, #ffd166 0 34px, #ef476f 34px 68px);
}
.scene-ballpit .pm__line, .scene-ballpit .pm__circle, .scene-ballpit .pm__box { border-color: rgba(255, 255, 255, 0.4); }
.scene-ballpit .pm__halfway { background: rgba(255, 255, 255, 0.4); }

/* ===== Editor stage, per scene =====
   The preview stands on the surface it will play on, so tapping a scene
   button explains itself without a word. */
.ed__stage.scene-grass {
  background:
    radial-gradient(ellipse at 50% 92%, rgba(0,0,0,0.35) 0%, transparent 60%),
    linear-gradient(#2f7d4a, #1d5230);
}
.ed__stage.scene-moon {
  background:
    radial-gradient(ellipse at 50% 92%, rgba(0,0,0,0.4) 0%, transparent 60%),
    radial-gradient(circle at 24% 26%, rgba(0,0,0,0.16) 0 20px, transparent 22px),
    linear-gradient(#85878f, #5c5e66);
}
.ed__stage.scene-pool {
  background:
    radial-gradient(ellipse at 50% 92%, rgba(0,0,0,0.3) 0%, transparent 60%),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.10) 0 3px, transparent 3px 13px),
    linear-gradient(#17a0c9, #0f6f9c);
}
.ed__stage.scene-ballpit {
  background:
    radial-gradient(ellipse at 50% 92%, rgba(0,0,0,0.3) 0%, transparent 60%),
    radial-gradient(circle at 16px 16px, #ef476f 0 13px, transparent 14px),
    radial-gradient(circle at 48px 30px, #ffd166 0 13px, transparent 14px),
    radial-gradient(circle at 80px 14px, #06d6a0 0 13px, transparent 14px),
    radial-gradient(circle at 32px 52px, #4cc9f0 0 13px, transparent 14px),
    linear-gradient(#6a4c8c, #533a70);
  background-size: 100% 100%, 112px 68px, 112px 68px, 112px 68px, 112px 68px, 100% 100%;
}

/* ===== Scene effects =====
   Named by CONFIG.fx, emitted by render.js. Every one is centred on the point
   it was spawned at and animates transform and opacity only. */
.puff, .ripple, .drop {
  position: absolute;
  pointer-events: none;
  will-change: transform, opacity;
}

/* Moon dust: a soft puff that spreads and settles. */
.puff {
  border-radius: 50%;
  background: radial-gradient(circle, rgba(228,231,237,0.8) 0%, rgba(188,192,200,0) 70%);
  animation: puff 0.6s ease-out forwards;
}
@keyframes puff {
  from { transform: translate(-50%, -50%) scale(0.35); opacity: 0.8; }
  to   { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)) scale(1.9); opacity: 0; }
}

/* Water: a flattened ring spreading out. Flattened because the pitch is seen
   from an angle, so a circle on the ground reads as an ellipse. */
.ripple {
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.7);
  animation: ripple 0.9s ease-out forwards;
}
@keyframes ripple {
  from { transform: translate(-50%, -50%) scale(0.25); opacity: 0.75; }
  to   { transform: translate(-50%, -50%) scale(1.7); opacity: 0; }
}

/* Water: droplets thrown up and out. */
.drop {
  border-radius: 50%;
  background: rgba(236, 250, 255, 0.92);
  animation: drop 0.62s cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}
@keyframes drop {
  from { transform: translate(-50%, -50%) scale(1); opacity: 0.92; }
  to   { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)) scale(0.3); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .puff, .ripple, .drop { display: none; }
}

/* Tackle: a soft ring and a few sparkles arcing up, where there used to be a
   burst of shards. Nothing here should read as an impact. */
.pop, .twinkle {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  will-change: transform, opacity;
}
.pop {
  border: 2px solid rgba(255, 255, 255, 0.5);
  animation: pop 0.44s ease-out forwards;
}
@keyframes pop {
  from { transform: translate(-50%, -50%) scale(0.3); opacity: 0.7; }
  to   { transform: translate(-50%, -50%) scale(1.5); opacity: 0; }
}
.twinkle {
  background: rgba(255, 240, 185, 0.95);
  box-shadow: 0 0 4px rgba(255, 240, 185, 0.7);
  animation: twinkle 0.54s ease-out forwards;
}
@keyframes twinkle {
  0%   { transform: translate(-50%, -50%) scale(0.4); opacity: 1; }
  60%  { opacity: 1; }
  100% { transform: translate(-50%, -50%) translate(var(--dx, 0px), var(--dy, 0px)) scale(1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .pop, .twinkle { display: none; } }

/* Loose balls on the ball pool floor. Kept deliberately cheap to paint: a flat
   colour and one highlight, no gradient, because there are well over a hundred
   of them and most never move. */
.pit-ball {
  position: absolute;
  left: 0; top: 0;
  border-radius: 50%;
  pointer-events: none;
  box-shadow: inset 2px 2px 0 rgba(255, 255, 255, 0.35),
              inset -1px -2px 0 rgba(0, 0, 0, 0.18);
}
