/* Free-Kick Curve — the game's own look.
   Loaded AFTER ../css/gamekit.css, so anything here is a deliberate local
   override (mostly tighter vertical rhythm: goal + wall + ball + scoreboard all
   have to sit above the fold at 390x700).

   Colour comes from gamekit.css's tokens (--gk-*); there is no local palette
   copy and no literal slate anywhere. Orange stays the CTA colour only. */

* { box-sizing: border-box; }

body.gk-theme { margin: 0; font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; color: var(--gk-ink); }

/* The play shell is a full-height column and the PITCH CARD is the flex child
   that absorbs every spare pixel, so the card reaches the bottom of the phone
   instead of leaving half the screen as empty mint background. When the verdict
   + Next button appear under the card it simply shrinks again — that is what
   keeps both of them inside the fold at 390x700. `min-height:100vh` (not
   `height`) leaves the END screen free to grow and scroll normally. */
.app {
  max-width: 640px;
  margin: 0 auto;
  min-height: 100vh;
  padding: 8px 14px 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.app > * { flex: 0 0 auto; }
.app > .fk-card { flex: 1 1 auto; min-height: 0; }
.app > .gk-header .gk-title { font-size: 17px; }

/* ---------- HUD: the standard pills + the mascot chip on ONE row ---------- */
/* The mascot rides inside this row (not a block of its own), so it adds ZERO
   scroll height and can never cover the header or the pitch. Both the pill and
   the chip are trimmed here so all FOUR pills (progress/score/streak/best) plus
   the chip fit a 390px row on one line with room to spare — the row used to
   overflow into the chip as soon as the 🔥 streak pill appeared (measured:
   best pill right edge 265px vs chip left edge 262px, i.e. they touched). */
.fk-hud { position: relative; z-index: 4; display: flex; align-items: center; gap: 6px; padding-right: 6px; }
.fk-hud .gk-pills { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; justify-content: flex-start; gap: 5px; }
.fk-hud .gk-pill { padding: 6px 9px; font-size: 15px; gap: 4px; }
.fk-hud .gk-mascot { flex: 0 0 auto; padding: 3px 8px; gap: 4px; }
.fk-hud .gk-mascot-emoji { font-size: 22px; }
.fk-hud .gk-mascot-name { font-size: 12px; }
/* The shared bubble hangs BELOW the chip, i.e. over the top of the pitch card.
   The HUD sits above the card (z-index) so the bubble is never half-painted
   under it; it is capped so a long line still ends well above the crossbar —
   and the card now carries a band of sky above the goal, so even a 3-line
   bubble stays off the goal itself. */
.fk-hud .gk-bubble { max-width: 170px; font-size: 14px; padding: 6px 9px; }

/* ---------- the pitch card ---------- */
/* The card fills whatever height is left over (see .app above). The scene
   inside is NOT stretched with it: the projection pins its pixel scale to the
   39:28 box it was composed for (js/free-kick.js frameH), so a taller card only
   ever shows more sky above the goal and more foreground grass below the ball —
   the goal, wall and ball keep the exact framing they have in the 2D fallback. */
.fk-card { display: flex; justify-content: center; }
.fk-pitch {
  position: relative;
  flex: 1 1 auto;
  min-height: 150px;
  min-width: 0;
  border-radius: var(--gk-radius);
  overflow: hidden;
  box-shadow: var(--gk-shadow);
  background: linear-gradient(180deg, #8fc4e8 0%, #cfe8f7 28%, #63bd69 28%, #4aa254 100%);
  touch-action: none;
  overscroll-behavior: contain;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.fk-pitch canvas { position: absolute; left: 0; top: 0; display: block; }
/* The 3D canvas is added on top of the 2D one (a canvas can only ever have one
   context type, so they must be separate elements). Hiding the 2D one keeps it
   alive and uninvolved. The two DOM overlays must sit ABOVE the 3D canvas —
   without an explicit z-index they would be painted underneath it (measured:
   the "Now!" cue was invisible). */
#fkCanvas3d { z-index: 1; }
.has-3d #fkCanvas2d { visibility: hidden; }

/* the "Now!" beat between letting go and the strike */
.fk-cue {
  z-index: 3;
  position: absolute;
  left: 50%; top: 12%;
  transform: translate(-50%, -50%) scale(.6);
  padding: 8px 22px;
  border-radius: 999px;
  background: rgba(232, 78, 15, .95);
  color: #fff;
  font-size: 26px;
  font-weight: 900;
  letter-spacing: .02em;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease, transform .12s ease;
}
.fk-cue.is-on { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* the swipe hint: pinned to the BOTTOM of the card, i.e. the deep foreground
   grass BEHIND the ball — the flight path leaves the ball upward, so the strip
   below the ball is the one place a hint can never sit on it. It used to sit at
   25% (the empty band between ball and wall) which put it straight across the
   ball's route to goal (measured: the banner's band covered the wall's feet and
   the ball's own flight line). 14px so it stays readable; it fades out with the
   first shot of a run (el.hint is cleared on shoot()) and the card's height
   never depends on it. */
.fk-hint {
  z-index: 3;
  position: absolute;
  left: 8px; right: 8px; bottom: 8px;
  padding: 6px 10px;
  border-radius: 12px;
  background: rgba(20, 83, 45, .82);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  opacity: 0;
  transition: opacity .18s ease;
  pointer-events: none;
}
.fk-hint.is-on { opacity: 1; }
.fk-hint.is-warn { background: rgba(232, 78, 15, .9); }

/* ---------- 3D grade: a cheap vignette + warm lift (NO post-processing pass).
   A CSS overlay on the canvas container is the family's sanctioned substitute
   for an EffectComposer pass: it costs one composite, works on any GPU, and it
   never touches the renderer. Only under .has-3d, so the 2D fallback keeps its
   own flat look. z-index 2 = above the 3D canvas (z1), below the cue/hint (z3). */
.has-3d .fk-pitch::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 50% 40%, rgba(255,242,205,.07) 0%, rgba(255,242,205,0) 46%),
    radial-gradient(132% 122% at 50% 50%, rgba(0,0,0,0) 50%, rgba(8,26,16,.36) 100%);
}

/* ---------- broadcast HUD: TV score bug + lower-third banner ----------
   DOM/CSS over the canvas (no post-processing pass). The score bug lives in the
   SKY band at the top of the card; the banner shares the bottom grass band with
   the swipe hint (and hides it while shown). Neither can cover the ball, the
   goal or the aim lane. Both are pointer-events:none — no tap target changes. */
.fk-bug {
  z-index: 3;
  position: absolute;
  left: 8px; right: 8px; top: 7px;
  display: flex;
  align-items: stretch;
  height: 22px;
  border-radius: 7px;
  overflow: hidden;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .02em;
  line-height: 1;
  box-shadow: 0 2px 8px rgba(0,0,0,.35);
  pointer-events: none;
}
.fk-bug > span { display: flex; align-items: center; white-space: nowrap; }
.fk-bug-live {
  padding: 0 7px;
  background: #d21f2f;
  color: #fff;
}
.fk-bug-live::before {
  content: "";
  width: 6px; height: 6px;
  margin-right: 5px;
  border-radius: 50%;
  background: #fff;
  animation: fk-live-pulse 1.5s ease-in-out infinite;
}
@keyframes fk-live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .22; } }
.fk-bug-team {
  flex: 1 1 auto;
  min-width: 0;
  justify-content: flex-start;
  padding: 0 8px;
  background: rgba(11,25,43,.92);
  color: #eaf2ff;
}
.fk-bug-score {
  padding: 0 8px;
  background: #0d1f36;
  color: #ffd23c;
  font-size: 12px;
  border-left: 1px solid rgba(255,255,255,.14);
}
.fk-bug-kick {
  padding: 0 8px;
  background: rgba(11,25,43,.92);
  color: #b9cdea;
  border-left: 1px solid rgba(255,255,255,.14);
}

.fk-banner {
  z-index: 3;
  position: absolute;
  left: 8px; right: 8px; bottom: 8px;
  padding: 7px 12px;
  border-radius: 12px;
  text-align: center;
  font-size: 19px;
  font-weight: 900;
  letter-spacing: .03em;
  color: #fff;
  background: linear-gradient(90deg, #14532d, #1f7a48);
  box-shadow: 0 4px 14px rgba(0,0,0,.4);
  transform: translateY(16px);
  opacity: 0;
  pointer-events: none;
  transition: transform .28s cubic-bezier(.2,1.4,.4,1), opacity .24s ease;
}
.fk-banner.is-on { transform: translateY(0); opacity: 1; }
.fk-banner.is-ok { background: linear-gradient(90deg, #b5730f, #ffc233); color: #3a2400; }

/* ---------- feedback + action + the verdict POP ---------- */
.fk-fb:empty { display: none; }
.fk-fb .gk-verdict { padding: 10px 14px; animation: fk-verdict-pop .3s cubic-bezier(.2,1.5,.4,1) both; }
@keyframes fk-verdict-pop { from { transform: scale(.84); opacity: .35; } to { transform: scale(1); opacity: 1; } }
/* colour is never the only signal — a green ring on a correct verdict */
.fk-fb .gk-verdict--ok { box-shadow: 0 0 0 3px rgba(46,158,79,.32), var(--gk-shadow); }
/* Colour is never the only signal: the verdict carries the same ✓ / ✗ badge the
   answer buttons carry (GameKit.mark's visual language), and the header word
   stays GameKit's own praise / "Not quite". */
.fk-fb .gk-verdict--ok .gk-verdict-line::before { content: "\2713  "; }
.fk-fb .gk-verdict--bad .gk-verdict-line::before { content: "\2717  "; }
.fk-act { display: flex; flex-direction: column; gap: 8px; }
.fk-act:empty { display: none; }

/* ---------- end screen ---------- */
.fk-end {
  background: var(--gk-card);
  border-radius: var(--gk-radius);
  box-shadow: var(--gk-shadow);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: stretch;
}
.fk-end-top { text-align: center; }
.fk-end-emoji { font-size: 44px; line-height: 1; }
.fk-end h2 { margin: 4px 0 0; font-size: 20px; color: var(--gk-green-900); }
.fk-end-score { font-size: 40px; font-weight: 900; color: var(--gk-green-700); line-height: 1.05; }
.fk-end-score span { font-size: 20px; color: var(--gk-muted); }
.fk-end-line { margin: 2px 0 0; font-size: 16px; font-weight: 700; color: var(--gk-muted); }
.fk-end-best {
  display: inline-block;
  margin-top: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  background: #fffbe6;
  color: #7a6000;
  font-size: 15px;
  font-weight: 900;
}
.fk-end-pills { display: flex; justify-content: center; }
.fk-mascot--end { display: flex; justify-content: center; }
/* The shared reward card is generous by design; on a phone end screen the
   vertical budget is tight, so it is trimmed locally (no shared rule is edited):
   the Play again button has to stay reachable with at most a small scroll. */
.fk-end .gk-reward { padding: 10px; gap: 6px; }
.fk-end .gk-sticker-pop { display: flex; align-items: center; gap: 10px; padding: 6px 10px; text-align: left; }
.fk-end .gk-sticker-pop-emoji { font-size: 30px; }
.fk-end .gk-sticker-pop-label { margin-top: 0; font-size: 15px; }
.fk-end .gk-sticker-pop-rarity { font-size: 11px; }
.fk-end .gk-reward-chips { flex-wrap: wrap; justify-content: center; gap: 6px; }
.fk-end .gk-reward-chips .gk-sticker { min-width: 56px; padding: 5px 3px; flex: 0 0 auto; max-width: 106px; }
.fk-end .gk-sticker-emoji { font-size: 20px; }
.fk-end .gk-sticker-label { font-size: 10px; }
.fk-end .gk-reward-count { font-size: 15px; }
.fk-end .gk-reward-home { min-height: 44px; }

/* very short screens only: everything still fits, nothing is dropped */
@media (max-height: 640px) {
  .app { gap: 6px; padding-bottom: 16px; }
  .fk-pitch { min-height: 120px; }
  .fk-hint { font-size: 14px; }
}

/* narrow phones: the four pills + the chip get a little more headroom */
@media (max-width: 420px) {
  .fk-hud .gk-pills { gap: 4px; }
  .fk-hud .gk-pill { padding: 6px 8px; font-size: 14px; }
  .fk-hud .gk-mascot-emoji { font-size: 20px; }
  .fk-hud .gk-mascot-name { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .fk-cue, .fk-hint { transition: none; }
  .fk-fb .gk-verdict { animation: none; }
  .fk-banner { transition: none; }
  .fk-bug-live::before { animation: none; }
}
