:root{
  --bg: #0a1730;
  --bg-2: #122448;
  --tray: #3a5f95;
  --tray-2: #2c4a75;
  --tile: #f7f9fc;
  --tile-shadow: #b8c4d9;
  --ink: #16294a;
  --gold: #c99f2e;
  --gold-bright: #ffd23f;
  --sage: #5c9a76;
  --sage-dim: #3c6650;
  --rust: #d9534f;
  --text: #d7e1f2;
  --text-dim: #90a4c4;
  --radius-tile: 10px;
  --tile-letter-size: 32px;
  --reading-scale: 1;
}
*{ box-sizing: border-box; }
/* Mobile WebKit/Blink draw a plain gray/blue rectangle over any tappable
   element on touch — it ignores rounded corners and custom hover/active
   states, so buttons and other clickable elements flash an ugly highlight
   box on every tap. The tiles already opt out of this (see .tile below);
   applying it globally covers every other clickable control (logo/home
   button, chips, reveal toggle, settings controls, etc.) consistently. */
button, a, [role="button"], .chip{
  -webkit-tap-highlight-color: transparent;
}
html,body{
  margin:0; padding:0; min-height:100vh;
  background:
    radial-gradient(ellipse at 20% -10%, #16294a 0%, transparent 55%),
    radial-gradient(ellipse at 100% 110%, #071022 0%, transparent 60%),
    var(--bg);
  color: var(--text);
  font-family: 'Inter', sans-serif;
  -webkit-font-smoothing: antialiased;
}
.wrap{
  max-width: 640px;
  margin: 0 auto;
  padding: 14px 18px 60px;
}
.header{
  display:flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.brand{
  display:flex;
  align-items:center;
  gap: clamp(6px, 2.5vw, 14px);
  min-width: 0;
  background:none;
  border:none;
  padding:0;
  margin:0;
  font:inherit;
  text-align:left;
  cursor:pointer;
}
.brand:focus-visible{
  outline: 2px solid var(--gold-bright, #e0b84a);
  outline-offset: 4px;
  border-radius: 8px;
}
.logo-img{
  height: clamp(38px, 11vw, 60px);
  width: auto;
  display:block;
  flex-shrink: 0;
}
.wordmark{
  font-family: 'Fraunces', serif;
  font-optical-sizing: auto;
  font-weight: 600;
  /* fluid instead of a fixed breakpoint jump — scales continuously across
     phone widths (320-430px) instead of overflowing to a second line right
     up until one specific breakpoint kicks in. */
  font-size: clamp(14px, 5.2vw, 34px);
  letter-spacing: -0.01em;
  color: #f5f8ff;
  text-shadow: 0 2px 4px rgba(0,0,0,0.45), 0 6px 14px rgba(0,0,0,0.3);
  line-height: 1.05;
}
.tagline{
  font-size: clamp(8px, 2.15vw, 12.5px);
  color: var(--text-dim);
  margin-top: 2px;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.header-actions{
  display:flex;
  align-items:center;
  gap: 10px;
  position: relative;
}
.menu-btn{
  display:flex;
  align-items:center;
  justify-content:center;
  width: 40px;
  height: 40px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 10px;
  color: var(--text);
  cursor:pointer;
  transition: background 0.15s ease, transform 0.1s ease;
}
.menu-btn:hover{ background: rgba(255,255,255,0.1); }
.menu-btn:active{ transform: translateY(1px); }

.dropdown-panel{
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 240px;
  background: var(--bg-2);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 14px;
  padding: 14px;
  box-shadow: 0 20px 40px rgba(0,0,0,0.4);
  z-index: 30;
  animation: panelIn 0.2s ease both;
}
.dropdown-panel[hidden]{ display:none !important; }
.placeholder-body{
  display:flex;
  flex-direction: column;
  align-items:center;
  text-align:center;
  gap: 8px;
  padding: 10px 4px 4px;
}
.placeholder-icon{ font-size: 26px; }
.placeholder-body p{
  margin:0;
  font-size: 12.5px;
  color: var(--text-dim);
  line-height: 1.4;
}

.main-menu-panel{
  display:flex;
  flex-direction: column;
  gap: 4px;
  width: 200px;
  padding: 8px;
}
.main-menu-item{
  display:flex;
  align-items:center;
  gap: 10px;
  width:100%;
  background: none;
  border: none;
  border-radius: 8px;
  padding: 10px 10px;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  cursor:pointer;
  text-align:left;
}
.main-menu-item:hover{ background: rgba(255,255,255,0.07); }
.main-menu-item svg{ flex-shrink:0; color: var(--text-dim); }

.settings-accordion{
  margin-bottom: 12px;
}
.settings-accordion-toggle{
  width:100%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: 12.5px;
  border-radius: 10px;
  padding: 10px 12px;
  cursor:pointer;
  margin-bottom: 8px;
}
.settings-accordion-toggle:hover{ background: rgba(255,255,255,0.08); }
.settings-accordion-toggle .chevron{ transition: transform 0.2s ease; flex-shrink:0; }
.settings-accordion-toggle[aria-expanded="true"] .chevron{ transform: rotate(180deg); }
.settings-accordion-panel{
  padding: 4px 2px 12px;
}
.settings-accordion-panel[hidden]{ display:none !important; }
.settings-preset-row{
  display:flex;
  gap: 6px;
  margin-bottom: 10px;
}
.settings-preset-btn{
  flex:1;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 10.5px;
  font-weight: 600;
  border-radius: 8px;
  padding: 7px 4px;
  cursor:pointer;
}
.settings-preset-btn:hover{ background: rgba(255,255,255,0.1); }
.settings-preset-btn.active{
  background: var(--gold-bright);
  color: #16294a;
  border-color: var(--gold);
}
.settings-reset-btn{
  width:100%;
  background: none;
  border: 1px solid rgba(255,255,255,0.14);
  color: var(--text-dim);
  font-family: 'Inter', sans-serif;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 8px;
  padding: 7px 4px;
  cursor:pointer;
}
.settings-reset-btn:hover{ color: var(--text); background: rgba(255,255,255,0.05); }
.settings-header{
  display:flex;
  align-items:center;
  justify-content:space-between;
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  margin-bottom: 12px;
}
.settings-close{
  background:none;
  border:none;
  color: var(--text-dim);
  font-size: 20px;
  line-height:1;
  cursor:pointer;
  padding: 0 2px;
}
.settings-close:hover{ color: var(--text); }
.settings-row{
  display:flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}
.settings-row label{
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-dim);
}
.settings-row input[type="range"]{
  width: 100%;
  accent-color: var(--gold-bright);
}
.settings-save{
  width: 100%;
}
.stat{
  text-align: center;
}
.stat .label{
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-dim);
  margin-bottom: 2px;
}
.stat .value{
  font-family: 'IBM Plex Mono', monospace;
  font-size: 22px;
  font-weight: 600;
  color: var(--text);
}
.stat .value.countdown-pop{
  animation: countdownPop 0.35s ease;
  text-shadow: 0 0 10px var(--sage), 0 0 20px rgba(92,154,118,0.7);
}
@keyframes countdownPop{
  0%{ transform: scale(1.5); opacity: 0.4; }
  100%{ transform: scale(1); opacity: 1; }
}
.stat.timer.low .value{
  color: var(--rust);
  animation: pulse 1s infinite;
}
@keyframes pulse{
  0%,100%{ opacity:1; } 50%{ opacity:0.45; }
}

.tray{
  position: relative;
  background:
    radial-gradient(ellipse at 30% 15%, #1c3057 0%, transparent 65%),
    linear-gradient(160deg, #0f1b32, #060d1c);
  border-radius: 22px;
  padding: 14px;
  border: 3px solid #f5c451;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.05) inset,
    0 30px 60px -20px rgba(0,0,0,0.7),
    0 0 0 1px rgba(0,0,0,0.4),
    0 0 0px rgba(92,154,118,0);
  transition: border-color 0.6s ease, box-shadow 0.6s ease;
}
/* Shown only until the very first renderBoard() call — the dictionary
   fetch + trie-build that happens before any board can render takes a
   moment on a slow connection, and an empty tray in that window reads as
   broken rather than loading. */
.board-loading{
  min-height: 280px;
  display:flex;
  align-items:center;
  justify-content:center;
  color: var(--text-dim);
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  letter-spacing: 0.02em;
  animation: boardLoadingPulse 1.4s ease-in-out infinite;
}
.board-loading[hidden]{ display:none !important; }
@keyframes boardLoadingPulse{
  0%,100%{ opacity: 0.5; }
  50%{ opacity: 1; }
}
.tray.tray-blinking{
  animation: trayBlink 0.3s steps(1,end) 6;
}
@keyframes trayBlink{
  0%,49%{ border-color: #f5c451; }
  50%,100%{ border-color: rgba(245,196,81,0.12); }
}
.tray.tray-glowing{
  animation: trayGlow 2.2s ease-in-out infinite;
}
@keyframes trayGlow{
  0%,100%{
    box-shadow:
      0 1px 0 rgba(255,255,255,0.05) inset,
      0 30px 60px -20px rgba(0,0,0,0.7),
      0 0 0 1px rgba(0,0,0,0.4),
      0 0 0px rgba(245,196,81,0);
  }
  50%{
    box-shadow:
      0 1px 0 rgba(255,255,255,0.05) inset,
      0 30px 60px -20px rgba(0,0,0,0.7),
      0 0 0 1px rgba(0,0,0,0.4),
      0 0 22px 4px rgba(245,196,81,0.5);
  }
}
/* "Get ready" countdown right before a round starts: the border alternates
   dim/bright once per second, driven by script.js toggling .tray-bright in
   lockstep with the number shown (5 brightens, 4 dims, 3 brightens…). The
   0.3s transition just smooths each step rather than driving the timing
   itself. When tray-ready is removed (round actually begins), the .tray
   transition above fades it back to the default gold. */
.tray.tray-ready{
  border-color: #3c6650;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.05) inset,
    0 30px 60px -20px rgba(0,0,0,0.7),
    0 0 0 1px rgba(0,0,0,0.4),
    0 0 6px 1px rgba(92,154,118,0.2);
  transition: border-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}
.tray.tray-ready.tray-bright{
  border-color: #5c9a76;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.05) inset,
    0 30px 60px -20px rgba(0,0,0,0.7),
    0 0 0 1px rgba(0,0,0,0.4),
    0 0 26px 6px rgba(92,154,118,0.7);
}
.round-end-banner{
  position:absolute;
  inset:0;
  z-index: 20;
  pointer-events:none;
}
.round-end-banner[hidden]{ display:none !important; }

.mascot-pop{
  position:absolute;
  left: 4%;
  bottom: 4%;
  opacity:0;
  transition: opacity 0.3s ease;
}
.round-end-banner.visible .mascot-pop{
  opacity:1;
}
.round-end-banner.fading .mascot-pop{
  opacity:0;
}

.mascot-img{
  width: 100px;
  height: auto;
  display:block;
  filter: drop-shadow(0 14px 18px rgba(0,0,0,0.6)) drop-shadow(0 4px 6px rgba(0,0,0,0.4));
}
.round-end-banner.visible .mascot-img{
  animation: mascotPopIn 0.6s cubic-bezier(.34,1.56,.64,1) both;
}

@keyframes mascotPopIn{
  0%{ transform: translateY(50px) scale(0.3) rotate(-8deg); }
  55%{ transform: translateY(-10px) scale(1.1) rotate(3deg); }
  75%{ transform: translateY(4px) scale(0.96) rotate(-1deg); }
  100%{ transform: translateY(0) scale(1) rotate(0deg); }
}

.speech-bubble{
  position:absolute;
  left: 82px;
  bottom: 66%;
  width: max-content;
  max-width: 175px;
  white-space: pre-line;
  text-align:center;
  background: #fff;
  color: #16294a;
  font-family: 'Fraunces', serif;
  font-weight: 700;
  font-size: 15.5px;
  line-height: 1.25;
  padding: 9px 14px;
  border-radius: 16px;
  box-shadow: 0 10px 24px rgba(0,0,0,0.5), 0 3px 6px rgba(0,0,0,0.35);
  transform-origin: 12% 88%;
  opacity:0;
}
.round-end-banner.visible .speech-bubble{
  animation: bubblePopIn 0.5s cubic-bezier(.34,1.56,.64,1) both;
  animation-delay: 0.18s;
}
.speech-bubble::after{
  content:'';
  position:absolute;
  left: -9px;
  bottom: 8px;
  width:0; height:0;
  border-style:solid;
  border-width: 7px 11px 7px 0;
  border-color: transparent #fff transparent transparent;
  filter: drop-shadow(-2px 2px 2px rgba(0,0,0,0.15));
}

@keyframes bubblePopIn{
  0%{ transform: scale(0.3) translateY(12px); opacity:0; }
  55%{ transform: scale(1.08) translateY(-3px); opacity:1; }
  100%{ transform: scale(1) translateY(0); opacity:1; }
}

@media (max-width: 420px){
  .mascot-img{ width: 78px; }
  .speech-bubble{ left: 66px; font-size: 13.5px; max-width: 145px; padding: 7px 11px; }
}

.grid{
  position: relative;
  display:grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
.trail-svg{
  position:absolute;
  inset: 0;
  pointer-events:none;
  overflow: visible;
}
.tile{
  position: relative;
  aspect-ratio: 1;
  background-image: url('assets/tile-bg.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: center;
  display:flex;
  align-items:center;
  justify-content:center;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  /* long-press on mobile otherwise pops up the browser's own image
     callout/menu (iOS) or a "Download image" context menu (Android) on
     what the browser treats as an image-backed element. */
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  /* the browser's default tap/long-press highlight is a plain rectangle —
     it ignores the tile's rounded shape (which is baked into the artwork,
     not a CSS border-radius), so it visibly pokes out past the corners. */
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.08s ease, filter 0.08s ease;
}
.tile::after{
  content:'';
  position:absolute;
  inset: 10%;
  border-radius: 22%;
  opacity:0;
  transition: opacity 0.15s ease, background-color 0.15s ease;
  z-index:1;
  pointer-events:none;
}
.tile:hover{
  filter: brightness(1.06);
}
.tile .letter{
  position:relative;
  z-index:2;
  font-family: 'Arial Black', Impact, 'Fraunces', sans-serif;
  font-weight: 900;
  font-size: var(--tile-letter-size, 32px);
  color: #16294a;
  /* no text-transform here on purpose: script.js already builds the
     correct casing per tile ("Qu" for the Qu die, plain uppercase for
     everything else) — forcing uppercase here would turn "Qu" back into
     "QU", which isn't how the die face is actually printed. */
  letter-spacing: -0.01em;
}
/* Wild tile — a star instead of a letter; the gold glow/pulse marks it as
   special so it reads as "pick a letter" rather than a die that rolled
   blank. Shows up on a random tile on a random subset of rounds. */
.tile.wildcard .letter{
  color: var(--gold);
  /* the star is an inline SVG (see renderBoard in script.js), not a text
     glyph — a fixed square flex box sized to the tile-letter-size variable
     centers it exactly, sidestepping the font-baseline quirks that made a
     literal '★' character sit visibly high instead of centered. */
  display:flex;
  align-items:center;
  justify-content:center;
  width: var(--tile-letter-size, 32px);
  height: var(--tile-letter-size, 32px);
}
.tile.wildcard::before{
  content:'';
  position:absolute;
  inset: 6%;
  border-radius: 22%;
  box-shadow: 0 0 0 2px rgba(255,210,63,0.55);
  animation: wildcardPulse 1.8s ease-in-out infinite;
  z-index:1;
  pointer-events:none;
}
@keyframes wildcardPulse{
  0%,100%{ box-shadow: 0 0 0 2px rgba(255,210,63,0.35); }
  50%{ box-shadow: 0 0 0 4px rgba(255,210,63,0.7); }
}
.tile.selected{
  transform: translateY(4px) scale(0.95);
  filter: brightness(0.96);
  animation: selectPop 0.16s ease;
}
@keyframes selectPop{
  0%{ transform: scale(1); }
  45%{ transform: scale(1.07) translateY(-2px); }
  100%{ transform: translateY(4px) scale(0.95); }
}
.tile.selected::after{
  opacity: 1;
  background-color: rgba(255,210,63,0.4);
  transition: opacity 0.06s ease;
}
.tile.good-flash{ animation: goodFlash 0.6s ease; }
.tile.bad-flash{ animation: badFlash 0.5s ease; }
@keyframes goodFlash{
  0%{ filter: brightness(1.35) saturate(1.4); }
  100%{ filter: brightness(1) saturate(1); }
}
@keyframes badFlash{
  0%{ filter: brightness(0.7) saturate(1.5) hue-rotate(-15deg); }
  100%{ filter: brightness(1) saturate(1); }
}
.tile.path-preview::after{
  opacity: 1;
  background-color: rgba(92,154,118,0.4);
  transition: transform 0.15s ease;
}
.tile.path-preview-pop{
  animation: revealPop 0.26s ease;
}
@keyframes revealPop{
  0%{ transform: scale(1); }
  40%{ transform: scale(1.16); }
  100%{ transform: scale(1); }
}
.tile.path-preview-glow{
  animation: glowPopLoop var(--pop-duration, 1400ms) ease-in-out infinite;
}
.tile.path-preview-glow::after{
  opacity: 1;
  background-color: rgba(255,210,63,0.4);
}
.tile.path-preview-glow .letter{
  -webkit-text-fill-color: #16294a;
  -webkit-text-stroke: 2.5px #ffffff;
  paint-order: stroke fill;
  text-shadow:
    -1.5px -1.5px 0 #fff,
    1.5px -1.5px 0 #fff,
    -1.5px 1.5px 0 #fff,
    1.5px 1.5px 0 #fff;
}
@keyframes glowPopLoop{
  0%{ transform: scale(1); }
  6%{ transform: scale(1.05); }
  12%{ transform: scale(1); }
  100%{ transform: scale(1); }
}

.current-word-bar{
  margin: 0 0 12px;
  min-height: 40px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap: 6px;
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: calc(22px * var(--reading-scale, 1));
  color: var(--gold-bright);
  letter-spacing: 0.04em;
  background: rgba(255,255,255,0.03);
  border-radius: 10px;
  padding: 4px 10px;
}
.current-word-bar .msg{
  font-family: 'Inter', sans-serif;
  font-size: calc(13px * var(--reading-scale, 1));
  font-weight: 500;
  color: var(--text-dim);
  letter-spacing: 0.02em;
}
.current-word-bar .msg.good{ color: var(--sage); }
.current-word-bar .msg.bad{ color: var(--rust); }

.panels{
  margin-top: 16px;
}
.panels[hidden]{ display:none !important; }
.found-panel{
  display:flex;
  flex-direction: column;
  background: var(--bg-2);
  border-radius: 18px;
  padding: 14px 16px;
  min-height: 90px;
  border: 1px solid rgba(255,255,255,0.06);
  box-shadow: 0 14px 30px rgba(0,0,0,0.25);
  transition: box-shadow 0.3s ease;
}
.found-panel.showing-results{
  box-shadow: 0 20px 40px rgba(0,0,0,0.35), 0 0 0 1px rgba(255,210,63,0.12);
}
/* Ordering differs between live play and post-round results — rather than
   duplicating markup in two DOM positions, flex `order` re-flows the same
   elements: live play is header -> live word -> found chips; results is
   stats/reveal-list -> found chips -> reveal toggle (chips always sit right
   above the toggle button, never below it). */
.found-header{ order: 0; }
.current-word-bar{ order: 1; }
.chips{ order: 2; }
.results-block, .reveal-list{ order: 0; }
.reveal-toggle{ order: 3; }
.found-panel.showing-results .chips{ order: 1; }
.found-panel.showing-results .reveal-toggle{ order: 2; }
/* Redundant with the Round Complete stat grid once results are showing. */
.found-panel.showing-results .found-header{ display:none; }
/* The possible-words list already shows every found word highlighted in
   gold, so the separate found-chips list would just duplicate them right
   next to it — hide it while that list is open. */
.found-panel.showing-reveal-list .chips{ display:none; }
.found-header{
  display:flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 18px;
  margin: 0 0 10px;
  font-size: calc(12.5px * var(--reading-scale, 1));
  color: var(--text);
}
.found-header .found-label{
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
  font-size: calc(11px * var(--reading-scale, 1));
  font-weight: 600;
  margin-right: 2px;
}
.found-header .found-stat{
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 600;
  text-transform: uppercase;
}
/* Timer relocated here from the top header — styled to match the
   Words Found stat (inline label + value) and pushed to the row's right
   corner, same way Score used to sit opposite Time up top. Deliberately
   not touching `color` here: the low-time red warning and countdown green
   glow are set by .stat.timer.low/.countdown-pop elsewhere and should keep
   working unchanged regardless of where this stat physically sits. */
.found-header .stat.timer{
  margin-left: auto;
  display:flex;
  align-items:baseline;
  gap: 6px;
  text-align: left;
}
.found-header .stat.timer .label{
  font-size: calc(11px * var(--reading-scale, 1));
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
  font-weight: 600;
  margin: 0;
}
.found-header .stat.timer .value{
  font-family: 'IBM Plex Mono', monospace;
  font-size: calc(12.5px * var(--reading-scale, 1));
  font-weight: 700;
  text-transform: uppercase;
}
.chips{
  display:flex;
  flex-wrap: wrap;
  gap: 6px;
}
.chip{
  font-family: 'IBM Plex Mono', monospace;
  font-size: calc(12.5px * var(--reading-scale, 1));
  background: rgba(92,154,118,0.16);
  color: #a9d6bb;
  border: 1px solid rgba(92,154,118,0.35);
  padding: 4px 9px;
  border-radius: 999px;
  text-transform: uppercase;
  cursor: pointer;
}
.chip.missed{
  background: rgba(255,210,63,0.08);
  color: var(--text-dim);
  border: 1px solid rgba(255,210,63,0.25);
}
/* Words the player already found, inside the possible-words reveal list —
   bright gold (text included) so they read as "claimed", distinct from the
   dim/muted look of .missed (words still up for grabs). */
.chip.reveal-found{
  background: rgba(255,210,63,0.28);
  color: var(--gold-bright);
  border: 1px solid rgba(255,210,63,0.55);
}
.chip.active{
  background: var(--gold-bright);
  color: #16294a;
  border: 1px solid var(--gold);
  font-weight: 700;
  box-shadow: 0 0 0 2px rgba(255,210,63,0.3);
}
.chip.missed.active{
  background: var(--gold-bright);
  color: #16294a;
  border: 1px solid var(--gold);
}
.chip.chip-dup-glow{
  animation: chipDupGlow 3s ease-out;
}
@keyframes chipDupGlow{
  0%{
    background: rgba(255,210,63,0.4);
    border-color: var(--gold-bright);
    color: var(--gold-bright);
    box-shadow: 0 0 0 0 rgba(255,210,63,0.8);
  }
  20%{
    background: rgba(255,210,63,0.4);
    border-color: var(--gold-bright);
    color: var(--gold-bright);
    box-shadow: 0 0 14px 4px rgba(255,210,63,0.6);
  }
  100%{
    background: rgba(92,154,118,0.16);
    border-color: rgba(92,154,118,0.35);
    color: #a9d6bb;
    box-shadow: 0 0 0 0 rgba(255,210,63,0);
  }
}
.empty-note{
  font-size: calc(13px * var(--reading-scale, 1));
  color: var(--text-dim);
  font-style: italic;
}

.controls{
  display:flex;
  gap: 10px;
  margin-top: 18px;
}
button.primary, button.secondary{
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: 14px;
  border: none;
  border-radius: 12px;
  padding: 13px 20px;
  cursor: pointer;
  letter-spacing: 0.01em;
}
button.primary{
  flex: 1;
  background: linear-gradient(160deg, var(--gold-bright), var(--gold));
  color: #16294a;
  box-shadow: 0 4px 0 #8a6b25, 0 8px 16px rgba(0,0,0,0.35);
}
button.primary:active{ transform: translateY(3px); box-shadow: 0 1px 0 #8a6b25; }
button.primary:disabled{ opacity: 0.4; cursor: not-allowed; }
button.secondary{
  background: rgba(255,255,255,0.06);
  color: var(--text);
  border: 1px solid rgba(255,255,255,0.14);
}
button.secondary:active{ transform: translateY(1px); }
button.secondary.danger{
  background: rgba(217,83,79,0.14);
  border: 1px solid rgba(217,83,79,0.4);
  color: #f2a5a2;
}
button.secondary.danger:hover{
  background: rgba(217,83,79,0.22);
}

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

/* Live word bar hides once results take over the same panel, so the two
   states never fight for the same space. */
.found-panel.showing-results .current-word-bar{ display:none; }

.results-block{
  margin: 4px 0 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  animation: panelIn 0.4s ease both;
}
.results-block[hidden]{ display:none !important; }
.results-title{
  font-family: 'Fraunces', serif;
  font-weight: 600;
  color: var(--gold-bright);
  text-align:center;
  margin: 0 0 6px;
  font-size: calc(21px * var(--reading-scale, 1));
}
.results-summary{
  font-size: calc(13px * var(--reading-scale, 1));
  line-height: 1.5;
  color: var(--text-dim);
  text-align:center;
  margin: 0 0 14px;
}
.stat-grid{
  display:grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.stat-card{
  background: rgba(0,0,0,0.25);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 12px;
  padding: 10px 8px;
  text-align:center;
  opacity:0;
  animation: statCardIn 0.4s ease both;
}
.stat-card:nth-child(1){ animation-delay: 0.05s; }
.stat-card:nth-child(2){ animation-delay: 0.12s; }
.stat-card:nth-child(3){ animation-delay: 0.19s; }
.stat-card:nth-child(4){ animation-delay: 0.26s; }
.stat-card:nth-child(5){ animation-delay: 0.33s; }
@keyframes statCardIn{
  from{ opacity:0; transform: translateY(6px) scale(0.94); }
  to{ opacity:1; transform: translateY(0) scale(1); }
}
.stat-card.highlight{
  background: linear-gradient(160deg, rgba(255,210,63,0.22), rgba(255,210,63,0.06));
  border: 1px solid rgba(255,210,63,0.4);
  box-shadow: 0 0 18px rgba(255,210,63,0.15);
}
.stat-big{
  font-family:'IBM Plex Mono',monospace;
  font-size: calc(20px * var(--reading-scale, 1));
  font-weight: 600;
  color: var(--gold-bright);
}
/* these two hold actual words (can run 8+ letters) rather than short
   numbers, and now sit in half-width cards — shrink so long words don't
   overflow their card. */
#longestWord, #longestPossibleWord{ font-size: calc(15px * var(--reading-scale, 1)); }
/* cycles between tied longest-possible words, one at a time */
#longestPossibleWord{ transition: opacity 0.3s ease; }
#longestPossibleWord.fading{ opacity: 0; }
.stat-small{
  font-size: calc(9.5px * var(--reading-scale, 1));
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
  margin-top: 2px;
}

.reveal-toggle{
  width:100%;
  display:flex;
  align-items:center;
  justify-content:center;
  gap: 8px;
  margin-top: 12px;
  font-family: 'Inter', sans-serif;
  font-weight: 600;
  font-size: calc(13.5px * var(--reading-scale, 1));
  background: rgba(255,255,255,0.06);
  color: var(--text);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 12px;
  padding: 11px 16px;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.1s ease;
}
.reveal-toggle:active{ transform: translateY(1px); }
.reveal-toggle:hover{ background: rgba(255,255,255,0.1); }
.reveal-toggle .chevron{ transition: transform 0.25s ease; }
.reveal-toggle.expanded .chevron{ transform: rotate(180deg); }
/* needed because .reveal-toggle's own `display:flex` (an author rule)
   otherwise wins over the browser's default [hidden]{display:none} even
   without !important — author styles always beat user-agent defaults. */
.reveal-toggle[hidden]{ display:none !important; }

/* Categorized by score tier — each tier is a full-width row section,
   longest/highest-scoring tier first (top to bottom); the words *within*
   a tier flow horizontally and wrap like a normal chip list. */
.reveal-list{
  display:flex;
  flex-direction: column;
  gap: 12px;
  margin: 12px 0 0;
  /* fixed, viewport-relative container instead of letting the list push the
     whole page taller — scrolls internally so browsing the full word list
     takes at most one scroll gesture instead of scrolling the whole page. */
  max-height: 60vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-right: 4px;
}
.reveal-list[hidden]{ display:none !important; }
.reveal-column{
  background: rgba(0,0,0,0.22);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 12px;
  padding: 8px 10px;
}
.reveal-column-title{
  font-size: calc(10px * var(--reading-scale, 1));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.reveal-column-words{
  display:flex;
  flex-wrap: wrap;
  gap: 6px;
}
::-webkit-scrollbar{ width: 6px; }
::-webkit-scrollbar-thumb{ background: rgba(255,255,255,0.15); border-radius: 4px; }

/* Floating "look up this word" button — appears once a chip in either the
   Words Found list or the possible-words reveal list is tapped after the
   round has ended (see attachChipRevealHandler/showDictionaryFab in
   script.js). Fixed to the viewport (not anchored to the chip or the
   document's scroll position) since script.js positions it in pixels via
   left/top — see repositionFab(): it defaults to the board's lower-left
   corner the first time ever, then always restores wherever the player
   last dragged it. touch-action: none stops a drag from also scrolling
   the page underneath it on mobile. */
.dictionary-fab{
  position: fixed;
  left: 0;
  top: 0;
  width: 56px;
  height: 56px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--bg-2);
  box-shadow: 0 10px 24px rgba(0,0,0,0.45), 0 0 0 2px rgba(255,210,63,0.4);
  cursor: grab;
  touch-action: none;
  z-index: 40;
  animation: panelIn 0.2s ease both;
  overflow: hidden;
}
.dictionary-fab[hidden]{ display:none !important; }
.dictionary-fab:active{ cursor: grabbing; transform: scale(0.96); }
.dictionary-fab img{
  width:100%;
  height:100%;
  object-fit: cover;
  display:block;
  pointer-events: none;
}

.definition-modal{
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(4,9,20,0.7);
  display:flex;
  align-items:center;
  justify-content:center;
  padding: 20px;
}
.definition-modal[hidden]{ display:none !important; }
.definition-modal-inner{
  width: 100%;
  max-width: 340px;
  max-height: 80vh;
  display:flex;
  flex-direction: column;
  background: var(--bg-2);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 20px 50px rgba(0,0,0,0.5);
  animation: panelIn 0.2s ease both;
}
.definition-modal-header{
  display:flex;
  align-items:center;
  justify-content:space-between;
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: 17px;
  color: var(--gold-bright);
  letter-spacing: 0.03em;
  margin-bottom: 10px;
  flex-shrink: 0;
}
.definition-modal-body{
  overflow-y: auto;
  display:flex;
  flex-direction: column;
  gap: 10px;
}
/* One box per part-of-speech category (Noun, Verb, ...), each holding a
   numbered list of every definition in that category — grouping by
   category rather than one box per individual definition makes the part
   of speech impossible to miss at a glance. */
.definition-category{
  background: rgba(0,0,0,0.22);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  padding: 10px 12px;
}
.definition-category-title{
  display:inline-block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #16294a;
  background: var(--gold-bright);
  padding: 2px 9px;
  border-radius: 999px;
  margin-bottom: 8px;
}
.definition-list{
  margin: 0;
  padding-left: 1.25em;
  display:flex;
  flex-direction: column;
  gap: 6px;
}
.definition-list li{
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--text);
}
.definition-loading, .definition-empty{
  font-size: 13px;
  color: var(--text-dim);
  font-style: italic;
}
.definition-note{
  margin: 0 0 2px;
  font-size: 11.5px;
  color: var(--text-dim);
  font-style: italic;
}
.definition-source{
  margin-top: 4px;
  font-size: 10.5px;
  color: var(--text-dim);
  text-align: right;
}

.definition-modal-footer{
  display:flex;
  align-items:center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,0.08);
  flex-shrink: 0;
}
.report-word-btn{
  background: none;
  border: 1px solid rgba(217,83,79,0.4);
  color: #f2a5a2;
  font-family: 'Inter', sans-serif;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 8px;
  padding: 6px 10px;
  cursor:pointer;
}
.report-word-btn:hover{ background: rgba(217,83,79,0.14); }
.report-word-status{
  font-size: 11px;
  color: var(--text-dim);
  font-style: italic;
}

.report-word-panel{
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(4,9,20,0.75);
  display:flex;
  align-items:center;
  justify-content:center;
  padding: 20px;
}
.report-word-panel[hidden]{ display:none !important; }
.report-word-inner{
  width: 100%;
  max-width: 320px;
  background: var(--bg-2);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 20px 50px rgba(0,0,0,0.5);
  animation: panelIn 0.2s ease both;
}
.report-word-reason{
  width:100%;
  min-height: 70px;
  resize: vertical;
  background: rgba(0,0,0,0.22);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 8px 10px;
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  margin-bottom: 10px;
}
.report-word-submit{ width:100%; }

@media (max-width: 480px){
  /* .brand/.logo-img/.wordmark/.tagline now scale fluidly via clamp() in
     their base rules above, so no fixed-breakpoint override is needed here
     — that's what kept failing at odd widths like 344/375/390px. Tile
     letter size is now user-controlled via the Settings slider instead of
     a fixed mobile override — see --tile-letter-size in :root. */
}
