:root {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI",
    Helvetica, Arial, sans-serif;
  color-scheme: dark;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

* { box-sizing: border-box; }

html {
  background: #0b0e16;
  overscroll-behavior: none;
}

html, body, #root {
  margin: 0; padding: 0;
  min-height: 100%;
  color: #fff;
}

body {
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  overscroll-behavior: none;
}

/* Disable text selection in interactive UI but allow it in clue text. */
.app, .topbar, .keyboard, .board, .cw-board {
  user-select: none;
  -webkit-user-select: none;
}

button { font: inherit; }

/* On devices without hover (phones), iOS Safari fires :hover on tap and
   leaves the state stuck until the user taps elsewhere — so any hover
   transforms (lift, scale) visually linger after the tap. Disable
   hover transforms on no-hover devices, but only when the element is
   *not* currently being pressed; that keeps :active press feedback
   intact during the brief tap-down phase. */
@media (hover: none) {
  *:hover:not(:active) {
    transform: none !important;
  }
}
.signin-link {
  position: relative;
  display: inline-block;
  cursor: pointer;
  /* Keep the visible underline + the invisible overlay tightly hugged to
     the text so clicks outside the words don't trigger sign-in. */
  line-height: 1.2;
}

.signin-link-text {
  color: #fff;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1.5px;
  text-decoration-color: rgba(255, 255, 255, 0.55);
  transition: text-decoration-color 200ms ease;
}

.signin-link:hover .signin-link-text,
.signin-link:focus-within .signin-link-text {
  text-decoration-color: #fff;
}

/* Transparent host for the GIS-rendered button. Sits on top of the visible
   text so a click lands on the GIS iframe; `overflow: hidden` clips both
   the rendering and the pointer-events to the link's bounding box. */
.signin-link-gis {
  position: absolute;
  inset: 0;
  opacity: 0;
  overflow: hidden;
  cursor: pointer;
  border-radius: 4px;
}

/* Scale the GIS button up so even a 200px button covers the entire link
   regardless of the underlying text width. */
.signin-link-gis > div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(3);
  transform-origin: center;
}
.lb-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  padding: 16px;
}

.lb-panel {
  width: 100%;
  max-width: 460px;
  max-height: 85vh;
  overflow-y: auto;
  background: rgba(20, 22, 32, 0.92);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow);
  border-radius: 18px;
  padding: 18px 18px 14px;
  color: #fff;
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
}

.lb-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.lb-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
  margin: 0;
}
.lb-close {
  background: transparent;
  border: none;
  color: rgba(255,255,255,0.7);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 8px;
}
.lb-close:hover { background: rgba(255,255,255,0.10); color: #fff; }

.lb-state {
  text-align: center;
  padding: 24px 0;
  color: rgba(255,255,255,0.7);
  font-size: 14px;
}
.lb-error { color: #ff8585; }

.lb-cta {
  font-size: 13px;
  color: rgba(255,255,255,0.75);
  background: rgba(99, 102, 241, 0.16);
  border: 1px solid rgba(99, 102, 241, 0.4);
  padding: 8px 12px;
  border-radius: 10px;
  margin-bottom: 12px;
  text-align: center;
}

.lb-section { margin-top: 10px; }
.lb-section-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255,255,255,0.55);
  margin-bottom: 6px;
}
.lb-metric { color: rgba(255,255,255,0.45); font-weight: 500; letter-spacing: 0; text-transform: none; }

.lb-empty {
  text-align: center;
  color: rgba(255,255,255,0.5);
  font-size: 13px;
  padding: 16px 0;
}

.lb-rows { display: flex; flex-direction: column; gap: 4px; }

.lb-row {
  display: grid;
  grid-template-columns: 28px 28px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(255,255,255,0.03);
  border: 1px solid transparent;
}
.lb-row.me {
  background: rgba(99, 102, 241, 0.18);
  border-color: rgba(99, 102, 241, 0.45);
}

.lb-rank {
  font-size: 12px;
  font-weight: 700;
  color: rgba(255,255,255,0.65);
  text-align: center;
}
.lb-avatar {
  width: 28px; height: 28px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255,255,255,0.08);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}
.lb-avatar img { width: 100%; height: 100%; object-fit: cover; }
.lb-name {
  font-size: 13px;
  font-weight: 500;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lb-score {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.02em;
}

@media (max-width: 480px) {
  .lb-panel { padding: 14px; }
}
.dlb-panel {
  width: 100%;
  background: rgba(255,255,255,0.04);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 18px;
  padding: 14px 16px;
  color: #fff;
  box-shadow: inset 0 1px 0 var(--glass-hi);
  /* Reserve room for the header (≈32px) + 2 rows (2×44 + 1×4 gap = 92px),
     so the panel doesn't grow/shrink as entries load. */
  min-height: 152px;
}

.dlb-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 10px;
}
.dlb-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: rgba(255,255,255,0.65);
}
.dlb-metric {
  font-size: 11px;
  color: rgba(255,255,255,0.45);
}

.dlb-state {
  text-align: center;
  padding: 16px 0;
  color: rgba(255,255,255,0.6);
  font-size: 13px;
}
.dlb-error { color: #ff8585; }

.dlb-empty {
  text-align: center;
  color: rgba(255,255,255,0.5);
  font-size: 13px;
  padding: 12px 0;
}

.dlb-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* Show 2 rows max; scroll for the rest. Each row is ~44px (28 avatar +
     14 padding + 2 border) and the gap between rows is 4px, so 2 rows
     plus 1 gap = 92px. */
  max-height: 92px;
  overflow-y: auto;
}

.dlb-row {
  display: grid;
  grid-template-columns: 28px 28px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 10px;
  background: rgba(255,255,255,0.03);
  border: 1px solid transparent;
}
.dlb-row.me {
  background: rgba(99, 102, 241, 0.18);
  border-color: rgba(99, 102, 241, 0.45);
}

.dlb-rank {
  font-size: 12px;
  font-weight: 700;
  color: rgba(255,255,255,0.65);
  text-align: center;
}
.dlb-avatar {
  width: 28px; height: 28px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255,255,255,0.08);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}
.dlb-avatar img { width: 100%; height: 100%; object-fit: cover; }
.dlb-name {
  font-size: 13px;
  font-weight: 500;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dlb-score {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.02em;
}

@media (max-width: 480px) {
  .dlb-panel { padding: 12px; }
}

/* Loading-state skeletons. Same row geometry as a real entry; the rank
   shows a centred dot, the avatar circle stays visible (no shimmer to
   keep the dot quiet), and the name/score swap in muted bars that pulse. */
.dlb-row--placeholder { background: rgba(255,255,255,0.02); }
.dlb-row--placeholder .dlb-rank { color: rgba(255,255,255,0.25); }
.dlb-row--placeholder .dlb-avatar { background: rgba(255,255,255,0.05); }
.dlb-skel {
  display: inline-block;
  height: 10px;
  border-radius: 4px;
  background: rgba(255,255,255,0.08);
  animation: dlb-pulse 1.4s ease-in-out infinite;
}
.dlb-skel--name  { width: 60%; }
.dlb-skel--score { width: 32px; }
@keyframes dlb-pulse {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 1; }
}

/* Click-to-open-history wrapper. The trigger itself wears the panel chrome
   so hover/focus lights up *both* the leaderboard rows and the streak
   footer simultaneously — they're a single visual component. The inner
   .dlb-panel and the .daily-streak chip drop their own backgrounds when
   nested here; without this, hovering would only highlight one half. */
.dlb-trigger {
  appearance: none;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;

  /* Panel chrome (moved off .dlb-panel so the whole card reacts on hover). */
  background: rgba(255,255,255,0.04);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 18px;
  padding: 14px 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi);
  /* Match the standalone .dlb-panel so the merged card stays a stable
     height as entries load. */
  min-height: 152px;
  transition: background 200ms ease, border-color 200ms ease,
              box-shadow 200ms ease, transform 200ms ease;
}
/* Strip nested chrome — the trigger is the single visual frame. */
.dlb-trigger > .dlb-panel {
  background: transparent;
  border: 0;
  padding: 0;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  min-height: auto;
}
.dlb-trigger > .daily-streak {
  background: transparent;
  border: 0;
  padding: 4px 0 0;
  margin-top: 8px;
  border-top: 1px solid rgba(255,255,255,0.08);
  border-radius: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  align-self: stretch;
  justify-content: center;
}
.dlb-trigger > .daily-streak:hover {
  /* Cancel the standalone hover lift — the trigger handles the lift now. */
  background: transparent;
  border-color: transparent;
  border-top-color: rgba(255,255,255,0.08);
  transform: none;
}
.dlb-trigger:hover {
  background: rgba(255,255,255,0.07);
  border-color: rgba(99, 142, 255, 0.34);
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 0 0 1px rgba(99, 142, 255, 0.18),
    0 8px 22px rgba(0,0,0,0.28);
  transform: translateY(-1px);
}
.dlb-trigger:focus-visible {
  outline: 2px solid rgba(99, 142, 255, 0.55);
  outline-offset: 3px;
}
.dh-backdrop {
  position: fixed; inset: 0;
  background: rgba(6, 8, 16, 0.82);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  padding: 16px;
  animation: dh-fade-in 200ms ease-out;
}

@keyframes dh-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Glass panel matching the daily-result-card aesthetic: translucent surface
   over the backdrop blur, soft inset highlight, and a subtle indigo accent
   ring so the modal reads as part of the daily-themed surfaces. */
.dh-panel {
  width: 100%;
  max-width: 540px;
  max-height: 85vh;
  overflow-y: auto;
  background: rgba(20, 23, 36, 0.78);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 20px;
  padding: 18px 18px 14px;
  color: #fff;
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 14px 30px rgba(0,0,0,0.45),
    0 0 0 1px rgba(99,142,255,0.18);
  animation: dh-panel-in 360ms cubic-bezier(.2, 1.5, .3, 1);
}

@keyframes dh-panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.dh-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}

/* ---- Calendar ---- (top of the modal: visual at-a-glance of played days,
   navigable month-by-month, with the per-day list below.) */
.dh-calendar {
  margin-bottom: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
.dh-monthnav {
  display: grid;
  grid-template-columns: 32px 1fr 32px;
  align-items: center;
  margin-bottom: 10px;
}
.dh-navbtn {
  appearance: none;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  color: rgba(255,255,255,0.85);
  width: 30px; height: 30px;
  border-radius: 9px;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 160ms ease, border-color 160ms ease, opacity 160ms ease;
}
.dh-navbtn:hover:not(:disabled) {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.24);
}
.dh-navbtn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.dh-monthlabel {
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #fff;
  text-transform: capitalize; /* Spanish months render lowercase otherwise. */
}
.dh-calgrid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}
.dh-weekday {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.45);
  text-align: center;
  padding: 2px 0 4px;
}
/* Each cell is a button now (clickable to select that day). The grid
   inside lays out: day number top-left, rank top-right, metric value
   centred at the bottom for played days. Empty days render just the
   day number and stay clickable. */
.dh-day {
  appearance: none;
  font: inherit;
  cursor: pointer;
  aspect-ratio: 1 / 1;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto 1fr;
  align-items: start;
  justify-items: center;
  padding: 4px 4px 5px;
  border-radius: 9px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.06);
  color: rgba(255,255,255,0.55);
  font-variant-numeric: tabular-nums;
  transition: background 160ms ease, border-color 160ms ease, transform 160ms ease;
  /* Game-art is positioned absolute; clip its scaled-up SVG to the cell. */
  position: relative;
  overflow: hidden;
}
.dh-day:hover:not(:disabled) {
  background: rgba(255,255,255,0.07);
  border-color: rgba(255,255,255,0.18);
}
.dh-day:disabled {
  cursor: default;
  opacity: 0.45;
}

/* Played cells get the game's accent gradient via inline `style.background`,
   so the calendar reads as a colour-coded grid of which game ran which day.
   Data-point text gets a tight shadow so it stays legible against any
   gradient. */
.dh-day.is-played .dh-day-num,
.dh-day.is-played .dh-day-rank,
.dh-day.is-played .dh-day-value {
  text-shadow:
    0 1px 2px rgba(0,0,0,0.85),
    0 0 6px rgba(0,0,0,0.55);
}
.dh-day--empty {
  background: transparent;
  border-color: transparent;
}
.dh-day-num {
  grid-column: 1; grid-row: 1;
  justify-self: start;
  font-size: 10px;
  font-weight: 600;
}
.dh-day-rank {
  grid-column: 2; grid-row: 1;
  justify-self: end;
  font-size: 9px;
  font-weight: 700;
  color: rgba(255,255,255,0.7);
  letter-spacing: -0.02em;
}
.dh-day-value {
  grid-column: 1 / -1; grid-row: 2;
  align-self: center;
  font-size: 13px;
  font-weight: 800;
  color: #fff;
  letter-spacing: -0.01em;
}
/* Played day: tinted via inline `style={{ background: game.accent }}` —
   so each game gets its own gradient. Just clean up the border + add a
   top highlight to give it depth. */
.dh-day.is-played {
  border-color: rgba(255,255,255,0.22);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
}
.dh-day.is-played:hover:not(:disabled) {
  border-color: rgba(255,255,255,0.45);
  filter: brightness(1.08);
}
/* Today: extra ring so it's findable even before being played. Stacks
   with .is-played so today + played shows both. */
.dh-day.is-today {
  outline: 1.5px solid rgba(255,255,255,0.55);
  outline-offset: 1px;
}
/* Selected day: stronger purple ring; takes precedence over today/played. */
.dh-day.is-selected {
  outline: 2px solid rgba(167, 139, 250, 0.95);
  outline-offset: 1px;
}
.dh-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.78);
  margin: 0;
}
.dh-close {
  background: transparent;
  border: none;
  color: rgba(255,255,255,0.6);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 8px;
  transition: background 160ms ease, color 160ms ease;
}
.dh-close:hover { background: rgba(255,255,255,0.10); color: #fff; }
.dh-close:focus-visible {
  outline: 2px solid rgba(255,255,255,0.45);
  outline-offset: 2px;
}

.dh-state {
  text-align: center;
  padding: 24px 0;
  color: rgba(255,255,255,0.7);
  font-size: 14px;
}
.dh-error { color: #ff8585; }

.dh-empty {
  text-align: center;
  color: rgba(255,255,255,0.6);
  font-size: 14px;
  padding: 28px 12px;
  font-style: italic;
}

/* ---- Day summary ---- (info + leaderboard for the calendar's selected
   day. Replaces the older per-row history list.) */
.dh-summary {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.dh-summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
}
/* The detail row groups art (left) + game/result (middle) + play CTA
   (right) into one card-like strip. */
.dh-summary-detail {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px;
  border-radius: 14px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
}
.dh-summary-art {
  flex: 0 0 auto;
  width: 96px;
  height: 96px;
  border-radius: 14px;
  overflow: hidden;
  position: relative;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.18),
    inset 0 0 0 1px rgba(0,0,0,0.32);
}
/* Pin the inner wrapper dead-centre and let the Graphic flex-centre
   inside it. Two-level centring isolates us from each Graphic's
   internal padding/margin quirks. */
.dh-summary-art-inner {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: 100%;
  transform: translate(-50%, -50%) scale(0.6);
  transform-origin: center;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Force the Graphic's outer wrapper to fill our inner wrapper exactly,
   ignoring any internal padding so the centring stays geometric. */
.dh-summary-art-inner > * {
  width: 100% !important;
  height: 100% !important;
  padding: 0 !important;
  margin: 0 !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
}
/* Pin animations at this scale — a tile-sized spinning Graphic is
   distracting next to the result text. */
.dh-summary-art *,
.dh-summary-art *::before,
.dh-summary-art *::after {
  animation: none !important;
}
.dh-summary-text {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.dh-summary-result-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.dh-summary-play {
  flex: 0 0 auto;
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(99, 142, 255, 0.20);
  border: 1px solid rgba(99, 142, 255, 0.45);
  color: #fff;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease, transform 160ms ease;
}
.dh-summary-play:hover {
  background: rgba(99, 142, 255, 0.30);
  border-color: rgba(99, 142, 255, 0.65);
  transform: translateY(-1px);
}
.dh-summary-play-arrow {
  font-size: 14px;
  line-height: 1;
}
.dh-summary-date {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
  font-weight: 700;
}
.dh-summary-game {
  font-size: 15px;
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dh-summary-result {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}
.dh-summary-value {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 22px;
  font-weight: 800;
  color: #fff;
  letter-spacing: 0.02em;
}
.dh-summary-metric {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
  font-weight: 700;
}
.dh-summary-meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.dh-summary-rank {
  font-size: 11px;
  font-weight: 700;
  color: rgba(255,255,255,0.85);
  font-variant-numeric: tabular-nums;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(99, 102, 241, 0.20);
  border: 1px solid rgba(99, 102, 241, 0.35);
}
.dh-summary-points {
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.18);
  color: #fff;
}
.dh-summary-points.is-bonus {
  background: rgba(250, 204, 21, 0.16);
  border-color: rgba(250, 204, 21, 0.45);
  color: #fef9c3;
  text-shadow: 0 0 8px rgba(250, 204, 21, 0.35);
}
.dh-summary--empty .dh-summary-message {
  font-size: 13px;
  color: rgba(255,255,255,0.55);
  font-style: italic;
  margin-top: 4px;
}

@media (max-width: 480px) {
  .dh-panel { padding: 14px; }
  .dh-summary-game  { font-size: 14px; }
  .dh-summary-value { font-size: 19px; }
}

.daily-streak {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.14);
  color: rgba(255,255,255,0.92);
  font-size: 12px;
  line-height: 1;
  /* Button reset — the chip is now interactive (opens the calendar). */
  appearance: none;
  font-family: inherit;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease, transform 200ms ease;
}
.daily-streak:hover {
  background: rgba(255,255,255,0.10);
  border-color: rgba(255,255,255,0.24);
  transform: translateY(-1px);
}
.daily-streak:focus-visible {
  outline: 2px solid rgba(99,142,255,0.55);
  outline-offset: 3px;
}

.daily-streak-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
}

.daily-streak-label {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10px;
  font-weight: 600;
  color: rgba(255,255,255,0.6);
}

.daily-streak-value {
  font-size: 16px;
  font-weight: 700;
  color: rgba(255,255,255,0.98);
  font-variant-numeric: tabular-nums;
}

.daily-streak-unit {
  font-size: 11px;
  color: rgba(255,255,255,0.7);
}

.daily-streak-sep {
  color: rgba(255,255,255,0.3);
  font-size: 14px;
}
.wordle-graphic {
  display: flex; align-items: center; justify-content: center;
  padding: 0 14px;
}

.wg-row {
  display: flex;
  gap: 10px;
  align-items: center;
}

/* One flat tile per letter — no front/back faces. The reveal flip is a
   one-shot animation that ends at this resting pose so the static state
   is correct even when the animation never runs (e.g. mobile, where
   .card-art's animation kill applies). */
.wg-tile {
  width: 72px;
  height: 72px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 30px;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
  background: var(--wg-color);
  border: 1px solid var(--wg-border);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 0 22px var(--wg-glow);
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
  animation: wg-flip-reveal 0.7s cubic-bezier(.4,.05,.2,1) backwards;
}

/* Edge-on at 50%, swap the bg/border at 51%, flip back to flat. Ends at
   the same state as the base rule above. `animation-fill-mode: backwards`
   shows the 0% (blank) state during the staggered delay. */
@keyframes wg-flip-reveal {
  0% {
    transform: rotateX(0deg);
    background: rgba(255,255,255,0.22);
    border-color: rgba(255,255,255,0.4);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.5),
      inset 0 -10px 20px rgba(0,0,0,0.18);
  }
  50% {
    transform: rotateX(90deg);
    background: rgba(255,255,255,0.22);
    border-color: rgba(255,255,255,0.4);
    box-shadow: none;
  }
  51% {
    transform: rotateX(90deg);
    background: var(--wg-color);
    border-color: var(--wg-border);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.45),
      0 0 22px var(--wg-glow);
  }
  100% {
    transform: rotateX(0deg);
    background: var(--wg-color);
    border-color: var(--wg-border);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.45),
      0 0 22px var(--wg-glow);
  }
}

.wg-correct {
  --wg-color:  rgba(83,141,78,0.95);
  --wg-border: rgba(160,255,160,0.55);
  --wg-glow:   rgba(83,200,90,0.6);
}
.wg-present {
  --wg-color:  rgba(214,168,47,0.95);
  --wg-border: rgba(255,220,140,0.55);
  --wg-glow:   rgba(255,200,80,0.55);
}
.wg-absent  {
  --wg-color:  rgba(60,60,62,0.92);
  --wg-border: rgba(255,255,255,0.10);
  --wg-glow:   rgba(0,0,0,0.4);
}

/* GameSelector.css disables every animation inside .card-art / .daily-card-art
   on phones to avoid continuous repaint cost. The Wordle reveal is one-shot
   (not a loop) so it doesn't have that cost — re-enable it specifically. */
@media (max-width: 480px) {
  .wg-tile { width: 56px; height: 56px; }
  .wg-tile span { font-size: 24px; }
  .card-art .wg-tile,
  .daily-card-art .wg-tile {
    animation: wg-flip-reveal 0.7s cubic-bezier(.4,.05,.2,1) backwards !important;
  }
}
.cw-graphic {
  display: flex; align-items: center; justify-content: center;
  padding: 0 14px;
}

.cwg-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 56px);
  grid-template-rows: repeat(3, 56px);
  gap: 8px;
}

.cwg-cell {
  position: relative;
  border-radius: 12px;
  background: rgba(255,255,255,0.15);
  border: 1px solid rgba(255,255,255,0.35);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 4px 10px rgba(0,0,0,0.22);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  animation: cwg-cell 6s ease-in-out infinite;
  animation-delay: inherit;
}
.cwg-cell::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(160deg, rgba(255,255,255,0.5), rgba(255,255,255,0) 50%);
  pointer-events: none;
}
.cwg-cell::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  border: 2px solid transparent;
  animation: cwg-cursor 6s ease-in-out infinite;
  animation-delay: inherit;
  pointer-events: none;
}

.cwg-letter {
  position: relative; z-index: 1;
  font-size: 26px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5);
  opacity: 0;
  -webkit-transform: scale(0.4) rotate(-6deg);
  transform: scale(0.4) rotate(-6deg);
  animation: cwg-letter 6s cubic-bezier(.2,.9,.3,1.4) infinite;
  animation-delay: inherit;
}

@keyframes cwg-cursor {
  0%, 4%    { border-color: transparent; box-shadow: 0 0 0 rgba(99,142,255,0); }
  5%        { border-color: rgba(180,210,255,0.9); box-shadow: 0 0 18px rgba(99,142,255,0.85); }
  10%, 100% { border-color: transparent; box-shadow: 0 0 0 rgba(99,142,255,0); }
}

@keyframes cwg-letter {
  0%, 8%    { opacity: 0; -webkit-transform: scale(0.4) rotate(-6deg); transform: scale(0.4) rotate(-6deg); }
  16%       { opacity: 1; -webkit-transform: scale(1.15) rotate(0deg); transform: scale(1.15) rotate(0deg); }
  22%       { opacity: 1; -webkit-transform: scale(1) rotate(0deg);    transform: scale(1) rotate(0deg); }
  82%       { opacity: 1; -webkit-transform: scale(1) rotate(0deg);    transform: scale(1) rotate(0deg); }
  92%       { opacity: 0; -webkit-transform: scale(0.85) rotate(0deg); transform: scale(0.85) rotate(0deg); }
  100%      { opacity: 0; -webkit-transform: scale(0.4);               transform: scale(0.4); }
}

@keyframes cwg-cell {
  0%, 70%   {
    background: rgba(255,255,255,0.15);
    border-color: rgba(255,255,255,0.35);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.45),
      0 4px 10px rgba(0,0,0,0.22);
  }
  80%, 88%  {
    background: rgba(83,141,78,0.85);
    border-color: rgba(160,255,160,0.7);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.55),
      0 0 24px rgba(83,200,90,0.7);
  }
  100% {
    background: rgba(255,255,255,0.15);
    border-color: rgba(255,255,255,0.35);
  }
}

@media (max-width: 480px) {
  .cwg-grid {
    grid-template-columns: repeat(3, 44px);
    grid-template-rows: repeat(3, 44px);
    gap: 6px;
  }
  .cwg-letter { font-size: 20px; }
}
.hm-graphic {
  display: flex; align-items: center; justify-content: center;
  height: 100%;
  padding: 8px;
}
.hmg-svg {
  width: 70%; max-width: 180px; height: 100%;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
}
.hmg-pole {
  stroke: rgba(255,255,255,0.7);
  stroke-width: 5;
  stroke-linecap: round;
  fill: none;
}
.hmg-fig {
  stroke: #fff;
  stroke-width: 5;
  stroke-linecap: round;
  fill: none;
  opacity: 0;
  animation: hmg-cycle 6s ease-in-out infinite;
}
.hmg-d1 { animation-delay: 0.0s; }
.hmg-d2 { animation-delay: 0.4s; }
.hmg-d3 { animation-delay: 0.8s; }
.hmg-d4 { animation-delay: 1.2s; }
.hmg-d5 { animation-delay: 1.6s; }
.hmg-d6 { animation-delay: 2.0s; }
@keyframes hmg-cycle {
  0%, 5%       { opacity: 0; transform: scale(0.7); transform-origin: center; }
  20%, 70%     { opacity: 1; transform: scale(1); }
  85%, 100%    { opacity: 0; transform: scale(0.7); }
}
.sk-graphic {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 14px;
  box-sizing: border-box;
}
.skg-grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(9, 1fr);
  gap: 1px;
  width: 100%;
  max-width: 180px;
  aspect-ratio: 1 / 1;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
}
.skg-cell {
  background: rgba(255,255,255,0.12);
  border: 1px solid rgba(255,255,255,0.18);
  color: #fff;
  font-weight: 800;
  font-size: 11px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 2px;
  animation: skg-twinkle 4s ease-in-out infinite;
}
.skg-cell.empty {
  background: rgba(255,255,255,0.05);
  border-color: rgba(255,255,255,0.10);
}
.skg-cell.br { border-right-color: rgba(255,255,255,0.55); border-right-width: 2px; }
.skg-cell.bb { border-bottom-color: rgba(255,255,255,0.55); border-bottom-width: 2px; }
@keyframes skg-twinkle {
  0%, 100% { background: rgba(255,255,255,0.12); }
  50%      { background: rgba(255,255,255,0.22); }
}
.skg-cell.empty { animation: none; }
.mem-graphic {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 14px;
  box-sizing: border-box;
  -webkit-perspective: 800px;
  perspective: 800px;
}
.memg-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 10px;
  width: 100%;
  max-width: 220px;
  aspect-ratio: 3 / 2;
}
.memg-card {
  position: relative;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  animation: memg-flip 4.6s ease-in-out infinite;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
}
.memg-face {
  position: absolute; inset: 0;
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 30px;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  border: 1px solid rgba(255,255,255,0.4);
}
.memg-back {
  background: linear-gradient(135deg, rgba(99,142,255,0.7), rgba(180,90,220,0.7));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45);
}
.memg-back::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background:
    radial-gradient(50% 50% at 30% 30%, rgba(255,255,255,0.5), transparent 60%),
    repeating-linear-gradient(45deg, rgba(255,255,255,0.06) 0 6px, transparent 6px 12px);
}
.memg-front {
  background: rgba(255,255,255,0.22);
  -webkit-transform: rotateY(180deg);
  transform: rotateY(180deg);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
}
@keyframes memg-flip {
  0%, 12%   { -webkit-transform: rotateY(0deg);   transform: rotateY(0deg); }
  35%, 75%  { -webkit-transform: rotateY(180deg); transform: rotateY(180deg); }
  100%      { -webkit-transform: rotateY(360deg); transform: rotateY(360deg); }
}
.ag-graphic {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 14px;
  box-sizing: border-box;
}
.agg-orbit {
  position: relative;
  width: 160px; height: 160px;
  animation: agg-spin 12s linear infinite;
}
.agg-letter {
  position: absolute;
  top: 50%; left: 50%;
  width: 42px; height: 42px;
  margin: -21px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 800;
  color: #fff;
  background: rgba(255,255,255,0.18);
  border: 1px solid rgba(255,255,255,0.45);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.5),
    0 6px 16px rgba(0,0,0,0.3);
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
  transform:
    rotate(calc(var(--i) * (360deg / var(--n))))
    translate(60px)
    rotate(calc(var(--i) * (-360deg / var(--n))));
  animation: agg-counterspin 12s linear infinite;
}
.agg-core {
  position: absolute;
  top: 50%; left: 50%;
  width: 36px; height: 36px;
  margin: -18px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.6), rgba(99,142,255,0.5));
  box-shadow: 0 0 20px rgba(255,255,255,0.3);
}
@keyframes agg-spin {
  to { transform: rotate(360deg); }
}
@keyframes agg-counterspin {
  to { transform:
    rotate(calc(var(--i) * (360deg / var(--n)) - 360deg))
    translate(60px)
    rotate(calc(var(--i) * (-360deg / var(--n)) + 360deg)); }
}
.ws-graphic {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 12px;
  box-sizing: border-box;
}
.wsg-grid {
  display: grid;
  width: 100%;
  max-width: 200px;
  aspect-ratio: 1 / 1;
  gap: 3px;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
}
.wsg-cell {
  background: rgba(255,255,255,0.10);
  border: 1px solid rgba(255,255,255,0.18);
  color: #fff;
  font-weight: 800;
  font-size: 11px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 4px;
}
.wsg-cell.hi {
  background: rgba(99,142,255,0.55);
  border-color: rgba(180,210,255,0.85);
  animation: wsg-pulse 3.4s ease-in-out infinite;
}
.wsg-cell.hi-1 { animation-delay: 0s; }
.wsg-cell.hi-2 { animation-delay: 0.6s; }
.wsg-cell.hi-3 { animation-delay: 1.2s; }
.wsg-cell.hi-4 { animation-delay: 1.8s; }
@keyframes wsg-pulse {
  0%, 100% {
    background: rgba(99,142,255,0.32);
  }
  50% {
    background: rgba(83,141,78,0.55);
    border-color: rgba(160,255,160,0.5);
  }
}
.bg-graphic {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 14px;
  box-sizing: border-box;
}
.bgg-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(4, 1fr);
  gap: 6px;
  width: 100%;
  max-width: 200px;
  aspect-ratio: 1 / 1;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
}
.bgg-cell {
  background: rgba(255,255,255,0.18);
  border: 1px solid rgba(255,255,255,0.4);
  color: #fff;
  font-weight: 800;
  font-size: 14px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45);
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
.bgg-cell.on {
  background: rgba(99,142,255,0.7);
  border-color: rgba(180,210,255,0.85);
  transform: scale(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.55),
    0 0 14px rgba(99,142,255,0.5);
}
.cn-graphic {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 14px;
  box-sizing: border-box;
}
.cng-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(4, 1fr);
  gap: 4px;
  width: 100%;
  max-width: 220px;
  aspect-ratio: 1.4 / 1;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
}
.cng-cell {
  display: flex; align-items: center; justify-content: center;
  font-size: 9px;
  font-weight: 800;
  color: #1a1a1a;
  border-radius: 4px;
  letter-spacing: 0.04em;
  background: rgba(255,255,255,0.18);
  animation: cng-reveal 5s ease-in-out infinite;
}
.cng-cell.c-yellow { background: linear-gradient(135deg, #f9e08c, #f3c13a); }
.cng-cell.c-green  { background: linear-gradient(135deg, #aede9a, #6fbf73); }
.cng-cell.c-blue   { background: linear-gradient(135deg, #9fc5ff, #5a93ff); color: #0d1730; }
.cng-cell.c-purple { background: linear-gradient(135deg, #cda1ff, #9b6fec); color: #1a1030; }
@keyframes cng-reveal {
  0%, 5%   { transform: scale(0.85); opacity: 0.4; }
  20%, 75% { transform: scale(1);    opacity: 1; }
  90%, 100%{ transform: scale(0.95); opacity: 0.6; }
}
.brk-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  box-sizing: border-box;
}

.brk-wall {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
  max-width: 220px;
}
.brk-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
}
.brk-brick {
  height: 12px;
  border-radius: 3px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45),
              inset 0 -2px 0 rgba(0,0,0,0.15);
  animation: brk-pulse 3.6s ease-in-out infinite;
}

.brk-paddle {
  position: absolute;
  bottom: 24px;
  width: 70px;
  height: 8px;
  border-radius: 4px;
  background: #e0e7ff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6);
  animation: brk-slide 3.6s ease-in-out infinite;
}

.brk-ball {
  position: absolute;
  bottom: 36px;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 0 8px rgba(255,255,255,0.6);
  animation: brk-bounce 3.6s ease-in-out infinite;
}

@keyframes brk-pulse {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50% { transform: translateY(-2px); opacity: 0.85; }
}

@keyframes brk-slide {
  0%, 100% { transform: translateX(-30px); }
  50% { transform: translateX(30px); }
}

@keyframes brk-bounce {
  0% { transform: translate(-30px, 0); }
  25% { transform: translate(0, -40px); }
  50% { transform: translate(30px, 0); }
  75% { transform: translate(0, -40px); }
  100% { transform: translate(-30px, 0); }
}
.snk-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  box-sizing: border-box;
}

.snk-board {
  position: relative;
  width: 100%;
  max-width: 200px;
  aspect-ratio: 1 / 1;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 14px;
  background-image:
    linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
  background-size: 20% 20%;
}

.snk-seg, .snk-seg-head, .snk-food {
  position: absolute;
  width: 18%;
  height: 18%;
  border-radius: 5px;
}

.snk-seg-1 { background: hsl(160, 65%, 45%); }
.snk-seg-2 { background: hsl(160, 65%, 50%); }
.snk-seg-3 { background: hsl(160, 65%, 55%); }
.snk-seg-4 { background: hsl(160, 65%, 60%); }
.snk-seg-head { background: #bef264; box-shadow: 0 0 10px rgba(190,242,100,0.5); }

.snk-seg, .snk-seg-head { animation: snk-march 4s linear infinite; }
.snk-seg-1    { animation-delay: 0.00s; }
.snk-seg-2    { animation-delay: 0.10s; }
.snk-seg-3    { animation-delay: 0.20s; }
.snk-seg-4    { animation-delay: 0.30s; }
.snk-seg-head { animation-delay: 0.40s; }

@keyframes snk-march {
  0%   { left: 8%;  top: 60%; }
  20%  { left: 28%; top: 60%; }
  40%  { left: 28%; top: 28%; }
  60%  { left: 60%; top: 28%; }
  80%  { left: 60%; top: 70%; }
  100% { left: 8%;  top: 60%; }
}

.snk-food {
  background: radial-gradient(circle, #f87171 60%, #b91c1c 100%);
  border-radius: 999px;
  box-shadow: 0 0 8px rgba(248,113,113,0.6);
  left: 74%;
  top: 14%;
  animation: snk-pulse 1.6s ease-in-out infinite;
}

@keyframes snk-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.18); }
}
.inv-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  padding: 14px;
  box-sizing: border-box;
  overflow: hidden;
  background:
    radial-gradient(circle at 20% 18%, rgba(255,255,255,0.7) 0 1px, transparent 2px),
    radial-gradient(circle at 75% 28%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 45% 8%, rgba(255,255,255,0.6) 0 1px, transparent 2px),
    radial-gradient(circle at 88% 12%, rgba(255,255,255,0.4) 0 1px, transparent 2px);
}

.inv-row {
  position: absolute;
  left: 14%;
  right: 14%;
  display: flex;
  justify-content: space-between;
  animation: inv-march 2.4s steps(2) infinite;
}
.inv-row-1 { top: 24%; }
.inv-row-2 { top: 44%; }

.inv-alien {
  width: 14%;
  aspect-ratio: 1.4 / 1;
  background: currentColor;
  -webkit-mask: var(--inv-mask) center / contain no-repeat;
  mask: var(--inv-mask) center / contain no-repeat;
}

.inv-a {
  color: #22d3ee;
  --inv-mask: radial-gradient(circle at 30% 50%, #000 18%, transparent 20%),
              radial-gradient(circle at 70% 50%, #000 18%, transparent 20%),
              linear-gradient(#000, #000);
  background:
    radial-gradient(circle at 50% 60%, #22d3ee 60%, transparent 62%),
    radial-gradient(circle at 30% 40%, #f472b6 22%, transparent 24%),
    radial-gradient(circle at 70% 40%, #f472b6 22%, transparent 24%);
  -webkit-mask: none;
  mask: none;
  border-radius: 30% 30% 18% 18%;
  box-shadow: inset 0 -3px 0 rgba(0,0,0,0.25);
}

.inv-b {
  color: #a78bfa;
  background:
    radial-gradient(circle at 50% 55%, #a78bfa 55%, transparent 60%),
    radial-gradient(circle at 35% 38%, #fde047 18%, transparent 22%),
    radial-gradient(circle at 65% 38%, #fde047 18%, transparent 22%);
  border-radius: 50% 50% 26% 26%;
  box-shadow: inset 0 -3px 0 rgba(0,0,0,0.25);
}

@keyframes inv-march {
  0%   { transform: translateX(0); }
  50%  { transform: translateX(-8%); }
  100% { transform: translateX(0); }
}

.inv-ship {
  position: absolute;
  left: 50%;
  bottom: 12%;
  width: 22%;
  height: 9%;
  transform: translateX(-50%);
  background: linear-gradient(180deg, #67e8f9 0%, #0e7490 100%);
  border-radius: 6px 6px 2px 2px;
  box-shadow: 0 0 12px rgba(34,211,238,0.4);
  animation: inv-glide 3s ease-in-out infinite;
}
.inv-ship::before {
  content: '';
  position: absolute;
  top: -22%;
  left: 50%;
  width: 14%;
  height: 30%;
  transform: translateX(-50%);
  background: #67e8f9;
  border-radius: 2px;
  box-shadow: 0 0 6px rgba(103,232,249,0.7);
}

@keyframes inv-glide {
  0%, 100% { transform: translateX(-50%); }
  50%      { transform: translateX(-30%); }
}

.inv-shot {
  position: absolute;
  width: 3px;
  height: 12%;
  left: 50%;
  top: 56%;
  background: #fde047;
  border-radius: 2px;
  box-shadow: 0 0 6px rgba(253,224,71,0.7);
  animation: inv-laser 1.4s linear infinite;
}

@keyframes inv-laser {
  0%   { top: 64%; opacity: 0; }
  20%  { opacity: 1; }
  90%  { top: 24%; opacity: 1; }
  100% { top: 22%; opacity: 0; }
}
.ast-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background:
    radial-gradient(circle at 22% 18%, rgba(255,255,255,0.7) 0 1px, transparent 2px),
    radial-gradient(circle at 70% 14%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 44% 8%,  rgba(255,255,255,0.6) 0 1px, transparent 2px),
    radial-gradient(circle at 86% 60%, rgba(255,255,255,0.45) 0 1px, transparent 2px),
    radial-gradient(circle at 18% 70%, rgba(255,255,255,0.45) 0 1px, transparent 2px),
    radial-gradient(circle at 60% 82%, rgba(255,255,255,0.5) 0 1px, transparent 2px);
}

.ast-rock {
  position: absolute;
  border-radius: 38% 62% 56% 44% / 50% 40% 60% 50%;
  background: linear-gradient(135deg, rgba(203,213,245,0.45) 0%, rgba(99,142,255,0.18) 100%);
  border: 2px solid rgba(203,213,245,0.7);
  box-shadow: inset 0 -3px 0 rgba(0,0,0,0.18);
  animation: ast-drift 12s linear infinite;
}
.ast-rock-1 { width: 28%; aspect-ratio: 1.1/1; left: 14%; top: 18%; animation-duration: 14s; }
.ast-rock-2 { width: 18%; aspect-ratio: 1/1; left: 62%; top: 36%; animation-duration: 9s; animation-direction: reverse; }
.ast-rock-3 { width: 14%; aspect-ratio: 1.2/1; left: 38%; top: 64%; animation-duration: 11s; }

@keyframes ast-drift {
  0%   { transform: translate(0, 0) rotate(0deg); }
  50%  { transform: translate(6%, -4%) rotate(180deg); }
  100% { transform: translate(0, 0) rotate(360deg); }
}

.ast-ship {
  position: absolute;
  left: 50%;
  bottom: 18%;
  width: 0;
  height: 0;
  transform: translateX(-50%) rotate(0deg);
  border-left: 9px solid transparent;
  border-right: 9px solid transparent;
  border-bottom: 22px solid #bef264;
  filter: drop-shadow(0 0 6px rgba(190,242,100,0.55));
  animation: ast-spin 6s linear infinite;
  transform-origin: 50% 70%;
}

@keyframes ast-spin {
  0%   { transform: translateX(-50%) rotate(0deg); }
  100% { transform: translateX(-50%) rotate(360deg); }
}

.ast-laser {
  position: absolute;
  width: 3px;
  height: 12%;
  left: 50%;
  bottom: 32%;
  transform: translateX(-50%);
  background: #fde047;
  border-radius: 2px;
  box-shadow: 0 0 6px rgba(253,224,71,0.7);
  animation: ast-shoot 1.6s linear infinite;
  opacity: 0;
}

@keyframes ast-shoot {
  0%   { transform: translate(-50%, 0); opacity: 0; }
  20%  { opacity: 1; }
  90%  { transform: translate(-50%, -160%); opacity: 1; }
  100% { transform: translate(-50%, -180%); opacity: 0; }
}
.sq-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background:
    radial-gradient(circle at 18% 18%, rgba(255,255,255,0.6) 0 1px, transparent 2px),
    radial-gradient(circle at 70% 14%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 44% 8%,  rgba(255,255,255,0.55) 0 1px, transparent 2px),
    radial-gradient(circle at 86% 60%, rgba(255,255,255,0.45) 0 1px, transparent 2px),
    radial-gradient(circle at 18% 70%, rgba(255,255,255,0.45) 0 1px, transparent 2px);
}

.sq-formation {
  position: absolute;
  width: 16%;
  aspect-ratio: 1.4 / 1;
  border-radius: 30% 30% 14% 14%;
  animation: sq-sway 3.4s ease-in-out infinite;
}
.sq-f-1 { left: 24%; top: 22%; background: linear-gradient(135deg, #f472b6 0%, #ec4899 100%); }
.sq-f-2 { left: 60%; top: 22%; background: linear-gradient(135deg, #fde047 0%, #f59e0b 100%); animation-delay: 0.3s; }
.sq-f-3 { left: 24%; top: 40%; background: linear-gradient(135deg, #22d3ee 0%, #0ea5e9 100%); animation-delay: 0.6s; }
.sq-f-4 { left: 60%; top: 40%; background: linear-gradient(135deg, #a78bfa 0%, #6366f1 100%); animation-delay: 0.9s; }

@keyframes sq-sway {
  0%, 100% { transform: translate(0,0); }
  50%      { transform: translate(8%, 0); }
}

.sq-diver {
  position: absolute;
  width: 14%;
  aspect-ratio: 1.4 / 1;
  border-radius: 30% 30% 14% 14%;
  background: linear-gradient(135deg, #f472b6 0%, #ec4899 100%);
  box-shadow: 0 0 14px rgba(244,114,182,0.55);
  animation: sq-dive 3s ease-in-out infinite;
}

@keyframes sq-dive {
  0%   { left: 30%; top: 22%; transform: rotate(0deg); }
  50%  { left: 60%; top: 56%; transform: rotate(40deg); }
  100% { left: 78%; top: 80%; transform: rotate(80deg); opacity: 0; }
}

.sq-ship {
  position: absolute;
  left: 50%;
  bottom: 12%;
  width: 22%;
  height: 9%;
  transform: translateX(-50%);
  background: linear-gradient(180deg, #67e8f9 0%, #0e7490 100%);
  border-radius: 6px 6px 2px 2px;
  box-shadow: 0 0 12px rgba(34,211,238,0.4);
}
.sq-ship::before {
  content: '';
  position: absolute;
  top: -22%;
  left: 50%;
  width: 14%;
  height: 30%;
  transform: translateX(-50%);
  background: #67e8f9;
  border-radius: 2px;
  box-shadow: 0 0 6px rgba(103,232,249,0.7);
}
.df-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background:
    radial-gradient(circle at 16% 18%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 78% 28%, rgba(255,255,255,0.35) 0 1px, transparent 2px),
    radial-gradient(circle at 50% 8%, rgba(255,255,255,0.45) 0 1px, transparent 2px),
    linear-gradient(180deg, #052e1b 0%, #170b13 60%, #2a0712 100%);
}

.df-mountains {
  position: absolute;
  left: 0; right: 0;
  bottom: 18%;
  height: 16%;
  background:
    linear-gradient(135deg, transparent 50%, rgba(190,242,100,0.5) 50%) 0 0/22% 100%,
    linear-gradient(45deg, transparent 50%, rgba(190,242,100,0.5) 50%) 11% 0/22% 100%;
  background-color: transparent;
}

.df-human {
  position: absolute;
  bottom: 10%;
  width: 6px;
  height: 14px;
  background: #fde68a;
  border-radius: 2px;
}
.df-human::before {
  content: '';
  position: absolute;
  top: -5px;
  left: 0;
  width: 6px;
  height: 6px;
  background: #fde68a;
  border-radius: 50%;
}
.df-human-1 { left: 20%; }
.df-human-2 { left: 76%; }

.df-lander {
  position: absolute;
  width: 12%;
  aspect-ratio: 2 / 1;
  border-radius: 50%;
  left: 60%;
  top: 28%;
  background: linear-gradient(180deg, #fef3c7 0%, #ef4444 100%);
  box-shadow: 0 0 12px rgba(239,68,68,0.55);
  animation: df-hover 2.6s ease-in-out infinite;
}

@keyframes df-hover {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(-12%, 6%); }
}

.df-ship {
  position: absolute;
  width: 22%;
  height: 6%;
  left: 14%;
  top: 50%;
  background: linear-gradient(180deg, #bef264 0%, #65a30d 100%);
  clip-path: polygon(100% 50%, 80% 0%, 0% 30%, 0% 70%, 80% 100%);
  filter: drop-shadow(0 0 8px rgba(190,242,100,0.55));
  animation: df-glide 4s ease-in-out infinite;
}

@keyframes df-glide {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(8%, -4%); }
}

.df-laser {
  position: absolute;
  height: 2px;
  width: 18%;
  left: 36%;
  top: 53%;
  background: #fde047;
  box-shadow: 0 0 6px rgba(253,224,71,0.7);
  animation: df-shoot 1.6s linear infinite;
}

@keyframes df-shoot {
  0%   { transform: translateX(0); opacity: 0; }
  20%  { opacity: 1; }
  90%  { transform: translateX(80%); opacity: 1; }
  100% { transform: translateX(100%); opacity: 0; }
}
.ch-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: linear-gradient(180deg, #0a0c20 0%, #100922 100%);
}

.ch-pellet {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #fde68a;
  box-shadow: 0 0 4px rgba(253,230,138,0.6);
}
.ch-p-1 { left: 18%; top: 36%; }
.ch-p-2 { left: 30%; top: 36%; }
.ch-p-3 { left: 42%; top: 36%; }
.ch-p-4 { left: 54%; top: 36%; }
.ch-p-5 { left: 66%; top: 36%; }
.ch-p-6 { left: 78%; top: 36%; }

.ch-power {
  position: absolute;
  left: 84%;
  top: 28%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #fde047;
  box-shadow: 0 0 8px rgba(253,224,71,0.8);
  animation: ch-pulse 1.2s ease-in-out infinite;
}

@keyframes ch-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.4); }
}

.ch-ghost {
  position: absolute;
  width: 22%;
  aspect-ratio: 1 / 1;
  border-radius: 50% 50% 12% 12%;
  bottom: 36%;
}
.ch-g-r {
  left: 16%;
  background: linear-gradient(180deg, #ef4444 0%, #b91c1c 100%);
  animation: ch-bob 1.4s ease-in-out infinite;
}
.ch-g-c {
  left: 64%;
  background: linear-gradient(180deg, #22d3ee 0%, #0e7490 100%);
  animation: ch-bob 1.4s ease-in-out infinite;
  animation-delay: 0.4s;
}
.ch-ghost::after {
  content: '';
  position: absolute;
  top: 30%;
  left: 22%;
  right: 22%;
  height: 25%;
  background:
    radial-gradient(circle at 25% 50%, #fff 30%, transparent 32%),
    radial-gradient(circle at 75% 50%, #fff 30%, transparent 32%);
}

@keyframes ch-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6%); }
}

.ch-chomp {
  position: absolute;
  left: 40%;
  top: 36%;
  width: 22%;
  aspect-ratio: 1 / 1;
  background: #facc15;
  border-radius: 50%;
  filter: drop-shadow(0 0 8px rgba(250,204,21,0.55));
  animation: ch-mouth 0.6s ease-in-out infinite;
  -webkit-mask:
    radial-gradient(circle at 50% 50%, #000 50%, transparent 51%);
  mask:
    radial-gradient(circle at 50% 50%, #000 50%, transparent 51%);
}

@keyframes ch-mouth {
  0%, 100% { clip-path: polygon(50% 50%, 100% 30%, 100% 70%); }
  50%      { clip-path: polygon(50% 50%, 100% 50%, 100% 50%); }
}
.stk-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: linear-gradient(180deg, #0a0e22 0%, #1a0a2e 100%);
}

.stk-cell {
  position: absolute;
  width: 14%;
  aspect-ratio: 1 / 1;
  border-radius: 4px;
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.32),
              inset 0 -2px 0 rgba(0,0,0,0.22);
}

.stk-c-blue   { background: #60a5fa; }
.stk-c-red    { background: #f87171; }
.stk-c-yellow { background: #fde047; }
.stk-c-green  { background: #4ade80; }
.stk-c-purple { background: #a78bfa; }
.stk-c-orange { background: #fb923c; }

.stk-falling {
  position: absolute;
  width: 14%;
  aspect-ratio: 1 / 1;
  border-radius: 4px;
  background: #22d3ee;
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.32),
              inset 0 -2px 0 rgba(0,0,0,0.22),
              0 0 8px rgba(34,211,238,0.4);
  animation: stk-fall 2.4s ease-in-out infinite;
}
.stk-f-1 { left: 16%; animation-delay: 0s; }
.stk-f-2 { left: 32%; animation-delay: 0s; }
.stk-f-3 { left: 48%; animation-delay: 0s; }
.stk-f-4 { left: 64%; animation-delay: 0s; }

@keyframes stk-fall {
  0%   { top: -16%; }
  60%  { top: 38%; }
  62%  { top: 38%; }
  100% { top: 38%; }
}
.cb-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background:
    radial-gradient(ellipse at 30% 0%, rgba(56,189,248,0.18) 0%, transparent 60%),
    linear-gradient(180deg, #0a1226 0%, #0e1730 100%);
}

.cb-line {
  position: absolute;
  left: 8%; right: 8%;
  top: 16%;
  height: 0;
  border-top: 2px dashed rgba(248,113,113,0.85);
}

.cb-ball {
  position: absolute;
  width: 22%;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  box-shadow:
    inset -4px -6px 8px rgba(0,0,0,0.35),
    inset 4px 4px 8px rgba(255,255,255,0.4),
    0 4px 8px rgba(0,0,0,0.25);
}

.cb-ball-g {
  background: radial-gradient(circle at 30% 30%, #4ade80 0%, #16a34a 70%, #166534 100%);
}
.cb-ball-y {
  background: radial-gradient(circle at 30% 30%, #fef08a 0%, #facc15 70%, #a16207 100%);
}

/* Three greens line up at bottom, pulse, then fade as the merged yellow
   floats up in their place. */
.cb-ball-1 { left: 18%; bottom: 22%; animation: cb-pulse 2.4s ease-in-out infinite; }
.cb-ball-2 { left: 40%; bottom: 22%; animation: cb-pulse 2.4s ease-in-out infinite; animation-delay: 0.15s; }
.cb-ball-3 { left: 62%; bottom: 22%; animation: cb-pulse 2.4s ease-in-out infinite; animation-delay: 0.3s; }

@keyframes cb-pulse {
  0%, 50%   { transform: scale(1); opacity: 1; }
  70%       { transform: scale(1.08); opacity: 1; }
  85%       { transform: scale(0.6); opacity: 0; }
  100%      { transform: scale(0.6); opacity: 0; }
}

.cb-ball-merge {
  left: 40%;
  bottom: 22%;
  animation: cb-merge 2.4s ease-in-out infinite;
  opacity: 0;
}

@keyframes cb-merge {
  0%, 80%   { transform: scale(0.4); opacity: 0; }
  90%       { transform: scale(1.1); opacity: 1; }
  100%      { transform: scale(1) translateY(-30%); opacity: 1; }
}
.rg-graphic {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 14px;
  box-sizing: border-box;
}

.rg-ring {
  position: relative;
  width: 120px;
  height: 120px;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.35));
}

.rg-letter {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 22px;
  height: 22px;
  margin-left: -11px;
  margin-top: -11px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 800;
  color: #fff;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 50%;
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
  transform:
    rotate(var(--rg-angle))
    translateY(-46px)
    rotate(calc(-1 * var(--rg-angle)));
}

.rg-letter-current {
  background: linear-gradient(160deg, #fde047 0%, #f59e0b 100%);
  border-color: rgba(255,255,255,0.7);
  color: #1f1300;
  text-shadow: none;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    0 0 12px rgba(253,224,71,0.55);
  animation: rg-pulse 1.8s ease-in-out infinite;
}

@keyframes rg-pulse {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 0 10px rgba(253,224,71,0.4); }
  50%      { box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 0 18px rgba(253,224,71,0.8); }
}
.sbg {
  display: flex; align-items: center; justify-content: center;
  padding: 4px 12px;
}

/* Pointy-top regular hexagons, sized so the 6-around-1 cluster reads as a
   flower at thumbnail size. Matches in-game proportions (H ≈ W × 1.155 and
   rows overlap by H/4) just shrunk for the card. */
.sbg-honeycomb {
  --sbg-cell-w: 44px;
  --sbg-cell-h: 51px;
  --sbg-row-overlap: 13px; /* H/4 */
  display: flex; flex-direction: column; align-items: center;
}
.sbg-row { display: flex; gap: 0; }
.sbg-row + .sbg-row {
  margin-top: calc(-1 * var(--sbg-row-overlap));
}

.sbg-hex {
  width: var(--sbg-cell-w);
  height: var(--sbg-cell-h);
  position: relative;
  filter: drop-shadow(0 4px 10px rgba(0,0,0,0.28));
}
.sbg-hex-face {
  position: absolute; inset: 0;
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.28), rgba(255,255,255,0.08));
  border: 1px solid rgba(255,255,255,0.22);
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  font-weight: 900; font-size: 18px;
  letter-spacing: 0.04em;
  text-shadow: 0 1px 2px rgba(0,0,0,0.45);
  user-select: none;
}
.sbg-hex.is-center .sbg-hex-face {
  background: linear-gradient(180deg, #fde68a 0%, #facc15 55%, #ca8a04 100%);
  border-color: rgba(255, 240, 180, 0.85);
  color: #2a1a00;
  text-shadow: 0 1px 0 rgba(255,255,255,0.5);
}

@media (max-width: 480px) {
  .sbg-honeycomb {
    --sbg-cell-w: 38px;
    --sbg-cell-h: 44px;
    --sbg-row-overlap: 11px;
  }
  .sbg-hex-face { font-size: 16px; }
}
.bbl-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  box-sizing: border-box;
}

.bbl-grid {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  width: 100%;
  max-width: 200px;
  margin-top: -28px;
}

.bbl-row {
  display: flex;
  gap: 3px;
  justify-content: center;
}
.bbl-row--offset {
  /* Offset half a bubble for the hex layout. */
  transform: translateX(8px);
}

.bbl-bubble {
  width: 14px;
  height: 14px;
  border-radius: 999px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55),
              inset 0 -2px 0 rgba(0, 0, 0, 0.18),
              0 1px 2px rgba(0, 0, 0, 0.25);
  animation: bbl-pulse 3.6s ease-in-out infinite;
}

.bbl-launcher {
  position: absolute;
  bottom: 22px;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: #facc15;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6),
              0 2px 6px rgba(0, 0, 0, 0.4);
}

.bbl-shot {
  position: absolute;
  bottom: 56px;
  left: 50%;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  border-radius: 999px;
  background: #22c55e;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6),
              0 0 10px rgba(34, 197, 94, 0.55);
  animation: bbl-fly 2.8s ease-in-out infinite;
}

@keyframes bbl-pulse {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50%      { transform: translateY(-1px); opacity: 0.88; }
}

@keyframes bbl-fly {
  0%   { transform: translate(-22px, 0); }
  35%  { transform: translate(-2px, -36px); }
  70%  { transform: translate(18px, -10px); }
  100% { transform: translate(-22px, 0); }
}
.selector {
  width: 100%;
  max-width: 920px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  padding-top: 28px;
  animation: sel-in 380ms cubic-bezier(.2,.9,.3,1.2);
}

/* Practice view shows nine cards on a 3-col grid; collapsing the surrounding
   gap + top padding keeps the whole grid above the fold on a typical laptop
   viewport so the user doesn't have to scroll. */
.selector--practice {
  gap: 28px;
  padding-top: 6px;
}

@keyframes sel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.hero-title {
  margin: 0;
  font-size: 44px;
  font-weight: 800;
  letter-spacing: -0.02em;
  text-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.hero-sub {
  margin: 0 0 28px;
  font-size: 16px;
  color: rgba(255,255,255,0.7);
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
  width: 100%;
  perspective: 1200px;
}

/* Home view: focused hero column at a narrow width. Three rows:
   - upper 1fr: empty spacer so the daily block lands at viewport centre
   - auto:     the daily block (card + optional leaderboard)
   - lower 1fr: practice CTA, anchored to the bottom.
   Children are pinned to specific rows because auto-placement would
   otherwise drop the daily-block into row 1 and leave the bottom empty. */
.home-stack {
  width: 100%;
  max-width: 560px;
  min-height: calc(100vh - 200px);
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  align-items: stretch;
  justify-items: stretch;
}
.home-stack > .daily-block   { grid-row: 2; }
.home-stack > .practice-cta  { grid-row: 3; align-self: end; }

/* Card + leaderboard cluster: stays centred as a group within the middle
   row. Adding the leaderboard pushes the card up only as much as needed
   to keep the cluster visually balanced. */
.daily-block {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

@media (max-width: 480px) {
  .selector { padding-top: 12px; }
  .hero-title { font-size: 32px; }
  .hero-sub { font-size: 14px; margin-bottom: 18px; }
  .cards { gap: 12px; }
  .card {
    padding: 14px;
    gap: 10px;
    /* 19 stacked backdrop-filter blurs are the dominant scroll-perf cost
       on phones — each one re-samples the page behind it as the card
       moves through the viewport. Flatten to a denser translucent fill;
       the rest of the glass treatment (border + inset highlight) stays. */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: rgba(255,255,255,0.08);
  }
  .card-art { height: 150px; }
  .card-title { font-size: 18px; }
  .card-tagline { font-size: 12px; }
  /* Freeze per-card and daily-card art loops. With 19 cards each
     animating 30-50 cells via `infinite` keyframes, the continuous
     repaint cost is the second-largest mobile drain after the
     backdrop-filter stack above. Static state still reads fine — most
     animations are subtle pulses/twinkles. */
  .card-art *, .daily-card-art * { animation: none !important; }

  /* Lock the home page to exactly one viewport, regardless of phone size.
     .daily-card-art is the only flex-grow element — it absorbs whatever
     vertical space is left after the label, title, tagline, result block,
     leaderboard, and practice CTA take their natural amount. So on:
       - iPhone SE       → small art, no scroll
       - iPhone 13       → medium art
       - 15 Pro Max      → tall hero art
     With no per-device tuning. Padding and gaps stay comfortable; the
     art does all the absorbing. */
  .home-stack {
    /* 100svh is the smallest viewport variant — iOS Safari's URL bar at
       full height. Using svh (not dvh) means the page never overflows
       the visible area, even on initial load. Chrome subtracted:
       topbar (~52px) + .main padding (14 + 24 = 38px) = 90px, plus the
       bottom safe-area inset for the iOS home indicator. .main bumps
       its padding-bottom by the same env() so total page height stays
       exactly 100svh.

       `min-height` (not `height`) so the stack *aims* for one viewport
       — flex sizing on the daily card + art absorbs leftover space when
       content fits — but can grow taller and let the page scroll when
       it doesn't (e.g. long title wrapping + level-hint pill + result
       line). Pairs with App.tsx not adding `app--no-scroll` to `/`. */
    min-height: calc(100svh - 90px - env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    gap: 14px;
  }
  /* `min-height: auto` (default — don't override to 0) so the
     daily-block's content-min propagates up to .home-stack. Without
     this, an oversized daily-card stays clipped at its flex share and
     the page can't scroll. The block still fills the stack via flex:1
     in the common (fits-cleanly) case. */
  .home-stack > .daily-block { flex: 1; }
  .home-stack > .practice-cta { flex: 0 0 auto; align-self: stretch; }
  .daily-block { gap: 12px; }
  .daily-card {
    /* Drop the desktop 290px reservation; flex chain manages height now.
       `min-height: auto` (the default — don't override to 0) so when the
       text content (title + tagline + result + level hint + cta/hint)
       exceeds the card's flex allotment, the card grows past its share
       and the home-stack pushes the page taller instead of letting the
       last line spill below the painted card boundary. */
    flex: 1;
    /* Cap the card so the art doesn't balloon to dominate tall phones.
       svh tracks the smallest viewport variant, matching the .home-stack
       lock. The flex chain still lets the card shrink below this on
       short viewports. */
    max-height: 65svh;
    padding: 16px 18px;
    gap: 12px;
    /* Same flatten as .card above — see comment there for rationale. */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: rgba(255,255,255,0.10);
  }
  /* .daily-card-body and .daily-card-art structural overrides
     (flex-direction, width, height) live in a separate @media block
     placed *after* the base rules below, because the base rules come
     after this block in source order and would otherwise win the
     cascade. Only flex-shrink behavior is set here. */
  .daily-card-title { font-size: 22px; }
}

/* Outer container: never transforms. Owns the stable hit area (via the
   .card-hover overlay) so :hover persists even when the visual .card
   beneath rotates 360° and visually disappears mid-flip. */
.card-tile {
  position: relative;
}

.card {
  position: relative;
  text-align: left;
  background: rgba(255,255,255,0.04);
  backdrop-filter: blur(32px) saturate(200%);
  -webkit-backdrop-filter: blur(32px) saturate(200%);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 20px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  padding: 16px;
  color: #fff;
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: transform 380ms cubic-bezier(.2, 1.5, .3, 1),
              box-shadow 280ms ease,
              border-color 220ms ease;
  overflow: hidden;
}

/* Invisible button overlay. Captures hover + click and never moves, so
   :hover stays stable on the tile while the .card transforms underneath
   (no flicker as the card lifts out from under the cursor). */
.card-hover {
  position: absolute; inset: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 22px;
  cursor: pointer;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  z-index: 2;
}
.card-hover:focus-visible {
  outline: 2px solid rgba(255,255,255,0.5);
  outline-offset: 3px;
}

.card::before {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(160deg, rgba(255,255,255,0.18), rgba(255,255,255,0) 45%);
  pointer-events: none;
  border-radius: inherit;
  transition: opacity 280ms ease;
}

/* Hover effects only on devices with a real pointer. On touch, :hover would
   stick after a tap — :active below stays outside the gate so tap-press
   feedback still works. */
@media (hover: hover) {
  .card-tile:hover .card {
    transform: translateY(-8px) scale(1.018);
    border-color: rgba(255,255,255,0.4);
    box-shadow:
      inset 0 1px 0 var(--glass-hi),
      0 28px 60px rgba(0, 0, 0, 0.5),
      0 0 0 1px rgba(255,255,255,0.06);
  }
  .card-tile:hover .card::before { opacity: 1.4; }
}
.card-tile:active .card {
  transform: translateY(-2px) scale(0.985);
  transition: transform 120ms cubic-bezier(.4,0,.6,1);
}

/* Art slot reads as a frosted panel carved into the card. Inset shadows
   give it depth (dark top, light catch at bottom, hairline rim). */
.card-art {
  width: 100%;
  height: 170px;
  border-radius: 14px;
  position: relative;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  box-sizing: border-box;
  filter: saturate(0.85) brightness(0.92);
  box-shadow:
    inset 0 6px 18px rgba(0,0,0,0.5),
    inset 0 -2px 4px rgba(255,255,255,0.08),
    inset 0 0 0 1px rgba(0,0,0,0.32);
  perspective: 900px;
  transition: box-shadow 380ms cubic-bezier(.2, 1.5, .3, 1),
              filter 280ms ease,
              transform 380ms cubic-bezier(.2, 1.5, .3, 1);
}
.card-art > * { position: relative; z-index: 1; }
.card-art::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(160deg, rgba(255,255,255,0.18), transparent 50%);
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* On hover the slot pops out: inset shadows flip from carved (dark top)
   to raised (bright top edge, dark bottom), and the slot lifts a hair
   so the carved → raised contrast reads tactilely. */
@media (hover: hover) {
  .card-tile:hover .card-art {
    filter: saturate(1.05) brightness(1.05);
    transform: translateY(-3px);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.45),
      inset 0 -8px 18px rgba(0,0,0,0.28),
      inset 0 0 0 1px rgba(255,255,255,0.18),
      0 10px 22px -6px rgba(0,0,0,0.45);
  }
}

.card-body { width: 100%; display: flex; flex-direction: column; gap: 4px; }
.card-title {
  font-size: 20px; font-weight: 800; letter-spacing: 0.04em;
}
.card-tagline {
  font-size: 13px; color: rgba(255,255,255,0.75);
  line-height: 1.4;
  /* Reserve two lines so all card bodies share the same height even
     when a tagline only takes one line. */
  min-height: 2.8em;
}

/* ---------- Daily Challenge hero card ----------
   The home-page hero. Distinct from regular cards: wider, horizontal layout,
   accent label at the top, stronger glow so it reads as the primary action. */
.daily-card {
  position: relative;
  width: 100%;
  background: rgba(255,255,255,0.06);
  backdrop-filter: blur(32px) saturate(200%);
  -webkit-backdrop-filter: blur(32px) saturate(200%);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 24px;
  padding: 26px 28px;
  /* Reserve the height of the tallest variant (completed + signed-in user
     with a level-hint pill and "come back tomorrow" line) so the card
     doesn't grow in steps as DailyContext data loads. */
  min-height: 290px;
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    var(--shadow),
    0 0 0 1px rgba(99,142,255,0.28),
    0 0 48px -4px rgba(99,142,255,0.32);
  display: flex;
  flex-direction: column;
  gap: 16px;
  transition: transform 380ms cubic-bezier(.2, 1.5, .3, 1),
              box-shadow 280ms ease,
              border-color 220ms ease;
}
/* Hover lift mirrors the regular cards' energy but keeps the indigo accent
   ring/glow that marks the daily as the hero. Applies in both fresh and
   completed states — clicking the completed card still opens the result
   view, so hover should still affirm interactivity. */
@media (hover: hover) {
  .daily-card:hover {
    transform: translateY(-6px) scale(1.012);
    border-color: rgba(255,255,255,0.4);
    box-shadow:
      inset 0 1px 0 var(--glass-hi),
      0 28px 60px rgba(0,0,0,0.5),
      0 0 0 1px rgba(99,142,255,0.45),
      0 0 56px -2px rgba(99,142,255,0.42);
  }
}
.daily-card:active {
  transform: translateY(-1px) scale(0.992);
  transition: transform 120ms cubic-bezier(.4,0,.6,1);
}

.daily-card-label {
  align-self: flex-start;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 12px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(99,142,255,0.5), rgba(168,85,247,0.5));
  border: 1px solid rgba(255,255,255,0.22);
  color: #fff;
}

.daily-card-body {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 22px;
}

.daily-card-art {
  flex: 0 0 auto;
  width: 260px;
  height: 160px;
  border-radius: 16px;
  position: relative;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  filter: saturate(0.85) brightness(0.92);
  box-shadow:
    inset 0 6px 18px rgba(0,0,0,0.5),
    inset 0 -2px 4px rgba(255,255,255,0.08),
    inset 0 0 0 1px rgba(0,0,0,0.32);
  transition: box-shadow 380ms cubic-bezier(.2, 1.5, .3, 1),
              filter 280ms ease,
              transform 380ms cubic-bezier(.2, 1.5, .3, 1);
}
/* Carved → raised pop on hover, mirroring the regular .card-art treatment. */
@media (hover: hover) {
  .daily-card:hover .daily-card-art {
    filter: saturate(1.05) brightness(1.05);
    transform: translateY(-3px);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.45),
      inset 0 -8px 18px rgba(0,0,0,0.28),
      inset 0 0 0 1px rgba(255,255,255,0.18),
      0 12px 24px -6px rgba(0,0,0,0.5);
  }
}
.daily-card-art > * { position: relative; z-index: 1; transform: scale(0.7); }
.daily-card-art::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(160deg, rgba(255,255,255,0.18), transparent 50%);
  mix-blend-mode: overlay;
  pointer-events: none;
}

.daily-card-text {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.daily-card-title {
  font-size: 32px;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1.1;
  color: #fff;
}
.daily-card-tagline {
  font-size: 15px;
  color: rgba(255,255,255,0.78);
  line-height: 1.4;
}
.daily-card-status {
  margin-top: 8px;
  font-size: 13px;
  font-weight: 600;
  color: rgba(180,255,200,0.92);
}
.daily-card-result {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.daily-card-result-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: rgba(255,255,255,0.55);
}
.daily-card-result-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.daily-card-result-value {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 26px;
  font-weight: 800;
  color: #fff;
  letter-spacing: 0.01em;
}
.daily-card-result-metric {
  font-size: 13px;
  color: rgba(255,255,255,0.7);
}
.daily-card-result-hint {
  margin-top: 4px;
  font-size: 12px;
  color: rgba(180,255,200,0.85);
}
.daily-card-level-hint {
  margin-top: 6px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 4px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  width: fit-content;
}
.daily-card-level-hint-pill {
  display: inline-flex;
  min-width: 26px;
  justify-content: center;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(167, 139, 250, 0.18);
  border: 1px solid rgba(167, 139, 250, 0.4);
  color: #f3e8ff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.daily-card-level-hint-text {
  font-size: 12px;
  font-weight: 600;
  color: rgba(255,255,255,0.86);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
.daily-card-level-hint-sub {
  color: rgba(255,255,255,0.55);
  font-weight: 500;
}
.daily-card-cta-row {
  margin-top: 12px;
}
.daily-card-cta {
  display: inline-block;
  padding: 8px 18px;
  border-radius: 999px;
  background: rgba(255,255,255,0.16);
  border: 1px solid rgba(255,255,255,0.28);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #fff;
}

.daily-card.is-completed .daily-card-art { filter: saturate(0.6) brightness(0.85); }

.daily-card-hover {
  position: absolute; inset: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 22px;
  cursor: pointer;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  z-index: 2;
}
.daily-card-hover:focus-visible {
  outline: 2px solid rgba(255,255,255,0.5);
  outline-offset: 3px;
}
.daily-card-hover:disabled { cursor: default; }

.daily-card--placeholder {
  text-align: center;
  align-items: center;
}
.daily-card--placeholder .daily-card-message {
  font-size: 14px;
  color: rgba(255,255,255,0.7);
}

/* Tablet / landscape-phone range. At ≤480px the mobile block below is
   slightly more compact, so this rule is scoped to leave the phone case
   alone. */
@media (min-width: 481px) and (max-width: 560px) {
  .daily-card {
    padding: 20px 20px;
    gap: 14px;
    /* Column layout stacks art (150) above text — taller worst case than desktop. */
    min-height: 430px;
  }
  .daily-card-body { flex-direction: column; align-items: stretch; gap: 14px; }
  .daily-card-art { width: 100%; height: 150px; }
  .daily-card-art > * { transform: scale(0.85); }
  .daily-card-title { font-size: 26px; }
}

/* Mobile structural overrides for daily-card-body and daily-card-art —
   placed after the base rules so the cascade actually wins. Pairs with
   the upper (max-width: 480px) block which carries the .home-stack lock
   and flex-shrink behavior. */
@media (max-width: 480px) {
  .daily-card-body {
    flex: 1;
    /* No `min-height: 0` override — pairs with .daily-card and
       .daily-block above. Body's content-min (art floor + text natural
       height) needs to propagate up so the page scrolls instead of the
       last text line spilling below the painted card boundary. */
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  /* Art absorbs leftover vertical space. min-height keeps it visible on
     tiny viewports; if the rest of the content + this min ever exceeds
     viewport, the page scrolls a touch instead of clipping. */
  .daily-card-art {
    width: 100%;
    height: auto;
    flex: 1;
    min-height: 80px;
  }
  .daily-card-art > * { transform: scale(0.78); }
  /* Text section is content-sized — base rule has flex: 1 1 auto which
     would split the body 50/50 with the art and leave empty space below
     the CTA when the text content is short (e.g. "not yet played"). */
  .daily-card-text { flex: 0 0 auto; }
}

/* Short viewports: don't force the column taller than the screen. Use
   explicit min margins around the daily card so the hero still has air
   between subscribe + practice when auto-margins would collapse to zero. */
@media (max-height: 720px) {
  .home-stack { min-height: 0; }
  .home-stack > .daily-card { margin-top: 28px; margin-bottom: 36px; }
}

/* ---------- Practice CTA (home view) ----------
   Sits below the Daily Challenge card. One click takes the user to the
   Practice view where every game is listed. */
.practice-cta {
  position: relative;
  width: 100%;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 18px 22px;
  border-radius: 22px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.10);
  color: #fff;
  cursor: pointer;
  text-align: left;
  backdrop-filter: blur(32px) saturate(200%);
  -webkit-backdrop-filter: blur(32px) saturate(200%);
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  transition: transform 280ms cubic-bezier(.2, 1.5, .3, 1),
              box-shadow 280ms ease,
              border-color 220ms ease,
              background 200ms ease;
}
.practice-cta-label {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 11px;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(255,62,165,0.4), rgba(56,189,248,0.4));
  border: 1px solid rgba(255,255,255,0.18);
  color: #fff;
}
.practice-cta-tagline {
  font-size: 14px;
  color: rgba(255,255,255,0.85);
}
.practice-cta-arrow {
  font-size: 22px;
  color: rgba(255,255,255,0.85);
  transition: transform 220ms ease;
}
@media (hover: hover) {
  .practice-cta:hover {
    transform: translateY(-3px);
    background: rgba(255,255,255,0.07);
    border-color: rgba(255,255,255,0.28);
    box-shadow:
      inset 0 1px 0 var(--glass-hi),
      0 18px 40px rgba(0,0,0,0.45);
  }
  .practice-cta:hover .practice-cta-arrow { transform: translateX(4px); }
}
.practice-cta:active { transform: translateY(1px) scale(0.995); }
.practice-cta:focus-visible {
  outline: 2px solid rgba(255,255,255,0.5);
  outline-offset: 3px;
}

@media (max-width: 480px) {
  .practice-cta {
    padding: 14px 16px;
    gap: 12px;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: rgba(255,255,255,0.07);
  }
  .practice-cta-tagline { font-size: 13px; }
}

/* Slow-desktop fallback. The existing bg-perf probe (bgPerfProbe.ts)
   sets `html.bg-low-perf` when the device can't keep the backdrop
   layer at ~60fps. Treat it as a general "this device is slow" signal
   and apply the same flatten + animation freeze the mobile block above
   uses. Skipped on `<=480px` viewports because mobile already handles
   itself, mirroring the probe's own opt-out. */
html.bg-low-perf .card,
html.bg-low-perf .daily-card,
html.bg-low-perf .practice-cta {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html.bg-low-perf .card { background: rgba(255,255,255,0.08); }
html.bg-low-perf .daily-card { background: rgba(255,255,255,0.10); }
html.bg-low-perf .practice-cta { background: rgba(255,255,255,0.07); }
html.bg-low-perf .card-art *,
html.bg-low-perf .daily-card-art * { animation: none !important; }

/* ---------- Practice view header ---------- */
.practice-header {
  display: flex;
  align-items: center;
  width: 100%;
}
.practice-back {
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding: 0 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  color: rgba(255,255,255,0.85);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: transform 150ms ease, background 200ms ease, color 200ms ease;
}
@media (hover: hover) {
  .practice-back:hover {
    background: rgba(255,255,255,0.14);
    color: #fff;
    transform: translateY(-1px);
  }
}
.practice-back:active { transform: translateY(1px) scale(0.98); }

/* Estimated game-duration pill. Shared between the practice grid cards
   and the daily card — small, subdued, sits inline below the tagline. */
.duration-pill {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  margin-top: 8px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  font-size: 11px;
  font-weight: 600;
  color: rgba(255,255,255,0.7);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
.auth-pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.auth-identity {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 12px 0 3px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  color: rgba(255,255,255,0.85);
  cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
  transition: transform 150ms ease, background 200ms ease, color 200ms ease;
}
.auth-identity.is-anonymous {
  background: linear-gradient(135deg, rgba(255,62,165,0.12), rgba(56,189,248,0.12));
}
.auth-identity:hover {
  background: rgba(255,255,255,0.14);
  color: #fff;
  transform: translateY(-1px);
}
.auth-identity:active { transform: translateY(1px) scale(0.98); }

.auth-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  border-radius: 999px;
  background: rgba(255,255,255,0.10);
  color: rgba(255,255,255,0.85);
  overflow: hidden;
  flex: 0 0 auto;
}
.auth-identity.is-anonymous .auth-avatar {
  background: linear-gradient(135deg, rgba(255,62,165,0.32), rgba(56,189,248,0.32));
}

.auth-avatar-img {
  width: 100%; height: 100%;
  object-fit: cover;
}
.auth-avatar-fallback {
  font-weight: 700;
  font-size: 13px;
  color: #fff;
}

.auth-name {
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.02em;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.auth-identity.is-anonymous .auth-name {
  color: rgba(255,255,255,0.7);
  font-style: italic;
}

/* Transparent overlay holding the GIS-rendered "Sign in with Google" button.
   Sits on top of the avatar pill so a click on the avatar lands on the GIS
   iframe and opens the Google popup natively. */
.auth-gis-overlay {
  position: absolute;
  inset: 0;
  opacity: 0;
  overflow: hidden;
  border-radius: 999px;
  cursor: pointer;
}
.auth-gis-overlay > div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
/* Reflect the overlay's hover on the visible avatar so it still feels
   interactive (the auth-identity itself can't see hover — overlay is on top). */
.auth-pill:has(.auth-gis-overlay:hover) .auth-identity.is-anonymous {
  background: rgba(255,255,255,0.14);
  color: #fff;
  transform: translateY(-1px);
}
.auth-pill:has(.auth-gis-overlay:active) .auth-identity.is-anonymous {
  transform: translateY(1px) scale(0.98);
}

.auth-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 240px;
  background: rgba(20, 22, 32, 0.96);
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  padding: 12px;
  box-shadow: var(--shadow);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  z-index: 20;
}

.auth-menu-name {
  color: #fff;
  font-weight: 600;
  font-size: 13px;
  padding: 4px 8px 0;
}
.auth-menu-email {
  color: rgba(255,255,255,0.55);
  font-size: 11px;
  padding: 0 8px 6px;
  word-break: break-all;
}
.auth-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: rgba(255,255,255,0.85);
  font-size: 13px;
  font-weight: 500;
  padding: 8px;
  border-radius: 8px;
  cursor: pointer;
  margin-top: 4px;
}
.auth-menu-item:hover { background: rgba(255,255,255,0.10); color: #fff; }

.auth-menu-warn {
  margin-top: 10px;
  padding: 8px;
  border-radius: 8px;
  background: rgba(220, 38, 38, 0.12);
  border: 1px solid rgba(220, 38, 38, 0.4);
  color: #ff8585;
  font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  text-align: center;
}

@media (max-width: 480px) {
  .auth-pill { gap: 6px; }
  .auth-identity { padding: 0 3px; height: 32px; }
  .auth-avatar { width: 26px; height: 26px; }

  /* On mobile, collapse the pill to just the avatar circle — keeping the
     name causes the topbar to wrap to two rows on narrower phones. The
     dropdown menu still surfaces the full name + email when tapped. */
  .auth-name { display: none; }
}

@media (max-width: 360px) {
  .auth-pill { gap: 4px; }
}
.lb-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: rgba(255,255,255,0.85);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 6px 12px;
  border-radius: 999px;
  cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: transform 150ms ease, background 200ms ease, color 200ms ease;
}
.lb-trigger:hover {
  background: rgba(255,255,255,0.16);
  color: #fff;
  transform: translateY(-1px);
}
.lb-trigger:active { transform: translateY(1px) scale(0.98); }
.lb-trigger svg { opacity: 0.8; }

/* Phones: collapse to icon-only so the trigger fits in compact game
   toolbars alongside score/next chips. Tooltip still surfaces the label. */
@media (max-width: 480px) {
  .lb-trigger {
    padding: 6px 10px;
    gap: 0;
  }
  .lb-trigger span { display: none; }
}
/* Base — deep navy canvas; sits behind everything else. */
.bg-base {
  position: fixed; inset: 0;
  z-index: -3;
  background:
    radial-gradient(70% 90% at 25% 20%, #2a3550 0%, transparent 65%),
    radial-gradient(70% 90% at 80% 30%, #2b3146 0%, transparent 65%),
    radial-gradient(80% 100% at 50% 95%, #1a2238 0%, transparent 65%),
    #0b0e16;
  filter: saturate(110%);
  animation: bg-drift 24s ease-in-out infinite alternate;
}
.bg-base::after {
  content: ""; position: absolute; inset: -10%;
  background:
    radial-gradient(40% 60% at 30% 70%, rgba(120,130,180,0.18) 0%, transparent 65%),
    radial-gradient(40% 60% at 70% 40%, rgba(90,110,160,0.16) 0%, transparent 65%);
  animation: bg-drift2 28s ease-in-out infinite alternate;
}
@keyframes bg-drift {
  0%   { transform: translate3d(-2%, -1%, 0) scale(1.05); }
  100% { transform: translate3d(2%, 2%, 0) scale(1.12); }
}
@keyframes bg-drift2 {
  0%   { transform: translate3d(3%, 2%, 0) rotate(0deg); }
  100% { transform: translate3d(-3%, -2%, 0) rotate(8deg); }
}

/* Aurora — vibrant drifting color blobs. Three of them. */
.bg-aurora {
  position: fixed; inset: 0;
  z-index: -2;
  pointer-events: none;
  overflow: hidden;
}
.bg-aurora .blob {
  position: absolute;
  width: 90vw; height: 90vw;
  max-width: 1100px; max-height: 1100px;
  border-radius: 50%;
  filter: blur(36px) saturate(120%);
  opacity: 0.55;
  will-change: transform;
}
/* Each blob's keyframes start at its `top/left/right/bottom` anchor and drift
   inward — so without an animation-delay the page would spend several seconds
   looking grey while the blobs slide on-screen. Negative delays start each
   animation mid-cycle, putting the colorful composition on the very first
   frame. Each delay is ~half the duration so we land near the colorful end
   of the alternate. */
.bg-aurora .blob.pink {
  background: radial-gradient(circle, rgba(255,62,165,0.4) 0%, rgba(255,62,165,0.12) 28%, transparent 65%);
  top: -50%; left: -45%;
  width: 38vw; height: 38vw;
  opacity: 0.32;
  animation: aurora-a 22s ease-in-out infinite alternate;
  animation-delay: -11s;
}
.bg-aurora .blob.cyan {
  background: radial-gradient(circle, #38bdf8 0%, rgba(56,189,248,0.55) 28%, transparent 65%);
  bottom: -25%; right: -25%;
  animation: aurora-b 28s ease-in-out infinite alternate;
  animation-delay: -14s;
}
.bg-aurora .blob.violet {
  background: radial-gradient(circle, #a855f7 0%, rgba(168,85,247,0.55) 28%, transparent 65%);
  top: 25%; left: 35%;
  animation: aurora-c 34s ease-in-out infinite alternate;
  animation-delay: -17s;
}
@keyframes aurora-a {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  100% { transform: translate3d(35vw, 25vh, 0) scale(1.25); }
}
@keyframes aurora-b {
  0%   { transform: translate3d(0, 0, 0) scale(1.1); }
  100% { transform: translate3d(-30vw, -22vh, 0) scale(0.95); }
}
@keyframes aurora-c {
  0%   { transform: translate3d(-15vw, 0, 0) scale(0.9); }
  100% { transform: translate3d(20vw, -10vh, 0) scale(1.15); }
}

/* Floating game letters/symbols rising slowly. */
.bg-tiles {
  position: fixed; inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}
.bg-tile {
  position: absolute;
  bottom: -10vh;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 800;
  letter-spacing: 0.04em;
  /* Lightning CSS (Vite's prod minifier) strips a bare `currentColor`
     argument from `drop-shadow()`, leaving the shadow effectively colorless
     in the bundled CSS. Wrapping it in `var()` with a `currentColor` fallback
     keeps the optimizer's hands off the value. */
  filter:
    drop-shadow(0 0 18px var(--tile-glow, currentColor))
    drop-shadow(0 0 4px rgba(0,0,0,0.4));
  animation: tile-rise linear infinite;
  will-change: transform, opacity;
  user-select: none;
}

@keyframes tile-rise {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg); opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { transform: translate3d(var(--drift, 0), -120vh, 0) rotate(360deg); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .bg-base, .bg-base::after,
  .bg-aurora .blob,
  .bg-tile { animation: none; }
}

/* Pause CSS animations when the tab is backgrounded. */
.bg-paused .bg-base,
.bg-paused .bg-base::after,
.bg-paused .bg-aurora .blob,
.bg-paused .bg-tile { animation-play-state: paused !important; }

/* Devices that fail the launch fps probe get the same static treatment as
   mobile: no animations, tiles hidden. Set by BackgroundFun.tsx. */
.bg-low-perf .bg-base,
.bg-low-perf .bg-base::after,
.bg-low-perf .bg-aurora .blob,
.bg-low-perf .bg-tile { animation: none !important; }
.bg-low-perf .bg-tile { display: none; }

@media (max-width: 480px) {
  .bg-tile { font-size: 32px !important; }
  .bg-aurora .blob { filter: blur(28px) saturate(120%); }

  /* Freeze every background layer on phones. An animated backdrop forces
     every backdrop-filter glass surface in the app to re-sample its blur
     each frame — that's the dominant source of mobile lag, more than any
     individual game's animations. With a still background, the rasterized
     backdrop can be cached and glass panels become essentially free. */
  .bg-base, .bg-base::after,
  .bg-aurora .blob,
  .bg-tile { animation: none; }
  .bg-tile { display: none; }
}
.wordle {
  display: flex; flex-direction: column; align-items: center;
  gap: 16px;
  width: 100%;
  max-width: 520px;
  animation: w-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes w-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.panel {
  background: var(--glass-bg);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
  border-radius: 22px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  padding: 14px;
}

.board {
  display: grid;
  grid-template-rows: repeat(6, 1fr);
  gap: 8px;
}
.row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  perspective: 800px;
}

.tile {
  width: 60px; height: 60px;
  border-radius: 12px;
  border: 1px solid var(--glass-border);
  background: rgba(255, 255, 255, 0.08);
  /* No backdrop-filter: the parent .panel is already frosted, and putting
     it on 30 tiles that flip/scale at once stalls mobile GPUs. */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.25),
    inset 0 -10px 20px rgba(0,0,0,0.15),
    0 4px 14px rgba(0,0,0,0.25);
  display: flex; align-items: center; justify-content: center;
  font-size: 30px; font-weight: 800; text-transform: uppercase;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
  transform-style: preserve-3d;
  transition: transform 180ms cubic-bezier(.2,.9,.3,1.4);
  position: relative;
  overflow: hidden;
}
.tile::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(160deg, rgba(255,255,255,0.35), rgba(255,255,255,0) 40%);
  pointer-events: none;
}

.tile.filled {
  border-color: rgba(255,255,255,0.45);
  background: rgba(255,255,255,0.10);
}
.tile.pop { animation: tile-pop 220ms cubic-bezier(.2,.9,.3,1.6); }
@keyframes tile-pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}

.tile.flip { animation: tile-flip 600ms ease forwards; }
@keyframes tile-flip {
  0%   { transform: rotateX(0deg); }
  45%  { transform: rotateX(90deg); }
  55%  { transform: rotateX(90deg); }
  100% { transform: rotateX(0deg); }
}

.tile.absent {
  background: rgba(58, 58, 60, 0.55);
  border-color: rgba(255,255,255,0.12);
}
.tile.present {
  background: rgba(214, 168, 47, 0.55);
  border-color: rgba(255,220,140,0.4);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.35),
    0 6px 18px rgba(214,168,47,0.35);
}
.tile.correct {
  background: rgba(83, 141, 78, 0.55);
  border-color: rgba(160,255,160,0.45);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    0 8px 24px rgba(83,141,78,0.55);
}

.row.shake { animation: row-shake 0.45s cubic-bezier(.36,.07,.19,.97); }
@keyframes row-shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-7px); }
  40%, 60% { transform: translateX(7px); }
}

.row.bounce .tile { animation: row-bounce 700ms ease; }
.row.bounce .tile:nth-child(1) { animation-delay:   0ms; }
.row.bounce .tile:nth-child(2) { animation-delay:  80ms; }
.row.bounce .tile:nth-child(3) { animation-delay: 160ms; }
.row.bounce .tile:nth-child(4) { animation-delay: 240ms; }
.row.bounce .tile:nth-child(5) { animation-delay: 320ms; }
@keyframes row-bounce {
  0%   { transform: translateY(0); }
  30%  { transform: translateY(-22px) scale(1.04); }
  50%  { transform: translateY(0); }
  65%  { transform: translateY(-10px); }
  100% { transform: translateY(0); }
}

.keyboard {
  display: flex; flex-direction: column; gap: 6px;
  width: 100%;
  padding: 10px;
}
.kb-row { display: flex; gap: 6px; justify-content: center; }
.key {
  color: #fff; font-weight: 700; font-size: 14px; text-transform: uppercase;
  background: rgba(255,255,255,0.12);
  border: 1px solid var(--glass-border);
  border-radius: 10px;
  padding: 0; height: 52px;
  flex: 1; min-width: 28px;
  cursor: pointer;
  /* No backdrop-filter: 30 frosted keys re-composite on every tap on
     mobile, which is what made the keyboard feel laggy. */
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 4px 14px rgba(0,0,0,0.2);
  transition: transform 120ms ease, background 200ms ease, box-shadow 200ms ease;
  text-shadow: 0 1px 2px rgba(0,0,0,0.3);
}
.key:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.key:active { transform: translateY(1px) scale(0.98); }
.key.wide   { flex: 1.6; font-size: 12px; }
.key.absent  { background: rgba(58, 58, 60, 0.55); border-color: rgba(255,255,255,0.08); }
.key.present { background: rgba(214, 168, 47, 0.55); border-color: rgba(255,220,140,0.35); }
.key.correct { background: rgba(83, 141, 78, 0.55); border-color: rgba(160,255,160,0.4); }

.message {
  min-height: 28px;
  display: flex; align-items: center; justify-content: center;
}
.toast {
  background: rgba(255,255,255,0.18);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
  color: #fff; font-weight: 700;
  padding: 10px 16px; border-radius: 999px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  animation: toast-in 240ms cubic-bezier(.2,.9,.3,1.4);
  letter-spacing: 0.05em;
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.wordle-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}

.newgame {
  color: #fff; font-weight: 700; letter-spacing: 0.08em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 10px 18px; cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 18px rgba(0,0,0,0.25);
  transition: transform 150ms ease, background 200ms ease;
}
.newgame:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.newgame:active { transform: translateY(1px) scale(0.98); }

.confetti-layer {
  position: fixed; inset: 0; pointer-events: none; z-index: 50;
  overflow: hidden;
}
.confetti {
  position: absolute; top: -10px; width: 8px; height: 14px;
  border-radius: 2px;
  animation: c-fall linear forwards;
}
@keyframes c-fall {
  0%   { transform: translateY(0) rotate(var(--rot, 0deg));                        opacity: 1; }
  100% { transform: translateY(110vh) rotate(calc(var(--rot, 0deg) + 720deg));     opacity: 0.9; }
}

.loading {
  color: rgba(255,255,255,0.7);
  font-size: 14px;
}

@media (max-width: 480px) {
  /* Fill the locked .game-stage. Tile size derives from whichever
     dimension is the binding constraint (viewport width / 5 or remaining
     vertical space / 6), so the board scales naturally on every phone
     without per-device tuning. The 440px subtracted from 100svh accounts
     for: topbar 52 + main padding 38 + game-header 50 + Wordle internal
     content excluding the board (message, gaps, actions, keyboard, board
     padding) ≈ 300. */
  .wordle {
    --tile-size: clamp(
      32px,
      min(
        calc((100vw - 60px) / 5),
        calc((100svh - 440px - env(safe-area-inset-bottom)) / 6)
      ),
      64px
    );
    width: 100%;
    max-width: none;
    height: 100%;
    gap: 10px;
    padding: 4px 4px 8px;
    box-sizing: border-box;
  }
  .board { padding: 10px; gap: 6px; }
  .row   { gap: 6px; }
  .tile {
    width: var(--tile-size);
    height: var(--tile-size);
    font-size: calc(var(--tile-size) * 0.55);
    border-radius: 10px;
  }
  .keyboard { padding: 8px; gap: 5px; }
  .kb-row { gap: 4px; }
  .key {
    height: 44px;
    border-radius: 8px;
    min-width: 0;
    font-size: 13px;
  }
  .key.wide { font-size: 11px; }
}
.crossword {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 920px;
  animation: cw-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes cw-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.panel {
  background: var(--glass-bg);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
  border-radius: 22px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  padding: 16px;
}

.cw-active-clue {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.25);
  color: #fff;
  font-weight: 600;
  max-width: 100%;
}
.cw-active-num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; height: 24px;
  background: rgba(255,255,255,0.18);
  border-radius: 999px;
  font-size: 12px;
  padding: 0 6px;
}
.cw-active-dir { font-size: 16px; opacity: 0.8; }
.cw-active-text { font-size: 14px; }

.cw-layout {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(280px, 1fr);
  gap: 18px;
  align-items: start;
  width: 100%;
}

.cw-board-panel {
  display: flex; flex-direction: column; gap: 14px;
  align-items: center;
}

.cw-board {
  display: grid;
  gap: 6px;
}

.cw-cell {
  width: 64px; height: 64px;
  border-radius: 12px;
  border: 1px solid var(--glass-border);
  background: rgba(255,255,255,0.08);
  position: relative;
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; font-weight: 800;
  color: #fff;
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
  cursor: pointer;
  overflow: hidden;
  backdrop-filter: blur(8px) saturate(160%);
  -webkit-backdrop-filter: blur(8px) saturate(160%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.25),
    inset 0 -10px 20px rgba(0,0,0,0.15),
    0 4px 14px rgba(0,0,0,0.25);
  transition: background 200ms ease, transform 150ms cubic-bezier(.2,.9,.3,1.4),
              box-shadow 200ms ease, border-color 200ms ease;
}
.cw-cell::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(160deg, rgba(255,255,255,0.32), rgba(255,255,255,0) 45%);
  pointer-events: none;
}
.cw-cell.black {
  background: rgba(0,0,0,0.55);
  border-color: rgba(255,255,255,0.05);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
  cursor: default;
}
.cw-cell.black::before { display: none; }

.cw-cell.active {
  background: rgba(99, 142, 255, 0.28);
  border-color: rgba(160,190,255,0.55);
}
.cw-cell.cursor {
  background: rgba(99, 142, 255, 0.55);
  border-color: rgba(180,210,255,0.85);
  transform: scale(1.04);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 8px 22px rgba(99,142,255,0.45);
}

.cw-cell.solved {
  background: rgba(83, 141, 78, 0.55);
  border-color: rgba(160,255,160,0.45);
  animation: cw-solved-pulse 1.4s ease-in-out;
}
@keyframes cw-solved-pulse {
  0%, 100% { box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    0 0 0 rgba(83,141,78,0); }
  50% { box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    0 0 32px rgba(83,141,78,0.7); }
}

.cw-num {
  position: absolute; top: 4px; left: 6px;
  font-size: 11px; font-weight: 700;
  color: rgba(255,255,255,0.85);
  letter-spacing: 0;
  text-shadow: 0 1px 1px rgba(0,0,0,0.35);
}
.cw-letter { font-size: 30px; }

.cw-actions {
  display: flex; gap: 10px;
}

.cw-btn {
  color: #fff; font-weight: 700; letter-spacing: 0.06em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 9px 16px; cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 18px rgba(0,0,0,0.2);
  transition: transform 150ms ease, background 200ms ease;
}
.cw-btn:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.cw-btn:active { transform: translateY(1px) scale(0.98); }
.cw-btn.ghost  { background: transparent; }

.cw-clue-panel {
  display: flex; flex-direction: column; gap: 16px;
  max-height: 560px; overflow: auto;
}

.cw-clues-title {
  margin: 0 0 8px;
  font-size: 12px; font-weight: 800;
  letter-spacing: 0.18em; color: rgba(255,255,255,0.7);
  text-transform: uppercase;
}
.cw-clues ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }

.cw-clue {
  display: flex; gap: 8px; align-items: baseline;
  padding: 8px 10px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 14px;
  color: rgba(255,255,255,0.85);
  transition: background 180ms ease, color 180ms ease, transform 180ms ease;
}
.cw-clue:hover { background: rgba(255,255,255,0.06); color: #fff; }
.cw-clue.active {
  background: rgba(99, 142, 255, 0.22);
  color: #fff;
  border-left: 3px solid rgba(160,190,255,0.85);
  padding-left: 7px;
}
.cw-clue-num { font-weight: 800; font-size: 13px; min-width: 18px; }
.cw-clue-text { line-height: 1.3; }

.cw-banner {
  position: fixed; left: 0; right: 0; bottom: 30px;
  display: flex; justify-content: center;
  pointer-events: none;
}
.cw-banner-text {
  background: rgba(83, 141, 78, 0.55);
  border: 1px solid rgba(160,255,160,0.6);
  color: #fff;
  font-weight: 800; letter-spacing: 0.08em;
  padding: 12px 22px;
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 12px 36px rgba(83,141,78,0.55);
  animation: cw-banner-in 300ms cubic-bezier(.2,.9,.3,1.4);
}
@keyframes cw-banner-in {
  from { opacity: 0; transform: translateY(20px) scale(0.92); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

/* Invisible-but-focusable input. Tapping a cell focuses it on mobile so the
   OS keyboard pops up; on desktop the global keydown handler still works
   when the input isn't focused. */
.cw-input {
  position: absolute;
  left: 0; top: 0;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
  border: 0;
  outline: 0;
  background: transparent;
  color: transparent;
  caret-color: transparent;
  font-size: 16px; /* prevent iOS zoom-on-focus */
  -webkit-user-select: none;
  user-select: none;
}

@media (max-width: 760px) {
  .cw-layout { grid-template-columns: 1fr; }
  .cw-cell {
    width: clamp(48px, 17vw, 64px);
    height: clamp(48px, 17vw, 64px);
  }
  .cw-letter { font-size: clamp(22px, 6.5vw, 28px); }
  /* Drop the inner scroll on phones — the outer .game-stage already scrolls,
     and a nested overflow:auto here lets iOS hijack the finger gesture
     before it can reach the rest of the clues below the fold. */
  .cw-clue-panel { max-height: none; overflow: visible; }
}

@media (max-width: 480px) {
  .crossword { gap: 10px; }
  .cw-active-clue { padding: 8px 12px; gap: 8px; }
  .cw-active-text { font-size: 13px; }
  .cw-board { gap: 4px; }
  .cw-cell {
    border-radius: 10px;
    width: clamp(44px, 18vw, 56px);
    height: clamp(44px, 18vw, 56px);
  }
  .cw-num { font-size: 9px; top: 2px; left: 4px; }
  .cw-clue-panel { padding: 12px; }
  .cw-clue { font-size: 13px; padding: 7px 8px; }
}
.hangman {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 560px;
  animation: hm-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes hm-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.hm-header {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  padding: 8px 14px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  color: #fff;
}
.hm-cat, .hm-tries {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px;
}
.hm-cat-label, .hm-tries-label {
  color: rgba(255,255,255,0.6);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 11px;
  font-weight: 700;
}
.hm-cat-value { font-weight: 700; }
.hm-tries-value {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 26px;
  padding: 0 8px;
  border-radius: 999px;
  background: rgba(255,255,255,0.12);
  font-weight: 800;
}
.hm-tries.danger .hm-tries-value {
  background: rgba(220, 80, 80, 0.45);
  box-shadow: 0 0 16px rgba(220, 80, 80, 0.4);
}

.hm-stage {
  width: 100%;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
}
.hm-stage.shake { animation: hm-shake 0.4s cubic-bezier(.36,.07,.19,.97); }
@keyframes hm-shake {
  10%, 90% { transform: translateX(-2px); }
  30%, 70% { transform: translateX(-7px); }
  50%      { transform: translateX(7px); }
}
.hm-svg {
  width: 100%; max-width: 240px; height: auto;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.3));
}
.hm-line {
  stroke: rgba(255,255,255,0.6);
  stroke-width: 4;
  stroke-linecap: round;
  fill: none;
}
.hm-figure {
  stroke: #fff;
  stroke-width: 4;
  stroke-linecap: round;
  fill: none;
  animation: hm-draw 320ms ease-out;
  transform-origin: center;
}
@keyframes hm-draw {
  from { opacity: 0; transform: scale(0.7); }
  to   { opacity: 1; transform: scale(1); }
}

.hm-word {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 8px;
  padding: 4px;
}
.hm-slot {
  display: flex; flex-direction: column; align-items: center;
  width: 36px;
  position: relative;
}
.hm-slot-ch {
  font-size: 26px; font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
  height: 32px; line-height: 32px;
  transition: transform 220ms cubic-bezier(.2,.9,.3,1.4);
}
.hm-slot.shown .hm-slot-ch {
  animation: hm-pop 280ms cubic-bezier(.2,.9,.3,1.4);
}
@keyframes hm-pop {
  0%   { transform: scale(0.6) rotateX(-90deg); opacity: 0; }
  60%  { transform: scale(1.15) rotateX(0deg);  opacity: 1; }
  100% { transform: scale(1) rotateX(0deg);     opacity: 1; }
}
.hm-slot-line {
  width: 28px; height: 3px;
  border-radius: 2px;
  background: rgba(255,255,255,0.55);
  margin-top: 2px;
}

.hm-banner {
  padding: 10px 18px;
  border-radius: 999px;
  font-weight: 800; letter-spacing: 0.05em;
  color: #fff;
  display: inline-flex; align-items: center; gap: 12px;
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
  animation: hm-banner-in 280ms cubic-bezier(.2,.9,.3,1.4);
}
.hm-banner.win {
  background: rgba(83, 141, 78, 0.55);
  border-color: rgba(160,255,160,0.5);
  box-shadow: 0 8px 28px rgba(83,141,78,0.45);
}
.hm-banner.lose {
  background: rgba(180, 60, 60, 0.55);
  border-color: rgba(255,160,160,0.5);
  box-shadow: 0 8px 28px rgba(180,60,60,0.45);
}
.hm-reveal {
  background: rgba(255,255,255,0.18);
  padding: 4px 10px;
  border-radius: 999px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
@keyframes hm-banner-in {
  from { opacity: 0; transform: translateY(8px) scale(0.95); }
  to   { opacity: 1; transform: translateY(0)   scale(1); }
}

.hm-newgame {
  color: #fff; font-weight: 700; letter-spacing: 0.08em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 10px 18px; cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 18px rgba(0,0,0,0.25);
  transition: transform 150ms ease, background 200ms ease;
}
.hm-newgame:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.hm-newgame:active { transform: translateY(1px) scale(0.98); }

.hm-keyboard .key:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.hm-keyboard .key.correct {
  background: rgba(83, 141, 78, 0.55);
  border-color: rgba(160,255,160,0.4);
}
.hm-keyboard .key.absent {
  background: rgba(58, 58, 60, 0.55);
  border-color: rgba(255,255,255,0.08);
}

@media (max-width: 480px) {
  .hangman { gap: 10px; }
  .hm-stage { padding: 12px; }
  .hm-svg { max-width: 200px; }
  .hm-slot { width: 28px; }
  .hm-slot-ch { font-size: 22px; height: 26px; line-height: 26px; }
  .hm-slot-line { width: 22px; }
  .hm-header { padding: 6px 12px; }
  .hm-cat, .hm-tries { font-size: 12px; }
}
.sudoku {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 560px;
  animation: sk-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes sk-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.sk-toolbar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
}
.sk-diff {
  display: inline-flex;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 3px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
}
.sk-diff-btn {
  border: 0; background: transparent;
  color: rgba(255,255,255,0.7);
  font-weight: 700; font-size: 13px;
  padding: 6px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 200ms ease, color 200ms ease;
}
.sk-diff-btn.active {
  background: rgba(255,255,255,0.18);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3);
}
.sk-mistakes {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-size: 13px;
}
.sk-mistakes-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.sk-mistakes-value {
  font-weight: 800; font-size: 14px;
}

.sk-board {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(9, 1fr);
  gap: 2px;
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 8px;
}

.sk-cell {
  position: relative;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.10);
  color: #fff;
  border-radius: 4px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: clamp(16px, 4.4vw, 22px);
  font-weight: 700;
  padding: 0;
  transition: background 150ms ease, transform 120ms ease;
  overflow: hidden;
}
.sk-cell::before {
  content: ""; position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(160deg, rgba(255,255,255,0.18), rgba(255,255,255,0) 50%);
  pointer-events: none;
}
.sk-cell.given { color: #fff; font-weight: 800; }
.sk-cell:not(.given) .sk-value { color: #c5d8ff; }
.sk-cell.peer { background: rgba(255,255,255,0.10); }
.sk-cell.samevalue {
  background: rgba(99, 142, 255, 0.22);
}
.sk-cell.cursor {
  background: rgba(99, 142, 255, 0.55);
  border-color: rgba(180,210,255,0.85);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.4),
              0 4px 14px rgba(99,142,255,0.4);
}
.sk-cell.wrong .sk-value {
  color: #ff8b8b;
  text-shadow: 0 0 6px rgba(255, 80, 80, 0.6);
}
.sk-cell.br { box-shadow: inset -2px 0 0 rgba(255,255,255,0.4); }
.sk-cell.bb { box-shadow: inset 0 -2px 0 rgba(255,255,255,0.4); }
.sk-cell.br.bb {
  box-shadow:
    inset -2px 0 0 rgba(255,255,255,0.4),
    inset 0 -2px 0 rgba(255,255,255,0.4);
}

.sk-value {
  position: relative; z-index: 1;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
.sk-notes {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  width: 100%; height: 100%;
  font-size: clamp(7px, 1.7vw, 9px);
  font-weight: 600;
  color: rgba(255,255,255,0.6);
  padding: 2px;
  box-sizing: border-box;
}
.sk-notes > span {
  display: flex; align-items: center; justify-content: center;
}
.sk-notes > span.on { color: rgba(255,255,255,0.9); }

@keyframes sk-shake {
  10%, 90% { transform: translateX(-2px); }
  30%, 70% { transform: translateX(-5px); }
  50%      { transform: translateX(5px); }
}
.sk-board[class*=" k-"] .sk-cell.cursor { animation: sk-shake 0.4s cubic-bezier(.36,.07,.19,.97); }

.sk-actions {
  display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
}
.sk-action {
  color: #fff; font-weight: 700; letter-spacing: 0.05em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 9px 16px; cursor: pointer;
  font-size: 13px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: transform 150ms ease, background 200ms ease;
}
.sk-action:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.sk-action:active { transform: translateY(1px) scale(0.98); }
.sk-action.active {
  background: rgba(99, 142, 255, 0.45);
  border-color: rgba(180,210,255,0.6);
}

.sk-pad {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  gap: 6px;
  width: 100%;
  padding: 10px;
}
.sk-pad-key {
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-weight: 800; font-size: 20px;
  height: 48px;
  border-radius: 10px;
  cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 4px 14px rgba(0,0,0,0.2);
  transition: transform 120ms ease, background 200ms ease;
}
.sk-pad-key:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.sk-pad-key:active { transform: translateY(1px) scale(0.98); }

.sk-banner {
  position: fixed; left: 0; right: 0; bottom: 30px;
  display: flex; justify-content: center;
  pointer-events: none;
  z-index: 50;
}
.sk-banner-text {
  background: rgba(83, 141, 78, 0.55);
  border: 1px solid rgba(160,255,160,0.6);
  color: #fff;
  font-weight: 800; letter-spacing: 0.08em;
  padding: 12px 22px;
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 12px 36px rgba(83,141,78,0.55);
  animation: sk-banner-in 300ms cubic-bezier(.2,.9,.3,1.4);
}
@keyframes sk-banner-in {
  from { opacity: 0; transform: translateY(20px) scale(0.92); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

@media (max-width: 480px) {
  .sudoku { gap: 10px; }
  .sk-board { padding: 6px; gap: 1px; }
  .sk-cell { border-radius: 3px; font-size: clamp(15px, 5vw, 20px); }
  .sk-pad { gap: 4px; padding: 8px; }
  .sk-pad-key { height: 42px; font-size: 18px; border-radius: 8px; }
  .sk-toolbar { flex-wrap: wrap; gap: 8px; }
  .sk-diff-btn { padding: 6px 10px; font-size: 12px; }
  .sk-action { padding: 8px 12px; font-size: 12px; }
}
.memory {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 640px;
  animation: mem-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes mem-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.mem-toolbar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.mem-size {
  display: inline-flex;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 3px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
}
.mem-size-btn {
  border: 0; background: transparent;
  color: rgba(255,255,255,0.7);
  font-weight: 700; font-size: 13px;
  padding: 6px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 200ms ease, color 200ms ease;
}
.mem-size-btn.active {
  background: rgba(255,255,255,0.18);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3);
}
.mem-stats { display: inline-flex; gap: 8px; }
.mem-stat {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-size: 13px;
}
.mem-stat-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.mem-stat-value { font-weight: 800; }

.mem-board {
  display: grid;
  gap: 10px;
  width: 100%;
  padding: 14px;
}

.mem-card {
  position: relative;
  aspect-ratio: 1 / 1;
  border: 0;
  background: transparent;
  padding: 0;
  cursor: pointer;
  perspective: 800px;
  transform-style: preserve-3d;
}
.mem-face {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 14px;
  border: 1px solid var(--glass-border);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  transition: transform 420ms cubic-bezier(.2,.9,.3,1.2);
  font-size: clamp(32px, 7vw, 44px);
  overflow: hidden;
}
.mem-back {
  background: linear-gradient(135deg, rgba(99,142,255,0.55), rgba(180,90,220,0.55));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    inset 0 -10px 20px rgba(0,0,0,0.18),
    0 6px 18px rgba(0,0,0,0.3);
}
.mem-back::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background:
    radial-gradient(50% 50% at 30% 30%, rgba(255,255,255,0.45), transparent 60%),
    repeating-linear-gradient(45deg, rgba(255,255,255,0.05) 0 8px, transparent 8px 16px);
  pointer-events: none;
}
.mem-front {
  /* No backdrop-filter: with 16–24 cards flipping (rotateY) in sequence,
     per-face blur re-composites stall mobile GPUs. The parent .panel is
     already frosted, so a solid translucent fill reads as glass. */
  background: rgba(255,255,255,0.18);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 8px 22px rgba(0,0,0,0.3);
  transform: rotateY(180deg);
}
.mem-front::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(160deg, rgba(255,255,255,0.35), rgba(255,255,255,0) 45%);
  pointer-events: none;
}
.mem-card.flipped .mem-back  { transform: rotateY(-180deg); }
.mem-card.flipped .mem-front { transform: rotateY(0deg); }
.mem-card.matched .mem-front {
  background: rgba(83, 141, 78, 0.42);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 0 26px rgba(83,200,90,0.45);
  animation: mem-pop 600ms ease;
}
@keyframes mem-pop {
  0%   { transform: rotateY(0deg) scale(1); }
  35%  { transform: rotateY(0deg) scale(1.08); }
  100% { transform: rotateY(0deg) scale(1); }
}

.mem-newgame {
  color: #fff; font-weight: 700; letter-spacing: 0.08em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 10px 18px; cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 18px rgba(0,0,0,0.25);
  transition: transform 150ms ease, background 200ms ease;
}
.mem-newgame:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.mem-newgame:active { transform: translateY(1px) scale(0.98); }

.mem-banner {
  position: fixed; left: 0; right: 0; bottom: 30px;
  display: flex; justify-content: center;
  pointer-events: none;
  z-index: 50;
}
.mem-banner-text {
  background: rgba(83, 141, 78, 0.55);
  border: 1px solid rgba(160,255,160,0.6);
  color: #fff;
  font-weight: 800; letter-spacing: 0.06em;
  padding: 12px 22px;
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 12px 36px rgba(83,141,78,0.55);
  animation: mem-banner-in 300ms cubic-bezier(.2,.9,.3,1.4);
}
@keyframes mem-banner-in {
  from { opacity: 0; transform: translateY(20px) scale(0.92); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

@media (max-width: 480px) {
  .mem-board { gap: 6px; padding: 8px; }
  .mem-face { font-size: clamp(24px, 8vw, 32px); border-radius: 10px; }
  .mem-toolbar { gap: 6px; }
  .mem-size-btn { padding: 6px 10px; font-size: 12px; }
  .mem-stat { padding: 6px 10px; font-size: 12px; }
}
.anagrams {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 620px;
  animation: ag-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes ag-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.ag-toolbar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.ag-stat {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-size: 13px;
}
.ag-stat-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.ag-stat-value { font-weight: 800; font-size: 14px; }

.ag-prompt {
  font-size: 13px;
  color: rgba(255,255,255,0.7);
  letter-spacing: 0.04em;
}

.ag-typed {
  display: flex; gap: 6px;
  padding: 6px;
}
.ag-typed-slot {
  width: 42px; height: 52px;
  border-radius: 10px;
  border: 1px dashed rgba(255,255,255,0.25);
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 800; font-size: 22px;
  background: rgba(255,255,255,0.04);
  transition: border-color 200ms ease, transform 150ms ease, background 200ms ease;
}
.ag-typed-slot.filled {
  border-style: solid;
  border-color: rgba(160,190,255,0.6);
  background: rgba(99,142,255,0.18);
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
@keyframes ag-pulse {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}
.ag-typed[class*="pulse-"] { animation: ag-pulse 360ms cubic-bezier(.2,.9,.3,1.4); }
@keyframes ag-shake {
  10%, 90% { transform: translateX(-2px); }
  30%, 70% { transform: translateX(-6px); }
  50%      { transform: translateX(6px); }
}
.ag-typed[class*="shake-"] { animation: ag-shake 0.4s cubic-bezier(.36,.07,.19,.97); }

.ag-letters {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;
}
.ag-letter {
  width: 56px; height: 56px;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  background: rgba(255,255,255,0.10);
  color: #fff; font-weight: 800; font-size: 22px;
  cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 6px 18px rgba(0,0,0,0.3);
  transition: transform 150ms cubic-bezier(.2,.9,.3,1.4), background 200ms ease;
}
.ag-letter:hover  { transform: translateY(-2px); background: rgba(255,255,255,0.18); }
.ag-letter:active { transform: translateY(2px) scale(0.94); }

.ag-actions {
  display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
}
.ag-btn {
  color: #fff; font-weight: 700; letter-spacing: 0.06em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 9px 16px; cursor: pointer;
  font-size: 13px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 18px rgba(0,0,0,0.2);
  transition: transform 150ms ease, background 200ms ease;
}
.ag-btn:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.ag-btn:active { transform: translateY(1px) scale(0.98); }
.ag-btn.primary {
  background: rgba(99, 142, 255, 0.5);
  border-color: rgba(180,210,255,0.6);
}

.message {
  min-height: 28px;
  display: flex; align-items: center; justify-content: center;
}
.ag-toast {
  background: rgba(255,255,255,0.18);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
  color: #fff; font-weight: 700;
  padding: 8px 14px; border-radius: 999px;
  animation: ag-toast-in 240ms cubic-bezier(.2,.9,.3,1.4);
  font-size: 13px;
}
@keyframes ag-toast-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.ag-list {
  width: 100%;
  max-height: 280px;
  overflow: auto;
}
.ag-list-title {
  margin: 0 0 8px;
  font-size: 12px; font-weight: 800;
  letter-spacing: 0.18em; color: rgba(255,255,255,0.7);
  text-transform: uppercase;
}
.ag-list-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 12px;
}
.ag-list-col {
  display: flex; flex-direction: column; gap: 4px;
  padding: 6px 8px;
  background: rgba(255,255,255,0.04);
  border-radius: 10px;
}
.ag-list-col-head {
  font-size: 11px; font-weight: 800;
  letter-spacing: 0.12em;
  color: rgba(255,255,255,0.55);
  text-transform: uppercase;
  margin-bottom: 2px;
}
.ag-list-word {
  font-size: 13px;
  color: rgba(255,255,255,0.45);
  letter-spacing: 0.05em;
  font-weight: 600;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.ag-list-word.got {
  color: #fff;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}

@media (max-width: 480px) {
  .anagrams { gap: 10px; }
  .ag-typed-slot { width: 34px; height: 44px; font-size: 18px; }
  .ag-letter { width: 46px; height: 46px; font-size: 18px; }
  .ag-list { max-height: 220px; }
}
.ws {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 640px;
  animation: ws-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes ws-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.ws-toolbar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.ws-stat {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-size: 13px;
}
.ws-stat-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.ws-stat-value { font-weight: 800; font-size: 14px; }

.ws-btn {
  color: #fff; font-weight: 700; letter-spacing: 0.06em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 9px 16px; cursor: pointer;
  font-size: 13px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: transform 150ms ease, background 200ms ease;
}
.ws-btn:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.ws-btn:active { transform: translateY(1px) scale(0.98); }

.ws-board {
  display: grid;
  width: 100%;
  aspect-ratio: 1 / 1;
  gap: 3px;
  padding: 8px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.ws-cell {
  position: relative;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.10);
  color: #fff;
  font-weight: 700;
  font-size: clamp(13px, 3.4vw, 18px);
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 120ms ease, transform 120ms ease;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
.ws-cell.sel {
  background: rgba(99, 142, 255, 0.55);
  border-color: rgba(180,210,255,0.85);
  transform: scale(1.04);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.4),
              0 4px 14px rgba(99,142,255,0.4);
}
.ws-cell.found {
  background: rgba(83, 141, 78, 0.5);
  border-color: rgba(160,255,160,0.5);
}
.ws-cell.found.sel {
  background: rgba(99, 142, 255, 0.55);
}

.ws-words {
  display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
}
.ws-word {
  padding: 4px 10px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  font-size: 13px;
  color: rgba(255,255,255,0.85);
  font-weight: 700;
  letter-spacing: 0.04em;
  transition: background 200ms ease, color 200ms ease, transform 200ms ease;
}
.ws-word.got {
  background: rgba(83, 141, 78, 0.45);
  border-color: rgba(160,255,160,0.45);
  color: #fff;
  text-decoration: line-through;
  opacity: 0.85;
}

.ws-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  letter-spacing: 0.04em;
}

.ws-banner {
  position: fixed; left: 0; right: 0; bottom: 30px;
  display: flex; justify-content: center;
  pointer-events: none;
  z-index: 50;
}
.ws-banner-text {
  background: rgba(83, 141, 78, 0.55);
  border: 1px solid rgba(160,255,160,0.6);
  color: #fff;
  font-weight: 800; letter-spacing: 0.08em;
  padding: 12px 22px;
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 12px 36px rgba(83,141,78,0.55);
  animation: ws-banner-in 300ms cubic-bezier(.2,.9,.3,1.4);
}
@keyframes ws-banner-in {
  from { opacity: 0; transform: translateY(20px) scale(0.92); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

@media (max-width: 480px) {
  .ws { gap: 10px; }
  .ws-board { gap: 2px; padding: 6px; }
  .ws-cell { border-radius: 4px; font-size: clamp(12px, 4vw, 16px); }
  .ws-word { font-size: 12px; padding: 4px 8px; }
}
.info-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  color: rgba(255,255,255,0.85);
  cursor: pointer;
  padding: 0;
  transition: background 160ms ease, color 160ms ease,
              border-color 160ms ease, transform 160ms ease;
}
.info-btn:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.28);
  color: #fff;
  transform: translateY(-1px);
}
.info-btn:focus-visible {
  outline: 2px solid rgba(255,255,255,0.45);
  outline-offset: 2px;
}

.info-backdrop {
  position: fixed; inset: 0;
  background: rgba(8, 10, 18, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  padding: 16px;
  animation: info-fade-in 180ms ease-out;
}
@keyframes info-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.info-panel {
  width: 100%;
  max-width: 420px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 20px;
  padding: 18px 20px 16px;
  color: #fff;
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 14px 30px rgba(0,0,0,0.35),
    0 0 0 1px rgba(99,142,255,0.18);
  animation: info-panel-in 320ms cubic-bezier(.2, 1.5, .3, 1);
}
@keyframes info-panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.info-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 10px;
  margin-bottom: 12px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
.info-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.78);
  margin: 0;
}
.info-close {
  background: transparent;
  border: none;
  color: rgba(255,255,255,0.6);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 8px;
  transition: background 160ms ease, color 160ms ease;
}
.info-close:hover { background: rgba(255,255,255,0.10); color: #fff; }

.info-body {
  font-size: 14px;
  line-height: 1.55;
  color: rgba(255,255,255,0.88);
}
.info-body p {
  margin: 0 0 10px;
}
.info-body p:last-child {
  margin-bottom: 0;
}
.boggle {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 520px;
  animation: bg-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes bg-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.bg-toolbar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.bg-stat {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-size: 13px;
}
.bg-stat-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.bg-stat-value {
  font-weight: 800; font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.bg-stat.danger .bg-stat-value {
  color: #ffb6b6;
  text-shadow: 0 0 12px rgba(255, 90, 90, 0.5);
}

.bg-btn {
  color: #fff; font-weight: 700; letter-spacing: 0.06em;
  background: rgba(99, 142, 255, 0.45);
  border: 1px solid rgba(180, 210, 255, 0.5);
  border-radius: 999px;
  padding: 9px 16px; cursor: pointer;
  font-size: 13px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 18px rgba(0,0,0,0.2);
  transition: transform 150ms ease, background 200ms ease;
}
.bg-btn:hover  { transform: translateY(-1px); background: rgba(99,142,255,0.6); }
.bg-btn:active { transform: translateY(1px) scale(0.98); }

.bg-typed {
  min-height: 32px;
  display: flex; align-items: center; justify-content: center;
}
.bg-typed-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  letter-spacing: 0.04em;
}
.bg-typed-word {
  background: rgba(99, 142, 255, 0.22);
  color: #fff;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid rgba(160,190,255,0.55);
  font-size: 16px;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}

.bg-board {
  display: grid;
  width: 100%;
  aspect-ratio: 1 / 1;
  gap: 8px;
  padding: 14px;
  user-select: none;
  -webkit-user-select: none;
  /* iOS Safari: suppress the long-press callout and tap-highlight that
     would otherwise interrupt the drag a couple of cells in. */
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
/* Only swallow touch gestures while a round is live. Outside of a round
   (pre-start blur, post-time-up review) the board is the largest target
   on the phone, and an unconditional `touch-action: none` blocked the
   user from scrolling the page to reach the found-words list and the
   daily-completion banner below the board. `.idle` is present iff
   `running` is false, so this also re-enables scroll the instant the
   timer hits zero. */
.bg-board:not(.idle) { touch-action: none; }
.bg-board.idle .bg-cell { opacity: 0.7; }

/* Pre-start state: blur the letters so the player can't pre-scan the board
   before deciding to start. The blur lifts the moment the round starts. */
.bg-board.unstarted .bg-cell {
  filter: blur(8px);
  pointer-events: none;
}

.bg-cell {
  position: relative;
  /* Solid translucent fill — no per-cell backdrop-filter. The board panel
     already supplies the glass blur once on its own surface; replicating
     it on each of the 16 cells caused massive GPU compositing cost on
     mobile (every .sel transform forced a re-blur per cell, dropping
     frames and stalling the drag). */
  background: rgba(40, 50, 80, 0.55);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-weight: 800;
  font-size: clamp(22px, 7vw, 34px);
  border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-drag: none;
  transition: background 120ms ease, transform 120ms ease,
              border-color 120ms ease, filter 240ms ease;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.3),
    inset 0 -10px 20px rgba(0,0,0,0.18),
    0 4px 14px rgba(0,0,0,0.25);
}
.bg-cell::before {
  content: ""; position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(160deg, rgba(255,255,255,0.32), rgba(255,255,255,0) 45%);
  pointer-events: none;
}
.bg-cell.sel {
  background: rgba(99, 142, 255, 0.55);
  border-color: rgba(180,210,255,0.85);
  transform: scale(1.04);
}
.bg-cell.last {
  background: rgba(160, 200, 255, 0.65);
  box-shadow: 0 0 28px rgba(99,142,255,0.6),
              inset 0 1px 0 rgba(255,255,255,0.5);
}

.message {
  min-height: 28px;
  display: flex; align-items: center; justify-content: center;
}
.bg-toast {
  background: rgba(255,255,255,0.18);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
  color: #fff; font-weight: 700;
  padding: 8px 14px; border-radius: 999px;
  animation: bg-toast-in 240ms cubic-bezier(.2,.9,.3,1.4);
  font-size: 13px;
}
@keyframes bg-toast-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.bg-found {
  width: 100%;
  max-height: 220px;
  overflow: auto;
}
.bg-found-title {
  margin: 0 0 8px;
  font-size: 12px; font-weight: 800;
  letter-spacing: 0.18em; color: rgba(255,255,255,0.7);
  text-transform: uppercase;
}
.bg-found-list {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.bg-found-word {
  background: rgba(83, 141, 78, 0.42);
  border: 1px solid rgba(160,255,160,0.4);
  color: #fff;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.bg-banner {
  position: fixed; left: 0; right: 0; bottom: 30px;
  display: flex; justify-content: center;
  pointer-events: none;
  z-index: 50;
}
.bg-banner-text {
  background: rgba(180, 60, 60, 0.55);
  border: 1px solid rgba(255,160,160,0.6);
  color: #fff;
  font-weight: 800; letter-spacing: 0.08em;
  padding: 12px 22px;
  border-radius: 999px;
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 12px 36px rgba(180,60,60,0.55);
  animation: bg-banner-in 300ms cubic-bezier(.2,.9,.3,1.4);
}
@keyframes bg-banner-in {
  from { opacity: 0; transform: translateY(20px) scale(0.92); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

@media (max-width: 480px) {
  .bg { gap: 10px; }
  /* Width-bounded by the viewport, height-bounded so the toolbar, typed
     hint, message line, and found-words list all fit inside the locked
     .game-stage without scrolling. The 380px subtraction is the rest of
     the chrome (~50 toolbar + ~32 typed + ~28 message + ~150 found list
     + ~40 gaps + ~80 inside-stage padding/header allowance). Clamped so
     the board can't collapse to nothing on very short viewports. */
  .boggle {
    --bg-board-size: clamp(
      220px,
      min(
        calc(100vw - 28px),
        calc(100svh - 380px - env(safe-area-inset-bottom))
      ),
      480px
    );
  }
  .bg-board {
    width: var(--bg-board-size);
    gap: 6px; padding: 10px;
  }
  .bg-cell { border-radius: 10px; font-size: clamp(20px, 8vw, 28px); }
  /* Drop the inner scroll on phones — the outer .game-stage already scrolls,
     and a nested scroller here lets iOS hijack the finger gesture before it
     can reach the daily-completion banner below. */
  .bg-found { max-height: none; overflow: visible; }

  /* When the daily-completion banner shares the locked stage with the
     game, reserve ~150px more vertical for the banner so the chips list
     plus banner fit below the (now shorter) board. */
  .game-stage:has(.daily-banner) .boggle {
    --bg-board-size: clamp(
      200px,
      min(
        calc(100vw - 28px),
        calc(100svh - 540px - env(safe-area-inset-bottom))
      ),
      480px
    );
  }
}
.cn {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 600px;
  animation: cn-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes cn-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.cn-toolbar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.cn-prompt {
  font-size: 13px;
  color: rgba(255,255,255,0.7);
  letter-spacing: 0.04em;
}
.cn-mistakes {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-size: 13px;
}
.cn-mistakes-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.cn-mistakes-dots {
  display: inline-flex; gap: 5px;
}
.cn-dot {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: rgba(255,255,255,0.7);
  box-shadow: 0 0 10px rgba(255,255,255,0.3);
  transition: background 200ms ease, transform 200ms ease;
}
.cn-dot.gone {
  background: rgba(180, 60, 60, 0.5);
  box-shadow: none;
  transform: scale(0.7);
}

.cn-solved {
  width: 100%;
  display: flex; flex-direction: column; gap: 6px;
}
.cn-solved-row {
  padding: 10px 14px;
  border-radius: 12px;
  text-align: center;
  color: #1a1a1a;
  font-weight: 800;
  letter-spacing: 0.04em;
  animation: cn-solved-in 380ms cubic-bezier(.2,.9,.3,1.4);
}
.cn-solved-row.diff-yellow { background: linear-gradient(135deg, #f9e08c, #f3c13a); }
.cn-solved-row.diff-green  { background: linear-gradient(135deg, #aede9a, #6fbf73); }
.cn-solved-row.diff-blue   { background: linear-gradient(135deg, #9fc5ff, #5a93ff); color: #0d1730; }
.cn-solved-row.diff-purple { background: linear-gradient(135deg, #cda1ff, #9b6fec); color: #1a1030; }
.cn-solved-cat { font-size: 14px; }
.cn-solved-words {
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  margin-top: 2px;
  opacity: 0.85;
}
@keyframes cn-solved-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.95); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.cn-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  width: 100%;
}
.cn-grid[class*=" k-"] { animation: cn-shake 0.45s cubic-bezier(.36,.07,.19,.97); }
@keyframes cn-shake {
  10%, 90% { transform: translateX(-2px); }
  30%, 70% { transform: translateX(-6px); }
  50%      { transform: translateX(6px); }
}

.cn-tile {
  border: 1px solid var(--glass-border);
  background: rgba(255,255,255,0.10);
  color: #fff;
  font-weight: 800;
  font-size: clamp(11px, 2.5vw, 14px);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  border-radius: 12px;
  cursor: pointer;
  padding: 14px 6px;
  min-height: 64px;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  word-break: break-word;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 4px 14px rgba(0,0,0,0.2);
  transition: transform 150ms cubic-bezier(.2,.9,.3,1.4), background 200ms ease;
}
.cn-tile:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.cn-tile:active { transform: translateY(1px) scale(0.98); }
.cn-tile.on {
  background: rgba(40,40,50,0.85);
  border-color: rgba(255,255,255,0.4);
  color: #fff;
  transform: scale(0.96);
}
.cn-tile:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.cn-actions {
  display: flex; gap: 8px; flex-wrap: wrap; justify-content: center;
}
.cn-btn {
  color: #fff; font-weight: 700; letter-spacing: 0.05em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 9px 16px; cursor: pointer;
  font-size: 13px;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: transform 150ms ease, background 200ms ease;
}
.cn-btn:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.cn-btn:active { transform: translateY(1px) scale(0.98); }
.cn-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.cn-btn.primary {
  background: rgba(99, 142, 255, 0.5);
  border-color: rgba(180,210,255,0.6);
}

.message {
  min-height: 28px;
  display: flex; align-items: center; justify-content: center;
}
.cn-toast {
  background: rgba(255,255,255,0.18);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid var(--glass-border);
  color: #fff; font-weight: 700;
  padding: 8px 14px; border-radius: 999px;
  animation: cn-toast-in 240ms cubic-bezier(.2,.9,.3,1.4);
  font-size: 13px;
}
@keyframes cn-toast-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

@media (max-width: 480px) {
  .cn { gap: 10px; }
  .cn-tile { min-height: 56px; padding: 10px 4px; font-size: clamp(10px, 3vw, 12px); }
  .cn-toolbar { gap: 6px; }
  .cn-solved-cat { font-size: 13px; }
  .cn-solved-words { font-size: 11px; }
}
.bricks {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 480px;
}

.bricks-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.bricks-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 72px;
}
.bricks-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.bricks-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: #fff;
}

.bricks-stage {
  position: relative;
  width: 100%;
  /* The world is 600 × 800 (3:4). The canvas scales to width and the
     aspect-ratio keeps the height honest on every device. */
  aspect-ratio: 3 / 4;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  /* No drag-to-scroll while steering the paddle on touch devices. */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
}

.bricks-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.bricks-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.bricks-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
}

.bricks-msg-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
}
.bricks-msg-sub {
  font-size: 13px;
  color: rgba(255,255,255,0.78);
  font-variant-numeric: tabular-nums;
}
.bricks-msg-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  font-style: italic;
}

.bricks-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.bricks-restart:hover {
  background: rgba(255,255,255,0.22);
  transform: translateY(-1px);
}
.bricks-restart:active {
  transform: translateY(1px) scale(0.98);
}

.bricks-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

@media (max-width: 480px) {
  .bricks { gap: 10px; }
  .bricks-toolbar { gap: 10px; }
  .bricks-stat { min-width: 64px; padding: 5px 12px; }
  .bricks-stat-value { font-size: 14px; }
  .bricks-msg-title { font-size: 18px; }
}
.snake {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 480px;
}

.snake-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.snake-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 72px;
}
.snake-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.snake-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.snake-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: crosshair;
  background: rgba(255,255,255,0.04);
}

.snake-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.snake-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.snake-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}

.snake-msg-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.snake-msg-sub {
  font-size: 13px;
  color: rgba(255,255,255,0.78);
  font-variant-numeric: tabular-nums;
}
.snake-msg-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  font-style: italic;
}

.snake-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.snake-restart:hover {
  background: rgba(255,255,255,0.22);
  transform: translateY(-1px);
}
.snake-restart:active {
  transform: translateY(1px) scale(0.98);
}

/* On-screen D-pad. Touch devices get the buttons; pointers with a real
   hover capability use the keyboard or board swipe and don't need them. */
.snake-dpad {
  display: grid;
  grid-template-columns: repeat(3, 56px);
  grid-template-rows: repeat(3, 56px);
  gap: 6px;
  margin-top: 4px;
}
@media (hover: hover) and (pointer: fine) {
  .snake-dpad { display: none; }
}

.snake-dpad-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: #fff;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  font: inherit;
  font-weight: 700;
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
}
.snake-dpad-btn:active {
  background: rgba(255,255,255,0.18);
  transform: scale(0.95);
}
.snake-dpad-up    { grid-column: 2; grid-row: 1; }
.snake-dpad-left  { grid-column: 1; grid-row: 2; }
.snake-dpad-right { grid-column: 3; grid-row: 2; }
.snake-dpad-down  { grid-column: 2; grid-row: 3; }

.snake-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

@media (max-width: 480px) {
  .snake { gap: 10px; }
  .snake-toolbar { gap: 10px; }
  .snake-stat { min-width: 64px; padding: 5px 12px; }
  .snake-stat-value { font-size: 14px; }
  .snake-msg-title { font-size: 18px; }
  .snake-dpad {
    grid-template-columns: repeat(3, 52px);
    grid-template-rows: repeat(3, 52px);
  }
}
.invaders {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 480px;
}

.invaders-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.invaders-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 72px;
}
.invaders-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.invaders-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.invaders-stage {
  position: relative;
  width: 100%;
  /* World is 600 × 800 (3:4) — same as Bricks. */
  aspect-ratio: 3 / 4;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: crosshair;
  background:
    radial-gradient(circle at 20% 14%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 78% 22%, rgba(255,255,255,0.4) 0 1px, transparent 2px),
    radial-gradient(circle at 42% 8%,  rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 92% 36%, rgba(255,255,255,0.35) 0 1px, transparent 2px),
    radial-gradient(circle at 12% 60%, rgba(255,255,255,0.35) 0 1px, transparent 2px),
    radial-gradient(circle at 64% 70%, rgba(255,255,255,0.4) 0 1px, transparent 2px),
    radial-gradient(ellipse at 50% 100%, rgba(34,211,238,0.18) 0%, transparent 60%),
    linear-gradient(180deg, #050518 0%, #0b1226 100%);
}

.invaders-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.invaders-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.invaders-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}

.invaders-msg-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.invaders-msg-sub {
  font-size: 13px;
  color: rgba(255,255,255,0.78);
  font-variant-numeric: tabular-nums;
}
.invaders-msg-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  font-style: italic;
}

.invaders-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.invaders-restart:hover {
  background: rgba(255,255,255,0.22);
  transform: translateY(-1px);
}
.invaders-restart:active {
  transform: translateY(1px) scale(0.98);
}

/* Mobile-only fire button. Touch devices need an explicit shoot affordance
   so the player isn't relying on tap-while-dragging. Hidden on devices with
   a real hover/fine pointer (mouse + keyboard cover those cases). */
.invaders-fire {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 88px;
  height: 56px;
  border-radius: 16px;
  border: 1px solid var(--glass-border);
  background: rgba(34,211,238,0.18);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  user-select: none;
  -webkit-user-select: none;
}
.invaders-fire:active {
  background: rgba(34,211,238,0.34);
  transform: scale(0.97);
}
@media (hover: hover) and (pointer: fine) {
  .invaders-fire { display: none; }
}

.invaders-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

@media (max-width: 480px) {
  .invaders { gap: 10px; }
  .invaders-toolbar { gap: 10px; }
  .invaders-stat { min-width: 64px; padding: 5px 12px; }
  .invaders-stat-value { font-size: 14px; }
  .invaders-msg-title { font-size: 18px; }
}
.ast {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 480px;
}

.ast-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.ast-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 72px;
}
.ast-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.ast-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.ast-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: crosshair;
  background:
    radial-gradient(circle at 18% 12%, rgba(255,255,255,0.55) 0 1px, transparent 2px),
    radial-gradient(circle at 72% 24%, rgba(255,255,255,0.42) 0 1px, transparent 2px),
    radial-gradient(circle at 38% 8%,  rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 88% 56%, rgba(255,255,255,0.32) 0 1px, transparent 2px),
    radial-gradient(circle at 12% 64%, rgba(255,255,255,0.32) 0 1px, transparent 2px),
    radial-gradient(circle at 58% 76%, rgba(255,255,255,0.42) 0 1px, transparent 2px),
    radial-gradient(circle at 30% 90%, rgba(255,255,255,0.3) 0 1px, transparent 2px),
    linear-gradient(160deg, #060617 0%, #0b0f24 100%);
}

.ast-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.ast-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.ast-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}

.ast-msg-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.ast-msg-sub {
  font-size: 13px;
  color: rgba(255,255,255,0.78);
  font-variant-numeric: tabular-nums;
}
.ast-msg-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  font-style: italic;
}

.ast-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.ast-restart:hover {
  background: rgba(255,255,255,0.22);
  transform: translateY(-1px);
}
.ast-restart:active {
  transform: translateY(1px) scale(0.98);
}

/* Touch-only control panel: rotate L/R on the left, thrust + fire on the
   right. Hidden on hover-capable / fine pointer devices. */
.ast-controls {
  display: flex;
  width: 100%;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding: 0 4px;
  box-sizing: border-box;
}
.ast-pad-group {
  display: flex;
  gap: 8px;
}
.ast-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 56px;
  border-radius: 16px;
  border: 1px solid var(--glass-border);
  background: rgba(255,255,255,0.08);
  color: #fff;
  font: inherit;
  font-size: 22px;
  font-weight: 700;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
}
.ast-btn-thrust { background: rgba(251,146,60,0.20); }
.ast-btn-fire {
  background: rgba(34,211,238,0.20);
  font-size: 18px;
}
.ast-btn:active {
  transform: scale(0.96);
  background: rgba(255,255,255,0.18);
}

@media (hover: hover) and (pointer: fine) {
  .ast-controls { display: none; }
}

.ast-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

/* Modality-aware copy: default = touch (matches `.ast-controls`); fine
   pointers see the keyboard variants. Pair: `.ast-start-touch` /
   `.ast-start-kb`, `.ast-hint-touch` / `.ast-hint-kb`. */
.ast-start-kb,
.ast-hint-kb { display: none; }
@media (hover: hover) and (pointer: fine) {
  .ast-start-touch,
  .ast-hint-touch { display: none; }
  .ast-start-kb,
  .ast-hint-kb { display: block; }
}

@media (max-width: 480px) {
  .ast { gap: 10px; }
  .ast-toolbar { gap: 10px; }
  .ast-stat { min-width: 64px; padding: 5px 12px; }
  .ast-stat-value { font-size: 14px; }
  .ast-msg-title { font-size: 18px; }
  .ast-btn { width: 58px; height: 52px; }
}
.sq {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 480px;
}

.sq-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.sq-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 72px;
}
.sq-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.sq-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.sq-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 4;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: crosshair;
  background:
    radial-gradient(circle at 20% 14%, rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 78% 22%, rgba(255,255,255,0.4) 0 1px, transparent 2px),
    radial-gradient(circle at 42% 8%,  rgba(255,255,255,0.5) 0 1px, transparent 2px),
    radial-gradient(circle at 92% 36%, rgba(255,255,255,0.35) 0 1px, transparent 2px),
    radial-gradient(circle at 12% 60%, rgba(255,255,255,0.35) 0 1px, transparent 2px),
    radial-gradient(circle at 64% 70%, rgba(255,255,255,0.4) 0 1px, transparent 2px),
    linear-gradient(180deg, #1b1430 0%, #2a0e3a 100%);
}

.sq-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.sq-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.sq-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}

.sq-msg-title { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; }
.sq-msg-sub { font-size: 13px; color: rgba(255,255,255,0.78); font-variant-numeric: tabular-nums; }
.sq-msg-hint { font-size: 12px; color: rgba(255,255,255,0.55); font-style: italic; }

.sq-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.sq-restart:hover { background: rgba(255,255,255,0.22); transform: translateY(-1px); }
.sq-restart:active { transform: translateY(1px) scale(0.98); }

.sq-fire {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 88px;
  height: 56px;
  border-radius: 16px;
  border: 1px solid var(--glass-border);
  background: rgba(244,114,182,0.20);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  user-select: none;
  -webkit-user-select: none;
}
.sq-fire:active {
  background: rgba(244,114,182,0.36);
  transform: scale(0.97);
}
@media (hover: hover) and (pointer: fine) {
  .sq-fire { display: none; }
}

.sq-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

@media (max-width: 480px) {
  .sq { gap: 10px; }
  .sq-toolbar { gap: 10px; }
  .sq-stat { min-width: 64px; padding: 5px 12px; }
  .sq-stat-value { font-size: 14px; }
  .sq-msg-title { font-size: 18px; }
}
.df {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 520px;
}

.df-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.df-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 64px;
}
.df-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.df-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.df-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: crosshair;
  background:
    radial-gradient(circle at 14% 20%, rgba(255,255,255,0.4) 0 1px, transparent 2px),
    radial-gradient(circle at 70% 26%, rgba(255,255,255,0.3) 0 1px, transparent 2px),
    radial-gradient(circle at 38% 80%, rgba(255,255,255,0.25) 0 1px, transparent 2px),
    linear-gradient(180deg, #052e1b 0%, #170b13 60%, #2a0712 100%);
}

.df-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.df-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.df-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}
.df-msg-title { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; }
.df-msg-sub { font-size: 13px; color: rgba(255,255,255,0.78); font-variant-numeric: tabular-nums; }
.df-msg-hint { font-size: 12px; color: rgba(255,255,255,0.55); font-style: italic; }

.df-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.df-restart:hover { background: rgba(255,255,255,0.22); transform: translateY(-1px); }
.df-restart:active { transform: translateY(1px) scale(0.98); }

.df-controls {
  display: flex;
  width: 100%;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding: 0 4px;
  box-sizing: border-box;
}

.df-pad {
  display: grid;
  grid-template-columns: repeat(3, 52px);
  grid-template-rows: repeat(3, 52px);
  gap: 6px;
}
.df-btn-up    { grid-column: 2; grid-row: 1; }
.df-btn-left  { grid-column: 1; grid-row: 2; }
.df-btn-right { grid-column: 3; grid-row: 2; }
.df-btn-down  { grid-column: 2; grid-row: 3; }

.df-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  border: 1px solid var(--glass-border);
  background: rgba(255,255,255,0.08);
  color: #fff;
  font: inherit;
  font-size: 18px;
  font-weight: 700;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
}
.df-btn-fire {
  width: 64px;
  height: 64px;
  background: rgba(34,211,238,0.22);
}
.df-btn:active {
  transform: scale(0.96);
  background: rgba(255,255,255,0.18);
}

@media (hover: hover) and (pointer: fine) {
  .df-controls { display: none; }
}

.df-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

/* Default = touch (matches `.df-controls`); fine pointers see the kb copy. */
.df-hint-kb { display: none; }
@media (hover: hover) and (pointer: fine) {
  .df-hint-touch { display: none; }
  .df-hint-kb { display: block; }
}

@media (max-width: 480px) {
  .df { gap: 10px; }
  .df-toolbar { gap: 10px; }
  .df-stat { min-width: 60px; padding: 5px 12px; }
  .df-stat-value { font-size: 14px; }
  .df-msg-title { font-size: 18px; }
  .df-pad {
    grid-template-columns: repeat(3, 48px);
    grid-template-rows: repeat(3, 48px);
  }
  .df-btn { width: 48px; height: 48px; }
  .df-btn-fire { width: 60px; height: 60px; }
}
.ch {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 480px;
}

.ch-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}

.ch-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 64px;
}
.ch-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.ch-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.ch-stage {
  position: relative;
  width: 100%;
  /* Square maze. */
  aspect-ratio: 1 / 1;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: crosshair;
  background: linear-gradient(180deg, #0a0c20 0%, #100922 100%);
}

.ch-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.ch-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.ch-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}

.ch-msg-title { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; }
.ch-msg-sub { font-size: 13px; color: rgba(255,255,255,0.78); font-variant-numeric: tabular-nums; }
.ch-msg-hint { font-size: 12px; color: rgba(255,255,255,0.55); font-style: italic; }

.ch-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.ch-restart:hover { background: rgba(255,255,255,0.22); transform: translateY(-1px); }
.ch-restart:active { transform: translateY(1px) scale(0.98); }

.ch-dpad {
  display: grid;
  grid-template-columns: repeat(3, 56px);
  grid-template-rows: repeat(3, 56px);
  gap: 6px;
  margin-top: 4px;
}
@media (hover: hover) and (pointer: fine) {
  .ch-dpad { display: none; }
}

.ch-dpad-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: #fff;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  font: inherit;
  font-weight: 700;
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
}
.ch-dpad-btn:active {
  background: rgba(255,255,255,0.18);
  transform: scale(0.95);
}
.ch-dpad-up    { grid-column: 2; grid-row: 1; }
.ch-dpad-left  { grid-column: 1; grid-row: 2; }
.ch-dpad-right { grid-column: 3; grid-row: 2; }
.ch-dpad-down  { grid-column: 2; grid-row: 3; }

.ch-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

@media (max-width: 480px) {
  .ch { gap: 10px; }
  .ch-toolbar { gap: 10px; }
  .ch-stat { min-width: 60px; padding: 5px 12px; }
  .ch-stat-value { font-size: 14px; }
  .ch-msg-title { font-size: 18px; }
  .ch-dpad {
    grid-template-columns: repeat(3, 52px);
    grid-template-rows: repeat(3, 52px);
  }
}
.stk {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 360px;
}

.stk-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}

.stk-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 56px;
}
.stk-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.stk-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.stk-stat--next {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
.stk-next {
  display: block;
  width: 56px;
  height: 28px;
}

.stk-stage {
  position: relative;
  width: 100%;
  /* 10×20 board → 1:2 ratio. */
  aspect-ratio: 1 / 2;
  padding: 0;
  overflow: hidden;
  border-radius: 14px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: pointer;
  background: linear-gradient(180deg, #0a0e22 0%, #1a0a2e 100%);
}

.stk-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.stk-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.stk-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}
.stk-msg-title { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; }
.stk-msg-sub { font-size: 13px; color: rgba(255,255,255,0.78); font-variant-numeric: tabular-nums; }
.stk-msg-hint { font-size: 12px; color: rgba(255,255,255,0.55); font-style: italic; }

.stk-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.stk-restart:hover { background: rgba(255,255,255,0.22); transform: translateY(-1px); }
.stk-restart:active { transform: translateY(1px) scale(0.98); }

.stk-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

.stk-hint-kb { display: none; }
@media (hover: hover) and (pointer: fine) {
  .stk-hint-touch { display: none; }
  .stk-hint-kb { display: block; }
}

@media (max-width: 480px) {
  /* Cell size is the smaller of the width-bound (viewport minus padding,
     divided by 10 cols) and the height-bound (100svh minus chrome and
     other .stk content, divided by 20 rows). The stage's pixel
     dimensions follow from that, so the whole 10×20 board always fits —
     never wider than the viewport, never taller than the available
     height. */
  .stk {
    --stk-cell: clamp(
      12px,
      min(
        calc((100vw - 28px) / 10),
        calc((100svh - 180px - env(safe-area-inset-bottom)) / 20)
      ),
      32px
    );
    gap: 8px;
    max-width: none;
  }

  /* Condense toolbar to a single row so it stops eating two rows of
     vertical budget. Drop the stat labels — values alone are meaningful
     for score/lines/level, and the next-piece preview is self-explanatory. */
  .stk-toolbar { gap: 6px; flex-wrap: nowrap; }
  .stk-stat-label { display: none; }
  .stk-stat {
    flex-direction: row;
    align-items: center;
    min-width: 0;
    padding: 5px 12px;
    gap: 6px;
  }
  .stk-stat-value { font-size: 14px; }
  .stk-stat--next { padding: 4px 8px; }
  .stk-next { width: 48px; height: 24px; }
  .stk-msg-title { font-size: 18px; }

  /* Stage sized explicitly from the cell variable. 10 cols × 20 rows,
     guaranteed to fit both axes. */
  .stk-stage {
    flex: 0 0 auto;
    align-self: center;
    width: calc(var(--stk-cell) * 10);
    height: calc(var(--stk-cell) * 20);
    aspect-ratio: auto;
    max-width: none;
  }

  .stk-hint { font-size: 11px; }
}
.cb {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 360px;
}

.cb-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}

.cb-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 56px;
}
.cb-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.cb-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.cb-stat--next {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
.cb-next {
  display: block;
  width: 56px;
  height: 28px;
}

.cb-stage {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: row;
  padding: 0;
  overflow: hidden;
  border-radius: 14px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  background: rgba(255,255,255,0.02);
}

/* Tier ladder strip on the left. Stretches to the playfield height; the
   10 slots split it equally so each "bead" lines up with the visual scale
   of the playfield rows. */
.cb-sidebar {
  flex: 0 0 28px;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0, 0.45);
  border-right: 1px solid rgba(255,255,255,0.08);
}
.cb-tier-slot {
  flex: 1;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cb-tier-bead {
  display: block;
  width: 70%;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  border: 1.5px solid;
  box-shadow:
    inset -2px -3px 4px rgba(0,0,0,0.35),
    inset 2px 2px 3px rgba(255,255,255,0.45);
  opacity: 0.28;          /* default = not reached yet */
  transition: opacity 200ms ease;
}
.cb-tier-slot.is-reached .cb-tier-bead {
  opacity: 1;
}
.cb-tier-slot.is-current::after {
  content: '◂';
  position: absolute;
  right: 1px;
  color: #fff;
  font-size: 10px;
  line-height: 1;
  text-shadow: 0 0 4px rgba(0,0,0,0.6);
}

.cb-playfield {
  flex: 1;
  position: relative;
  aspect-ratio: 1 / 2;     /* matches the 6x12 canvas */
  cursor: pointer;
  background:
    radial-gradient(ellipse at 30% 0%, rgba(56,189,248,0.18) 0%, transparent 60%),
    linear-gradient(180deg, #0a1226 0%, #0e1730 100%);
}

.cb-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.cb-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

.cb-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
  text-align: center;
  background: rgba(20, 22, 32, 0.78);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 80%;
  color: #fff;
}
.cb-msg-title { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; }
.cb-msg-sub { font-size: 13px; color: rgba(255,255,255,0.78); font-variant-numeric: tabular-nums; }
.cb-msg-hint { font-size: 12px; color: rgba(255,255,255,0.55); font-style: italic; }

.cb-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.cb-restart:hover { background: rgba(255,255,255,0.22); transform: translateY(-1px); }
.cb-restart:active { transform: translateY(1px) scale(0.98); }

/* Segmented mode toggle on the pre-start overlay. */
.cb-mode {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  margin-top: 6px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.06);
}
.cb-mode-pill {
  padding: 6px 12px;
  border-radius: 999px;
  border: 0;
  background: transparent;
  color: rgba(255,255,255,0.7);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background 160ms ease, color 160ms ease;
}
.cb-mode-pill:hover { color: #fff; }
.cb-mode-pill.is-active {
  background: rgba(255,255,255,0.18);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
}

/* Touch-only control row. Hidden on hover-capable pointers. */
.cb-controls {
  display: flex;
  gap: 8px;
  width: 100%;
  justify-content: center;
  flex-wrap: wrap;
}
.cb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 14px;
  border: 1px solid var(--glass-border);
  background: rgba(255,255,255,0.08);
  color: #fff;
  font: inherit;
  font-size: 22px;
  font-weight: 700;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
}
.cb-btn-drop { background: rgba(34,211,238,0.20); }
.cb-btn:active {
  transform: scale(0.96);
  background: rgba(255,255,255,0.18);
}
@media (hover: hover) and (pointer: fine) {
  .cb-controls { display: none; }
}

.cb-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}

/* Default = touch (matches `.cb-controls`); fine pointers see the kb copy. */
.cb-hint-kb { display: none; }
@media (hover: hover) and (pointer: fine) {
  .cb-hint-touch { display: none; }
  .cb-hint-kb { display: block; }
}

@media (max-width: 480px) {
  /* Fill the locked .game-stage. The cell size is the smaller of the
     width-bound (viewport minus padding minus sidebar, divided by 6 cols)
     and the height-bound (100svh minus chrome and other .cb content,
     divided by 12 rows). The playfield's pixel dimensions follow from
     that, so the whole board always fits — never wider than the
     viewport, never taller than the available height. */
  .cb {
    --cb-cell: clamp(
      18px,
      min(
        calc((100vw - 60px) / 6),
        calc((100svh - 270px - env(safe-area-inset-bottom)) / 12)
      ),
      52px
    );
    height: 100%;
    max-width: none;
    box-sizing: border-box;
    padding: 0;
    gap: 8px;
  }

  /* Toolbar: condense to one row of compact controls. Drop labels —
     the value alone is meaningful for score (a number), the next-piece
     visual is self-explanatory, and the leaderboard button collapses to
     its trophy icon (handled in LeaderboardButton.css). */
  .cb-toolbar { gap: 6px; flex-wrap: nowrap; }
  .cb-stat-label { display: none; }
  .cb-stat {
    flex-direction: row;
    align-items: center;
    min-width: 0;
    padding: 5px 12px;
    gap: 6px;
  }
  .cb-stat-value { font-size: 14px; }
  .cb-stat--next { padding: 4px 8px; }
  .cb-next { width: 48px; height: 24px; }
  .cb-msg-title { font-size: 18px; }

  /* Stage sized explicitly from the cell variable. Sidebar 22 + 6 cols
     wide, 12 rows tall — guaranteed to fit both axes. */
  .cb-stage {
    flex: 0 0 auto;
    align-self: center;
    width: calc(var(--cb-cell) * 6 + 22px);
    height: calc(var(--cb-cell) * 12);
  }
  .cb-playfield {
    flex: 1;
    aspect-ratio: auto;
    height: 100%;
    width: auto;
  }
  .cb-sidebar { flex-basis: 22px; }

  .cb-controls { gap: 6px; }
  .cb-btn { width: 48px; height: 48px; font-size: 18px; border-radius: 12px; }
  .cb-hint { font-size: 11px; }

  /* When the daily completion banner shares the locked stage with the
     game, reserve ~150px of vertical space for it by enlarging the
     chrome budget in the cell formula, and let .cb size to its
     content so the banner fits below it inline (no scroll needed). */
  .game-stage:has(.daily-banner) > .cb {
    --cb-cell: clamp(
      16px,
      min(
        calc((100vw - 60px) / 6),
        calc((100svh - 420px - env(safe-area-inset-bottom)) / 12)
      ),
      52px
    );
    height: auto;
  }
}
.spellingbee {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 620px;
  animation: sb-in 380ms cubic-bezier(.2,.9,.3,1.2);
}
@keyframes sb-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.sb-toolbar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.sb-stat {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-size: 13px;
}
.sb-stat-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.sb-stat-value { font-weight: 800; font-size: 14px; }

.sb-prompt {
  font-size: 13px;
  color: rgba(255,255,255,0.7);
  letter-spacing: 0.02em;
  text-align: center;
  max-width: 480px;
}

.sb-typed {
  min-height: 44px;
  display: flex; align-items: center; gap: 2px;
  padding: 6px 14px;
  letter-spacing: 0.04em;
  color: #fff; font-weight: 800; font-size: 26px;
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
  transition: transform 150ms ease;
}
.sb-typed-empty { color: rgba(255,255,255,0.35); font-size: 22px; }
.sb-typed-ch { display: inline-block; }
.sb-typed-ch.is-center { color: var(--sb-gold, #facc15); }
.sb-typed-ch.is-bad    { color: rgba(255,120,120,0.85); }
@keyframes sb-pulse {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.08); }
  100% { transform: scale(1); }
}
.sb-typed[class*="pulse-"] {
  animation: sb-pulse 360ms cubic-bezier(.2,.9,.3,1.4);
}
@keyframes sb-shake {
  10%, 90% { transform: translateX(-2px); }
  30%, 70% { transform: translateX(-6px); }
  50%      { transform: translateX(6px); }
}
.sb-typed[class*="shake-"] {
  animation: sb-shake 0.4s cubic-bezier(.36,.07,.19,.97);
}

/* ----- Honeycomb ----- */
.sb-honeycomb {
  /* Pointy-top regular hexagon: W (flat-to-flat) × H (point-to-point),
     where H = W × 2/√3 ≈ W × 1.155. Cells in a row touch flat-to-flat
     (gap 0); rows overlap by H/4 so the 4 corner neighbours interlock at
     the canonical (±W/2, ±3H/4) offsets of a 6-around-1 honeycomb. */
  --sb-cell-w: 86px;
  --sb-cell-h: 99px;
  --sb-row-overlap: 25px; /* H/4 */
  --sb-gold: #facc15;
  display: flex; flex-direction: column; align-items: center;
  padding: 6px 4px 8px;
}
.sb-row {
  display: flex; gap: 0;
}
/* Rows 1 and 3 (the outer pairs) interlock with the middle row by sitting
   above/below at a vertical overlap. Negative margin pulls them in so the
   hex points meet visually like a flower. */
.sb-row + .sb-row {
  margin-top: calc(-1 * var(--sb-row-overlap));
}

.sb-hex {
  appearance: none;
  border: 0;
  padding: 0; margin: 0;
  width: var(--sb-cell-w);
  height: var(--sb-cell-h);
  position: relative;
  cursor: pointer;
  background: transparent;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.25));
  transition: transform 140ms cubic-bezier(.2,.9,.3,1.4);
}
.sb-hex:hover  { transform: translateY(-2px); }
.sb-hex:active { transform: translateY(2px) scale(0.96); }

.sb-hex-face {
  position: absolute; inset: 0;
  /* Pointy-top regular hexagon, vertices in % of bounding box: */
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.18), rgba(255,255,255,0.06));
  border: 1px solid rgba(255,255,255,0.18);
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  font-weight: 900; font-size: 26px;
  letter-spacing: 0.04em;
  text-shadow: 0 1px 2px rgba(0,0,0,0.45);
  user-select: none;
}
.sb-hex.is-center .sb-hex-face {
  background:
    linear-gradient(180deg, #fde68a 0%, #facc15 55%, #ca8a04 100%);
  border-color: rgba(255, 240, 180, 0.8);
  color: #2a1a00;
  text-shadow: 0 1px 0 rgba(255,255,255,0.5);
}

/* ----- Actions / buttons ----- */
.sb-actions {
  display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
}
.sb-btn {
  color: #fff; font-weight: 700; letter-spacing: 0.06em;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 9px 16px; cursor: pointer;
  font-size: 13px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.3),
    0 6px 18px rgba(0,0,0,0.2);
  transition: transform 150ms ease, background 200ms ease;
}
.sb-btn:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.sb-btn:active { transform: translateY(1px) scale(0.98); }
.sb-btn.primary {
  background: linear-gradient(180deg, #fde68a 0%, #facc15 100%);
  color: #2a1a00;
  border-color: rgba(255, 240, 180, 0.7);
}

.message {
  min-height: 28px;
  display: flex; align-items: center; justify-content: center;
}
.sb-toast {
  background: rgba(255,255,255,0.18);
  border: 1px solid var(--glass-border);
  color: #fff; font-weight: 700;
  padding: 8px 14px; border-radius: 999px;
  animation: sb-toast-in 240ms cubic-bezier(.2,.9,.3,1.4);
  font-size: 13px;
}
@keyframes sb-toast-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

/* Pangram celebration: brief gold flash across the whole component. */
@keyframes sb-pangram-flash {
  0%   { box-shadow: 0 0 0 0 rgba(250, 204, 21, 0.0); }
  20%  { box-shadow: 0 0 0 8px rgba(250, 204, 21, 0.25); }
  100% { box-shadow: 0 0 0 0 rgba(250, 204, 21, 0.0); }
}
.spellingbee.pangram-flash .sb-honeycomb {
  border-radius: 24px;
  animation: sb-pangram-flash 900ms ease-out;
}

/* ----- Found list ----- */
.sb-found {
  width: 100%;
  max-height: 240px;
  overflow: auto;
}
.sb-found-title {
  margin: 0 0 8px;
  font-size: 12px; font-weight: 800;
  letter-spacing: 0.16em; color: rgba(255,255,255,0.7);
  text-transform: uppercase;
}
.sb-found-sub {
  font-weight: 600; color: rgba(255,255,255,0.5);
  letter-spacing: 0.1em;
  text-transform: none;
}
.sb-found-list {
  display: flex; flex-wrap: wrap; gap: 6px 10px;
}
.sb-found-empty {
  color: rgba(255,255,255,0.45);
  font-size: 13px;
}
.sb-found-word {
  font-size: 13px;
  color: rgba(255,255,255,0.85);
  letter-spacing: 0.04em;
  font-weight: 700;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  text-transform: lowercase;
}
.sb-found-word.is-pangram {
  color: var(--sb-gold, #facc15);
  text-shadow: 0 1px 2px rgba(0,0,0,0.4);
}

@media (max-width: 480px) {
  .spellingbee { gap: 10px; }
  .sb-honeycomb {
    --sb-cell-w: 72px;
    --sb-cell-h: 83px;
    --sb-row-overlap: 21px;
  }
  .sb-hex-face { font-size: 22px; }
  .sb-typed { font-size: 22px; min-height: 38px; }
  .sb-found { max-height: 200px; }
}
.rosco {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 520px;
}

/* ---------- Toolbar ---------- */
.rosco-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}
.rosco-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 5px 12px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 48px;
  font-variant-numeric: tabular-nums;
}
.rosco-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.rosco-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
}
.rosco-time.is-low .rosco-stat-value {
  color: #ffb4a8;
  text-shadow: 0 0 8px rgba(255,140,120,0.55);
}

/* ---------- Ring ----------
   25 letters around the perimeter. The ring is just visual now — the
   clue + input + buttons live in .rosco-panel below, so the inner
   space only has to fit a decorative big-letter focal point.

   --rosco-radius must be a length, not a percentage: translate() %'s
   resolve against the *transformed element* (the letter) in CSS, not
   the ring container, so a "46%" radius would clump every letter near
   the center instead of putting them on the perimeter. Computing it
   from --rosco-size keeps the ring proportional to whatever size the
   container ends up at. */
.rosco-ring {
  position: relative;
  /* CRITICAL: --rosco-size must only contain length units (px, vw),
     never percentages. The value flows into --rosco-radius which is
     used inside translateY() — and percentages inside translate()
     resolve against the *element being transformed* (the 40px chip),
     not the ring container. A `90%` here silently turned into "90%
     of 40px = 36px" and collapsed the radius to negative, stacking
     every chip at the ring's center. vw resolves against the
     viewport in every context, so the math stays consistent. */
  --rosco-size: min(380px, 88vw);
  --rosco-letter-size: 40px;
  --rosco-radius: calc((var(--rosco-size) - var(--rosco-letter-size)) / 2 - 4px);
  width: var(--rosco-size);
  aspect-ratio: 1 / 1;
}
/* Soft ring outline behind the letters so the circle shape always
   reads, even when most letters are in the muted pending state. */
.rosco-ring::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(2 * var(--rosco-radius));
  height: calc(2 * var(--rosco-radius));
  margin-left: calc(-1 * var(--rosco-radius));
  margin-top: calc(-1 * var(--rosco-radius));
  border-radius: 50%;
  border: 1px dashed rgba(255,255,255,0.12);
  pointer-events: none;
}

.rosco-letter {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--rosco-letter-size);
  height: var(--rosco-letter-size);
  margin-left: calc(-1 * var(--rosco-letter-size) / 2);
  margin-top: calc(-1 * var(--rosco-letter-size) / 2);
  transform:
    rotate(var(--angle))
    translateY(calc(-1 * var(--rosco-radius)))
    rotate(calc(-1 * var(--angle)));
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 16px;
  color: #fff;
  background: rgba(20, 26, 48, 0.85);
  border: 1.5px solid rgba(255,255,255,0.28);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.18),
    0 2px 6px rgba(0,0,0,0.35);
  transition:
    background 240ms ease,
    border-color 240ms ease,
    box-shadow 240ms ease,
    transform 240ms cubic-bezier(.2,.9,.3,1.2);
}
.rosco-letter span { text-shadow: 0 1px 2px rgba(0,0,0,0.55); }

.rosco-letter.is-current {
  background: linear-gradient(160deg, #fde047 0%, #f59e0b 100%);
  border-color: rgba(255,255,255,0.7);
  color: #1f1300;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.7),
    0 0 22px rgba(253,224,71,0.55);
  transform:
    rotate(var(--angle))
    translateY(calc(-1 * var(--rosco-radius)))
    rotate(calc(-1 * var(--angle)))
    scale(1.18);
  animation: rosco-pulse 1.6s ease-in-out infinite;
  z-index: 2;
}
.rosco-letter.is-current span { text-shadow: none; }

@keyframes rosco-pulse {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,0.7), 0 0 18px rgba(253,224,71,0.45); }
  50%      { box-shadow: inset 0 1px 0 rgba(255,255,255,0.7), 0 0 30px rgba(253,224,71,0.85); }
}

.rosco-letter.is-correct {
  background: rgba(83,141,78,0.95);
  border-color: rgba(160,255,160,0.55);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    0 0 14px rgba(83,200,90,0.5);
}
.rosco-letter.is-wrong {
  background: rgba(190,60,60,0.92);
  border-color: rgba(255,160,160,0.55);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.35),
    0 0 12px rgba(255,90,90,0.45);
}
.rosco-letter.is-passed {
  background: rgba(180,120,40,0.85);
  border-color: rgba(255,200,140,0.55);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.35),
    0 0 10px rgba(255,180,80,0.35);
}

/* Decorative big letter in the dead-center of the ring. Pure visual —
   no interaction. Mirrors the perimeter highlight so the player sees
   which letter they're on without having to scan the circle. */
.rosco-center-letter {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 72px;
  font-weight: 900;
  color: rgba(253,224,71,0.18);
  letter-spacing: 0;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  text-shadow: 0 0 24px rgba(253,224,71,0.25);
}

/* ---------- Panel (clue + input + buttons) ---------- */
.rosco-panel {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  padding: 14px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 var(--glass-hi);
  box-sizing: border-box;
}

.rosco-start {
  align-self: center;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22);
}
.rosco-start:hover { background: rgba(255,255,255,0.22); }

.rosco-clue {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: center;
}
.rosco-clue-prefix {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}
.rosco-clue-prefix strong {
  color: #fde047;
  font-size: 14px;
  letter-spacing: 0;
}
.rosco-clue-text {
  font-size: 17px;
  font-weight: 500;
  line-height: 1.4;
  color: #fff;
}

.rosco-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}
.rosco-input {
  width: 100%;
  padding: 11px 14px;
  border-radius: 12px;
  border: 1px solid var(--glass-border);
  background: rgba(0,0,0,0.32);
  color: #fff;
  font: inherit;
  font-size: 18px;
  font-weight: 600;
  text-align: center;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  outline: none;
  box-sizing: border-box;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.rosco-input::placeholder { color: rgba(255,255,255,0.3); }
.rosco-input:focus {
  border-color: rgba(253,224,71,0.65);
  box-shadow: 0 0 0 3px rgba(253,224,71,0.18);
}

.rosco-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.rosco-btn {
  flex: 1 1 0;
  min-width: 0;
  padding: 10px 12px;
  border-radius: 999px;
  border: 1px solid var(--glass-border);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18);
}
.rosco-btn-submit {
  background: linear-gradient(160deg, rgba(83,141,78,0.95), rgba(34,180,90,0.8));
  border-color: rgba(160,255,160,0.45);
}
.rosco-btn-submit:hover { filter: brightness(1.08); }
.rosco-btn-pass { background: rgba(255,255,255,0.10); }
.rosco-btn-pass:hover { background: rgba(255,255,255,0.18); }
.rosco-btn:active { transform: scale(0.97); }

/* ---------- Typo confirmation (close-enough guess) ---------- */
.rosco-typo {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  text-align: center;
}
.rosco-typo-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.rosco-typo-label {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
}
.rosco-typo-guess {
  font-size: 16px;
  font-weight: 600;
  color: rgba(255,255,255,0.78);
  font-style: italic;
}
.rosco-typo-question {
  font-size: 15px;
  font-weight: 600;
  color: rgba(255,255,255,0.92);
  line-height: 1.35;
}
.rosco-typo-suggested {
  color: #fde047;
  font-weight: 800;
  letter-spacing: 0.02em;
  margin: 0 1px;
}
.rosco-typo-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-top: 2px;
}

/* ---------- Wrong-answer reveal (pause panel) ---------- */
.rosco-reveal {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  text-align: center;
}
.rosco-reveal-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.rosco-reveal-label {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
}
.rosco-reveal-guess {
  font-size: 18px;
  font-weight: 700;
  color: #ffb4a8;
  text-decoration: line-through;
  text-decoration-color: rgba(255,140,120,0.5);
  text-underline-offset: 2px;
}
.rosco-reveal-correct {
  font-size: 20px;
  font-weight: 800;
  color: #a7f3a8;
  letter-spacing: 0.02em;
}
.rosco-btn-continue {
  align-self: center;
  flex: 0 1 auto;
  padding: 10px 20px;
  min-width: 140px;
  margin-top: 2px;
}

/* ---------- Missed-words list (game-over) ---------- */
.rosco-missed {
  width: 100%;
  margin-top: 8px;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,0.12);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.rosco-missed-title {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
  text-align: center;
}
.rosco-missed-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 220px;
  overflow-y: auto;
}
.rosco-missed-item {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  align-items: baseline;
  gap: 8px;
  padding: 5px 10px;
  border-radius: 8px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  font-size: 13px;
  text-align: left;
}
.rosco-missed-item.is-wrong { border-left: 3px solid rgba(255,140,140,0.7); }
.rosco-missed-item.is-passed,
.rosco-missed-item.is-pending {
  border-left: 3px solid rgba(255,200,140,0.6);
}
.rosco-missed-letter {
  font-weight: 800;
  color: #fde047;
  font-size: 13px;
  letter-spacing: 0;
}
.rosco-missed-word {
  font-weight: 600;
  color: rgba(255,255,255,0.92);
}
.rosco-missed-guess {
  font-size: 11px;
  font-style: italic;
  color: rgba(255,255,255,0.5);
  white-space: nowrap;
}
.rosco-missed-item.is-wrong .rosco-missed-guess {
  text-decoration: line-through;
  text-decoration-color: rgba(255,140,140,0.6);
}

.rosco-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.rosco-result-title { font-size: 18px; font-weight: 800; }
.rosco-result-score { font-size: 14px; color: rgba(255,255,255,0.8); }
.rosco-result-hint { font-size: 12px; color: rgba(255,255,255,0.55); font-style: italic; }
.rosco-restart {
  margin-top: 4px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.rosco-restart:hover { background: rgba(255,255,255,0.22); }

/* ---------- Hints (modality-aware) ---------- */
.rosco-hint {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-align: center;
  font-style: italic;
}
.rosco-hint-kb { display: none; }
@media (hover: hover) and (pointer: fine) {
  .rosco-hint-touch { display: none; }
  .rosco-hint-kb { display: block; }
}

/* ---------- Mobile ---------- */
@media (max-width: 480px) {
  .rosco { gap: 10px; max-width: none; }
  .rosco-toolbar { gap: 6px; }
  .rosco-stat { padding: 4px 10px; min-width: 44px; }
  .rosco-stat-value { font-size: 14px; }
  .rosco-ring {
    /* Phone cap. Same rule applies: lengths only (no percentages), so
       the calc(...) for --rosco-radius resolves consistently in
       both `width` and `translateY()` contexts. */
    --rosco-size: min(280px, 80vw);
    --rosco-letter-size: 32px;
  }
  .rosco-letter { font-size: 13px; }
  .rosco-center-letter { font-size: 56px; }
  .rosco-panel { padding: 12px; gap: 8px; }
  .rosco-clue-text { font-size: 15px; }
  .rosco-input { font-size: 17px; padding: 10px 12px; }
  .rosco-btn { font-size: 12px; padding: 9px 10px; }
}
.bubble {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  max-width: 480px;
}

.bubble-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}

.bubble-stat {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  min-width: 72px;
}
.bubble-stat-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}
.bubble-stat-value {
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* Combo pill stays muted at ×1; lights up + jiggles once a chain begins. */
.bubble-stat--combo .bubble-stat-value {
  color: rgba(255, 255, 255, 0.45);
  transition: color 180ms ease, text-shadow 180ms ease;
}
.bubble-stat--combo.is-active {
  border-color: rgba(253, 224, 71, 0.55);
  box-shadow: 0 0 14px rgba(253, 224, 71, 0.35);
  animation: bubble-combo-pop 320ms ease-out;
}
.bubble-stat--combo.is-active .bubble-stat-value {
  color: #fde047;
  text-shadow: 0 0 8px rgba(253, 224, 71, 0.65);
}
@keyframes bubble-combo-pop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}

/* Toolbar icon buttons (sound, swap) — match stat-pill glass aesthetic. */
.bubble-icon-btn {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: 1px solid var(--glass-border);
  background: rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  color: #fff;
  font-size: 18px;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  transition: background 160ms ease, transform 160ms ease, border-color 160ms ease;
}
.bubble-icon-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.14);
  transform: translateY(-1px);
}
.bubble-icon-btn:active:not(:disabled) {
  transform: translateY(1px) scale(0.96);
}
.bubble-icon-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.bubble-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 4;
  padding: 0;
  overflow: hidden;
  border-radius: 18px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: crosshair;
}

/* Red border tint when the run ends in failure — visceral game-over cue
 * on top of the in-canvas shake. */
.bubble-stage.is-over {
  border: 1px solid rgba(239, 68, 68, 0.5);
  box-shadow: 0 0 24px rgba(239, 68, 68, 0.35);
}

.bubble-canvas {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.bubble-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 12, 24, 0.42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
  animation: bubble-fade-in 320ms ease-out;
}
@keyframes bubble-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.bubble-msg {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 20px 24px;
  text-align: center;
  background: rgba(20, 22, 32, 0.82);
  border: 1px solid var(--glass-border);
  border-radius: 18px;
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  pointer-events: auto;
  max-width: 88%;
  min-width: 260px;
  animation: bubble-msg-in 360ms cubic-bezier(0.18, 0.89, 0.32, 1.28);
}
@keyframes bubble-msg-in {
  from { opacity: 0; transform: scale(0.85) translateY(8px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

.bubble-msg-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
}
.bubble-msg-score {
  font-size: 38px;
  font-weight: 900;
  color: #fde047;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-shadow: 0 0 18px rgba(253, 224, 71, 0.45);
  margin: 2px 0 6px;
}
.bubble-msg-hint {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.55);
  font-style: italic;
}
.bubble-msg-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
}

.bubble-stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 18px;
  margin: 4px 0 6px;
  padding: 0;
}
.bubble-stats-grid > div {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}
.bubble-stats-grid dt {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin: 0;
}
.bubble-stats-grid dd {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.bubble-restart {
  margin-top: 4px;
  padding: 9px 18px;
  border-radius: 999px;
  border: 1px solid var(--glass-hi);
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22);
  transition: background 180ms ease, transform 180ms ease;
}
.bubble-restart:hover {
  background: rgba(255, 255, 255, 0.22);
  transform: translateY(-1px);
}
.bubble-restart:active {
  transform: translateY(1px) scale(0.98);
}

.bubble-hint {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.55);
  text-align: center;
  font-style: italic;
}
/* Modality-aware: only show the relevant control hint. */
.bubble-hint--touch { display: block; }
.bubble-hint--kb    { display: none; }
@media (hover: hover) and (pointer: fine) {
  .bubble-hint--touch { display: none; }
  .bubble-hint--kb    { display: block; }
}

@media (max-width: 480px) {
  .bubble { gap: 10px; }
  .bubble-toolbar { gap: 8px; }
  .bubble-stat { min-width: 60px; padding: 5px 10px; }
  .bubble-stat-label { font-size: 9px; letter-spacing: 0.12em; }
  .bubble-stat-value { font-size: 14px; }
  .bubble-icon-btn { width: 32px; height: 32px; font-size: 16px; }
  .bubble-msg-title { font-size: 18px; }
  .bubble-msg-score { font-size: 32px; }
}
.gi-backdrop {
  position: fixed; inset: 0;
  background: rgba(6, 8, 16, 0.82);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 60;
  padding: 16px;
  animation: gi-fade-in 200ms ease-out;
}

@keyframes gi-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.gi-panel {
  width: 100%;
  max-width: 480px;
  max-height: 88svh;
  overflow-y: auto;
  background: rgba(20, 23, 36, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 22px;
  padding: 18px 20px 20px;
  color: #fff;
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 14px 30px rgba(0, 0, 0, 0.45),
    0 0 0 1px rgba(99, 142, 255, 0.18);
  animation: gi-panel-in 360ms cubic-bezier(.2, 1.5, .3, 1);
}

@keyframes gi-panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.gi-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  gap: 8px;
}

.gi-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.10em;
  color: rgba(255, 255, 255, 0.92);
  margin: 0;
  flex: 1;
  min-width: 0;
}

.gi-close {
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.6);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 8px;
  transition: background 160ms ease, color 160ms ease;
  flex: 0 0 auto;
}
.gi-close:hover { background: rgba(255, 255, 255, 0.10); color: #fff; }
.gi-close:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.45);
  outline-offset: 2px;
}

.gi-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.88);
}

.gi-body p { margin: 0; }

/* Modality-aware blocks. Default = touch; desktop with hover+pointer
   swaps to the kb variant. Pairs with the project rule that touch users
   must never see kb-only copy and vice versa. */
.gi-modality--touch { display: block; }
.gi-modality--kb { display: none; }

@media (hover: hover) and (pointer: fine) {
  .gi-modality--touch { display: none; }
  .gi-modality--kb { display: block; }
}

.gi-modality {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 4px;
  border-top: 1px dashed rgba(255, 255, 255, 0.10);
}
.daily-confetti-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  overflow: hidden;
}
.daily-confetti {
  position: absolute;
  top: -10px;
  width: 8px;
  height: 14px;
  border-radius: 2px;
  animation: daily-c-fall linear forwards;
}
@keyframes daily-c-fall {
  0%   { transform: translateY(0) rotate(var(--rot, 0deg));                    opacity: 1; }
  100% { transform: translateY(110vh) rotate(calc(var(--rot, 0deg) + 720deg)); opacity: 0.85; }
}
.daily-banner {
  width: min(560px, 100%);
  margin-top: 22px;
  padding: 16px 20px;
  background: rgba(255,255,255,0.05);
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 18px;
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 14px 30px rgba(0,0,0,0.35),
    0 0 0 1px rgba(99,142,255,0.18);
  color: #fff;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 6px;
  animation: daily-banner-in 360ms cubic-bezier(.2, 1.5, .3, 1);
}

@keyframes daily-banner-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.daily-banner-status {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: 0.04em;
}
.daily-banner-status.won  { color: rgba(180,255,200,0.95); }

.daily-banner-line {
  font-size: 14px;
  color: rgba(255,255,255,0.85);
}
.daily-banner-line.secondary {
  color: rgba(255,255,255,0.6);
  font-size: 13px;
}
.daily-banner-line.saved {
  color: rgba(180,255,200,0.9);
  font-weight: 600;
}

.daily-banner-rank {
  margin-top: 6px;
  font-size: 14px;
  color: rgba(255,255,255,0.85);
}
.daily-banner-rank strong {
  font-weight: 800;
  color: #fff;
}

.daily-banner-rank-celebrate {
  margin-top: 6px;
  font-size: 16px;
  font-weight: 800;
  color: rgba(255, 220, 130, 0.98);
  letter-spacing: 0.02em;
  animation: daily-banner-rank-pulse 1.6s ease-in-out infinite;
}

@keyframes daily-banner-rank-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.04); }
}
.daily-result {
  width: min(560px, 100%);
  margin: 16px auto 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.daily-result-card {
  width: 100%;
  padding: 22px 24px;
  background: rgba(255,255,255,0.05);
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 20px;
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 14px 30px rgba(0,0,0,0.35),
    0 0 0 1px rgba(99,142,255,0.18);
  color: #fff;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 8px;
  animation: daily-result-in 360ms cubic-bezier(.2, 1.5, .3, 1);
}

@keyframes daily-result-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.daily-result-status {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.04em;
}
.daily-result-status.won  { color: rgba(180,255,200,0.95); }

.daily-result-game {
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
}

.daily-result-metric-row {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  margin: 4px 0;
}

.daily-result-value {
  font-size: 36px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.daily-result-metric {
  font-size: 14px;
  color: rgba(255,255,255,0.6);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.daily-result-rank {
  margin-top: 4px;
  /* Reserve the slot height even before `useDailyRank` resolves so the card
     doesn't pop taller when the rank line lands. ~26px fits the celebrate
     variant (17px font, line-height ~1.5). */
  min-height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.daily-result-rank-line {
  font-size: 15px;
  color: rgba(255,255,255,0.85);
}
.daily-result-rank-line strong {
  font-weight: 800;
  color: #fff;
}

.daily-result-rank-celebrate {
  font-size: 17px;
  font-weight: 800;
  color: rgba(255, 220, 130, 0.98);
  letter-spacing: 0.02em;
  animation: rank-pulse 1.6s ease-in-out infinite;
}

@keyframes rank-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.04); }
}

.daily-result-hint {
  margin-top: 6px;
  font-size: 13px;
  color: rgba(255,255,255,0.55);
}
.daily-gate {
  width: min(520px, 100%);
  margin: 24px auto;
  padding: 28px 24px;
  background: rgba(255,255,255,0.05);
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 20px;
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 14px 30px rgba(0,0,0,0.35),
    0 0 0 1px rgba(99,142,255,0.18);
  color: #fff;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 14px;
  animation: daily-gate-in 360ms cubic-bezier(.2, 1.5, .3, 1);
}

@keyframes daily-gate-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.daily-gate-title {
  margin: 0;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.daily-gate-body {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255,255,255,0.78);
}

.daily-gate-cta {
  display: flex;
  justify-content: center;
  margin-top: 4px;
  font-size: 16px;
}

.daily-gate-google {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.18);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease,
              transform 180ms ease;
}
.daily-gate-google:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.28);
  transform: translateY(-1px);
}
.daily-gate-google:active { transform: translateY(0); }
.daily-gate-google:focus-visible {
  outline: 2px solid rgba(255,255,255,0.5);
  outline-offset: 3px;
}
.daily-subscribe {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}

.daily-subscribe-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
  align-items: center;
}

.daily-subscribe-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.14);
  color: rgba(255,255,255,0.92);
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background 180ms ease, border-color 180ms ease,
              color 180ms ease, transform 180ms ease;
}

.daily-subscribe-btn:not(:disabled):hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.24);
  transform: translateY(-1px);
}

.daily-subscribe-btn:focus-visible {
  outline: 2px solid rgba(255,255,255,0.5);
  outline-offset: 3px;
}

.daily-subscribe-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}

.daily-subscribe-icon {
  font-size: 13px;
  line-height: 1;
}

/* Narrow viewports: collapse the pill to icon-only so the topbar
   (logo + subscribe + auth) fits on a single row. Square 32×32 to match
   LevelPill and the auth avatar — uniform row. */
@media (max-width: 480px) {
  .daily-subscribe-label { display: none; }
  .daily-subscribe-btn {
    width: 32px;
    height: 32px;
    padding: 0;
    gap: 0;
    justify-content: center;
  }
  .daily-subscribe-icon { font-size: 16px; }
}

.daily-subscribe-error,
.daily-subscribe-success {
  font-size: 11px;
  text-align: right;
}
.daily-subscribe-error { color: #fca5a5; }
.daily-subscribe-success { color: #86efac; }
.lvm-backdrop {
  position: fixed; inset: 0;
  background: rgba(6, 8, 16, 0.82);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 60;
  padding: 16px;
  animation: lvm-fade-in 200ms ease-out;
}

@keyframes lvm-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.lvm-panel {
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  background: rgba(20, 23, 36, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 22px;
  padding: 18px 20px 20px;
  color: #fff;
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  box-shadow:
    inset 0 1px 0 var(--glass-hi),
    0 14px 30px rgba(0, 0, 0, 0.45),
    0 0 0 1px rgba(99, 142, 255, 0.18);
  animation: lvm-panel-in 360ms cubic-bezier(.2, 1.5, .3, 1);
}

@keyframes lvm-panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.lvm-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.lvm-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.78);
  margin: 0;
}

.lvm-close {
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.6);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 8px;
  transition: background 160ms ease, color 160ms ease;
}
.lvm-close:hover { background: rgba(255, 255, 255, 0.10); color: #fff; }
.lvm-close:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.45);
  outline-offset: 2px;
}

/* ----- Hero ----- */

.lvm-hero {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 6px 4px 16px;
}

.lvm-hero-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.lvm-hero-eyebrow {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.lvm-hero-num {
  font-size: 44px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: #fff;
}

.lvm-hero-tone {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.78);
  text-transform: capitalize;
}

/* ----- Progress ----- */

.lvm-progress {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.lvm-progress-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.7);
}

.lvm-progress-now {
  font-weight: 600;
  color: rgba(255, 255, 255, 0.92);
  font-variant-numeric: tabular-nums;
}

.lvm-progress-total {
  font-size: 11px;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

.lvm-bar {
  position: relative;
  height: 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.10);
  overflow: hidden;
}

.lvm-bar-fill {
  height: 100%;
  background: linear-gradient(
    90deg,
    rgba(99, 142, 255, 0.85),
    rgba(167, 139, 250, 0.85)
  );
  box-shadow: 0 0 12px rgba(167, 139, 250, 0.45);
  transition: width 360ms cubic-bezier(.2, 1, .3, 1);
  border-radius: 999px;
}

/* ----- Section labels ----- */

.lvm-section-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin: 16px 4px 8px;
}

/* ----- Yesterday ----- */

.lvm-yest-card {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 14px;
  padding: 12px 14px;
}

.lvm-yest-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
}

.lvm-yest-date {
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.88);
  text-transform: capitalize;
}

.lvm-yest-points {
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #c4b5fd;
  text-shadow: 0 0 12px rgba(167, 139, 250, 0.35);
}

.lvm-yest-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.lvm-yest-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.86);
}

.lvm-yest-pill {
  display: inline-flex;
  min-width: 28px;
  justify-content: center;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(167, 139, 250, 0.2);
  border: 1px solid rgba(167, 139, 250, 0.4);
  color: #f3e8ff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.lvm-yest-empty {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.6);
  font-style: italic;
  padding: 8px 4px;
}

/* ----- Rules ----- */

.lvm-rules-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.lvm-rules-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.86);
  padding: 8px 10px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.lvm-rule-pill {
  display: inline-flex;
  min-width: 32px;
  height: 26px;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  border-radius: 999px;
  background: rgba(99, 142, 255, 0.18);
  border: 1px solid rgba(99, 142, 255, 0.35);
  color: #dbeafe;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.lvm-rule-pill--bonus {
  background: rgba(250, 204, 21, 0.16);
  border-color: rgba(250, 204, 21, 0.45);
  color: #fef9c3;
}

.lvm-rule-pill--neutral {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.18);
  color: #fff;
}

/* ----- Recent ----- */

.lvm-recent-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.lvm-recent-list li {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  padding: 6px 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.05);
}

.lvm-recent-date {
  color: rgba(255, 255, 255, 0.6);
  font-variant-numeric: tabular-nums;
  text-transform: capitalize;
  min-width: 56px;
}

.lvm-recent-game {
  color: rgba(255, 255, 255, 0.86);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lvm-recent-pill {
  display: inline-flex;
  min-width: 28px;
  justify-content: center;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.lvm-recent-pill.is-bonus {
  background: rgba(250, 204, 21, 0.16);
  border-color: rgba(250, 204, 21, 0.45);
  color: #fef9c3;
}

.lvm-loading {
  text-align: center;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
  padding: 8px 0 0;
}
/* Mirrors the box dimensions of `.daily-subscribe-btn` so the topbar
   pills line up at the same height. */
.level-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px 6px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.92);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  transition: background 180ms ease, border-color 180ms ease,
              transform 180ms ease;
  -webkit-tap-highlight-color: transparent;
}

.level-pill:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.24);
  transform: translateY(-1px);
}

.level-pill:active {
  transform: translateY(0);
}

.level-pill:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.5);
  outline-offset: 3px;
}

/* Text block to the right of the badge: "Lv {n} · {pts}/{cap}" — mirrors
   the streak chip's `value · value` two-stat layout, just inlined into a
   single span to keep the pill height short. */
.level-pill-text {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.level-pill-num {
  font-weight: 700;
  font-size: 13px;
  color: #fff;
}
.level-pill-sep {
  color: rgba(255,255,255,0.3);
  font-size: 13px;
}
.level-pill-progress {
  font-size: 11px;
  font-weight: 600;
  color: rgba(255,255,255,0.7);
}

@media (max-width: 480px) {
  /* Square 32×32 on mobile so it lines up with the daily-subscribe and
     auth pills as a uniform row of icon buttons. */
  .level-pill {
    width: 32px;
    height: 32px;
    padding: 0;
    gap: 0;
    justify-content: center;
  }
  .level-pill-text { display: none; }
}
:root {
  --glass-bg: rgba(255, 255, 255, 0.08);
  --glass-border: rgba(255, 255, 255, 0.18);
  --glass-hi: rgba(255, 255, 255, 0.35);
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}

.app {
  position: relative;
  /* svh, not dvh: iOS Safari's URL bar collapses, expanding 100dvh past
     100svh. Pages that lock layouts to 100svh (e.g. daily home) would
     otherwise have their .app stretched past the visible area, creating
     a scrollable band of nothing below the locked content. svh matches
     the smallest viewport variant — safe for both states. */
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}

/* Mobile: routes whose content fits a single viewport (daily home, game
   pages with adapted CSS) lock the document so it cannot scroll — any
   tiny subpixel overflow gets clipped rather than triggering iOS
   rubber-band. Routes without this class (practice grid) stay scrollable
   because their content genuinely overflows. */
@media (max-width: 480px) {
  .app--no-scroll {
    height: 100svh;
    min-height: 0;
    overflow: hidden;
  }
}

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px;
  padding: 10px 16px;
  background: var(--glass-bg);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  border-bottom: 1px solid var(--glass-border);
  box-shadow: inset 0 1px 0 var(--glass-hi), var(--shadow);
  position: sticky; top: 0; z-index: 5;
}

/* Cover rubber-band overscroll above the topbar with the same glass look.
   `100dvh` (not `100vh`) so iOS Safari's URL-bar resize doesn't expose a gap. */
.topbar::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  bottom: 100%;
  height: 100dvh;
  background: var(--glass-bg);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  pointer-events: none;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Extra breathing room between the language pill and the user avatar */
.topbar-right .lang-toggle + .auth-pill,
.topbar-right .daily-subscribe + .auth-pill {
  margin-left: 10px;
}

@media (max-width: 480px) {
  .brand { gap: 6px; padding: 4px; }
  .brand-text { font-size: 13px; letter-spacing: 0.18em; }
  .gc-logo { width: 22px; height: 22px; }
  /* Tighten the gap before the avatar so the row fits without wrapping. */
  .topbar-right .lang-toggle + .auth-pill,
  .topbar-right .daily-subscribe + .auth-pill { margin-left: 4px; }

  /* Drop the topbar background entirely on phones — the frosted glass with
     backdrop-filter forces a re-sample on every scroll frame, which is
     where mobile scroll lag mostly comes from. Content (logo + pills +
     avatar) sits directly over the page background. */
  .topbar {
    padding: 10px 12px;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-bottom: none;
    box-shadow: none;
  }
  .topbar::before { display: none; }
}

@media (max-width: 360px) {
  .brand-text { font-size: 12px; letter-spacing: 0.14em; }
  .topbar { padding: 8px 12px; }
  .topbar-right { gap: 6px; }
}

.brand {
  background: none; border: none; cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
}

.gc-logo {
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.35));
  transition: transform 200ms ease;
}
.brand:hover .gc-logo { transform: rotate(-6deg) scale(1.05); }

/* Coin variant: cycling neon halo synced with the title palette */
.gc-logo-coin {
  animation: gc-logo-coin-glow 9s ease-in-out infinite;
}

@keyframes gc-logo-coin-glow {
  0%, 100% {
    filter:
      drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35))
      drop-shadow(0 0 8px rgba(255, 62, 165, 0.55));
  }
  33% {
    filter:
      drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35))
      drop-shadow(0 0 9px rgba(200, 80, 232, 0.6));
  }
  66% {
    filter:
      drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35))
      drop-shadow(0 0 9px rgba(56, 189, 248, 0.6));
  }
}

@media (prefers-reduced-motion: reduce) {
  .gc-logo-coin { animation: none; }
}

.brand-text {
  font-weight: 800;
  letter-spacing: 0.28em;
  font-size: 16px;
  white-space: nowrap;
}

/* --- Title styles ----------------------------------------------------- */

.brand-text-rainbow {
  background: linear-gradient(90deg, #ff3ea5 0%, #fbbf24 35%, #38bdf8 70%, #84cc16 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
}

/* ----- neon-real: refined cycling neon with realistic depth + natural flicker ----- */
.brand-text-neon-real {
  color: #fffaf2; /* warm-white tube glass tint, not pure #fff */
  -webkit-text-fill-color: #fffaf2;
  font-weight: 900;
  letter-spacing: 0.22em;
  animation:
    title-neon-real-hue 9s ease-in-out infinite,
    title-neon-real-flicker 12s linear infinite;
}

@keyframes title-neon-real-hue {
  0%, 100% {
    text-shadow:
      0 0 0.5px #fff,
      0 0 1.5px #fff,
      0 0 4px #ff7eb6,
      0 0 10px #ff3ea5,
      0 0 22px rgba(255, 62, 165, 0.85),
      0 0 44px rgba(255, 62, 165, 0.5),
      0 0 80px rgba(255, 62, 165, 0.22);
  }
  33% {
    text-shadow:
      0 0 0.5px #fff,
      0 0 1.5px #fff,
      0 0 4px #e09bff,
      0 0 10px #c850e8,
      0 0 22px rgba(200, 80, 232, 0.85),
      0 0 44px rgba(200, 80, 232, 0.5),
      0 0 80px rgba(200, 80, 232, 0.22);
  }
  66% {
    text-shadow:
      0 0 0.5px #fff,
      0 0 1.5px #fff,
      0 0 4px #84d6ff,
      0 0 10px #38bdf8,
      0 0 22px rgba(56, 189, 248, 0.85),
      0 0 44px rgba(56, 189, 248, 0.5),
      0 0 80px rgba(56, 189, 248, 0.22);
  }
}

/* Natural flicker: small dip, then a clustered stutter, then a small dip */
@keyframes title-neon-real-flicker {
  0%   { opacity: 1; }
  27%  { opacity: 1; }
  27.4% { opacity: 0.55; }
  27.7% { opacity: 1; }
  60%  { opacity: 1; }
  60.4% { opacity: 0.25; }
  60.7% { opacity: 0.7; }
  61.1% { opacity: 0.4; }
  61.4% { opacity: 0.85; }
  62%  { opacity: 1; }
  88%  { opacity: 1; }
  88.3% { opacity: 0.65; }
  88.6% { opacity: 1; }
  100% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .brand-text-neon-real { animation: none; }
}

/* --- Localhost-only dev selectors (stacked bottom-left) -------------- */

.dev-tools {
  position: fixed;
  bottom: 14px;
  left: 14px;
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}

.dev-switcher {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  padding: 4px 6px 4px 12px;
  max-width: calc(100vw - 32px);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  background: rgba(20, 24, 38, 0.7);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font: 600 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.06em;
}

.dev-switcher-label {
  color: rgba(255, 255, 255, 0.55);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-right: 2px;
}

.dev-switcher button {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.65);
  padding: 6px 10px;
  border-radius: 999px;
  cursor: pointer;
  text-transform: uppercase;
  font: inherit;
  letter-spacing: inherit;
  transition: color 180ms ease, background 180ms ease;
}

.dev-switcher button:hover { color: #fff; }

.dev-switcher button.is-active {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}

.dev-action {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  background: rgba(20, 24, 38, 0.7);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font: 600 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255, 200, 200, 0.75);
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease, border-color 180ms ease;
}

.dev-action:hover {
  color: #fff;
  background: rgba(244, 63, 94, 0.18);
  border-color: rgba(244, 63, 94, 0.5);
}

.dev-action:disabled {
  cursor: default;
  opacity: 0.4;
}

.dev-action:disabled:hover {
  background: rgba(20, 24, 38, 0.7);
  color: rgba(255, 200, 200, 0.75);
  border-color: rgba(255, 255, 255, 0.18);
}

@media (max-width: 480px) {
  .dev-tools {
    left: 10px;
    right: 10px;
    bottom: 10px;
    align-items: stretch;
  }
  .dev-switcher {
    justify-content: center;
  }
}

.game-header {
  position: relative;
  width: 100%;
  max-width: 720px;
  margin: 0 auto 6px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.game-header-right {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.game-header-info {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid var(--glass-border);
  color: #fff;
  font-weight: 700;
  font-size: 16px;
  cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: transform 150ms ease, background 200ms ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.game-header-info:hover  { transform: translateY(-1px); background: rgba(255, 255, 255, 0.16); }
.game-header-info:active { transform: translateY(1px) scale(0.98); }
.game-header-info:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.5);
  outline-offset: 3px;
}

@media (max-width: 480px) {
  .game-header-info {
    width: 32px;
    height: 32px;
    font-size: 14px;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* Absolutely positioned so the title sits in the visual centre of the
   header regardless of the Back button's width (which varies across
   languages — "Back" vs "Atrás"). pointer-events:none so clicks fall
   through to whatever's behind. */
.game-header-title {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.88);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  pointer-events: none;
  white-space: nowrap;
  max-width: calc(100% - 260px);
  overflow: hidden;
  text-overflow: ellipsis;
}

.game-stage {
  flex: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;
}

.back {
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--glass-border);
  color: #fff; font-weight: 600;
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: transform 150ms ease, background 200ms ease;
}
.back:hover  { transform: translateY(-1px); background: rgba(255,255,255,0.16); }
.back:active { transform: translateY(1px) scale(0.98); }

.main {
  flex: 1;
  padding: 20px 18px 32px;
  display: flex;
  flex-direction: column;
  /* Centering of the actual game now happens inside `.game-stage` so the
     "Back" button can pin to the top without dragging the centred group up. */
}

@media (max-width: 480px) {
  /* Add safe-area-inset-bottom to padding-bottom so content (practice
     CTA, leaderboard) clears the iOS home indicator. Locked-height
     descendants (.home-stack, .game-stage) subtract the same value so
     total page height stays = 100svh. */
  .main { padding: 14px 14px calc(24px + env(safe-area-inset-bottom)); }

  /* Hide the topbar entirely on phones during gameplay so the game can
     use the full vertical viewport. `.app--no-scroll` is set exclusively
     on game routes (App.tsx), so this only kicks in there — home and
     practice still show the topbar normally. The back button in
     .game-header is the user's way out. The stage-height override
     below drops the topbar's ~52px from the subtraction. */
  .app--no-scroll .topbar { display: none; }
  .app--no-scroll .game-stage {
    height: calc(100svh - 88px - env(safe-area-inset-bottom));
  }

  /* Lock the game stage to one viewport so game pages do not scroll on
     phones. svh (not dvh) matches the smallest viewport variant — the
     stage will not overflow even when iOS Safari's URL bar is fully
     visible. Chrome subtracted: topbar (~52) + .main padding (14 + 24 =
     38) + .game-header (~50) = ~140, plus the bottom safe-area inset.
     Game roots that opt into this pattern set width:100% / height:100% /
     overflow:hidden and lay themselves out with flex inside. Games not
     yet adapted will scroll within the stage, which is still better
     than scrolling the page. */
  .game-stage {
    height: calc(100svh - 140px - env(safe-area-inset-bottom));
    overflow: auto;
  }
}
