
/* One informal, arcade-ish font for everything (Google Fonts link in
   index.html's <head>; also used by text-bearing objects, functions_create.js). */
/* Fredoka's glyphs (e.g. "+") are built from overlapping contours, so
   -webkit-text-stroke outlines the overlap inside the glyph too. Every
   text-stroke rule here pairs it with paint-order: stroke fill (fill covers
   the inner half of the stroke) and a doubled width to keep the visible
   outline the same thickness. */
:root {
  --game-font: 'Fredoka', 'Comic Sans MS', sans-serif;
}

body {
  margin: 0;
  font-family: var(--game-font);
  overflow: hidden;
  -webkit-user-select: none;
  -moz-user-select: none;
  -o-user-select: none;
  -ms-user-select: none;
}

#main_section{
  position: relative;
}

p{
  color: white;
  margin: 0.6rem;
}

#canvas_container{
  z-index: 0;
}

/*
 *  Static half-pipe corner ramps (see setHalfPipeCorners, functions_create.js;
 *  drawHalfPipeCornerCanvas/setHalfPipeCornerColor, functions_canvas.js) -
 *  sit behind #canvas_container's game-object canvases (z-index 0 above),
 *  so balls visually sit in front of the ramp surface they're bouncing off.
*/
.half_pipe_corner_canvas {
  position: absolute;
  z-index: -1;
  pointer-events: none;
}

#background_spawn_charge_canvas {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 6;
  pointer-events: none;
  display: none;
}

.pop_burst_canvas {
  position: absolute;
  z-index: 6;
  pointer-events: none;
}

a {
color: #FFF;
}
a:visited {
  color: #A88;
}
a:hover {
  color: #FC4;
}
a:active {
  color: #FFA;

}



/*
 *  Stats
*/

#stats {
  position: absolute;
  top: 8px;
  left: 16px;
  z-index: 10;
  font-family: var(--game-font);
  font-size: 14px;
  color: #000000;
  background: rgba(255,255,255,0.55);
  padding: 8px;
  border-radius: 8px;
  border: 0px solid yellow;
  pointer-events: none;
  text-align: left;
}

#stats p{
  margin: 0;
  padding: 0;
  /* Override the global `p{color:white}` rule below, which otherwise wins
     over #stats's own inherited black (a directly-matching rule beats an
     inherited value regardless of specificity). */
  color: inherit;
}


/*
 *  Score
*/

#score_display {
  position: absolute;
  top: 80px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  text-align: center;
  pointer-events: none;
  font-family: var(--game-font);
}

#score_label {
  display: block;
  font-size: 28px;
  font-weight: bold;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #FFD63E;
  text-shadow: 0 2px 6px rgba(0,0,0,0.7), 0 0 12px rgba(0,0,0,0.5);
}

#score_value {
  display: block;
  font-size: 72px;
  font-weight: bold;
  line-height: 1;
  color: #FFD63E;
  text-shadow: 0 2px 6px rgba(0,0,0,0.7), 0 0 20px rgba(0,0,0,0.5);
}


/*
 *  Arcade-style Dropped/Missed/Clicked row - a colourful, central
 *  presentation (unlike #stats' plain monospace system-info box, which
 *  now only holds FPS/Dynamic Objects).
*/

/* Left panel: level/wave line, then the "Total" game counters. Sits below
   #stats (FPS box), same translucent-box look. */
#left_panel {
  position: absolute;
  top: 80px;
  left: 16px;
  z-index: 10;
  min-width: 190px;
  padding: 10px 14px;
  border-radius: 8px;
  background: rgba(255,255,255,0.55);
  color: #000;
  pointer-events: none;
  font-family: var(--game-font);
}

#level_line,
#wave_line,
#level_balls_line {
  margin: 0;
  font-size: 18px;
  font-weight: bold;
  color: inherit;
}

#wave_next_timer {
  margin-left: 0.8em;
}

#level_balls_line {
  margin-bottom: 18px;
}

#totals_header {
  margin: 0 0 6px;
  font-size: 16px;
  letter-spacing: 0.05em;
}

.arcade_stat {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
}

.arcade_stat_label {
  font-size: 15px;
}

.arcade_stat_value {
  font-size: 24px;
  font-weight: bold;
  line-height: 1.3;
  text-shadow: 0 1px 3px rgba(0,0,0,0.7);
}

/* "balls" (dropped) counter hidden for now - still kept up to date in JS. */
#arcade_stat_dropped {
  display: none;
}

#arcade_stat_missed .arcade_stat_value {
  color: #FF5C5C;
}

#arcade_stat_clicked .arcade_stat_value {
  color: #4DFF7A;
}

#arcade_stat_max_streak .arcade_stat_value {
  color: #FFD63E;
}


/*
 *  Wave countdown ("Next Wave in Ns") - hidden (display:none, set in JS)
 *  whenever a wave is active or the recap/info screens are up.
*/

#wave_countdown_display {
  /* Sits inside #score_display (index.html), one row below the score. */
  display: inline-block;
  margin-top: 1.2em;
  font-family: var(--game-font);
  font-size: 18px;
  letter-spacing: 0.05em;
  color: #000;
  background: rgba(255,255,255,0.3);
  padding: 6px 16px;
  border-radius: 8px;
  text-shadow: none;
}


/*
 *  Per-level dark-background chrome flip - setLevelTheme (functions_update.js)
 *  toggles this class on <body> based on each level's background luminance,
 *  reverting these three "sits directly on the page background" elements
 *  back to their original light-on-dark look for a dark level (the score
 *  display/arcade stat values/buttons/overlays all already have their own
 *  fixed dark boxes or drop-shadow treatment that reads fine either way, so
 *  they're left alone here).
*/
body.theme-dark #stats,
body.theme-dark #left_panel {
  color: #FFFFFF;
  background: rgba(0,0,0,0.4);
}

body.theme-dark #wave_countdown_display {
  color: #FFF;
  background: rgba(0,0,0,0.25);
  text-shadow: 0 1px 3px rgba(0,0,0,0.7);
}


/*
 *  Wave clear bonus pop-up (early wave clear) - big, centred, longer than
 *  a pop's score_popup.
*/

@keyframes wave_clear_bonus_rise {
  0% { transform: translate(-50%, -50%) scale(0.5); opacity: 0; }
  12% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
  25% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  75% { transform: translate(-50%, -80%) scale(1); opacity: 1; }
  100% { transform: translate(-50%, -140%) scale(0.9); opacity: 0; }
}

.wave_clear_bonus_popup {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  font-family: var(--game-font);
  font-weight: bold;
  font-size: 56px;
  white-space: nowrap;
  background: linear-gradient(90deg, #FF3B5C, #FF9D00, #F9F002, #3CFF3C, #33C6FF, #C13BFF);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Outline via drop-shadow, not text-stroke: the fill here is a clipped
     background, so paint-order can't hide text-stroke's inner overlap lines. */
  filter: drop-shadow(0 0 1.5px rgba(0,0,0,0.9)) drop-shadow(0 0 1.5px rgba(0,0,0,0.6));
  animation: wave_clear_bonus_rise 1800ms ease-out forwards;
}


/*
 *  Score pop-up (arcade-style floating points, on popping a circle)
*/

@keyframes score_popup_rise {
  0% { transform: translate(-50%, -50%) scale(0.6); opacity: 0; }
  15% { transform: translate(-50%, -70%) scale(1.2); opacity: 1; }
  70% { transform: translate(-50%, -160%) scale(1); opacity: 1; }
  100% { transform: translate(-50%, -240%) scale(0.85); opacity: 0; }
}

.score_popup {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  font-family: var(--game-font);
  font-weight: bold;
  white-space: nowrap;
  animation: score_popup_rise 900ms ease-out forwards;
}

.score_popup_positive {
  font-size: 32px;
  background: linear-gradient(90deg, #FF3B5C, #FF9D00, #F9F002, #3CFF3C, #33C6FF, #C13BFF);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Outline via drop-shadow, not text-stroke: the fill here is a clipped
     background, so paint-order can't hide text-stroke's inner overlap lines. */
  filter: drop-shadow(0 0 1px rgba(0,0,0,0.9)) drop-shadow(0 0 1px rgba(0,0,0,0.6));
}

.score_popup_empty {
  font-size: 22px;
  color: rgba(255,255,255,0.5);
  text-shadow: 0 2px 4px rgba(0,0,0,0.7);
}

.score_popup_negative {
  font-size: 30px;
  color: #FF3B3B;
  text-shadow: 0 2px 6px rgba(0,0,0,0.8), 0 0 10px rgba(255,0,0,0.5);
  -webkit-text-stroke: 2px rgba(0,0,0,0.6);
  paint-order: stroke fill;
}


/*
 *  UI controls (Pause / Start Again)
*/

#ui_controls {
  position: absolute;
  top: 8px;
  right: 16px;
  z-index: 10;
  display: flex;
  gap: 8px;
}

.ui_button {
  font-family: var(--game-font);
  font-size: 14px;
  font-weight: bold;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #2B1B00;
  background: linear-gradient(180deg, #FFE97A, #FFD63E 55%, #E8A61B);
  border: 2px solid #FFF3C4;
  border-radius: 10px;
  padding: 8px 16px;
  cursor: pointer;
  box-shadow: 0 3px 0 #8A6512, 0 4px 8px rgba(0,0,0,0.4);
  text-shadow: 0 1px 0 rgba(255,255,255,0.4);
}

.ui_button:hover {
  background: linear-gradient(180deg, #FFF3A0, #FFE066 55%, #F0B429);
  border-color: #FFF;
}

.ui_button:active {
  background: linear-gradient(180deg, #E8A61B, #FFD63E 55%, #FFE97A);
  box-shadow: 0 1px 0 #8A6512, 0 2px 4px rgba(0,0,0,0.4);
  transform: translateY(2px);
}

/* While the pause button reads "Resume" (see setPaused, functions_ui.js) -
   a more prominent, easy-to-find call to action, pulled out of #ui_controls'
   flex flow to sit dead-centre. */
#pause_button.centered {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 11;
  font-size: 28px;
}

#pause_button.centered:active {
  /* Combine centering with the shared press-down nudge above, rather than
     letting :active's own transform replace it and jump off-centre. */
  transform: translate(-50%, -50%) translateY(2px);
}


/*
 *  Splash panel
*/

#splash_panel_overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 30;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

/*
 *  Animated gradient backdrop, on its own isolated ::before layer animated
 *  via `filter: hue-rotate()` rather than animating the gradient's own
 *  colors/position directly - the latter (background-color/background-
 *  position) forces a full repaint every frame for as long as this panel is
 *  shown, which is exactly the CPU-drain pattern the main tobykurk.com site
 *  hit and fixed the same way (see its own CLAUDE.md, session 6). A `filter`
 *  animation is compositor-friendly instead. `#splash_panel_overlay` already
 *  has its own z-index, so it's already a stacking context and this child's
 *  z-index:-1 stays scoped behind just this panel's own content, not the
 *  whole page - same stacking-context requirement documented in that
 *  session's write-up.
*/
#splash_panel_overlay::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Light/bright base colors (not dark navy/purple) so the whole splash
     stays consistent with the light theme that level 1 opens into, instead
     of reading as a dark screen that then jarringly "flips to bright" the
     moment the game actually starts. */
  background: linear-gradient(135deg, #FFE5B4, #FFD1DC, #D4F1F4, #FFF3B0);
  animation: splash_panel_hue_shift 10s linear infinite;
}

@keyframes splash_panel_hue_shift {
  from { filter: hue-rotate(0deg); }
  to { filter: hue-rotate(360deg); }
}

#splash_panel {
  max-width: 26em;
  margin: 0 1rem;
  padding: 1.6rem 2rem;
  background: rgba(255,255,255,0.85);
  border: 1px solid rgba(0,0,0,0.12);
  border-radius: 12px;
  color: #222;
  font-family: var(--game-font);
  text-align: center;
}

#splash_panel h1 {
  margin: 0 0 0.4em;
  font-size: 44px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #FFD63E;
  /* A blurred drop-shadow alone (the original dark-panel treatment) reads
     weak now the panel itself is light - added a thin dark stroke so the
     gold stays crisp regardless of backdrop. */
  -webkit-text-stroke: 1.2px rgba(0,0,0,0.35);
  paint-order: stroke fill;
  text-shadow: 0 2px 0 #8A6512, 0 4px 10px rgba(0,0,0,0.4), 0 0 24px rgba(255,214,62,0.5);
}

#splash_panel p {
  margin: 0 0 0.6em;
  font-weight: bold;
  /* Override the global `p{color:white}` rule below, which otherwise wins
     over #splash_panel's own inherited dark text - same cascade trap as
     #stats p (see that rule's own comment). */
  color: inherit;
}

#splash_panel ol {
  text-align: left;
  margin: 0 0 1.2em;
  padding-left: 1.4em;
  line-height: 1.5;
}

#splash_panel #splash_panel_begin_prompt {
  margin: 0.8em 0 0;
  font-size: 18px;
  font-weight: bold;
  color: #FFD63E;
  -webkit-text-stroke: 1px rgba(0,0,0,0.3);
  paint-order: stroke fill;
  text-shadow: 0 1px 4px rgba(0,0,0,0.4);
}

#splash_panel #splash_panel_credits {
  margin-top: 1.2em;
  padding-top: 0.8em;
  border-top: 1px solid rgba(0,0,0,0.15);
}

#splash_panel #splash_panel_credits p {
  margin: 0.2em 0;
  font-size: 13px;
  font-weight: normal;
}

/* Override the global white link color (written for the dark overlay
   panels elsewhere) - these links now sit on the light splash card. */
#splash_panel_credits a {
  color: #1A5276;
}
#splash_panel_credits a:visited {
  color: #6C3483;
}
#splash_panel_credits a:hover {
  color: #2E86C1;
}
#splash_panel_credits a:active {
  color: #154360;
}


/*
 *  Level recap (shown between levels, auto-advances - see showLevelRecap)
*/

/*
 *  Light by default (matching the splash/level-1 light theme), flipped to
 *  the original dark look under body.theme-dark (see setLevelTheme,
 *  functions_update.js) - these panels appear mid-game, where the current
 *  level's own background is already known, unlike the startup splash
 *  (which has no "current level" context, so it stays fixed-light always).
*/
#level_recap_overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 30;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.75);
}

#level_recap_panel {
  max-width: 26em;
  margin: 0 1rem;
  padding: 1.6rem 2rem;
  background: rgba(255,255,255,0.9);
  border: 1px solid rgba(0,0,0,0.12);
  border-radius: 12px;
  color: #222;
  font-family: var(--game-font);
  text-align: center;
}

#level_recap_panel h1 {
  margin: 0 0 0.6em;
  font-size: 30px;
  color: #FFD63E;
  -webkit-text-stroke: 1px rgba(0,0,0,0.3);
  paint-order: stroke fill;
}

#level_recap_score_line {
  margin: 0 0 0.4em;
  font-size: 22px;
  font-weight: bold;
  color: inherit;
}

#level_recap_counters_line {
  margin: 0 0 0.3em;
  font-size: 15px;
  color: rgba(0,0,0,0.65);
}

#level_recap_missclicks_line {
  margin: 0 0 1em;
  font-size: 15px;
  color: rgba(0,0,0,0.65);
}

#level_recap_next_line {
  margin: 0;
  font-size: 14px;
  font-style: italic;
  color: rgba(0,0,0,0.55);
  /* Fades in once the recap starts accepting clicks. The delay is set from
   * LEVEL_RECAP_CLICK_DELAY_SECONDS in showLevelRecap() (functions_update.js),
   * which also restarts the animation on each recap. */
  animation: level_recap_next_line_fade_in 0.25s ease-out both;
}

@keyframes level_recap_next_line_fade_in {
  from { opacity: 0; }
  to   { opacity: 1; }
}


/*
 *  Level-start panel (shown briefly at the very start of every level,
 *  auto-advances into wave 1 - see showLevelStart)
*/

#level_start_overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 30;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.75);
}

#level_start_panel {
  max-width: 26em;
  margin: 0 1rem;
  padding: 1.6rem 2rem;
  background: rgba(255,255,255,0.9);
  border: 1px solid rgba(0,0,0,0.12);
  border-radius: 12px;
  color: #222;
  font-family: var(--game-font);
  text-align: center;
}

#level_start_panel h1 {
  margin: 0 0 0.5em;
  font-size: 32px;
  color: #FFD63E;
  -webkit-text-stroke: 1px rgba(0,0,0,0.3);
  paint-order: stroke fill;
}

#level_start_info_line {
  margin: 0 0 0.6em;
  font-size: 18px;
  color: inherit;
}

#level_start_countdown_line {
  margin: 0;
  font-size: 14px;
  font-style: italic;
  color: rgba(0,0,0,0.55);
}

body.theme-dark #level_start_countdown_line {
  color: rgba(255,255,255,0.6);
}


/*
 *  Dark-level overrides for the three panels above - reverts to their
 *  original dark-on-dark look (pre-light-theme) when the current level's
 *  background is dark (body.theme-dark, see setLevelTheme).
*/
body.theme-dark #level_recap_overlay,
body.theme-dark #level_start_overlay {
  background: rgba(0,0,0,0.85);
}

body.theme-dark #level_recap_panel,
body.theme-dark #level_start_panel {
  background: rgba(0,0,0,0.75);
  border-color: rgba(255,255,255,0.3);
  color: #FFF;
}

body.theme-dark #level_recap_counters_line,
body.theme-dark #level_recap_missclicks_line {
  color: rgba(255,255,255,0.75);
}

body.theme-dark #level_recap_next_line {
  color: rgba(255,255,255,0.6);
}