/* ————————————————————————————————————————————————
   HUERDLE · stylesheet
   charcoal, hairlines, serif display, mono instrumentation
   ———————————————————————————————————————————————— */

:root {
  --bg: #0e0e11;
  --panel-bg: #131318;
  --ink: #e9e4da;
  /* secondary / tertiary text — raised for legibility (was 0.58 / 0.32, which
     read too faint on the menu notes and elsewhere) */
  --ink-dim: rgba(233, 228, 218, 0.72);
  --ink-faint: rgba(233, 228, 218, 0.46);
  --line: rgba(233, 228, 218, 0.14);
  --line-strong: rgba(233, 228, 218, 0.34);
  --c1: #14525f;
  --c2: #e0a458;
  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --ease-out: cubic-bezier(0.22, 0.9, 0.26, 1);
  --ease-snap: cubic-bezier(0.34, 1.45, 0.4, 1);
  --strip-h: clamp(120px, 23vh, 208px);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.5;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  user-select: none;
  -webkit-user-select: none;
}

button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
button:focus-visible { outline: 1px dashed var(--ink-dim); outline-offset: 3px; }

.hidden { display: none !important; }

/* ———————————————————— atmosphere ———————————————————— */

.bg-glow {
  position: fixed;
  width: 58vmin; height: 58vmin;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.13;
  pointer-events: none;
  z-index: 0;
  transition: opacity 1.2s ease;
}
.glow-a { top: -12vmin; left: -8vmin;  animation: drift-a 31s ease-in-out infinite alternate; }
.glow-b { bottom: -14vmin; right: -9vmin; animation: drift-b 37s ease-in-out infinite alternate; }

@keyframes drift-a {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(9vmin, 7vmin) scale(1.18); }
}
@keyframes drift-b {
  from { transform: translate(0, 0) scale(1.12); }
  to   { transform: translate(-8vmin, -6vmin) scale(0.96); }
}

.bg-vignette {
  position: fixed; inset: 0;
  background: radial-gradient(120% 90% at 50% 42%, transparent 55%, rgba(0, 0, 0, 0.5) 100%);
  pointer-events: none;
  z-index: 1;
}

.bg-grain {
  position: fixed; inset: -120px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  opacity: 0.05;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: 2;
  animation: grain 1.4s steps(7) infinite;
}
@keyframes grain {
  0%   { transform: translate(0, 0); }
  14%  { transform: translate(-34px, 22px); }
  28%  { transform: translate(18px, -40px); }
  42%  { transform: translate(-46px, -14px); }
  57%  { transform: translate(30px, 34px); }
  71%  { transform: translate(-12px, 46px); }
  85%  { transform: translate(42px, -20px); }
  100% { transform: translate(0, 0); }
}

/* ———————————————————— top chrome ———————————————————— */

.top {
  position: fixed;
  top: 0; left: 0; right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 22px;
  z-index: 60;
  pointer-events: none;
}
.top > * { pointer-events: auto; }
.top-left, .top-right { flex: 1 0 0; display: flex; gap: 6px; }
.top-right { justify-content: flex-end; }

.top-center {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 11px;
  letter-spacing: 0.22em;
  color: var(--ink-dim);
  white-space: nowrap;
}
.hud-sep { width: 1px; height: 12px; background: var(--line-strong); }
.hud-time {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.14em;
  color: var(--ink);
}
.hud-time.low { color: #cf8f6a; } /* under ten seconds */

.ghost-btn {
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--ink-dim);
  padding: 8px 10px;
  transition: color 0.25s ease;
}
.ghost-btn:hover { color: var(--ink); }

.icon-btn {
  position: relative;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  color: var(--ink-dim);
  border: 1px solid transparent;
  border-radius: 50%;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.icon-btn:hover { color: var(--ink); border-color: var(--line); }
.icon-btn svg { width: 17px; height: 17px; display: block; }
.icon-btn.off { color: var(--ink-faint); }
.icon-btn.on { color: var(--ink); border-color: var(--line-strong); }
.icon-btn.off::after {
  content: "";
  position: absolute;
  left: 7px; right: 7px; top: 50%;
  height: 1.4px;
  background: var(--ink-dim);
  transform: rotate(-42deg);
}

/* lives */
.diamonds { display: inline-flex; align-items: center; gap: 9px; }
.diamond {
  width: 8px; height: 8px;
  border: 1px solid var(--ink-dim);
  transform: rotate(45deg);
  transition: background 0.3s ease, border-color 0.3s ease;
}
.diamond.full { background: var(--ink); border-color: var(--ink); }
.diamond.empty { border-color: var(--ink-faint); }
.diamond.crack { animation: crack 0.55s var(--ease-out) both; }
@keyframes crack {
  0%   { background: var(--ink); border-color: var(--ink); transform: rotate(45deg) scale(1); }
  30%  { transform: rotate(45deg) scale(1.7); }
  100% { background: transparent; border-color: var(--ink-faint); transform: rotate(45deg) scale(1); }
}

/* ———————————————————— screens ———————————————————— */

.screen {
  position: fixed; inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s ease, visibility 0.45s;
  z-index: 10;
  overflow-y: auto;
  /* always reserve the scrollbar's space, so a mode that needs to scroll
     doesn't shift the (centred) content sideways relative to one that doesn't */
  scrollbar-gutter: stable;
}
.screen.active { opacity: 1; visibility: visible; }

/* ———————————————————— menu ———————————————————— */

.menu-wrap {
  width: min(580px, 90vw);
  margin: 0 auto;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  /* top-anchored: the masthead + mode control hold a fixed position, and modes
     with fewer settings simply occupy less of the page (no recentring jump) */
  justify-content: flex-start;
  padding: 72px 0 48px;
  animation: rise 0.8s var(--ease-out) both;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

.masthead { text-align: center; margin-bottom: 34px; }

.title {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 460;
  font-size: clamp(3.1rem, 9.5vw, 4.9rem);
  letter-spacing: -0.015em;
  line-height: 1.04;
  font-optical-sizing: auto;
}
.t-color {
  background-image: linear-gradient(100deg, var(--c1), var(--c2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  transition: none;
}
.tagline {
  margin-top: 14px;
  font-size: 10px;
  letter-spacing: 0.42em;
  color: var(--ink-dim);
}

/* preview */
.preview { margin-bottom: 30px; }
/* the daily's date, sat just below the gradient and above the mode control.
   Its line is reserved on every mode (invisible when not the daily) so the
   mode control below never shifts as you switch modes. */
.menu-date {
  text-align: center;
  margin: -10px 0 24px;
  min-height: 1.7rem;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 440;
  font-size: 1.55rem;
  letter-spacing: 0.01em;
}
.menu-date.dim { visibility: hidden; }
.preview-strip {
  position: relative;
  height: 58px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background-image: linear-gradient(90deg, var(--c1), var(--c2));
  background-origin: border-box; /* span the full box — no wrap into the border */
  background-repeat: no-repeat;
}
.reroll {
  position: absolute;
  right: 9px; top: 50%;
  transform: translateY(-50%);
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--ink);
  background: rgba(14, 14, 17, 0.66);
  border: 1px solid var(--line);
  backdrop-filter: blur(2px);
  transition: background 0.25s ease, transform 0.25s ease;
}
.reroll:hover { background: rgba(14, 14, 17, 0.85); }
.reroll svg { width: 16px; height: 16px; }
.reroll.spin svg { animation: spin 0.55s var(--ease-out); }
@keyframes spin { from { transform: rotate(-300deg); } to { transform: rotate(0); } }

.ruler {
  display: flex;
  justify-content: space-between;
  height: 10px;
  margin-top: 7px;
  align-items: flex-start;
}
.tick { width: 1px; height: 6px; background: var(--ink-faint); }
.tick.major { height: 10px; background: var(--line-strong); }

.hex-row {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
}

/* settings — spec sheet rows */
.settings { border-top: 1px solid var(--line); }
.set-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  min-height: 64px;
  padding: 12px 2px;
  border-bottom: 1px solid var(--line);
}
.set-label {
  font-size: 10px;
  letter-spacing: 0.34em;
  color: var(--ink-dim);
}
.set-control { display: flex; align-items: center; gap: 16px; }
.set-control.col { flex-direction: column; align-items: flex-end; gap: 8px; }
.set-note {
  font-size: 10.5px;
  letter-spacing: 0.16em;
  color: var(--ink-dim);
  text-align: right; /* wraps (vs. overflowing) on a narrow screen, right-aligned */
}

/* segmented control */
.seg { display: flex; border: 1px solid var(--line-strong); border-radius: 2px; overflow: hidden; }
.seg-btn {
  padding: 9px 16px;
  font-size: 10.5px; /* at least as large as the .set-note text beside it */
  letter-spacing: 0.2em;
  color: var(--ink-dim);
  transition: background 0.25s ease, color 0.25s ease;
}
.seg-btn + .seg-btn { border-left: 1px solid var(--line-strong); }
.seg.compact .seg-btn { padding: 9px 10px; letter-spacing: 0.14em; }
.seg-btn.active { background: var(--ink); color: #121214; }
.seg-btn:not(.active):hover { color: var(--ink); }

/* swatches */
.swatches { display: flex; align-items: center; gap: 10px; }
.swatch { position: relative; display: block; width: 34px; height: 34px; cursor: pointer; }
.swatch input {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: 0;
  cursor: pointer;
}
.swatch-well {
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  box-shadow: inset 0 0 0 3px var(--bg);
  background: #777;
  pointer-events: none;
  transition: transform 0.2s var(--ease-out);
}
.swatch:hover .swatch-well { transform: scale(1.08); }
.swatch-dash { width: 12px; height: 1px; background: var(--line-strong); }

/* slider */
.slider-wrap { gap: 18px; }
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: clamp(150px, 30vw, 230px);
  height: 24px;
  background: transparent;
  cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 1px;
  background: var(--line-strong);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 11px; height: 11px;
  background: var(--ink);
  border: none;
  border-radius: 1px;
  transform: rotate(45deg);
  margin-top: -5.5px;
  transition: transform 0.15s ease;
}
input[type="range"]::-webkit-slider-thumb:hover { transform: rotate(45deg) scale(1.25); }
input[type="range"]::-moz-range-track { height: 1px; background: var(--line-strong); }
input[type="range"]::-moz-range-thumb {
  width: 11px; height: 11px;
  background: var(--ink);
  border: none;
  border-radius: 1px;
  transform: rotate(45deg);
}
output {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.1em;
  min-width: 2ch;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* dual-handle range (colour gap) */
.dual {
  position: relative;
  width: clamp(150px, 30vw, 230px);
  height: 24px;
}
.dual input[type="range"] {
  position: absolute;
  inset: 0;
  width: 100%;
  margin: 0;
  pointer-events: none;
}
.dual input[type="range"]::-webkit-slider-thumb { pointer-events: auto; }
.dual input[type="range"]::-moz-range-thumb { pointer-events: auto; }
.dual input[type="range"]:nth-child(2)::-webkit-slider-runnable-track { background: transparent; }
.dual input[type="range"]:nth-child(2)::-moz-range-track { background: transparent; }
#out-gap { min-width: 5ch; }

/* stepper */
.stepper { display: flex; align-items: center; border: 1px solid var(--line-strong); border-radius: 2px; }
.stepper button {
  width: 34px; height: 34px;
  font-size: 16px;
  color: var(--ink-dim);
  transition: color 0.2s ease, background 0.2s ease;
}
.stepper button:hover { color: var(--ink); background: rgba(233, 228, 218, 0.06); }
.stepper output { padding: 0 8px; font-size: 14px; }

.menu-warn {
  min-height: 22px;
  margin-top: 14px;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.22em;
  color: #cf8f6a;
}

/* buttons */
.btn {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  padding: 15px 30px;
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  color: var(--ink);
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease,
              letter-spacing 0.3s ease, opacity 0.25s ease;
}
.btn:hover:not(:disabled) { background: var(--ink); color: #121214; border-color: var(--ink); letter-spacing: 0.36em; }
.btn:disabled { opacity: 0.3; cursor: default; }
.btn.primary { background: var(--ink); color: #121214; border-color: var(--ink); }
.btn.primary:hover:not(:disabled) { background: #fff; border-color: #fff; }
/* the primary CTA is briefly held on results pop-ups so the figures land before
   you move on (and, when ads are on, it doubles as the ad's viewability window);
   it reads as "settling", not broken — a soft breathe, then fades up to full */
.btn.dwell:disabled { opacity: 0.42; cursor: default; }
@media (prefers-reduced-motion: no-preference) {
  .btn.dwell:disabled { animation: dwellBreathe 1.5s ease-in-out forwards; }
}
@keyframes dwellBreathe {
  0%   { opacity: 0.3; }
  60%  { opacity: 0.5; }
  100% { opacity: 0.62; }
}

/* overall-volume slider — drops down under the sound button on hover */
.vol-wrap { position: relative; display: inline-flex; }
.vol-pop {
  position: absolute; top: calc(100% + 8px); right: 0;
  background: rgba(18, 18, 22, 0.97);
  border: 1px solid var(--line); border-radius: 7px;
  padding: 11px 13px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5);
  z-index: 90;
  opacity: 0; visibility: hidden; transform: translateY(-6px); pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
}
.vol-pop.show { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
.vol-pop input[type="range"] { width: 116px; accent-color: var(--ink); cursor: pointer; display: block; }

.begin { width: 100%; margin-top: 6px; }

.menu-foot {
  margin-top: 22px;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.3em;
  color: var(--ink-faint);
  min-height: 15px;
}

/* daily challenge card — now just the finished-result summary */
.daily-card {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 22px 8px;
  margin-bottom: 6px;
  text-align: center;
}
.daily-result-line {
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* gold star marking a first place today, inline with the solve details */
.solve-star { color: #f2cf7a; text-shadow: 0 0 7px rgba(242, 207, 122, 0.5); }
.daily-next {
  margin-top: 9px;
  font-size: 10px;
  letter-spacing: 0.26em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* bordered leaderboard button — the last action in each board-backed mode */
.board-btn { width: 100%; margin-top: 12px; }

/* result hero stats — big mono numbers under the title, the key figures (moves,
   time) glowing gold so your result reads at a glance instead of as a paragraph */
.panel-stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(16px, 6vw, 38px);
  margin: 2px 0 14px;
}
.stat { display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 46px; }
.stat-val {
  font-family: var(--mono);
  font-size: clamp(1.55rem, 7vw, 2rem);
  font-weight: 500;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* the stat numbers carry their own verdict: gold = excellent, then a warm
   slide through pink to red as lives run low */
.stat-val.gold { color: #f2cf7a; text-shadow: 0 0 16px rgba(242, 207, 122, 0.35); }
.stat-val.warn { color: #e8b1a8; } /* 2 lives — slight pink */
.stat-val.low  { color: #e0938a; } /* 1 life — pink-red */
.stat-val.bad  { color: #d3685a; } /* 0 lives — red */
.stat-label { font-size: 8px; letter-spacing: 0.24em; color: var(--ink-faint); }
.stat-sub { font-size: 8.5px; letter-spacing: 0.1em; color: var(--ink-dim); }
/* each figure resolves INTO FOCUS as the panel opens — starting large, blurred
   and faded, then settling sharp. JS staggers them one by one (per-cell
   animation-delay) so they land in sequence. Motion-safe only. */
@media (prefers-reduced-motion: no-preference) {
  .panel-stats .stat { animation: statReveal 520ms var(--ease-out) both; }
  @keyframes statReveal {
    0%   { opacity: 0; transform: scale(1.5);  filter: blur(8px); }
    60%  { opacity: 1; transform: scale(0.97); filter: blur(0); }
    100% { opacity: 1; transform: scale(1);    filter: blur(0); }
  }
}

/* a Perfect solve gilds its title to match the gold move count */
.panel-title.gold { color: #f2cf7a; }

/* leaderboard standing in the result panel — sits just under the hero stats */
.panel-rank {
  margin: 0 0 16px;
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* leaderboard overlay (reuses .panel-backdrop / .panel) */
.board-panel { width: min(460px, 92vw); text-align: left; }
.board-panel .panel-title { text-align: center; }
/* the day's par — the fewest possible moves — sits just under the board title */
.board-fewest {
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.2em;
  color: #f2cf7a;
  margin: -6px 0 10px;
}
.board-sub {
  text-align: center;
  font-size: 9.5px;
  letter-spacing: 0.2em;
  color: var(--ink-dim);
  margin-bottom: 18px;
}
.board-list {
  list-style: none;
  margin: 0 0 22px;
  padding: 0;
  max-height: 46vh;
  overflow-y: auto;
}
/* anonymous rows: rank · score, with a YOU tag on your own line. The rank and
   YOU columns are fixed-width so a row with "YOU" (or the rank-1 💎) lines up
   exactly with every other row — the stat column never shifts */
.board-row {
  display: grid;
  grid-template-columns: 3em 1fr 2.6em;
  gap: 12px;
  align-items: baseline;
  padding: 9px 6px;
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.board-row.me { background: rgba(233, 228, 218, 0.06); }
/* ranks right-align to a common edge, so the rank-1 💎 sits in the cell's left
   slack as a leading badge without shifting the number out of line */
.b-rank { color: var(--ink-faint); font-size: 10px; letter-spacing: 0.1em; white-space: nowrap; text-align: right; }
.b-lead { font-size: 11px; }
/* min-width:0 lets the 1fr stat column actually shrink so its diamonds + text
   wrap instead of spilling over the rank / YOU columns on narrow phones */
.b-stat { color: var(--ink); letter-spacing: 0.06em; min-width: 0; }
/* lives kept (daily) — gold diamonds, the board's primary ranking key; the
   hollow ◇ glyphs read as lost lives */
.b-lives { color: #f2cf7a; letter-spacing: 0.12em; white-space: nowrap; }
.b-you { color: #f2cf7a; font-size: 9px; letter-spacing: 0.18em; text-align: right; }
/* gap between the leader and your neighbourhood */
.board-gap { text-align: center; color: var(--ink-faint); letter-spacing: 0.3em; padding: 4px 0; }

/* ad surface — lives ONLY inside the end pop-up, in the reading path between
   the result figures and the actions (divider above; a clear gap below keeps it
   off the buttons) */
.panel-ad {
  margin: 6px 0 26px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  text-align: center;
}
.ad-label {
  display: block;
  font-size: 8px;
  letter-spacing: 0.34em;
  color: var(--ink-faint);
  margin-bottom: 9px;
}
.ad-box {
  display: grid;
  place-items: center;
  min-height: 120px;
  border: 1px dashed var(--line-strong);
  border-radius: 3px;
  background: rgba(233, 228, 218, 0.02);
  color: var(--ink-faint);
  font-size: 9px;
  letter-spacing: 0.36em;
}
/* a real AdSense unit drops in here in place of .ad-box */
.panel-ad .adsbygoogle { display: block; min-height: 120px; }

/* how-to-play (reuses .panel-backdrop / .panel) */
.help-panel { width: min(500px, 92vw); text-align: left; max-height: 86vh; overflow-y: auto; }
.help-panel .panel-title { text-align: center; }
.help-body { margin-bottom: 28px; text-align: left; }
.help-body p {
  font-size: 12px;
  line-height: 1.75;
  color: var(--ink-dim);
  margin: 0 0 18px;
}
.help-modes { margin: 0; }
.help-modes dt {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  margin-top: 14px;
}
.help-modes dd {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink-dim);
}

/* consent banner */
.consent {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translate(-50%, 12px);
  width: min(620px, 92vw);
  z-index: 100;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 16px 18px;
  background: var(--panel-bg);
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s ease, transform 0.35s ease, visibility 0.35s;
}
.consent.show { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.consent-text {
  flex: 1 1 280px;
  font-size: 11px;
  letter-spacing: 0.04em;
  line-height: 1.7;
  color: var(--ink-dim);
}
.consent-text a { color: var(--ink); }
.consent-actions { display: flex; gap: 10px; }
.consent .btn { padding: 11px 18px; }

/* ———————————————————— game stage ———————————————————— */

.stage {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 76px 0 36px;
}

.toast {
  min-height: 20px;
  margin-bottom: 26px;
  font-size: 10.5px;
  letter-spacing: 0.28em;
  color: var(--ink-dim);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.4s ease, transform 0.4s ease;
  text-align: center;
  padding: 0 16px;
}
.toast.show { opacity: 1; transform: translateY(0); }

/* a brief, floating confirmation (share copied, …). Unlike .toast it is fixed
   to the viewport above every surface (menu, end panel, leaderboard) so it
   shows wherever it is triggered, not only on the game stage. */
.flash {
  position: fixed;
  left: 50%;
  bottom: calc(30px + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 10px);
  z-index: 200;
  pointer-events: none;
  max-width: min(420px, 86vw);
  padding: 11px 22px;
  background: var(--panel-bg);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 10px;
  letter-spacing: 0.26em;
  color: var(--ink);
  text-align: center;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.35s ease, transform 0.35s ease;
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.45);
}
.flash.show { opacity: 1; transform: translate(-50%, 0); }

/* timed mode: a prominent countdown sat right above the strip */
.timed-clock {
  font-variant-numeric: tabular-nums;
  font-size: clamp(2.1rem, 6vw, 3.1rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.06em;
  color: var(--ink);
  margin: -6px 0 18px;
  transition: color 0.3s ease;
}
.timed-clock.low { color: #cf8f6a; } /* under ten seconds */

.strip-frame {
  width: min(1080px, 92vw);
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: rgba(233, 228, 218, 0.022);
  transition: box-shadow 0.8s ease;
}
.strip-frame.enter { animation: strip-in 0.75s var(--ease-out) both; }
@keyframes strip-in {
  from { opacity: 0; transform: translateY(12px) scale(0.988); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.strip-frame.shake { animation: shake-x 0.55s ease both; }
@keyframes shake-x {
  0% { transform: translateX(0); }
  16% { transform: translateX(-9px); }
  32% { transform: translateX(8px); }
  48% { transform: translateX(-6px); }
  64% { transform: translateX(4px); }
  80% { transform: translateX(-2px); }
  100% { transform: translateX(0); }
}
.strip-frame.pulse { animation: frame-pulse 1s var(--ease-out) both; }
@keyframes frame-pulse {
  0%   { transform: scale(1); box-shadow: 0 0 0 rgba(233, 228, 218, 0); }
  30%  { transform: scale(1.013); box-shadow: 0 0 60px rgba(233, 228, 218, 0.14); }
  100% { transform: scale(1); box-shadow: 0 0 0 rgba(233, 228, 218, 0); }
}

.strip {
  position: relative;
  height: var(--strip-h);
  perspective: 1100px;
}
.strip.dimmed { filter: saturate(0.82) brightness(0.74); transition: filter 1.2s ease; }

.bars { position: absolute; inset: 0; }

/* bars */
.bar {
  position: absolute;
  top: 0;
  height: 100%;
  z-index: 1;
  will-change: transform;
  transition-property: transform, width;
  transition-duration: 450ms;
  transition-timing-function: var(--ease-out);
  cursor: grab;
  touch-action: none;
}
.bar.locked { cursor: default; }
.bar.dragging { z-index: 40; cursor: grabbing; }

.flip {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transition: transform 0.46s var(--ease-out);
}
.bar.flipped .flip { transform: rotateY(180deg); }

.face {
  position: absolute; inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 2px;
  transition: border-radius 0.5s ease, box-shadow 0.3s ease, transform 0.18s ease;
}
.face.back {
  transform: rotateY(180deg);
  background:
    repeating-linear-gradient(48deg,
      rgba(233, 228, 218, 0.085) 0 1px,
      transparent 1px 8px),
    #1e1e25;
  border: 1px solid rgba(233, 228, 218, 0.14);
}

/* flat overlay: on harder difficulties each bar is quantized to a single
   colour, killing the seam-continuity cue. It melts away on a win. */
.face.front .flat {
  position: absolute; inset: 0;
  border-radius: inherit;
  opacity: 0;
  transition: opacity 0.45s ease;
}
.bar.flattened .flat { opacity: 1; }
.strip.solid .flat { transition-duration: 0.95s; }

/* interaction affordances must never alter the colours being judged —
   geometry only: lifts, outlines and shadows, no filters */
.strip.playing .bar:not(.locked):not(.dragging):hover .face.front { transform: translateY(-4px); }
.strip.playing .bar:not(.locked):active { cursor: grabbing; }

.bar.dragging .face.front {
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55), 0 2px 10px rgba(0, 0, 0, 0.4);
}
.bar.selected .face.front {
  outline: 1.5px solid var(--ink);
  outline-offset: 3px;
  animation: sel-pulse 1.5s ease-in-out infinite;
}
@keyframes sel-pulse {
  0%, 100% { outline-color: rgba(233, 228, 218, 0.95); }
  50%      { outline-color: rgba(233, 228, 218, 0.35); }
}
.bar.kcur .face.front { outline: 1px dotted var(--ink-dim); outline-offset: 6px; }

.bar.deny { animation: deny 0.3s ease both; }
@keyframes deny {
  0%, 100% { margin-left: 0; }
  30% { margin-left: -3px; }
  70% { margin-left: 3px; }
}

/* lock glyph on the fixed end bars */
.bar.locked .face.front::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 7px;
  width: 9px; height: 11px;
  transform: translateX(-50%);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 11'%3E%3Crect x='0.6' y='4.6' width='7.8' height='5.8' rx='1' fill='none' stroke='white' stroke-width='1.1'/%3E%3Cpath d='M2.5 4.5V3a2 2 0 0 1 4 0v1.5' fill='none' stroke='white' stroke-width='1.1'/%3E%3C/svg%3E");
  background-size: contain;
  background-repeat: no-repeat;
  opacity: 0.42;
  mix-blend-mode: difference;
}

/* win: solidify */
.strip.solid .face { border-radius: 0; }

/* confirm cascade on correct submit */
.bar.confirm .face.front { animation: confirm-flash 0.55s ease both; }
@keyframes confirm-flash {
  0%   { filter: brightness(1); }
  35%  { filter: brightness(1.55); }
  100% { filter: brightness(1); }
}

/* ———————————————————— fx layer ———————————————————— */

.fxlayer {
  position: absolute; inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 30;
  border-radius: 2px;
}

.seams { position: absolute; inset: 0; opacity: 1; transition: opacity 0.45s ease; }
.seams.fade { opacity: 0; }
.seam {
  position: absolute;
  top: 0; bottom: 0;
  width: 1.5px;
  margin-left: -0.75px;
  background: rgba(10, 10, 12, 0.9);
  transform: scaleY(0);
  transition: transform 0.34s var(--ease-out);
}
.seam.in { transform: scaleY(1); }

.sweep {
  position: absolute;
  top: -8%; bottom: -8%;
  width: 34%;
  left: -40%;
  background: linear-gradient(102deg, transparent 0%, rgba(255, 255, 255, 0.11) 50%, transparent 100%);
  opacity: 0;
}
.sweep.run { animation: sweep-x 1.05s ease-in-out both; }
@keyframes sweep-x {
  0%   { left: -40%; opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { left: 108%; opacity: 0; }
}

.scanband {
  position: absolute;
  top: 0; bottom: 0;
  width: 13%;
  left: -15%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  opacity: 0;
}
.scanband.run { animation: scan-x 0.72s cubic-bezier(0.6, 0.05, 0.4, 0.95) both; }
@keyframes scan-x {
  0%   { left: -15%; opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { left: 103%; opacity: 0; }
}

.bloom {
  position: absolute; inset: -4px;
  background: radial-gradient(62% 120% at 50% 50%, rgba(255, 255, 255, 0.34), transparent 70%);
  opacity: 0;
}
.bloom.run { animation: bloom-k 0.95s ease-out both; }
@keyframes bloom-k {
  0%   { opacity: 0; }
  18%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ———————————————————— under-strip instrumentation ———————————————————— */

.game-ruler { width: calc(min(1080px, 92vw) - 22px); }
.game-hexes { width: calc(min(1080px, 92vw) - 22px); }

.actions {
  margin-top: 38px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.submit { min-width: 224px; }
.reset { margin-top: 14px; }
.reset:disabled { opacity: 0.3; pointer-events: none; }

/* ———————————————————— panel ———————————————————— */

.panel-backdrop {
  position: fixed; inset: 0;
  z-index: 80;
  /* a scrollable column so a panel taller than the viewport (e.g. the daily
     result + ad on a short phone) can scroll to reach every button, rather than
     centring and clipping the top/bottom. margin:auto still centres when it fits */
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 24px 0 calc(24px + env(safe-area-inset-bottom, 0px));
  background: rgba(8, 8, 10, 0.55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s ease, visibility 0.4s;
}
.panel-backdrop.show { opacity: 1; visibility: visible; }

.panel {
  width: min(440px, 88vw);
  margin: auto 0; /* centre when it fits; collapse and scroll when it doesn't */
  padding: 44px 40px 38px;
  text-align: center;
  background: var(--panel-bg);
  border: 1px solid var(--line);
  border-radius: 4px;
  transform: translateY(12px);
  transition: transform 0.45s var(--ease-out);
}
.panel-backdrop.show .panel { transform: translateY(0); }

.panel-title {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 420;
  font-size: 2.1rem;
  line-height: 1.15;
  margin-bottom: 16px;
}
.panel-sub {
  font-size: 10px;
  letter-spacing: 0.24em;
  line-height: 2.1;
  color: var(--ink-dim);
  margin-bottom: 30px;
  white-space: pre-line;
}
.panel-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ———————————————————— misc ———————————————————— */

#fx {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 70;
}

.noscript {
  position: fixed;
  inset: auto 0 40px;
  text-align: center;
  color: var(--ink-dim);
}

/* ———————————————————— responsive ———————————————————— */

@media (max-width: 640px) {
  .top { padding: 12px 12px; }
  .top-center { gap: 10px; font-size: 10px; letter-spacing: 0.16em; }
  .menu-wrap { padding-top: 64px; }
  .set-row { flex-wrap: wrap; min-height: 0; padding: 14px 2px; }
  .set-control { width: 100%; justify-content: space-between; }
  .stage { padding-top: 64px; }
  .actions { margin-top: 28px; }
  :root { --strip-h: clamp(110px, 20vh, 160px); }
  /* the four-option mode + intensity controls span the row and share width
     equally, so their labels stay as large as the note text without overflowing */
  #seg-game, #seg-intensity { width: 100%; }
  #seg-game .seg-btn, #seg-intensity .seg-btn {
    flex: 1 1 0; padding: 9px 4px; letter-spacing: 0.04em; font-size: 10.5px; text-align: center;
  }
  /* give leaderboard rows more width (less side padding) and tighten them, so
     the diamonds + numbers fit on one line instead of overlapping */
  .board-panel { padding-left: 18px; padding-right: 18px; }
  .board-row { gap: 8px; padding: 9px 2px; font-size: 11px; }
  .b-lives { letter-spacing: 0.06em; }
}

/* perfect intensity: the move counter */
.moves-line {
  margin-bottom: 14px;
  text-align: center;
  font-size: 10.5px;
  letter-spacing: 0.28em;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}
.moves-line.low { color: #cf8f6a; }

/* ———————————————————— celebration stamp ———————————————————— */

.stamp {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 45;
  pointer-events: none;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 460;
  font-size: clamp(2.4rem, 7vw, 4rem);
  color: var(--ink);
  text-shadow: 0 2px 26px rgba(10, 10, 12, 0.8);
  opacity: 0;
}
.stamp.gold {
  color: #f2dfae;
  text-shadow: 0 2px 26px rgba(10, 10, 12, 0.75), 0 0 36px rgba(255, 218, 138, 0.5);
}
.stamp.show { animation: stamp-in 1.9s var(--ease-out) both; }
@keyframes stamp-in {
  0%   { opacity: 0; transform: scale(0.92); letter-spacing: 0; }
  16%  { opacity: 1; }
  72%  { opacity: 1; transform: scale(1.03); letter-spacing: 0.04em; }
  100% { opacity: 0; transform: scale(1.06); letter-spacing: 0.05em; }
}

/* ———————————————————— quick motion setting ———————————————————— */

body.fast .flip { transition-duration: 0.2s; }
body.fast .seam { transition-duration: 0.16s; }
body.fast .face.front .flat { transition-duration: 0.2s; }
body.fast .strip.solid .flat { transition-duration: 0.45s; }
body.fast .sweep.run { animation-duration: 0.5s; }
body.fast .scanband.run { animation-duration: 0.4s; }
body.fast .bloom.run { animation-duration: 0.55s; }
body.fast .strip-frame.enter { animation-duration: 0.4s; }

/* ———————————————————— reduced motion ———————————————————— */

/* decorative loops only — game animation speed is the MOTION setting */
@media (prefers-reduced-motion: reduce) {
  .bg-grain { animation: none; }
  .bg-glow { animation: none; }
  .menu-wrap { animation: none; }
}
