/* SUMZ: the deep blue of its title card behind everything, its yellow and brick red for the UI, and green and
   orange for highlights, with chunky slab type and thick-outlined "sticker" cards and buttons with hard shadows.
   Always blue: there's no light version. The colour names are the ones the game has always used: pink is the red,
   yellow the yellow, blue the orange highlight, green the green */

:root, :root[data-theme] {
  --paper: #24365c; --paper-alt: #2f4573; --ink: #fffbe8; --muted: #b8c4e0; --line: #0f1a33;
  --yellow: #fdfc52; --pink: #b85757; --blue: #ff9f43; --green: #5cd38c;
  --blue-deep: #ffb46e; --green-deep: #5cd38c; --pink-deep: #d27272; --grey-deep: #3a5287;
  --pink-text: #f08c8c; --on-pink-text: #fff; --wrong: #ff8a8a; --on-neon: #1b2a4a;
  --trophy: #fdfc52; --trophy-outline: #0f1a33;
  --ui-accent: #b85757; --ui-accent-ink: #fff; --ui-pop: #fdfc52;
  --ui-hero: #fdfc52; --ui-hero-ink: #1b2a4a; --ui-soft: #3a5287; --ui-hero-line: #0f1a33;
  --ui-art-a: #fff; --ui-art-b: #1b2a4a; --ui-grid: #ffffff0d;
  --ui-practice-ink: #fdfc52; --ui-practice-surface: #3a5287; --ui-compete-surface: #5a3346;
  --right-text: #5cd38c;
  --shadow: #0f1a33;
  --font: "Lexend", ui-sans-serif, system-ui, sans-serif;
  --font-display: "Alfa Slab One", "Rockwell", "Roboto Slab", Georgia, serif;
  --font-title: "Monoton", "Alfa Slab One", sans-serif;
  --radius: 14px; --radius-big: 20px; --glow-strength: 0%;
  color-scheme: dark;
}

/* ── Base ───────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-synthesis: none;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
  font-weight: 600;
  text-decoration-color: var(--pink);
  text-decoration-thickness: 3px;
  text-underline-offset: 4px;
}

/* Text links (and the sign out button, styled as one): accent underline and a faint wash on hover.
   The wash is a touch of ink mixed into the paper, so it's slightly darker in light mode and lighter in dark */
a:not(.button, .logo, .greeting__avatar, .site-footer__player, .site-footer__tab, .site-footer__name, .badge-summary, .daily-done, .current-topic, .group-card, .challenge-card, .group-waiting, .board-switch__option, .back-link), .link-button {
  margin: 0 -0.2em;
  padding: 0.05em 0.2em;
  border-radius: 4px;
  transition: background-color 120ms, text-decoration-color 120ms;
}

a:not(.button, .logo, .greeting__avatar, .site-footer__player, .site-footer__tab, .site-footer__name, .badge-summary, .daily-done, .current-topic, .group-card, .challenge-card, .group-waiting, .board-switch__option, .back-link):hover, .link-button:hover {
  background-color: color-mix(in srgb, var(--ink) 5%, var(--paper));
  text-decoration-color: var(--green);
}

:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }

[hidden] { display: none !important; }

.site-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: calc(1.5rem + env(safe-area-inset-top)) 1rem 0;
}

.tagline { margin: 0; color: var(--muted); font-size: 1.05rem; font-weight: 600; text-align: center; }

.page {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
  max-width: 30rem;
  margin: 0 auto;
  padding: 1.5rem 1rem calc(6rem + env(safe-area-inset-bottom));
  text-align: center;
}

.page--narrow { max-width: 24rem; }

/* ── Clock: the logo and the test timer ───────── */

/* A clock face ringed by a minute in four neon quarters */
.clock { display: block; color: var(--ink); overflow: visible; }
.clock__track { opacity: 0.15; }

.logo {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--ink);
  text-decoration: none;
}

/* Grows with the screen, but never wider than a small phone allows */
.logo__mark {
  width: clamp(3.2rem, 14.4vw, 4rem);
  height: clamp(3.2rem, 14.4vw, 4rem);
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--blue) var(--glow-strength), transparent));
}

/* The wordmark: Maths in ink, Battle in pink */
.logo__word { display: block; font-size: clamp(1.7rem, 7.8vw, 2.2rem); font-weight: 800; letter-spacing: -0.04em; line-height: 1; }
.logo__minute { color: var(--pink-text); }

/* ── Icons ──────────────────────────────────────── */

/* The app's own icons (IconsHelper), sized with the text they sit in */
.icon { display: inline-block; width: 1.2em; height: 1.2em; flex: none; vertical-align: -0.22em; overflow: visible; }
.stars { display: inline-flex; align-items: center; gap: 0.05em; vertical-align: -0.18em; }
.stars .icon { vertical-align: 0; }
/* The flame fills 69% of its icon's height, and stops 21% above the bottom: lowered by that, it sits on the
   number's baseline, a little taller than the digits */
.streak__flame { width: 1.25em; height: 1.25em; margin-right: -0.18em; vertical-align: -0.26em; }
.banner .stars .icon { width: 1.2em; height: 1.2em; }

/* ── Type ───────────────────────────────────────── */

.heading {
  margin: 0;
  font-size: clamp(2rem, 9vw, 2.6rem);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 1.1;
}

.label {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.aside, .hint { margin: 0; color: var(--muted); }
.hint { margin-top: -0.4rem; font-size: 0.95rem; text-align: left; }

/* ── Buttons ────────────────────────────────────── */

.button {
  --fill: var(--grey-deep);
  --glow: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  min-height: 3.25rem;
  padding: 0.6rem 1.4rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--fill);
  box-shadow: 0 0 22px color-mix(in srgb, var(--glow) var(--glow-strength), transparent);
  color: #fff;
  cursor: pointer;
  font: inherit;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-decoration: none;
  text-transform: uppercase;
  touch-action: manipulation;
  transition: transform 100ms;
  -webkit-tap-highlight-color: transparent;
}

/* With no shadow to press into, a tap shrinks the button slightly */
.button:active { transform: scale(0.97); }

/* Coloured buttons: a deep shade so the white text reads, glowing in the full neon in dark mode */
.button--go { --fill: var(--green-deep); --glow: var(--green); }
.button--blue { --fill: var(--blue-deep); --glow: var(--blue); }
.button--share { --fill: var(--pink-deep); --glow: var(--pink); }
.button--cta { --fill: var(--blue-deep); --glow: var(--blue); min-height: 4rem; font-size: 1.5rem; }

/* In the logo's pink, as wide as the levels above it */
.button--start {
  --fill: var(--pink-text);
  --glow: var(--pink);
  width: 100%;
  color: var(--on-pink-text);
  min-height: 4.25rem;
  border-radius: var(--radius-big);
  font-size: clamp(1.75rem, 8.5vw, 2.25rem);
  letter-spacing: 0.04em;
}

.button--wide { width: 100%; }

.link-button {
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  text-decoration: underline var(--pink) 3px;
  text-underline-offset: 4px;
}

.inline { display: inline; }

/* ── Forms ──────────────────────────────────────── */

.form {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  width: 100%;
  text-align: left;
}

.form label, .choice legend { font-size: 1rem; font-weight: 700; }

.form input[type="text"],
.form input[type="password"] {
  width: 100%;
  padding: 0.75rem 0.9rem;
  border: 1.5px solid var(--muted);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 1.15rem;
  font-weight: 600;
}

.form input:focus-visible { border-color: var(--ink); outline: 3px solid var(--blue); outline-offset: 2px; }
.form .button { margin-top: 0.75rem; }

.choice {
  display: grid;
  gap: 0.5rem;
  margin: 0.75rem 0 0;
  padding: 0;
  border: 0;
}

.choice legend { margin-bottom: 0.5rem; padding: 0; }

.choice__option {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  font-weight: 500;
}

.choice__option:has(:checked) { border-color: var(--on-neon); background: var(--yellow); color: var(--on-neon); }
.choice__option input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--on-neon); }

.flash {
  width: 100%;
  margin: 0;
  padding: 0.7rem 1rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--green);
  color: var(--on-neon);
  font-weight: 600;
  list-style: none;
}

.flash--alert { background: var(--pink); }

/* Games played offline that the server refused, above whatever page is showing */
.refused-games { width: calc(100% - 2rem); max-width: 28rem; margin: 1rem auto 0; text-align: center; }

/* ── Home ───────────────────────────────────────── */

.greeting {
  min-width: 0;
  max-width: 100%;
  margin: 0.5rem 0 -0.75rem;
  font-size: clamp(2rem, 9vw, 2.6rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  overflow-wrap: anywhere;
}

.streak {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.5rem;
}

.streak__number {
  font-size: clamp(3.5rem, 20vw, 5.5rem);
  font-weight: 700;
  letter-spacing: -0.06em;
  line-height: 1;
}


.streak__number { text-shadow: 0 0 28px color-mix(in srgb, var(--yellow) var(--glow-strength), transparent); }

.streak__label {
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Play, right under the streak it keeps going, saying so when the streak needs it */
.button--play { flex-direction: column; gap: 0.15rem; width: var(--panel-width); min-height: 3.9rem; padding-block: 0.5rem; font-size: clamp(1.4rem, 6.5vw, 1.75rem); }
.button__note { font-size: 0.95rem; font-weight: 700; letter-spacing: 0.08em; opacity: 0.9; }

.save-nudge {
  margin: 0;
  padding: 0.75rem 1rem;
  border: 1.5px dashed var(--muted);
  border-radius: var(--radius);
  color: var(--muted);
  font-size: 1.05rem;
}

.install { display: flex; flex-direction: column; align-items: center; }

.stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem;
  width: 100%;
  margin: 0.25rem 0 0;
}

.stats div {
  --stripe: var(--yellow);
  padding: 0.85rem 0.7rem 0.7rem;
  overflow: hidden;
  border-radius: var(--radius);
  background: linear-gradient(var(--stripe) 0 6px, var(--paper-alt) 6px);
}

.stats div:nth-child(2) { --stripe: var(--green); }
.stats div:nth-child(3) { --stripe: var(--blue); }
.stats div:nth-child(4) { --stripe: var(--pink); }

.stats dt { color: var(--muted); font-size: 0.8rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }
.stats dd { margin: 0; font-size: 1.75rem; font-weight: 700; letter-spacing: -0.03em; }

/* ── Footer: fixed to the bottom like an app's tab bar ── */

/* Spread evenly like a phone's tab bar: who's playing, then home, groups, awards and stats */
.site-footer {
  position: fixed;
  inset: auto 0 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem max(1rem, calc((100% - 30rem) / 2 + 1rem)) calc(0.55rem + env(safe-area-inset-bottom));
  border-top: 1.5px solid var(--line);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(8px);
  font-size: 1rem;
}

.site-footer__start { display: flex; flex: 0 1 auto; align-items: center; gap: 0.5rem; min-width: 0; }
/* Name (or sign in and sign up) over the player's gems */
.site-footer__who { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.site-footer__name { overflow: hidden; color: inherit; font-weight: 700; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; }
.site-footer__gems { color: var(--muted); font-size: 0.9rem; font-weight: 700; white-space: nowrap; }
.site-footer__tab { flex: none; }

.site-footer__player, .site-footer__tab {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0 0.5rem;
  margin: 0 -0.5rem;
  border-radius: var(--radius);
  color: inherit;
  font-weight: 700;
  text-decoration: none;
}

.site-footer__player { min-width: 0; }
.site-footer__player:hover, .site-footer__tab:hover { background: color-mix(in srgb, var(--ink) 5%, var(--paper)); }
.site-footer__player span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.site-footer__auth { color: var(--muted); font-size: 0.9rem; white-space: nowrap; }

/* Icon above its label, like a tab bar, so three fit on a small phone */
.site-footer__tab { flex-direction: column; justify-content: center; gap: 0.1rem; font-size: 0.875rem; }

.footer-icon { width: 1.5rem; height: 1.5rem; }

.wide-form { width: 100%; }

/* ── Avatars ─────────────────────────────────────── */

.avatar {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  width: var(--avatar-size);
  height: var(--avatar-size);
  border: 2px solid var(--line);
  border-radius: 50%;
  object-fit: cover;
}

.avatar--small { --avatar-size: 2rem; }
.avatar--medium { --avatar-size: 2.75rem; }
.avatar--greeting { --avatar-size: 3.6rem; }
.avatar--large { --avatar-size: 6rem; }

/* No picture: the first letter on the player's neon colour */
.avatar--letter {
  --fill: var(--yellow);
  border-color: var(--on-neon);
  background: var(--fill);
  box-shadow: 0 0 16px color-mix(in srgb, var(--fill) var(--glow-strength), transparent);
  color: var(--on-neon);
  font-size: calc(var(--avatar-size) * 0.48);
  font-weight: 700;
  line-height: 1;
}

.avatar--green { --fill: var(--green); }
.avatar--blue { --fill: var(--blue); }
.avatar--pink { --fill: var(--pink); }

.greeting { display: flex; align-items: center; justify-content: center; gap: 0.75rem; }
.greeting__avatar { display: inline-flex; border-radius: 50%; text-decoration: none; }

.avatar-field { margin: 0 0 0.75rem; padding: 0; border: 0; }
.avatar-field legend { margin-bottom: 0.6rem; padding: 0; font-size: 1rem; font-weight: 700; }
.avatar-field__row { display: flex; align-items: center; gap: 1rem; margin-bottom: 0.6rem; }
.avatar-field__controls { display: grid; gap: 0.6rem; justify-items: start; }
.avatar-field__controls .button { min-height: 2.75rem; padding: 0.4rem 1rem; font-size: 0.95rem; cursor: pointer; }
.avatar-field__controls .button:focus-within { outline: 3px solid var(--blue); outline-offset: 3px; }
.avatar-field__remove { display: flex; align-items: center; gap: 0.4rem; font-size: 1rem; font-weight: 500; }
.avatar-field .hint { margin-top: 0; }

/* ── Groups ─────────────────────────────────────── */

/* Back up from a challenge to its group, or a group to the list: a pill in the corner, like the topic's */
.back-link { align-self: flex-start; padding: 0.35rem 0.9rem; border-radius: 999px; background: var(--paper-alt); color: var(--ink); font-weight: 700; text-decoration: none; }
.back-link:hover { background: color-mix(in srgb, var(--ink) 7%, var(--paper-alt)); }

/* A player's groups, and the challenges in one: tiles like the topics page's */
.group-cards, .challenge-cards { display: grid; gap: 0.75rem; width: 100%; margin: 0; padding: 0; list-style: none; }
.group-card, .challenge-card { display: flex; flex-direction: column; gap: 0.2rem; padding: 1rem; border-radius: var(--radius); background: var(--paper-alt); color: var(--ink); text-align: left; text-decoration: none; }
.group-card:hover, .challenge-card:hover { background: color-mix(in srgb, var(--ink) 6%, var(--paper-alt)); }
.group-card__name, .challenge-card__title { font-size: 1.15rem; font-weight: 800; }
.group-card__about, .challenge-card__status { color: var(--muted); font-size: 1rem; font-weight: 600; }
.group-card__waiting { color: var(--pink-text); font-size: 1rem; font-weight: 700; }
.challenge-card__you { font-size: 1.05rem; font-weight: 600; }
.challenge-card__you:empty { display: none; }
.challenge-card--ended { opacity: 0.75; }
.groups .settings__heading, .group .settings__heading, .challenge .settings__heading { align-self: flex-start; }

.group-join, .challenges, .leaderboard { display: flex; flex-direction: column; gap: 0.75rem; width: 100%; }
.group-join__form { display: flex; gap: 0.6rem; }
.group-join__code { flex: 1; min-width: 0; min-height: 3.25rem; padding: 0 0.9rem; border: 2px solid color-mix(in srgb, var(--ink) 25%, transparent); border-radius: var(--radius); background: var(--paper); color: var(--ink); font: inherit; font-size: 1.1rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.group-join__code::placeholder { letter-spacing: 0; text-transform: none; font-weight: 500; }

/* The owner's code to share: big enough to read out to a class */
.group-code { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; width: 100%; padding: 1rem; border-radius: var(--radius); background: linear-gradient(var(--green) 0 6px, var(--paper-alt) 6px); }
.group-code__label { margin: 0; color: var(--muted); font-size: 1rem; font-weight: 700; }
.group-code__code { margin: 0; font-size: 2.4rem; font-weight: 900; letter-spacing: 0.18em; }

.group-members { width: 100%; text-align: left; }
.group-members summary { cursor: pointer; font-weight: 700; }
.group-members ul { display: grid; gap: 0.5rem; margin: 0.75rem 0 0; padding: 0; list-style: none; }
.group-members__player { display: flex; align-items: center; gap: 0.6rem; }
.group-members__name { flex: 1; min-width: 0; }
.group-members__player .avatar { flex: none; }
/* Small and quiet, but a button: outlined in the ink colour */
.group-members__remove { --fill: transparent; min-height: 2.25rem; padding: 0.3rem 0.85rem; border: 1.5px solid color-mix(in srgb, var(--ink) 30%, transparent); color: var(--ink); font-size: 0.9rem; }

/* A challenge's leaderboard: the player's own row stands out */
.challenge__you { margin: 0; font-size: 1.2rem; font-weight: 700; }
.leaderboard__rows { display: grid; gap: 0.4rem; margin: 0; padding: 0; list-style: none; }
.leaderboard__row { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.75rem; border-radius: var(--radius); background: var(--paper-alt); text-align: left; }
.leaderboard__row--you { background: color-mix(in srgb, var(--yellow) 35%, var(--paper-alt)); }
.leaderboard__rank { display: inline-grid; place-items: center; width: 1.9rem; height: 1.9rem; border-radius: 50%; font-size: 1.05rem; font-weight: 800; }
/* The top three's places in the logo's colours */
.leaderboard__rank--1 { background: var(--yellow); color: var(--on-neon); }
.leaderboard__rank--2 { background: var(--blue); color: var(--on-neon); }
.leaderboard__rank--3 { background: var(--pink); color: var(--on-neon); }
.leaderboard__name { flex: 1; min-width: 0; overflow: hidden; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.leaderboard__score { font-size: 1.25rem; font-weight: 800; }
.leaderboard__wrong { color: var(--muted); font-size: 0.9rem; font-weight: 600; }

/* An every day challenge's leaderboards: today's, or the week's by total or best day */
.board-switch { display: grid; grid-template-columns: repeat(3, 1fr); padding: 0.25rem; border-radius: 999px; background: var(--paper-alt); }
.board-switch__option { padding: 0.45rem 0.5rem; border-radius: 999px; color: var(--muted); font-size: 1rem; font-weight: 700; text-align: center; text-decoration: none; }
.board-switch__option[aria-current="true"] { background: var(--blue-deep); color: #fff; }

/* On the home page, under Play */
.group-waiting { display: flex; flex-direction: column; gap: 0.15rem; width: var(--panel-width); padding: 0.75rem 1rem; border-radius: var(--radius); background: linear-gradient(90deg, var(--yellow) 0 6px, var(--paper-alt) 6px); color: var(--ink); text-decoration: none; }
.group-waiting__title { font-weight: 800; }
.group-waiting__about { color: var(--muted); font-size: 1rem; font-weight: 600; }
.banner--group { background: var(--yellow); color: var(--on-neon); }

/* The topic and level menus, one under the other in the form */
.form__pair { display: contents; }
.form__select { min-height: 3.25rem; padding: 0 0.75rem; border: 2px solid color-mix(in srgb, var(--ink) 25%, transparent); border-radius: var(--radius); background: var(--paper); color: var(--ink); font: inherit; font-weight: 600; }
.checkbox { display: flex; align-items: center; gap: 0.5rem; font-weight: 700; }
.checkbox input { width: 1.2rem; height: 1.2rem; accent-color: var(--green-deep); }

/* ── Topics ─────────────────────────────────────── */

/* The topic the player is on: a wide rounded button like the others, saying it changes the topic */
.current-topic {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  width: 100%;
}

.current-topic__name { display: flex; align-items: center; gap: 0.45rem; margin: 0; font-size: clamp(2rem, 9vw, 2.6rem); font-weight: 800; letter-spacing: -0.04em; line-height: 1.15; }
.current-topic__change { font-size: 1.05rem; font-weight: 700; }

/* Changing topic: a tile for each, with the player's progress in it */
.topic-cards { display: grid; gap: 0.75rem; width: 100%; margin: 0; padding: 0; list-style: none; }
.topic-card__form { display: contents; }

.topic-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
  padding: 1rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--paper-alt);
  color: var(--ink);
  cursor: pointer;
  font: inherit;
  text-align: left;
}

.topic-card:hover { background: color-mix(in srgb, var(--ink) 6%, var(--paper-alt)); }
.topic-card--current { background: linear-gradient(90deg, var(--pink) 0 6px, var(--paper-alt) 6px); }
.topic-card__icon .icon { width: 2.2rem; height: 2.2rem; }
.topic-card__body { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.topic-card__title { font-size: 1.15rem; font-weight: 800; }
.topic-card__now { color: var(--pink-text); font-size: 0.95rem; font-weight: 700; }
.topic-card__level { color: var(--muted); font-size: 1rem; font-weight: 600; }
/* Each level: its number in a small circle like the home page's, its stars under it, or a padlock */
.topic-card__levels { display: flex; flex-wrap: wrap; gap: 0.35rem 0.55rem; margin-top: 0.15rem; }
.topic-card__step { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; width: 2.7rem; }
.topic-card__number { display: grid; place-items: center; width: 1.7rem; height: 1.7rem; border-radius: 50%; background: var(--paper); font-size: 0.95rem; font-weight: 800; }
.topic-card__step--locked .topic-card__number { color: var(--muted); }
.topic-card__step--locked .icon { width: 0.75rem; height: 0.75rem; }
.topic-card__step .stars .icon { width: 0.8rem; height: 0.8rem; }
.topic-card__done { color: var(--green-deep); font-size: 0.95rem; font-weight: 700; }

/* Levels: unlocked ones can be picked, locked ones show a padlock */
/* The levels with their name and any action under them, spread across the page, with room for the medals */
:root { --panel-width: min(100%, 22rem); }
.levels-panel { display: grid; gap: 1.25rem; width: var(--panel-width); }

.levels { display: flex; justify-content: center; gap: 1.1rem; margin-top: 0.25rem; }
.levels__form { display: contents; }

.levels__level {
  display: grid;
  place-items: center;
  width: 3.1rem;
  height: 3.1rem;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 7%, var(--paper));
  color: var(--ink);
  cursor: pointer;
  font: inherit;
  font-size: 1.15rem;
  font-weight: 700;
  touch-action: manipulation;
}

.levels__level[aria-current="true"] { background: var(--blue-deep); color: #fff; box-shadow: 0 0 14px color-mix(in srgb, var(--blue) var(--glow-strength), transparent); }
.levels__level--locked { cursor: default; color: var(--ink); }
.levels__level--locked .icon { width: 1.15rem; height: 1.15rem; }
.levels__name { margin: -0.25rem 0 0; color: var(--ink); font-size: clamp(1.5rem, 7vw, 1.8rem); font-weight: 800; letter-spacing: -0.02em; line-height: 1.15; }
/* A medal level's best medal, on its circle and under its name */
.levels__level { position: relative; }
/* A level's best score, small under its circle */
.levels__best { position: absolute; top: calc(100% + 1.45rem); left: 50%; transform: translateX(-50%); color: var(--muted); font-size: 0.9rem; font-weight: 700; line-height: 1; }
.levels { margin-bottom: 1.4rem; }
.levels:has(.levels__best) { margin-bottom: 2.4rem; }
/* Under each level's circle: its stars, then its best */
.levels__level .stars { position: absolute; top: calc(100% + 0.3rem); left: 50%; transform: translateX(-50%); gap: 0.05rem; }
.levels__level .stars .icon { width: 0.95rem; height: 0.95rem; }
.levels__progress { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.25rem; margin: -1rem 0 0; color: var(--ink); font-size: 1.1rem; font-weight: 700; }
.levels__progress .stars .icon { width: 1.15rem; height: 1.15rem; }

/* Under the levels: playing the level picked (on stats), mixed practice, and the day's game if done */
.daily-done { color: var(--muted); font-weight: 600; text-align: center; text-decoration: none; }
.daily-done strong { color: var(--ink); }
.button--practise { width: 100%; margin-top: -0.5rem; }
.button--mixed { --fill: var(--blue-deep); --glow: var(--blue); width: 100%; margin-top: -0.5rem; }
.button--review { --fill: var(--paper-alt); width: 100%; margin-top: -0.5rem; color: var(--ink); }

/* Under the level's name, kept close to it, and kept from widening the levels like the name */
.levels__learn { width: 0; min-width: 100%; margin: -1rem 0 0; font-size: 1.1rem; font-weight: 700; white-space: nowrap; }

.level-progress { margin: 0; color: var(--muted); font-size: 1.05rem; }
.level-progress strong { color: var(--ink); }
.level-progress__rule { display: block; margin-top: 0.2rem; font-size: 0.9rem; }

.banner--level { background: var(--green); }
.banner--medal { background: var(--blue); }

.tables__example { display: block; color: var(--muted); font-size: 0.875rem; font-weight: 500; }

/* ── Score pops ─────────────────────────────────── */

/* Each right answer's score starts on the question, float up above it and fade slowly, so a fast run leaves
   several on screen at once. Bigger and brighter the quicker the answer was */
.score-pop {
  --drift: 0px;
  position: absolute;
  top: 18%;
  left: 50%;
  z-index: 2;
  color: var(--green-deep);
  font-size: 1.5rem;
  font-weight: 800;
  pointer-events: none;
  white-space: nowrap;
  animation: star-float 2.2s ease-out forwards;
}

/* A right answer's gems, then its speed's just below, so they rise as a pair; losing some for a wrong answer; and
   a new combo, biggest of all */
.score-pop--quick { top: 30%; color: var(--blue-deep); font-size: 1.6rem; }
.score-pop--lightning { top: 30%; color: var(--pink-text); font-size: 1.9rem; }
.score-pop--wrong { color: var(--wrong); font-size: 1.4rem; }
.score-pop--combo { top: 4%; color: var(--pink-text); font-size: 2.3rem; font-weight: 900; }

:root[data-theme="dark"] .score-pop--right { color: var(--green); }
:root[data-theme="dark"] .score-pop--quick { color: var(--blue); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .score-pop--right { color: var(--green); }
  :root:not([data-theme="light"]) .score-pop--quick { color: var(--blue); }
}

@keyframes star-float {
  0% { opacity: 0; transform: translate(calc(-50% + var(--drift) * 0.3), 0) scale(0.6); }
  10% { opacity: 1; transform: translate(calc(-50% + var(--drift) * 0.5), -14px) scale(1.1); }
  65% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--drift)), -170px) scale(1); }
}

/* Without motion they just fade where they appear */
@media (prefers-reduced-motion: reduce) {
  .score-pop { animation: star-fade 2.2s ease-out forwards !important; transform: translateX(-50%); }
}

@keyframes star-fade { 0%, 60% { opacity: 1; } 100% { opacity: 0; } }

/* What a game earned, on its results page */
/* Where a game's score came from: right answers, speed, combos, and what wrong ones lost */
.score-tally { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4rem; margin: 0; padding: 0; list-style: none; }
.score-tally .score-tally__wrong { color: var(--wrong); }
.score-tally li { padding: 0.15rem 0.6rem; border-radius: 999px; background: var(--paper-alt); color: var(--muted); font-size: 0.95rem; font-weight: 700; }

/* The player's collection, on the home page under the streak */
.gems-total { margin: -0.5rem 0 0; color: var(--muted); font-weight: 700; }
.gems-total strong { color: var(--ink); font-size: 1.15rem; }

/* Streak freezes on the home page: those held, and buying another */
.freezes { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; margin-top: -0.5rem; }
.freezes__held { display: flex; align-items: center; gap: 0.5rem; margin: 0; color: var(--muted); font-weight: 700; }
.freezes__icons { display: inline-flex; gap: 0.2rem; }
.freezes__icons .icon { width: 1.4rem; height: 1.4rem; }
.icon--faded { opacity: 0.3; }
.freezes__form { display: contents; }
.freezes__buy { --fill: var(--blue-deep); --glow: var(--blue); min-height: 2.6rem; padding: 0.4rem 1.1rem; font-size: 1rem; }
.freezes__hint { max-width: 22rem; margin: 0; color: var(--muted); font-size: 0.95rem; }

/* Settings: the player's gems and streak freezes, above their picture and name */
.collection { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; padding: 1rem; border-radius: var(--radius); background: linear-gradient(var(--blue) 0 6px, var(--paper-alt) 6px); }
.collection .gems-total, .collection .freezes { margin: 0; }

/* The settings page in three parts: about you, the game, and the app */
.settings__section { display: flex; flex-direction: column; align-items: center; gap: 1rem; width: 100%; }
.settings__section + .settings__section { padding-top: 1.5rem; border-top: 2px dashed color-mix(in srgb, var(--ink) 15%, transparent); }
.settings__heading { align-self: flex-start; margin: 0; font-size: 1.35rem; font-weight: 800; letter-spacing: -0.02em; }
.settings__saved { margin: 0; color: var(--green-deep); font-size: 1rem; font-weight: 700; text-align: center; }
.settings__saved:empty { display: none; }
.collection { width: 100%; }

/* Daily reminders on the settings page: a time, and turning them on or off */
.reminder { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; width: 100%; padding: 1rem; border-radius: var(--radius); background: linear-gradient(var(--pink) 0 6px, var(--paper-alt) 6px); }
.reminder .label { margin: 0; }
.reminder__about, .reminder__status { margin: 0; color: var(--muted); font-size: 1rem; }
.reminder__status:empty { display: none; }
.reminder__row { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
.reminder__time { min-height: 3.25rem; padding: 0 0.75rem; border: 0; border-radius: var(--radius); background: var(--paper); color: var(--ink); font: inherit; font-weight: 700; }

/* Share and Play again side by side on the results page */
.results__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; width: 100%; }
.results__actions--one { grid-template-columns: 1fr; }

/* A freeze earned in a game, on its results page */
/* On the results page: how the game compares with the level's best */
.best-line { margin: 0; color: var(--muted); font-size: 1.05rem; font-weight: 700; }
.best-line--new { color: var(--pink-text); font-size: 1.2rem; }
/* A daily challenge's week: thin columns from one baseline, this game's in the accent, the rest pink */
.week-chart { display: grid; gap: 0.6rem; width: 100%; margin: 0; }
.week-chart__title { color: var(--muted); font-size: 1.05rem; font-weight: 700; text-align: center; }
.week-chart__days { display: grid; grid-template-columns: repeat(7, 1fr); margin: 0; padding: 0; list-style: none; }
.week-chart__day { display: grid; justify-items: center; gap: 0.35rem; border-radius: 8px; outline-offset: 2px; }
.week-chart__plot { display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 0.2rem; width: 100%; height: 6.5rem; border-bottom: 1px solid var(--line); }
.week-chart__bar { width: min(24px, 60%); height: max(2px, calc(5rem * var(--share))); border-radius: 4px 4px 0 0; background: var(--pink); }
.week-chart__day--this .week-chart__bar { background: var(--ui-accent); }
.week-chart__value { visibility: hidden; color: var(--ink); font-size: 0.875rem; font-weight: 700; white-space: nowrap; }
.week-chart__value--shown, .week-chart__day:is(:hover, :focus-visible) .week-chart__value { visibility: visible; }
.week-chart__label { color: var(--muted); font-size: 0.875rem; font-weight: 600; }
.week-chart__day--this .week-chart__label { color: var(--ink); font-weight: 800; }

.freeze-earned { margin: 0; padding: 0.45rem 1rem; border-radius: 999px; background: var(--blue); color: var(--on-neon); font-weight: 700; }

/* ── Lessons ────────────────────────────────────── */

/* A level's tutorial, full screen like the game: a step at a time, then one to try with the keypad */
.lesson {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  gap: 1rem;
  height: 100dvh;
  max-width: 30rem;
  margin: 0 auto;
  padding: calc(0.75rem + env(safe-area-inset-top)) 1rem calc(0.75rem + env(safe-area-inset-bottom));
  text-align: center;
}

.lesson__close {
  position: absolute;
  top: calc(0.75rem + env(safe-area-inset-top));
  left: 0.75rem;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  color: var(--muted);
  font-size: 1.4rem;
  text-decoration: none;
}

.lesson__header { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; padding-top: 0.5rem; }
.lesson__title { margin: 0; font-size: 1.6rem; letter-spacing: -0.03em; }
.lesson__dots { display: flex; gap: 0.4rem; margin: 0.3rem 0 0; padding: 0; list-style: none; }
.lesson__dot { width: 0.6rem; height: 0.6rem; border-radius: 50%; background: color-mix(in srgb, var(--ink) 15%, var(--paper)); }
.lesson__dot--done { background: var(--pink-text); }

.lesson__stage { display: grid; place-items: center; min-height: 0; }
.lesson__step { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; }
.lesson__show { margin: 0; font-size: clamp(2.2rem, 11vw, 3.5rem); font-weight: 700; letter-spacing: -0.03em; line-height: 1.1; }
.lesson__line { display: block; }
/* The one to try, written by the topic: a function on each line, the equations of a pair in columns */
.lesson__show .function { display: block; color: var(--muted); font-size: 0.6em; }
.lesson__show .function--ask { color: var(--ink); font-size: 1em; }
.lesson__show--simultaneous-equations { font-size: clamp(1.7rem, 8vw, 2.6rem); }
.lesson__show .system__ask { display: block; margin-top: 0.3em; }
.lesson__say { max-width: 20rem; margin: 0; color: var(--muted); font-size: 1.15rem; font-weight: 600; }
.lesson__feedback { min-height: 1.4em; margin: 0; color: var(--pink-text); font-weight: 700; }
.lesson__hint { max-width: 20rem; margin: 0; padding: 0.5rem 0.9rem; border-radius: var(--radius); background: var(--paper-alt); font-weight: 600; }
.lesson__done .button--start { width: 100%; }
.lesson__hint-button { --fill: var(--paper-alt); color: var(--ink); }

/* ── Badges ─────────────────────────────────────── */

.badges { display: flex; flex-direction: column; gap: 0.6rem; width: 100%; }
.badges__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); gap: 0.6rem; margin: 0; padding: 0; list-style: none; }

/* Tiles like the stats ones: earned badges have a yellow stripe along the top */
.badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.95rem 0.5rem 0.75rem;
  border-radius: var(--radius);
  background: linear-gradient(var(--yellow) 0 6px, var(--paper-alt) 6px);
}

.badge__icon .icon { width: 2.2rem; height: 2.2rem; }
/* On a new award's yellow tile, its icon sits on a disc so a yellow one still shows */
.badges--new .badge__icon { display: grid; place-items: center; width: 3.1rem; height: 3.1rem; border-radius: 50%; background: var(--paper); }
.badge__name { font-weight: 800; line-height: 1.2; }
.badge__how { color: var(--muted); font-size: 0.875rem; line-height: 1.3; }

/* Not earned yet: faded, so the earned ones stand out */
.badge--locked { background: color-mix(in srgb, var(--paper-alt) 55%, var(--paper)); }
.badge--locked .badge__icon { filter: grayscale(1); opacity: 0.45; }
.badge--locked .badge__name { color: var(--muted); }

/* A new badge, on its results page: all yellow, glowing in the dark */
/* The results page's news spins in over everything else, as a copy fixed to the middle of the screen (reveal
   controller), before flying back to its place. An award's copy keeps its new-award look */
.badges--new .badge { padding-top: 0.75rem; background: var(--yellow); box-shadow: 0 0 20px color-mix(in srgb, var(--yellow) var(--glow-strength), transparent); color: var(--on-neon); }

/* On the stats page: a tile like the stats above it, with a pink stripe */
.badge-summary {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  width: 100%;
  padding: 0.85rem 0.7rem 0.8rem;
  border-radius: var(--radius);
  background: linear-gradient(var(--pink) 0 6px, var(--paper-alt) 6px);
  color: inherit;
  text-decoration: none;
  transition: transform 100ms;
}

.badge-summary:hover { background: linear-gradient(var(--pink) 0 6px, color-mix(in srgb, var(--ink) 6%, var(--paper-alt)) 6px); }
.badge-summary__label { color: var(--muted); font-size: 0.8rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }
.badge-summary__count { color: var(--muted); font-weight: 600; }
.badge-summary__count strong { color: var(--ink); font-size: 1.75rem; letter-spacing: -0.03em; }
.badge-summary__count::after { content: " ›"; }
.badge-summary__icons { display: flex; gap: 0.25rem; }
.badge-summary__icons .icon { width: 1.6rem; height: 1.6rem; }
.badge-summary__icons:empty { display: none; }

/* ── Stats ──────────────────────────────────────── */

.stats--three { grid-template-columns: repeat(3, 1fr); }

.summary { margin: 0; font-size: 1.15rem; line-height: 1.5; }
.summary strong { color: var(--pink-text); font-weight: 700; }


.tables {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.tables caption { margin-bottom: 0.5rem; }

.tables th, .tables td { padding: 0.45rem 0.3rem; text-align: right; white-space: nowrap; }
.tables thead th { color: var(--muted); font-size: 0.8rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }
.tables tbody tr { border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); }
.tables tbody th { font-weight: 700; text-align: left; }
.tables__bar { width: 100%; }

/* One hue for every bar: the percentage is a magnitude, and the number beside it carries the value */
.bar {
  display: block;
  height: 0.85rem;
  overflow: hidden;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 9%, var(--paper));
}

.bar__fill {
  display: block;
  height: 100%;
  background: var(--blue);
  box-shadow: 0 0 10px color-mix(in srgb, var(--blue) var(--glow-strength), transparent);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── Test ───────────────────────────────────────── */

/* Fill the screen, no scrolling, no zooming, no text selection while tapping fast */
body.testing {
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.test {
  --right: var(--green);
  --quarter: var(--yellow);
  display: grid;
  grid-template-rows: auto 1fr auto;
  height: 100dvh;
  max-width: 30rem;
  margin: 0 auto;
  padding: calc(0.75rem + env(safe-area-inset-top)) 1rem calc(0.75rem + env(safe-area-inset-bottom));
}

/* Score, clock, seconds: equal side columns keep the clock dead centre */
.test__bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0.9rem;
}

/* The timer is the logo's clock: its quarters fill in over the minute while one hand goes round */
.timer__clock {
  width: 5.5rem;
  height: 5.5rem;
  filter: drop-shadow(0 0 8px color-mix(in srgb, var(--quarter) var(--glow-strength), transparent));
}

.test__seconds, .test__score {
  border-radius: var(--radius);
  font-weight: 700;
}

.test[data-quarter="1"] { --quarter: var(--green); }
.test[data-quarter="2"] { --quarter: var(--blue); }
.test[data-quarter="3"] { --quarter: var(--pink); }

.test__seconds { justify-self: start; font-size: 1.75rem; }

/* The score, with the best to beat under it, which turns the logo's pink once it's passed */
.test__tally { display: flex; flex-direction: column; align-items: flex-end; justify-self: end; gap: 0.15rem; }
.test__best { color: var(--muted); font-size: 0.9rem; font-weight: 700; white-space: nowrap; }
.test--beating .test__score { color: var(--pink-text); text-shadow: 0 0 14px color-mix(in srgb, var(--pink) var(--glow-strength), transparent); }
.test--beating .test__best { color: var(--pink-text); }
.score-pop--best { color: var(--pink-text); font-size: 1.9rem; font-weight: 900; }
.score-pop .icon { width: 1em; height: 1em; vertical-align: -0.12em; }

.test__score {
  justify-self: end;
  padding: 0 0.3rem;
  font-size: 2.5rem;
  line-height: 1;
}

/* Sized to the room left between the clock and the keypad (cqh), so the carousel's three rows fit on any phone */
.test__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: 0;
  container-type: size;
}

.question {
  margin: 0;
  font-size: clamp(3.75rem, 17vw, 8rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  white-space: nowrap;
}

.question--done { font-size: clamp(2.75rem, 12vw, 5rem); }

/* Longer questions (equations, decimals and negatives) are smaller, so they fit on one line.
   The letter in an equation is italic, and fractions are stacked */
.test--equations .question, .question.question--long { font-size: clamp(2.2rem, 10.5vw, 4.5rem); }
.question.question--longer { font-size: clamp(1.9rem, 9vw, 3.75rem); }
.question var { font-style: italic; font-weight: 600; padding-right: 0.04em; }

/* Functions: each definition on its own line, smaller, then what's asked, f(4), at full size */
.test--functions .question,
.test--functions .question.question--long,
.test--functions .question.question--longer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35em;
  font-size: clamp(1.6rem, 8vw, 3rem);
  letter-spacing: -0.02em;
}

.test--functions .question.question--done { font-size: clamp(2.75rem, 12vw, 5rem); }

/* Simultaneous equations: the two lined up in columns (x term, sign, y term, =, total), then y given if
   it's been found, then what's asked */
.test--simultaneous-equations .question,
.test--simultaneous-equations .question.question--long,
.test--simultaneous-equations .question.question--longer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4em;
  font-size: clamp(1.9rem, 10vw, 3.2rem);
  letter-spacing: -0.02em;
}

.test--simultaneous-equations .question.question--done { font-size: clamp(2.75rem, 12vw, 5rem); }
.system { display: inline-grid; grid-template-columns: repeat(5, auto); gap: 0.15em 0.3em; align-items: baseline; }
.system__row { display: contents; }
.system__row > span:nth-child(1), .system__row > span:nth-child(3) { text-align: right; }
.system__row > span:nth-child(5) { text-align: left; }
.system__known { color: var(--muted); font-size: 0.8em; }
.system__ask { font-size: 1.3em; }
.function { color: var(--muted); }
.function--ask { color: var(--ink); font-size: 1.6em; }

/* Fractions: the fractions are the question, so they're stacked large, with "Simplify" above one on its own */
.test--fractions .question,
.test--fractions .question.question--long,
.test--fractions .question.question--longer { font-size: clamp(2.6rem, 12vw, 4.75rem); letter-spacing: -0.02em; }
.test--fractions .question.question--done { font-size: clamp(2.75rem, 12vw, 5rem); }
.test--fractions .frac { font-size: 0.85em; margin: 0 0.12em; }
.lesson__show--fractions { font-size: clamp(1.8rem, 8vw, 2.6rem); }
/* A lesson has its title and dots above the keypad too, so its keys are shorter than the game's, leaving room on
   small phones for the one to try */
.lesson__keypad .keypad__key { min-height: 52px; height: clamp(52px, 7.5dvh, 80px); }

@media (max-height: 700px) {
  .lesson { gap: 0.6rem; }
  .lesson__title { font-size: 1.25rem; }
  .lesson__try > .label { display: none; }
  .lesson__keypad .keypad__key { min-height: 44px; height: 44px; }
  .lesson__keypad .keypad__key:not(.keypad__key--submit) { font-size: 1.6rem; }
  .lesson__keypad .keypad { gap: 0.4rem; }
}
.lesson__show--fractions .frac { font-size: 0.8em; margin: 0 0.12em; }
.question__verb { display: block; color: var(--muted); font-size: 0.45em; font-weight: 700; letter-spacing: 0.02em; }

.frac {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  vertical-align: middle;
  margin: 0 0.08em;
  font-size: 0.62em;
  line-height: 1.05;
}

.frac > span:first-child { padding: 0 0.15em 0.04em; border-bottom: 0.08em solid currentColor; }
.frac > span:last-child { padding-top: 0.04em; }

.keypad__key--extra { background: var(--paper); }

/* Two extra keys (− and .): four columns, with a wide 0 along the bottom */
.keypad.keypad--wide { grid-template-columns: repeat(4, 1fr); }
.keypad--wide .keypad__key--zero { grid-column: 1 / -1; }

/* Fixed height so the layout never shifts as digits appear */
.answer {
  min-width: 3ch;
  height: clamp(3.25rem, 14vw, 5.5rem);
  margin: 0;
  border-bottom: 6px solid var(--blue);
  font-size: clamp(2.75rem, 13vw, 5rem);
  font-weight: 700;
  line-height: 1;
  text-align: center;
}

.answer--wrong { border-color: var(--wrong); color: var(--wrong); }

.test__status { margin: 0; color: var(--muted); font-weight: 500; }

.keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.55rem;
}

/* Soft keys: a faint border, so the numbers stand out rather than the boxes */
.keypad__key {
  min-height: 72px;
  height: clamp(72px, 9dvh, 86px);
  border: 1.5px solid color-mix(in srgb, var(--ink) 14%, transparent);
  border-radius: var(--radius);
  background: var(--paper-alt);
  color: var(--ink);
  font: inherit;
  font-size: 2rem;
  font-weight: 500;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* Instant press feedback, no transition to wait for */
.keypad__key:active {
  border-color: var(--on-neon);
  background: var(--quarter);
  box-shadow: 0 0 18px color-mix(in srgb, var(--quarter) var(--glow-strength), transparent);
  color: var(--on-neon);
  transform: scale(0.97);
}

.keypad__key--back { background: var(--paper); font-size: 1.6rem; }

.keypad__key--submit {
  grid-column: 1 / -1;
  min-height: 44px;
  height: 44px;
  font-size: 1.05rem;
}

/* ── Finished offline ─────────────────────────────── */

.offline-result { display: grid; justify-items: center; gap: 1rem; width: 100%; text-align: center; }
.offline-result__score { margin: 0; font-size: 1.15rem; font-weight: 600; }

/* ── Stopping a game ─────────────────────────────── */

.test { position: relative; }

.test__stop {
  position: absolute;
  top: calc(0.75rem + env(safe-area-inset-top));
  left: 0.75rem;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  font-size: 1.25rem;
  touch-action: manipulation;
}

.test__stop:hover { background: color-mix(in srgb, var(--ink) 6%, var(--paper)); color: var(--ink); }

/* While the warning is open the question is hidden, so the pause can't be used to think */
.test--paused .test__stage, .test--paused .keypad { filter: blur(14px); }

.dialog {
  width: min(22rem, calc(100vw - 2rem));
  padding: 1.5rem;
  border: 0;
  border-radius: var(--radius-big);
  background: var(--paper);
  color: var(--ink);
  text-align: center;
  box-shadow: 0 12px 40px rgb(0 0 0 / 0.25);
}

.dialog::backdrop { background: rgb(24 26 50 / 0.5); }
.dialog__title { margin: 0; font-size: 1.5rem; font-weight: 700; }
.dialog__text { margin: 0.5rem 0 1.25rem; color: var(--muted); }
.dialog__actions { display: grid; gap: 0.6rem; }

/* ── Results and share ──────────────────────────── */

.banner {
  margin: 0;
  padding: 0.45rem 1.1rem;
  border-radius: var(--radius);
  background: var(--yellow);
  box-shadow: 0 0 24px color-mix(in srgb, var(--yellow) var(--glow-strength), transparent);
  color: var(--on-neon);
  font-size: 1.25rem;
  font-weight: 700;
  transform: rotate(-2deg);
}

/* A big score, then how many were right */
.result { display: grid; justify-items: center; gap: 0.75rem; width: 100%; }
.result__right { display: block; font-size: clamp(1.5rem, 7vw, 2rem); font-weight: 700; }

.result__score { margin: 0; font-size: 1.15rem; font-weight: 600; text-align: center; }
.slow-time { background: color-mix(in srgb, var(--yellow) 30%, transparent); }

.card__number {
  display: block;
  font-size: clamp(4.5rem, 24vw, 6.5rem);
  font-weight: 700;
  letter-spacing: -0.06em;
  line-height: 1;
}

.result__stats { margin: 0; color: var(--muted); font-size: 1rem; font-weight: 500; }

.feedback { margin: 0; font-size: 1.25rem; font-weight: 600; letter-spacing: -0.02em; }

.missed { width: 100%; }

.missed ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin: 0.6rem 0 0;
  padding: 0;
  list-style: none;
}

.missed li {
  padding: 0.25rem 0.7rem;
  border: 2px solid var(--pink);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--pink) 14%, var(--paper));
  font-size: 1.15rem;
  font-weight: 600;
}

/* Right but slow: yellow rather than pink */
.missed li.missed__slow {
  border-color: color-mix(in srgb, var(--yellow) 70%, var(--ink));
  background: color-mix(in srgb, var(--yellow) 30%, var(--paper));
}

.hint--centre { margin-top: 0.6rem; text-align: center; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  .banner { transform: none; }
}

/* Head to head: challenging a friend, the two scores side by side, and a record against each rival */
.button--challenge { --fill: var(--paper-alt); color: var(--ink); }
.head-to-heads, .group-list { display: grid; gap: 0.75rem; width: 100%; }
.rival-rows { display: grid; gap: 0.5rem; width: 100%; margin: 0; padding: 0; list-style: none; }
.rival-row { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.5rem 0.5rem 0.75rem; border-radius: var(--radius); background: var(--paper-alt); text-align: left; }
.rival-row__who { display: flex; flex: 1; flex-direction: column; min-width: 0; }
.rival-row__name { overflow: hidden; font-weight: 800; text-overflow: ellipsis; white-space: nowrap; }
.rival-row__record { color: var(--muted); font-size: 0.95rem; font-weight: 600; }
.rival-row__button { min-height: 2.5rem; padding: 0.4rem 0.9rem; font-size: 1rem; }
.head-to-head-waiting { background: linear-gradient(90deg, var(--pink) 0 6px, var(--paper-alt) 6px); }

.versus { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 0.5rem; width: 100%; }
.versus__player { display: flex; flex-direction: column; align-items: center; gap: 0.25rem; padding: 0.9rem 0.5rem; border-radius: var(--radius-big); background: var(--paper-alt); }
.versus__player--winner { box-shadow: 0 0 0 3px var(--yellow), 0 0 22px color-mix(in srgb, var(--yellow) var(--glow-strength), transparent); }
.versus__name { max-width: 100%; overflow: hidden; font-weight: 800; text-overflow: ellipsis; white-space: nowrap; }
.versus__score { font-size: 2.6rem; font-weight: 800; line-height: 1; }
.versus__vs { color: var(--muted); font-weight: 800; text-transform: uppercase; }
.head-to-head__record { color: var(--muted); }
.versus__unknown { display: grid; place-items: center; width: 2.25rem; height: 2.25rem; border-radius: 50%; background: color-mix(in srgb, var(--ink) 12%, transparent); font-weight: 800; }
.head-to-head-link__target { font-size: 1.4rem; font-weight: 700; }
.head-to-head-link__target strong { color: var(--pink-text); font-size: 2.4rem; }

/* A head to head's ghost: the challenger's score at this point in their minute, pink while they're ahead and
   green once you are */
/* The combo: how much right answers in a row multiply the gems */
.test__combo { padding: 0.05rem 0.45rem; border-radius: 999px; background: var(--pink); color: var(--on-neon); font-size: 0.95rem; font-weight: 900; }
.test__combo--new { animation: combo-pulse 450ms ease-out; }
@keyframes combo-pulse { 0% { transform: scale(1.6); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .test__combo--new { animation: none; } }

.test__ghost { color: var(--muted); font-size: 0.9rem; font-weight: 700; white-space: nowrap; transition: color 150ms; }
.test__ghost--ahead { color: var(--pink-text); }
.test__ghost--behind { color: var(--green-deep); }
:root[data-theme="dark"] .test__ghost--behind { color: var(--green); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .test__ghost--behind { color: var(--green); } }

/* Live games: the lobby, the others' scores while playing, and the podium */
.live-start, .live-status, .live-podium { display: grid; gap: 0.6rem; width: 100%; }
.live-status__waiting { font-size: 1.2rem; font-weight: 700; }
.live-code { margin: 0; text-align: center; font-size: clamp(2.5rem, 12vw, 3.5rem); font-weight: 800; letter-spacing: 0.2em; padding-left: 0.2em; font-variant-numeric: tabular-nums; }
.live-players__count { list-style: none; }
.test--live { grid-template-rows: auto auto 1fr auto; }
.test__rivals { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.35rem 0.75rem; margin: 0; padding: 0 1rem; list-style: none; }
.test__rival { color: var(--muted); font-size: 0.95rem; font-weight: 700; white-space: nowrap; transition: color 150ms; }
.test__rival strong { font-size: 1rem; }
.test__rival--ahead { color: var(--pink-text); }
.test__rival--behind { color: var(--green-deep); }
:root[data-theme="dark"] .test__rival--behind { color: var(--green); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .test__rival--behind { color: var(--green); } }
.live-status .board-switch { grid-template-columns: 1fr 1fr; }
.board-switch__form { margin: 0; }
button.board-switch__option { width: 100%; border: 0; background: transparent; cursor: pointer; font: inherit; font-size: 1rem; font-weight: 700; }
.live-mode { margin: 0; color: var(--muted); }
.live-mode .icon { width: 1.1em; height: 1.1em; vertical-align: -0.2em; }

/* One-line questions grow to fill the room; functions and simultaneous equations keep their own sizes, as they
   take several lines */
.test:not(.test--functions, .test--simultaneous-equations) .question--current:not(.question--done, .question--long, .question--longer) {
  font-size: clamp(1.75rem, min(17vw, 30cqh), 8rem);
}
.test__stage .answer { height: clamp(1.9rem, min(14vw, 20cqh), 5.5rem); font-size: clamp(1.6rem, min(13vw, 18cqh), 5rem); }
/* Questions over several lines (simultaneous equations, functions, stacked fractions) shrink on a short stage */
@container (max-height: 22rem) { :is(.test--functions, .test--simultaneous-equations, .test--fractions) .question--current { zoom: 0.75; } }
@container (max-height: 15rem) { :is(.test--functions, .test--simultaneous-equations, .test--fractions) .question--current { zoom: 0.6; } }
@container (max-height: 11rem) { :is(.test--functions, .test--simultaneous-equations) .question--current { zoom: 0.48; } }

/* Short phones: shorter keys, like a lesson's, leaving room for the questions */
@media (max-height: 760px) {
  .test .keypad__key { min-height: 52px; height: clamp(52px, 7.5dvh, 72px); }
  .test .keypad { gap: 0.45rem; }
}
@media (max-height: 600px) {
  .test .keypad__key { min-height: 44px; height: 44px; }
  .test .keypad { gap: 0.35rem; }
}

/* How many are right so far, under the score */
.test__counts { display: flex; gap: 0.6rem; }
.test__count { display: flex; flex-direction: column; align-items: center; }
.test__count .test__score, .test__count .test__right { padding: 0 0.15rem; font-size: clamp(1.6rem, 7vw, 2.1rem); font-weight: 700; line-height: 1; }
.test__count-label { color: var(--muted); font-size: 0.8rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.test__rival .icon { width: 0.9em; height: 0.9em; margin-left: 0.1em; vertical-align: -0.1em; }

/* Power-ups in a Power game: the one held, to tap; news of what's hit whom; and each one's effect on the player
   it hits, for a few seconds. The clock keeps going through them all */
.test__live { display: grid; gap: 0.3rem; justify-items: center; }
.test__powers { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.25rem 0.6rem; min-height: 2.25rem; }
/* The power-up spinner: flicking between what it could be until it's tapped, then the one claimed, glowing */
.test__spinner { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.3rem 0.95rem 0.3rem 0.4rem; border: 0; border-radius: 999px; background: var(--yellow); box-shadow: 0 0 18px color-mix(in srgb, var(--yellow) 70%, transparent); color: var(--on-neon); cursor: pointer; font: inherit; font-weight: 900; animation: spinner-bob 600ms ease-in-out infinite alternate; touch-action: manipulation; }
.test__spinner-icon { display: grid; place-items: center; width: 2.4rem; height: 2.4rem; border-radius: 50%; background: var(--paper); }
.test__spinner-icon .icon { width: 1.8rem; height: 1.8rem; }
.test__spinner--landed { animation: combo-pulse 450ms ease-out; background: var(--pink); box-shadow: 0 0 22px color-mix(in srgb, var(--pink) 70%, transparent); }
.test__spinner--landed .test__spinner-label { display: none; }
.test__spinner:disabled { cursor: default; }
@keyframes spinner-bob { from { transform: translateY(0) scale(1); } to { transform: translateY(-3px) scale(1.06); } }
@media (prefers-reduced-motion: reduce) { .test__spinner { animation: none; } }


.test__power-news { margin: 0; color: var(--pink-text); font-size: 0.95rem; font-weight: 800; text-align: center; }
.test__power-news:empty { display: none; }

.test--flip .question--current { transform: rotate(180deg); transition: transform 300ms; }
.test--shrink .question--current { transform: scale(0.3); transition: transform 300ms; }
.test--freeze .keypad { filter: grayscale(1); opacity: 0.45; pointer-events: none; }
.test--freeze .keypad::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); background: color-mix(in srgb, var(--blue) 30%, transparent); pointer-events: none; }
.test--freeze .keypad { position: relative; }
.test--scramble .keypad__key[data-digit] { animation: combo-pulse 450ms ease-out; }
.test__ink { position: absolute; inset: 10% 15%; z-index: 3; border-radius: 48% 52% 45% 55% / 55% 45% 55% 45%; background: var(--ink); opacity: 0; pointer-events: none; }
.test--ink .test__ink { animation: ink-fade 5s ease-in forwards; }
@keyframes ink-fade { 0% { opacity: 0.97; transform: scale(0.6); } 8% { transform: scale(1.05); } 12% { transform: scale(1); } 60% { opacity: 0.92; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .test--ink .test__ink { animation: none; opacity: 0.9; }
}

/* Home: the greeting with the streak small beside it, then the three ways to play */
.greeting__hello { margin: 0; font: inherit; }
/* The flame as tall as the avatar beside the greeting */
.greeting .streak { display: inline-flex; flex-direction: row; align-items: center; gap: 0.1rem; margin: 0; color: var(--muted); font-size: 2rem; font-weight: 800; letter-spacing: -0.02em; }
.greeting .streak--done { color: var(--ink); }
.greeting .streak .streak__flame { width: 4.3rem; height: 4.3rem; margin: -0.35rem -0.5rem -0.35rem -0.35rem; vertical-align: 0; }
.home-actions { display: grid; gap: 0.9rem; width: var(--panel-width); }
.home-action { flex-direction: column; gap: 0.15rem; min-height: 4.5rem; font-size: clamp(1.4rem, 6.5vw, 1.75rem); }
.home-action__label { display: inline-flex; align-items: center; gap: 0.5rem; }
.home-action .icon { width: 1.1em; height: 1.1em; }
/* Quiet, off-white buttons; their icons keep their colour */
.home-action { --fill: var(--paper-alt); --glow: transparent; border: 1px solid color-mix(in srgb, var(--ink) 14%, transparent); box-shadow: none; color: var(--ink); font-weight: 700; text-shadow: none; text-transform: none; }
.home-action:hover { --fill: color-mix(in srgb, var(--ink) 6%, var(--paper-alt)); }
.home-action .button__note { color: var(--muted); }
.live-topic { display: grid; gap: 0.5rem; }
.live-topic .button { justify-self: center; }

/* The Daily Tables Test: today's score and where it stands among everyone's */
.daily-challenge, .daily-standing { display: grid; justify-items: center; gap: 0.75rem; width: 100%; }
.daily-standing__score { margin: 0; text-align: center; }

/* Sequences: five terms and a gap on one line, so smaller, the same size for every question */
.test--sequences .question--current:not(.question--done) { max-width: 100%; font-size: clamp(2rem, min(9.5vw, 16cqh), 3.4rem); letter-spacing: -0.02em; line-height: 1.15; text-align: center; text-wrap: balance; white-space: normal; }
/* Each daily game is a button that opens it: its name and whether it's done, then once open, the rest */
.daily-test { width: 100%; }
.daily-test__toggle { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; padding: 0.4rem; cursor: pointer; list-style: none; text-align: center; }
.daily-test__toggle::-webkit-details-marker { display: none; }
.daily-test__toggle::after { content: "▾"; color: var(--muted); font-size: 1rem; transition: transform 150ms; }
.daily-test[open] .daily-test__toggle::after { transform: rotate(180deg); }
/* Open, the score and where it stands are shown big below, so the button just says which challenge it is */
.daily-test[open] :is(.daily-test__score, .daily-test__status) { display: none; }
.daily-test__name { font-size: 1.25rem; font-weight: 800; }
.daily-test__name .icon { width: 1.1em; height: 1.1em; vertical-align: -0.15em; }
.daily-test__status { color: var(--muted); font-size: 1rem; font-weight: 700; }
.daily-test__score { font-size: 1.6rem; font-weight: 800; line-height: 1.1; }
.daily-test__score span { color: var(--muted); font-size: 1rem; font-weight: 700; }
.daily-test__body { display: grid; justify-items: center; gap: 0.75rem; margin-top: 0.75rem; }
.daily-test__number { color: var(--muted); font-weight: 700; }

/* ── SUMZ ───────────────────────────────── */
.home-actions--modes { grid-template-columns: 1fr 1fr; }
.home-action--solo .ui-secondary__icon { background: color-mix(in srgb, var(--blue) 22%, transparent); }
.home-action--battle .ui-secondary__icon { background: color-mix(in srgb, var(--pink) 22%, transparent); }
.how-to__list { display: grid; gap: 0.6rem; margin: 0; padding-left: 1.2rem; line-height: 1.5; }
.league { display: grid; gap: 0.75rem; }
.league-places { display: grid; gap: 0.4rem; margin: 0; padding: 0; list-style: none; }
.league-places .icon { width: 1.1em; height: 1.1em; vertical-align: -0.15em; }
.match { justify-items: center; text-align: center; }
.match__radar { display: grid; place-items: center; width: 6rem; height: 6rem; border-radius: 50%; background: color-mix(in srgb, var(--pink) 18%, transparent); animation: radar 1.6s ease-out infinite; }
.match__radar .icon { width: 3rem; height: 3rem; }
@keyframes radar { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--pink) 55%, transparent); } 100% { box-shadow: 0 0 0 1.75rem transparent; } }
@media (prefers-reduced-motion: reduce) { .match__radar { animation: none; } }
