/* style.css — retro arcade presentation: beveled panels, phosphor glow, CRT. */

/* --------------------------------------------------------------- tokens */

:root {
  --bg:          #06060c;
  --bg-deep:     #03030a;
  --panel:       #10101d;
  --panel-lit:   #181830;
  --edge:        #3a4a7a;
  --edge-bright: #5f76b8;
  --ink:         #d6def5;
  --ink-dim:     #7f8bb5;
  --accent:      #00e5e5;
  --accent-warm: #e8d500;
  --danger:      #e03a3a;
  --good:        #35d94f;

  --font: "Consolas", "SF Mono", "DejaVu Sans Mono", "Courier New", ui-monospace, monospace;
  --glow: 0 0 6px currentColor;

  /* Usable viewport height, used for every vertical size in this file.
     On phones `100vh` is the height with the browser UI *retracted*, so
     sizing against it guarantees the layout overflows while the address bar
     is still on screen. `svh` is the smallest (UI-expanded) height, which is
     the only one that reliably fits. */
  --app-h: 100vh;
}

@supports (height: 100svh) {
  :root { --app-h: 100svh; }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: var(--bg-deep);
}

body {
  font-family: var(--font);
  color: var(--ink);
  /* The faint radial lift keeps the cabinet from reading as a flat black
     rectangle on large displays. */
  background:
    radial-gradient(ellipse at 50% 0%, #16162c 0%, var(--bg) 55%, var(--bg-deep) 100%);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  overflow-x: hidden;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

/* -------------------------------------------------------------- CRT skin */

.crt { width: 100%; min-height: 100vh; position: relative; }

/* Scanlines and vignette are drawn over everything and never take pointer
   events, so they decorate without interfering. */
.crt::after,
.crt::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 60;
}

.crt::after {
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.26) 0px,
    rgba(0, 0, 0, 0.26) 1px,
    rgba(255, 255, 255, 0.012) 1px,
    rgba(255, 255, 255, 0.012) 3px
  );
  opacity: 0.75;
}

.crt::before {
  background: radial-gradient(ellipse at center, transparent 52%, rgba(0, 0, 0, 0.62) 100%);
}

body.no-scanlines .crt::after { display: none; }

/* -------------------------------------------------------------- cabinet */

.cabinet {
  width: min(1180px, 100%);
  margin: 0 auto;
  padding: 14px 16px 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.masthead { text-align: center; }

.logo {
  margin: 0;
  font-size: clamp(28px, 6vw, 52px);
  letter-spacing: 0.18em;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
}

/* Each letter takes a tetromino colour and its own phosphor bloom. */
.logo .l { text-shadow: 0 0 10px currentColor, 0 0 26px currentColor; }
.l-t  { color: #00e5e5; }
.l-e  { color: #e8d500; }
.l-r  { color: #a020f0; }
.l-i  { color: #22c822; }
.l-s  { color: #e02020; }
.l-s2 { color: #e88a00; }

.tagline {
  margin: 6px 0 0;
  color: var(--accent);
  font-size: 12px;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  text-shadow: var(--glow);
}

/* ---------------------------------------------------------------- stage */

.stage {
  display: flex;
  gap: 14px;
  justify-content: center;
  align-items: flex-start;
}

.rail {
  width: 156px;
  flex: 0 0 156px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Beveled panel: bright top-left rim, dark bottom-right rim. The same trick
   the block renderer uses, so the chrome and the pieces agree. */
.box {
  background: linear-gradient(180deg, var(--panel-lit), var(--panel));
  border: 2px solid var(--edge);
  border-top-color: var(--edge-bright);
  border-left-color: var(--edge-bright);
  padding: 9px 10px 11px;
  box-shadow: inset 0 0 22px rgba(0, 0, 0, 0.75);
}

.box-title {
  margin: 0 0 8px;
  font-size: 11px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: var(--glow);
  font-weight: 700;
}

.mini-canvas { display: block; width: 100%; }
.hold-canvas { height: 74px; }
.next-canvas { height: 268px; }

.stat-list { margin: 0; display: flex; flex-direction: column; gap: 6px; }

.stat {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.stat dt {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.stat dd {
  margin: 0;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.stat-list-major .stat dd {
  font-size: 20px;
  color: var(--accent-warm);
  text-shadow: 0 0 8px rgba(232, 213, 0, 0.5);
}

/* Modes hide the readouts they do not use. */
.stat[hidden] { display: none; }

/* ------------------------------------------------------------- the well */

.board-wrap { position: relative; flex: 0 0 auto; }

.board-canvas {
  display: block;
  /* Height drives the size and the aspect ratio derives the width; max-width
     is the guard that stops a short-and-narrow viewport from pushing the well
     wider than the screen. */
  height: min(calc(var(--app-h) - 190px), 640px);
  aspect-ratio: 1 / 2;
  width: auto;
  max-width: 100%;
  background: #0a0a12;
  border: 3px solid var(--edge);
  border-top-color: var(--edge-bright);
  border-left-color: var(--edge-bright);
  box-shadow:
    0 0 0 1px #000,
    0 0 30px rgba(0, 120, 200, 0.22),
    inset 0 0 40px rgba(0, 0, 0, 0.8);
  touch-action: none; /* gestures belong to the game, not to page scrolling */
}

/* --------------------------------------------------------- badges/toasts */

.badges {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  pointer-events: none;
  z-index: 5;
}

.badge {
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 3px 9px;
  border: 1px solid currentColor;
  background: rgba(6, 6, 14, 0.85);
  white-space: nowrap;
}

.badge-b2b { color: var(--accent-warm); text-shadow: var(--glow); }
.badge-combo { color: var(--good); text-shadow: var(--glow); }
.badge[hidden] { display: none; }

.toast-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  z-index: 6;
}

.toast {
  font-size: clamp(13px, 2.4vw, 19px);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: 0 0 10px currentColor, 0 2px 0 #000;
  animation: toast-rise 1.05s ease-out forwards;
  white-space: nowrap;
}

.toast-big { color: var(--accent-warm); font-size: clamp(16px, 3.2vw, 26px); }
.toast-points { color: var(--ink); font-size: 13px; letter-spacing: 0.1em; }

@keyframes toast-rise {
  0%   { opacity: 0; transform: translateY(14px) scale(0.9); }
  18%  { opacity: 1; transform: translateY(0) scale(1); }
  70%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-34px); }
}

.countdown {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(48px, 12vw, 110px);
  font-weight: 700;
  color: var(--accent);
  text-shadow: 0 0 22px currentColor;
  pointer-events: none;
  z-index: 8;
}

.countdown[hidden] { display: none; }

/* -------------------------------------------------------------- screens */

.screen {
  position: absolute;
  inset: 0;
  background: rgba(4, 4, 12, 0.93);
  border: 3px solid var(--edge);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  z-index: 10;
  overflow-y: auto;
}

.screen[hidden] { display: none; }

.screen-inner { width: 100%; text-align: center; }

.screen-title {
  margin: 0 0 14px;
  font-size: clamp(17px, 3.4vw, 25px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: 0 0 14px currentColor;
}

.mode-grid { display: flex; flex-direction: column; gap: 7px; margin-bottom: 14px; }

.mode-option {
  font: inherit;
  color: var(--ink);
  text-align: left;
  background: var(--panel);
  border: 2px solid var(--edge);
  padding: 7px 10px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.mode-option:hover { background: var(--panel-lit); border-color: var(--edge-bright); }

.mode-option.is-selected {
  border-color: var(--accent);
  background: var(--panel-lit);
  box-shadow: 0 0 14px rgba(0, 229, 229, 0.28);
}

.mode-name {
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.mode-blurb { font-size: 10.5px; color: var(--ink-dim); line-height: 1.4; }
.mode-best { font-size: 10px; color: var(--accent-warm); letter-spacing: 0.08em; }
.mode-best:empty { display: none; }

.screen-actions { display: flex; flex-direction: column; gap: 7px; align-items: stretch; }

.results-list {
  margin: 0 0 14px;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 12px;
  text-align: left;
  font-size: 12px;
}

.results-list dt { color: var(--ink-dim); letter-spacing: 0.1em; text-transform: uppercase; font-size: 10px; }
.results-list dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; color: var(--ink); }

.results-rank {
  margin: -6px 0 12px;
  color: var(--accent-warm);
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-shadow: var(--glow);
}

.results-rank[hidden] { display: none; }

.hint { font-size: 10px; color: var(--ink-dim); line-height: 1.5; margin: 12px 0 0; }
.hint[hidden] { display: none; }

/* -------------------------------------------------------------- buttons */

.btn {
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  background: linear-gradient(180deg, var(--panel-lit), var(--panel));
  border: 2px solid var(--edge);
  border-top-color: var(--edge-bright);
  border-left-color: var(--edge-bright);
  padding: 9px 14px;
  cursor: pointer;
  transition: background 90ms linear, color 90ms linear;
}

.btn:hover { background: var(--panel-lit); color: #fff; border-color: var(--edge-bright); }
.btn:active { transform: translate(1px, 1px); }

.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.btn-primary {
  color: var(--accent);
  border-color: var(--accent);
  text-shadow: var(--glow);
  box-shadow: 0 0 14px rgba(0, 229, 229, 0.22);
}

.btn-primary:hover { color: #fff; background: rgba(0, 229, 229, 0.16); }

.btn-small { padding: 7px 10px; font-size: 11px; }

.btn-icon {
  padding: 2px 9px;
  font-size: 19px;
  line-height: 1;
  letter-spacing: 0;
}

.blink { animation: blink 1.15s steps(2, start) infinite; }

@keyframes blink { 50% { opacity: 0.35; } }

/* --------------------------------------------------------------- footer */

.footer { text-align: center; color: var(--ink-dim); font-size: 10px; line-height: 1.8; }
.footer b { color: var(--accent); font-weight: 700; }

/* ---------------------------------------------------------- touch pad */

.touchpad {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 7px;
  max-width: 460px;
  margin: 4px auto 0;
  width: 100%;
}

.touchpad[hidden] { display: none; }

.tbtn {
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  background: linear-gradient(180deg, var(--panel-lit), var(--panel));
  border: 2px solid var(--edge);
  border-top-color: var(--edge-bright);
  border-left-color: var(--edge-bright);
  padding: 15px 0;
  cursor: pointer;
  touch-action: none;
  user-select: none;
}

.tbtn.is-active { background: var(--accent); color: #04040c; }
.tbtn-wide { grid-column: span 2; }

/* --------------------------------------------------------------- modals */

.modal {
  position: fixed;
  inset: 0;
  background: rgba(2, 2, 8, 0.9);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.modal[hidden] { display: none; }

.modal-panel {
  width: min(760px, 100%);
  max-height: calc(var(--app-h) - 32px);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 3px solid var(--edge);
  border-top-color: var(--edge-bright);
  border-left-color: var(--edge-bright);
  box-shadow: 0 0 40px rgba(0, 0, 0, 0.9);
}

.modal-panel-narrow { width: min(460px, 100%); }

.modal-head,
.modal-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 14px;
  border-bottom: 2px solid var(--edge);
  background: var(--panel-lit);
}

.modal-foot { border-bottom: none; border-top: 2px solid var(--edge); }

.modal-head h2 {
  margin: 0;
  font-size: 14px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: var(--glow);
}

.modal-body {
  padding: 14px;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
  align-content: start;
}

.settings-group-wide { grid-column: 1 / -1; }

.settings-group h3 {
  margin: 0 0 9px;
  font-size: 10px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: 1px solid var(--edge);
  padding-bottom: 5px;
}

.field { display: block; margin-bottom: 11px; }

.field-label {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  margin-bottom: 4px;
}

.field-label em { font-style: normal; color: var(--accent-warm); font-variant-numeric: tabular-nums; }
.field-help { display: block; font-size: 9.5px; color: var(--ink-dim); line-height: 1.5; margin-top: 3px; }

input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
  background: transparent;
}

select {
  font: inherit;
  font-size: 12px;
  width: 100%;
  color: var(--ink);
  background: var(--panel-lit);
  border: 2px solid var(--edge);
  padding: 5px 7px;
}

.check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  padding: 5px 0;
  cursor: pointer;
  color: var(--ink);
}

.check input { accent-color: var(--accent); width: 15px; height: 15px; }

.keybinds {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(245px, 1fr));
  gap: 5px;
}

.keybind {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: var(--panel-lit);
  border: 1px solid var(--edge);
  padding: 5px 8px;
}

.keybind-label { font-size: 11px; color: var(--ink-dim); letter-spacing: 0.08em; }

/* An action can hold two bindings; they sit side by side and wrap only if the
   row genuinely runs out of room. */
.keybind-keys {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.keybind-key {
  font: inherit;
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--accent);
  background: var(--bg);
  border: 1px solid var(--edge-bright);
  padding: 3px 7px;
  cursor: pointer;
  min-width: 60px;
  text-align: center;
  white-space: nowrap;
}

.keybind-key:hover { background: var(--panel); color: #fff; }
.keybind-key.is-capturing { color: var(--accent-warm); border-color: var(--accent-warm); animation: blink 0.7s steps(2, start) infinite; }

/* ---------------------------------------------------------- score table */

.score-mode { margin-bottom: 16px; }

.score-mode h3 {
  margin: 0 0 7px;
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent);
}

.score-table { width: 100%; border-collapse: collapse; font-size: 11px; }

.score-table th {
  text-align: left;
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
  border-bottom: 1px solid var(--edge);
  padding: 3px 5px;
  font-weight: 400;
}

.score-table td {
  padding: 3px 5px;
  border-bottom: 1px solid rgba(58, 74, 122, 0.28);
  font-variant-numeric: tabular-nums;
}

.score-table tr:first-child td { color: var(--accent-warm); }
.score-empty { color: var(--ink-dim); font-size: 10.5px; font-style: italic; }

/* ---------------------------------------------------------- responsive */

/* Three layouts, chosen by the shape of the viewport rather than its width
   alone. A landscape phone is *wide* and short, so a width-only breakpoint
   hands it the tall stacked layout and the well runs off the bottom.
 *
 *   wide + tall   -> rails flanking the well            (the base rules above)
 *   narrow        -> rails fold into strips above/below (portrait phones)
 *   short         -> everything compresses into one row (landscape phones)
 */

/* --- Menus escape the well ------------------------------------------------
   The screens are absolutely positioned inside .board-wrap, which is fine when
   the well is 640px tall and terrible when it is 300px: the mode list ends up
   scrolling inside a letterbox with its title and buttons clipped. Below these
   thresholds a screen takes over the whole viewport instead. Because the
   overlay is opaque and fixed, it also hides the game chrome behind it, so the
   empty HOLD and NEXT boxes stop competing with the menu for space. */
@media (max-width: 900px), (max-height: 620px) {
  .screen {
    position: fixed;
    inset: 0;
    border: none;
    padding: 16px 14px;
    /* Opaque, not translucent: at this size the panels behind would otherwise
       ghost through the menu text and make it harder to read. */
    background: #05050c;
    align-items: flex-start;
    /* Under the scanline layer (60) so menus keep the CRT treatment they have
       on desktop, but above all game chrome. */
    z-index: 55;
    overscroll-behavior: contain;
  }

  /* auto margins centre the panel when it fits and let it scroll from the top
     when it does not. */
  .screen-inner { max-width: 430px; margin: auto; padding: 6px 0; }

  .screen-title { font-size: clamp(19px, 5vw, 24px); margin-bottom: 16px; }

  /* Thumb-sized targets. 12px of padding on a 13px font clears the ~44px
     minimum comfortable tap height. */
  .mode-option { padding: 11px 13px; gap: 3px; }
  .mode-name { font-size: 14px; }
  .mode-blurb { font-size: 12px; }
  .mode-best { font-size: 11.5px; }
  .btn { padding: 13px 16px; font-size: 13px; }
  .screen-actions { gap: 9px; }

  .results-list { font-size: 13px; gap: 5px 14px; }
  .results-list dt { font-size: 11px; }
}

/* Sixteen result rows do not fit a landscape phone, so they pair up into two
   label/value columns and halve the height. */
@media (max-height: 620px) {
  .screen-inner { max-width: 620px; }
  .results-list { grid-template-columns: 1fr auto 1fr auto; font-size: 12px; }
  .screen-title { margin-bottom: 10px; }
  .screen-actions { flex-direction: row; justify-content: center; }
  .screen-actions .btn { flex: 0 1 200px; }
  .mode-grid { gap: 6px; }
  .mode-blurb { display: none; }
}

/* --- Wide layout, but with the thumb pad on (a tablet, or forced on) ----- */
/* The pad sits under the stage and costs about 130px, so the well has to give
   that back or the page starts scrolling. */
@media (min-width: 901px) and (min-height: 621px) {
  body.has-touchpad .board-canvas {
    height: min(calc(var(--app-h) - 330px), 640px);
  }
}

/* --- Narrow: rails fold above and below the well ------------------------ */
@media (max-width: 900px) and (orientation: portrait) {
  .stage { flex-direction: column; align-items: center; }

  .rail {
    width: min(100%, 460px);
    flex: 0 0 auto;
    flex-direction: row;
    gap: 9px;
  }

  .rail .box { flex: 1; }
  .rail-left { order: 1; }
  .board-wrap { order: 2; }
  .rail-right { order: 3; flex-wrap: wrap; }

  /* The panels are now short strips. The renderer sees that the next-queue
     canvas has become wider than tall and lays the previews out in a row. */
  .hold-canvas,
  .next-canvas { height: 56px; }

  /* Reserve room for the header, both panel strips and the thumb pad. The
     subtracted figures throughout this file were measured, not guessed. */
  .board-canvas { height: min(calc(var(--app-h) - 352px), 520px); }

  .rail-right .box:first-child { flex: 2; }
  .stat-list { flex: 1; }
  .rail-right .btn-small { flex: 0 0 100%; }
}

/* --- Phone portrait ------------------------------------------------------ */
@media (max-width: 560px) and (orientation: portrait) {
  .cabinet { padding: 6px 8px 10px; gap: 8px; }
  .masthead .logo { font-size: 24px; }
  .tagline { font-size: 10px; margin-top: 3px; letter-spacing: 0.3em; }

  .hold-canvas,
  .next-canvas { height: 46px; }

  .box { padding: 6px 8px 8px; }
  .box-title { margin-bottom: 5px; font-size: 10px; }
  .stat dd { font-size: 13px; }
  .stat-list-major .stat dd { font-size: 16px; }

  /* The live stats panel is the first thing to go: every number in it is
     reported again on the results screen, and the thumb pad has to be
     reachable without scrolling. */
  .stats-box { display: none; }

  /* Repack the panels so the well gets the room.
   *
   * Stacking the rails as full-width strips costs two rows of mostly empty
   * box, and on a 360px phone that left the well only 148px wide. Dissolving
   * the rails with `display: contents` promotes the individual panels to grid
   * items, so hold, next and pause share one row and the well grows by the
   * height of everything that row replaced.
   *
   *   [ hold ][ next ][pause]
   *   [       well        ]
   *   [       score       ]
   */
  .stage {
    display: grid;
    grid-template-columns: 1fr 1fr auto;
    gap: 8px;
    width: 100%;
    align-items: stretch;
  }

  .rail { display: contents; }

  .box-hold { grid-area: 1 / 1 / 2 / 2; }
  .box-next { grid-area: 1 / 2 / 2 / 3; }
  .rail-right .btn-small { grid-area: 1 / 3 / 2 / 4; }
  .board-wrap { grid-area: 2 / 1 / 3 / 4; justify-self: center; }
  .box-score { grid-area: 3 / 1 / 4 / 4; }

  /* Two stats per row instead of four stacked ones. This is the single
     cheapest ~45px of height on the page, and it goes straight into the well. */
  .stat-list-major {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 3px 12px;
  }

  .rail-right .btn-small { padding: 6px 11px; font-size: 10px; writing-mode: horizontal-tb; }
  .touchpad { gap: 5px; margin-top: 0; }
  .tbtn { padding: 12px 0; font-size: 14px; }

  .board-canvas { height: min(calc(var(--app-h) - 326px), 470px); }

  .footer { display: none; }

  .modal { padding: 8px; }
  .modal-panel { max-height: calc(var(--app-h) - 16px); }
  .modal-body { grid-template-columns: 1fr; padding: 12px; }
  .keybinds { grid-template-columns: 1fr; }
  .check { padding: 8px 0; font-size: 13px; }
  .check input { width: 18px; height: 18px; }
  .keybind { padding: 7px 8px; }
  .keybind-key { padding: 6px 9px; min-width: 66px; }
  input[type="range"] { height: 26px; }
}

/* Very short portrait (older small phones): drop the wordmark and tighten. */
@media (max-width: 560px) and (max-height: 700px) and (orientation: portrait) {
  .masthead .logo { font-size: 19px; letter-spacing: 0.12em; }
  .tagline { display: none; }
  .cabinet { gap: 6px; }
  .hold-canvas,
  .next-canvas { height: 40px; }
  .tbtn { padding: 10px 0; }
  .board-canvas { height: min(calc(var(--app-h) - 290px), 420px); }
}

/* --- Short / landscape --------------------------------------------------- */
/* Vertical space is the scarce resource and horizontal space is plentiful, so
   the whole cabinet becomes one row: panels, well, and thumb pad side by side
   with the header and footer dropped entirely. */
@media (max-height: 620px) and (orientation: landscape) {
  /* Held sideways the phone is gripped in two hands, so the controls split
     into a left thumb cluster and a right one with the well between them.
     `display: contents` on the pad promotes the individual buttons to items of
     this grid, which is what lets one container sit on both sides at once.
     The outer columns are `auto`, so when the pad is hidden they collapse to
     nothing and the well simply takes the whole width. */
  .cabinet {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto auto;
    /* The leading flexible row absorbs the slack so both button clusters sit
       low, where a thumb rests when the phone is gripped sideways, instead of
       being spread evenly down the edge. */
    grid-template-rows: 1fr auto auto auto;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 5px 8px;
    width: 100%;
    height: var(--app-h);
  }

  .masthead,
  .footer { display: none; }

  .stage {
    grid-column: 3;
    grid-row: 1 / -1;
    flex: 0 1 auto;
    gap: 9px;
    align-items: stretch;
    justify-content: center;
  }

  .touchpad { display: contents; }

  /* Left thumb: movement. */
  .tbtn[data-action="moveLeft"]  { grid-area: 2 / 1 / 3 / 2; }
  .tbtn[data-action="softDrop"]  { grid-area: 2 / 2 / 3 / 3; }
  .tbtn[data-action="moveRight"] { grid-area: 3 / 1 / 4 / 3; }

  /* Right thumb: rotation, drop, hold. */
  .tbtn[data-action="rotateCCW"] { grid-area: 2 / 4 / 3 / 5; }
  .tbtn[data-action="rotateCW"]  { grid-area: 2 / 5 / 3 / 6; }
  .tbtn[data-action="hardDrop"]  { grid-area: 3 / 4 / 4 / 6; }
  .tbtn[data-action="hold"]      { grid-area: 4 / 4 / 5 / 6; }

  .tbtn { min-width: 74px; }

  /* Panels align to the top of the well rather than floating at its middle. */
  .rail { width: 116px; flex: 0 0 116px; gap: 8px; justify-content: flex-start; }
  .box { padding: 6px 8px 8px; }
  .box-title { margin-bottom: 4px; font-size: 9px; letter-spacing: 0.2em; }

  .hold-canvas { height: 46px; }
  .next-canvas { height: 150px; }

  .stat dt { font-size: 9px; }
  .stat dd { font-size: 12px; }
  .stat-list-major .stat dd { font-size: 15px; }
  .stats-box { display: none; }

  .board-canvas { height: calc(var(--app-h) - 18px); }

  .tbtn { padding: 10px 0; font-size: 13px; }

  .modal-panel { max-height: 94vh; }
  .modal-body { padding: 10px 12px; gap: 10px; }
  .settings-group h3 { margin-bottom: 6px; }
  .field { margin-bottom: 8px; }
}

/* Anyone who has asked the system to reduce motion gets the game without the
   shake, blink and rise animations. */
@media (prefers-reduced-motion: reduce) {
  .blink,
  .toast { animation: none; }
  .toast { opacity: 1; }
}
