.earth-theme#numpad-container {
  background: #ffa409;
  background: linear-gradient(135deg, #ffa409 70%, #0a5dd2 100%);
}

.wind-theme#numpad-container {
  background: #91bd00;
  background: linear-gradient(135deg, #91bd00 70%, #0a5dd2 100%);
  /* .numpad-button {
    background-color: #8c8;
  } */
}

.water-theme#numpad-container {
  background: #0095d7;
  background: linear-gradient(135deg, #0095d7 70%, #0a5dd2 100%);
  /* .numpad-button {
    background-color: #bff;
  } */
}

.fire-theme#numpad-container {
  background: #d1215b;
  background: linear-gradient(135deg, #d1215b 70%, #0a5dd2 100%);
  /* .numpad-button {
    background-color: #ffb;
  } */
}

@media only screen and (max-width: 760px) {
  .numpad-theme-invisible {
    opacity: 1 !important;
  }
}

#numpad-container {
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  margin: auto;
  background-color: #003;
  z-index: 100;
  touch-action: manipulation;
  font-family: "Outfit", sans-serif;
  container-type: size;
  /* border-left: 1vb solid #069;
  border-right: 1vb solid #069;
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box; */
}

.numpad-row {
  position: absolute;
  height: 15%;
  width: 92%;
  margin: 0 4%;
  opacity: 1;
  transition: top 0.3s, opacity 0.3s;
}

#numpad-row-answer {
  top: 10%;
}

#numpad-row-timebar {
  top: 25%;
}

#numpad-row-123 {
  top: 36.5%;
}

#numpad-row-456 {
  top: 51.5%;
}

#numpad-row-789 {
  top: 66.5%;
}

#numpad-row-0 {
  top: 81.5%;
}

.numpad-theme-invisible {
  opacity: 0;
}

#numpad-row-123.numpad-theme-stack {
  top: 66.5%;
}
#numpad-row-456.numpad-theme-stack {
  top: 51.5%;
}
#numpad-row-789.numpad-theme-stack {
  top: 36.5%;
}
#numpad-row-0.numpad-theme-stack {
  top: 81.5%;
}

#numpad-close-button {
  position: absolute;
  top: 2cqh;
  right: 2cqh;
  width: 10cqh;
  height: 10cqh;
  background-color: unset;
  border: unset;
  opacity: 0.5;
  z-index: 10;
}

#numpad-close-button:hover {
  cursor: pointer;
  opacity: 1;
}

#numpad-mute-button {
  position: absolute;
  top: 4cqh;
  right: calc(50% - 3cqh);
  width: 6cqh;
  height: 6cqh;
  background-color: unset;
  border: unset;
  opacity: 0.5;
  z-index: 10;
}

#numpad-mute-button:hover {
  cursor: pointer;
  opacity: 1;
}

#numpad-skip-button {
  position: absolute;
  top: 4cqh;
  right: calc(30% - 3cqh);
  width: 6cqh;
  height: 6cqh;
  background-color: unset;
  border: unset;
  opacity: 0.5;
  z-index: 10;
}

#numpad-skip-button:hover {
  cursor: pointer;
  opacity: 1;
}

.numpad-button-container {
  float: left;
  width: 33.33%;
  height: 100%;
}

.numpad-button-container-wide {
  float: left;
  width: 100%;
  height: 100%;
}

.numpad-button {
  font-family: "Outfit", sans-serif;

  display: block;
  width: 90%;
  height: 92%;
  margin: auto;
  text-align: center;
  font-size: 10cqh;
  font-weight: 900;
  color: #fff;
  border: none;
  box-shadow: 0 0.5cqh 0 0 #00fdfa;
  background-color: #181b46;
}

@media (hover: hover) {
  .numpad-button:hover {
    background-color: #6f8cb7;
  }
  .numpad-button:active {
    margin-top: 1cqh;
    box-shadow: none;
  }
}

/* Touch + mouse press feedback driven by pointer events in math.js (see
   numpad press-feedback handler). Mirrors the desktop :active style above
   plus the hover background color (so press feedback is visible on touch,
   where :hover never fires), without sticking the way iOS Safari sometimes
   does with bare :active / :hover. */
.numpad-button.numpad-button-pressed {
  margin-top: 1cqh;
  box-shadow: none;
  background-color: #6f8cb7;
}

.numpad-button-wide {
  width: 30%;
}

.numpad-answer {
  position: absolute;
  display: table-cell;
  float: left;
  vertical-align: bottom;
  width: 90%;
  margin: 3% 0 0 5%;
  font-size: 12cqh;
  font-weight: bold;
  color: #fff;
}

#numpad-answer-clone {
  .numpad-problem {
    opacity: 0;
  }
}

.numpad-answer-float-and-fade {
  transition: 0.5s;
  transition-timing-function: ease-out;
  margin-top: -10%;
  opacity: 0;
}

.numpad-header {
  height: 10%;
  width: 100%;
  /* background-color: #030; */
}

.numpad-timebar-container {
  position: absolute;
  height: 10%;
  width: 100%;
  margin-top: 2%;
  /* background-color: #300;/ */
}

#numpad-timebar {
  position: absolute;
  margin-top: 4cqh;
  left: 5%;
  width: 90%;
  height: 3cqh;
  background-color: #181b46;
  border-radius: 3cqh;
  overflow: hidden;
}

#numpad-timebar-inner {
  background-color: white;
  width: 100%;
  height: 100%;
}

#numpad-time-value {
  position: absolute;
  text-align: right;
  color: white;
  font-size: 5cqh;
  font-weight: 300;
  margin-top: -4cqh;
  right: calc(5% + 1cqh);
}

.score-icon-ul {
  float: left;
  height: 6cqh;
  margin-left: 4cqh;
  margin-top: 4.5cqh;
  opacity: 0.5;
}

.score-value-ul {
  float: left;
  font-size: 6cqh;
  margin-top: 4cqh;
  margin-left: 1cqh;
  opacity: 0.5;
}

.numpad-floating-text {
  position: absolute;
  left: 30%;
  width: 40%;
  margin: auto;
  text-align: center;
  font-size: 6cqh;
  top: 30%;
  opacity: 1;
}

.numpad-floating-score-text {
  position: absolute;
  left: 30%;
  /* text-align: center; */
  font-size: 4cqh;
  top: 10cqh;
  opacity: 1;
}

.float-and-fade {
  transition: 1s;
  transition-timing-function: ease-out;
  top: 4cqh;
  opacity: 0;
}

@property --a {
  syntax: "<angle>";
  inherits: false;
  initial-value: 360deg;
}
.star-counter {
  --a: 0deg;
  position: absolute;
  height: 10cqh;
  width: 10cqh;
  margin-left: 4cqh;
  display: block;
  margin-top: 2cqh;
  border-radius: 50%;
  transition: --a 0.2s linear;
  background: conic-gradient(
    #ffffffff var(--a),
    #ffffffff 0deg,
    #585862d5 0deg,
    #585862d5 360deg
  );
}
.star-counter::before {
  position: absolute;
  content: "";
  width: 80%;
  height: 80%;
  background: #00000088;
  border-radius: 50%;
  left: 50%;
  top: 50%;
  /* color: #fac7c78f; */
  transform: translate(-50%, -50%);
}

.star-counter-text {
  width: 70%;
  height: 10cqh;
  color: white;
  position: absolute;
  left: 50%;
  top: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 0.3em;
  font-size: 5cqh;
  transform: translate(-50%, -50%);
}

.star-counter-stars {
  position: absolute;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  margin-top: 4cqh;
  margin-left: 15cqh;
  max-width: 45cqh;
  font-size: 4cqh;
  line-height: 1;
  overflow: hidden;
}

.star-counter-stars .banked-star {
  display: inline-block;
  flex-shrink: 0;
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.star-counter-stars .banked-star + .banked-star {
  margin-left: var(--banked-star-spacing, 0.4cqh);
}

.star-counter-stars .banked-star.expiring {
  opacity: 0;
  transform: scale(0.6);
}

.star-counter-stars .banked-star.fresh {
  animation: banked-star-pop 0.4s ease-out;
}

@keyframes banked-star-pop {
  0% { transform: scale(0); opacity: 0; }
  60% { transform: scale(1.3); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* Stars removed from math games — hide the in-game star counter (radial
   progress ring + banked-star row + count text). The styling/markup above is
   intentionally kept so it can be brought back by removing this one rule.
   !important beats the /play session rule that otherwise keeps the ring
   visible and any inline display set by math.js. */
#star-counter,
#star-counter-stars,
#star-counter-text {
  display: none !important;
}

/* Practice mode brings the radial counter back (ring + center count only;
   the banked-star row stays hidden). Overrides the hide rule above. The ring
   is a block; the count text must keep its `display: flex` so align-items
   vertically centers the number in the ring (block would top-align it). */
body.practice-active #star-counter {
  display: block !important;
}
body.practice-active #star-counter-text {
  display: flex !important;
}

/* The simplified free game used to bring the radial back here — the ring in
   the top-left corner filling one tick per correct answer. It is gone: the
   speed-tier row below is the round's live readout now, and two running
   tallies in the same corner competed for the same glance. math.js still
   drives --a and the text (harmless, and the full game reads them), so
   restoring the ring means re-adding the two rules that were here. */

/* Practice mode: total balance of the op's element, top-center. */
.numpad-practice-element {
  display: none;
}
body.practice-active .numpad-practice-element {
  display: flex;
  position: absolute;
  top: 2cqh;
  left: 50%;
  transform: translateX(-50%);
  align-items: center;
  gap: 1cqh;
  color: #fff;
  font-size: 6cqh;
  font-weight: 700;
  /* Below the pregame Start panel (#numpad-start-buttons / .numpad-menu-buttons,
     z-index 1) so it's covered during pregame and revealed once play starts. */
  z-index: 0;
}
body.practice-active .numpad-practice-element svg {
  width: 7cqh;
  height: 7cqh;
  /* The sprite's *_icon_white symbols have no fill attr, so they default to
     black — inherit the parent's white via currentColor (same as HUD chips). */
  fill: currentColor;
}

/* Practice mode: "Exit practice" button, top-right. Replaces the settings
   (menu) button, which is hidden during practice to keep the top bar clean. */
#numpad-exit-practice-button {
  display: none;
}
body.practice-active #numpad-exit-practice-button {
  display: block;
  position: absolute;
  top: 2cqh;
  right: 3cqh;
  background-color: rgba(0, 0, 0, 0.4);
  color: #fff;
  border: 0.3cqh solid #ffffff88;
  border-radius: 2cqh;
  padding: 1cqh 2cqh;
  font-family: "Outfit", sans-serif;
  font-size: 3.2cqh;
  font-weight: 600;
  z-index: 10;
  cursor: pointer;
}
body.practice-active #numpad-exit-practice-button:hover {
  background-color: rgba(0, 0, 0, 0.7);
}
body.practice-active #numpad-close-button {
  display: none;
}

.heart-counter {
  position: absolute;
  height: 10cqh;
  width: 10cqh;
  margin-left: 4cqh;
  margin-top: 2cqh;
  display: block;
}

.heart-counter-container {
  position: absolute;
  height: 10cqh;
  width: 10cqh;
  display: block;
  overflow-y: hidden;
}

.heart-counter-inner {
  height: 10cqh;
  width: 10cqh;
  position: absolute;
  bottom: 0;
}

.heart-counter-outline {
  height: 10cqh;
  width: 10cqh;
  position: absolute;
  bottom: 0;
}

.heart-counter-text {
  position: absolute;
  width: 10cqh;
  text-align: center;
  margin-top: 3.5cqh;
  font-size: 2cqh;
}

.numpad-banner-button {
  position: absolute;
  top: 40%;
  height: 15%;
  font-size: 6cqh;
  background-color: rgba(0, 0, 0, 0.9);
  display: block;
}

.numpad-menu-buttons {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 1;
  background-color: #0009;
}

.numpad-start-button {
  position: absolute;
  top: 40%;
  width: 67%;
  height: 12%;
  left: 0;
  right: 0;
  margin: auto;
  font-size: 6cqh;
}

#numpad-exit-button {
  top: 55%;
}

#numpad-menu-buttons {
  display: none;
}

#numpad-menu-audio-button {
  top: 30%;
}

#numpad-menu-display-button {
  top: 45%;
}

#numpad-menu-exit-button {
  top: 60%;
}

#numpad-menu-back-button {
  top: 75%;
  right: 16.5%;
}

.numpad-display-menu {
  display: none;
  position: absolute;
  width: 100%;
  height: 100%;
}

.numpad-display-banner {
  background-color: #0009;
  position: absolute;
  top: 5%;
  width: 96%;
  height: 24%;
  text-align: center;
  font-size: 6cqh;
  z-index: 100;
  padding: 2%;
}

.numpad-display-menu-name {
  margin: 0;
  font-size: 8cqh;
}

.numpad-display-menu-switch-button {
  display: inline-block;
  width: 25%;
  margin: 0 10%;
  padding: 0;
}

#numpad-display-back-button {
  top: 25%;
  width: 20%;
  left: 40%;
}

/* ---- speed-bonus tiers ---------------------------------------------------
   Four counters across the top of the numpad, replacing the radial that used
   to sit in the top-left. Slowest band on the left, fastest on the right, so
   the row reads as a ladder. Each chip carries its time threshold, its reward
   (the round's element × a multiplier) and how many answers have landed in
   that band this round. Markup is built per round by renderSpeedTiers() in
   math.js — the icons depend on which operation is being played.

   Sizing is in cqh against #numpad-container, which sets container-type: size
   and is itself aspect-locked, so the row scales with the pad rather than the
   window. */
.numpad-speed-tiers {
  /* Scoped to the simplified game. game.html is shared with the full game,
     which prices rounds through /api/v1/game_records and knows nothing about
     speed bands — showing it a row of bonuses it does not pay would be a
     lie. Mirrors how .numpad-elements gates itself on play-session-active. */
  display: none;
}

body.simple-mode .numpad-speed-tiers {
  position: absolute;
  top: 1.5cqh;
  left: 2cqh;
  /* Clear of the menu button in the top-right corner. */
  right: 13cqh;
  display: flex;
  justify-content: space-between;
  align-items: stretch;
  gap: 1cqh;
  /* Matches .numpad-elements: the pregame Start overlay is later in the DOM
     and shares this z-index, so it paints over the row while the round has
     not begun. */
  z-index: 1;
  pointer-events: none;
}

/* Which element the row is paying out in. Set on the container by
   renderSpeedTiers rather than per chip — all four bands pay the same
   element, only the multiplier differs. */
.numpad-speed-tiers-earth {
  --tier-color: var(--earth-color);
}
.numpad-speed-tiers-air {
  --tier-color: var(--air-color);
}
.numpad-speed-tiers-water {
  --tier-color: var(--water-color);
}
.numpad-speed-tiers-fire {
  --tier-color: var(--fire-color);
}

.numpad-speed-tier {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2cqh;
  padding: 0.6cqh 0.4cqh;
  background: rgba(0, 0, 0, 0.45);
  border: 0.25cqh solid rgba(255, 255, 255, 0.18);
  border-radius: 1.2cqh;
  color: #f7f3ec;
  line-height: 1.1;
}

/* The fastest band is the one worth chasing, so it is the one that looks
   like a prize: the element's own colour on the rim. */
.numpad-speed-tier:last-child {
  border-color: var(--tier-color, rgba(255, 255, 255, 0.18));
}

.numpad-speed-tier-threshold {
  font-size: 2.1cqh;
  font-weight: 600;
  opacity: 0.75;
  white-space: nowrap;
}

/* The band's running tally, as one unbroken expression: how many answers
   landed here × what each pays. No gaps anywhere in it — "7×2🟫" is a single
   token, not four things sitting near each other. */
.numpad-speed-tier-tally {
  display: flex;
  align-items: center;
  gap: 0;
}

.numpad-speed-tier-tally svg {
  width: 3cqh;
  height: 3cqh;
  fill: currentColor;
  flex-shrink: 0;
}

/* The count is the number that moves during a round, so it leads. */
.numpad-speed-tier-count {
  font-size: 3.6cqh;
  font-weight: 700;
}

.numpad-speed-tier-times {
  font-size: 2.4cqh;
  font-weight: 600;
  opacity: 0.8;
}

.numpad-speed-tier-multiplier {
  font-size: 2.8cqh;
  font-weight: 700;
}

/* Flash when a band scores. Glow and background only — no transform: scale.
   Scaling a flex container re-renders its icon and text at a new size every
   frame and the text visibly wobbles (the same reason
   .numpad-element-chip-flash avoids it). */
@keyframes numpad-speed-tier-score {
  0% {
    background-color: rgba(255, 255, 255, 0.55);
    box-shadow: 0 0 2cqh 0.3cqh rgba(255, 255, 255, 0.9);
  }
  100% {
    background-color: rgba(0, 0, 0, 0.45);
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
  }
}

.numpad-speed-tier.is-scoring {
  animation: numpad-speed-tier-score 0.8s ease-out;
}

/* ---- last answered problem ----------------------------------------------
   A one-line readout of the problem just answered and how long it took, in
   the gap between the problem display (row-answer, 10%–25%) and the timebar
   (row-timebar at 25%, bar itself 4cqh lower). Blank until the first answer
   of the round.

   Width is held short of the right edge so it clears #numpad-time-value,
   which occupies that corner at 5cqh. Scoped to the simplified game for the
   same reason as the speed tiers: game.html is shared with the full game,
   which has its own numpad conventions. */
.numpad-last-answer {
  display: none;
}

/* The mirror image of #numpad-time-value: same row, same vertical offset, the
   opposite side of the timebar. Both are absolutely positioned children of
   .numpad-timebar-container with no `top`, so they share a static position and
   the identical margin-top puts them on one line — no arithmetic to keep in
   step if the row ever moves.

   The height is the timer's own box (5cqh text at normal line-height ≈ 6cqh),
   with the text pushed to the bottom of it: this line is much smaller, and
   aligning the boxes at the top would leave it floating above the digits
   rather than sitting on the same line as them. */
body.simple-mode .numpad-last-answer {
  position: absolute;
  /* The timer's own offset is -4cqh; going less negative drops this nearer
     the bar without moving the timer with it. */
  margin-top: -2.6cqh;
  /* Mirrors the timer's `right: calc(5% + 1cqh)`. */
  left: calc(5% + 1cqh);
  height: 6cqh;

  display: flex;
  align-items: flex-end;
  /* The "some white space" between the sum and its time. */
  gap: 2cqh;
  /* Absolute with an auto width shrinks to fit, so this only bites if a line
     ever ran long enough to reach the timer. */
  max-width: 60%;

  font-size: 2.4cqh;
  line-height: 1.2;
  font-weight: 600;
  color: #f7f3ec;
  white-space: nowrap;
  overflow: hidden;
  pointer-events: none;
}

/* Brighter than the big display's plain `green`, which goes muddy at this
   size over the warmer numpad themes (earth is an orange gradient). */
.numpad-last-answer-value {
  color: #5dfb94;
}

.numpad-last-answer-time {
  opacity: 0.75;
  font-weight: 500;
}
