/* Falling Blocks */

:root {
  --bg: #04050a;
  --well: #090b13;
  --grid: rgba(255, 255, 255, 0.045);
  --edge: rgba(120, 200, 255, 0.16);
  --ink: #e9edf8;
  --dim: #7d879e;
  --panel: rgba(14, 17, 26, 0.94);
  --btn: #171c29;
  --btn2: #212838;
  --shadow: 0 2px 0 rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

* { box-sizing: border-box; }

/* `hidden` means display: none, everywhere in this page. Only the two panels
   had a rule saying so, so the best scores block carried the class and was
   shown anyway: the game over panel offered "Best scores" over nothing while
   the board was still being asked, and left it there for good when there was
   no answer at all (no SDK, or nobody has played yet). One rule for the name,
   so the next element given it cannot quietly mean nothing. */
.hidden { display: none; }

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
}

#app {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: calc(6px + env(safe-area-inset-top, 0px)) calc(6px + env(safe-area-inset-right, 0px)) calc(6px + env(safe-area-inset-bottom, 0px)) calc(6px + env(safe-area-inset-left, 0px));
}

/* ---------------------------------------------------------------- hud --- */

#hud {
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  gap: 8px;
  min-width: 0;
}

#hudMain {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  padding: 3px 8px;
  border-radius: 7px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.012));
  border: 1px solid rgba(255, 255, 255, 0.05);
}

.stat-score { flex: 0 1 auto; }

.lbl {
  font-size: 8.5px;
  line-height: 1.1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
  white-space: nowrap;
}

.val {
  font-size: clamp(16px, 4.6vw, 24px);
  line-height: 1.12;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.val-sm { font-size: clamp(13px, 3.5vw, 18px); }

.sub {
  font-size: 8.5px;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

#nextBox {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  padding: 3px 7px;
  border-radius: 7px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.012));
  border: 1px solid rgba(255, 255, 255, 0.05);
}

#next {
  width: 54px;
  height: 40px;
  display: block;
}

#hudBtns {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.iconBtn {
  width: 38px;
  height: 38px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: var(--btn);
  color: var(--ink);
  cursor: pointer;
}

.iconBtn:active { background: var(--btn2); }

.iconBtn svg { width: 21px; height: 21px; fill: currentColor; }
.iconBtn svg .stroke { fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; }
.iconBtn .ic-off, .iconBtn .ic-play { display: none; }
body.muted .iconBtn .ic-on { display: none; }
body.muted .iconBtn .ic-off { display: block; }
body.paused .iconBtn .ic-pause { display: none; }
body.paused .iconBtn .ic-play { display: block; }

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

#boardWrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

#wellFrame {
  position: relative;
  flex: 0 0 auto;
  border-radius: 7px;
  padding: 2px;
  background: linear-gradient(180deg, rgba(120, 200, 255, 0.18), rgba(120, 200, 255, 0.05));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 10px 30px rgba(0, 0, 0, 0.55);
}

#board {
  display: block;
  border-radius: 5px;
  background: var(--well);
  touch-action: none;
}

/* The line clear and level banner, in the 3D build, laid over the well. It
   takes no pointer events, so a tap on the well still reaches the game. */
#flashBanner {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  padding: 8px 0;
  text-align: center;
  font-size: clamp(13px, 4.2vw, 24px);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #fff;
  background: rgba(4, 5, 10, 0.72);
  text-shadow: 0 0 16px rgba(22, 216, 230, 0.5);
  pointer-events: none;
  z-index: 2;
}

#flashBanner.hidden { display: none; }

/* ------------------------------------------------------------ overlay --- */

/* Fixed rather than absolute: in landscape the board column is narrow, and a
   panel confined to it has no room for a two word title. Over the whole window
   it is centred in both shapes and has the width it needs.

   It takes no taps itself, so the sound and pause buttons in the HUD stay
   reachable while a panel is up: the pause button is how a phone resumes. */
#overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  z-index: 5;
  pointer-events: none;
}

#overlay.hidden { display: none; }

.panel {
  width: min(100%, 330px);
  max-height: 100%;
  overflow: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  padding: 16px 16px 18px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid rgba(255, 255, 255, 0.09);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.65);
  text-align: center;
  backdrop-filter: blur(6px);
  pointer-events: auto;
}

.panel.hidden { display: none; }

/* Two words where the old name was one. One line of it cannot be read at a
   decent size in a panel this wide, so the two words are stacked on purpose,
   which also means it breaks the same way on every screen. */
.panel h1 {
  margin: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.04;
  font-size: clamp(26px, 8.6vw, 40px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 0 18px rgba(22, 216, 230, 0.45);
}

/* Tracking adds a space after the last letter too, which leaves the line
   sitting a little left of centre. Take it back. */
.panel h1 span { margin-right: -0.16em; }

.panel h2 {
  margin: 0;
  font-size: clamp(18px, 6vw, 26px);
  letter-spacing: 0.18em;
  font-weight: 800;
}

.tagline {
  margin: 0;
  font-size: 11px;
  color: var(--dim);
  line-height: 1.5;
  max-width: 24em;
}

.hint {
  margin: 0;
  font-size: 12px;
  color: var(--dim);
}

.hint.smallish { font-size: 11px; }

kbd {
  display: inline-block;
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.07);
  font: inherit;
  font-size: 0.92em;
  color: var(--ink);
}

.keys {
  list-style: none;
  margin: 2px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
  font-size: 11.5px;
  color: var(--dim);
  text-align: left;
}

.keys li { display: flex; align-items: center; gap: 6px; }

.bigBtn {
  margin-top: 2px;
  padding: 11px 26px;
  min-height: 44px;
  border-radius: 9px;
  border: 1px solid rgba(120, 220, 255, 0.35);
  background: linear-gradient(180deg, rgba(22, 216, 230, 0.22), rgba(22, 216, 230, 0.08));
  color: #eafcff;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}

.bigBtn:active { background: rgba(22, 216, 230, 0.3); }

.final {
  display: flex;
  gap: 14px;
  justify-content: center;
  width: 100%;
}

.final div { display: flex; flex-direction: column; gap: 1px; }

.final span {
  font-size: 8.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
}

.final b {
  font-size: 19px;
  font-variant-numeric: tabular-nums;
}

.boardList { width: 100%; }

.blTitle {
  font-size: 8.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 4px;
}

/* The board is on the title panel and on the game over panel, so the rules are
   on the class rather than on one of the two ids. */
.boardList ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
}

.boardList li {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 2px 6px;
  border-radius: 5px;
  color: var(--dim);
}

.boardList li.me {
  color: var(--ink);
  background: rgba(22, 216, 230, 0.12);
}

/* A board nobody has scored on. Centred rather than justified, because there is
   nothing on the right for the text to be separated from. */
.boardList li.empty { justify-content: center; opacity: 0.8; }

.boardList .who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.boardList .pts { font-variant-numeric: tabular-nums; }

/* WHAT THIS RUN DID TO THE BOARD, on the screen where you find out. It is a box
   rather than a line of grey text because it is the answer to the question the
   game over screen exists to answer. */
.nameAsk {
  width: 100%;
  padding: 7px 9px 8px;
  border-radius: 8px;
  border: 1px solid rgba(22, 216, 230, 0.35);
  background: rgba(22, 216, 230, 0.1);
}

.nameHead {
  margin: 0 0 3px;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 800;
  color: #eafcff;
}

.nameBody {
  margin: 0;
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--dim);
}

/* Narrow phones: two tidy rows rather than one that breaks wherever it likes. */
@media (orientation: portrait) and (max-width: 359px) {
  #hud { flex-wrap: wrap; }
  #hudMain { flex: 1 1 100%; }
}

/* Short as well as narrow: 320x480 and 320x568 are the smallest screens still
   in use, and there the two tidy rows above are a luxury the board pays for.
   It is the only thing that can pay. The well is ten by twenty, so a window
   that is short as well as narrow leaves the board height bound with much of
   the width unused, and every pixel the hud and the pad take comes straight off
   the block size. Measured at 320x480 before this: hud 112, pad 96, and the
   well came out 110x220, a cell of 11, with 210 of the window's 320px of width
   sitting empty either side of it. One row of smaller type and a shallower pad
   hand the board 80px back, which is a cell of 16 rather than 11. */
@media (orientation: portrait) and (max-width: 359px) and (max-height: 620px) {
  #hud { flex-wrap: nowrap; gap: 4px; }
  #hudMain { flex: 1 1 auto; flex-wrap: nowrap; gap: 4px; }

  .stat { padding: 2px 5px; }
  .lbl, .sub { font-size: 7px; letter-spacing: 0.06em; }
  .val { font-size: 15px; }
  .val-sm { font-size: 12.5px; }

  #nextBox { padding: 2px 5px; }
  #next { width: 38px; height: 28px; }

  .iconBtn { width: 30px; height: 30px; }

  #pad { height: clamp(76px, 15vh, 100px); gap: 6px; }
}

.hint-touch { display: none; }

@media (pointer: coarse) {
  .hint-key { display: none; }
  .hint-touch { display: block; }
  .keys { display: none; }
}

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

#pad {
  flex: 0 0 auto;
  display: grid;
  gap: 7px;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 1fr 1fr;
  height: clamp(96px, 17vh, 132px);
  grid-template-areas:
    "left right rotL rotR"
    "down down drop drop";
}

.padBtn {
  grid-area: auto;
  min-width: 0;
  min-height: 0;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 11px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: linear-gradient(180deg, var(--btn2), var(--btn));
  color: var(--ink);
  box-shadow: var(--shadow);
  cursor: pointer;
  touch-action: none;
}

.padBtn:active { background: #2b3548; }

.padBtn svg { width: 42%; height: 42%; max-width: 34px; max-height: 34px; fill: currentColor; display: block; }
.padBtn svg.strokeIc { fill: none; }
.padWide svg { max-width: 30px; }

.padDrop {
  border-color: rgba(120, 220, 255, 0.3);
  background: linear-gradient(180deg, rgba(22, 216, 230, 0.2), rgba(22, 216, 230, 0.06));
}

[data-act="left"]  { grid-area: left; }
[data-act="right"] { grid-area: right; }
[data-act="rotL"]  { grid-area: rotL; }
[data-act="rotR"]  { grid-area: rotR; }
[data-act="down"]  { grid-area: down; }
[data-act="drop"]  { grid-area: drop; }

/* ---------------------------------------------------------- landscape --- */

@media (orientation: landscape) {
  #app {
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: 8px;
  }

  /* The board column is sized by script so the three panels sit together
     instead of drifting to the edges of a wide window. */
  #boardWrap { flex: 0 0 auto; }

  #hud {
    flex: 0 0 auto;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 6px;
    width: clamp(104px, 15vw, 168px);
    min-width: 0;
  }

  #hudMain {
    flex: 0 0 auto;
    flex-direction: column;
    align-items: stretch;
    flex-wrap: nowrap;
    gap: 5px;
  }

  .stat { padding: 4px 8px; }

  .val { font-size: clamp(15px, 2.1vw, 22px); }
  .val-sm { font-size: clamp(13px, 1.8vw, 18px); }

  #nextBox {
    flex: 0 0 auto;
    flex-direction: row;
    gap: 6px;
    align-items: center;
    justify-content: space-between;
    padding: 5px 8px;
  }

  #next { width: 52px; height: 40px; }

  #hudBtns { justify-content: flex-start; }

  #pad {
    flex: 0 0 auto;
    align-self: center;
    width: clamp(126px, 18vw, 200px);
    height: min(430px, calc(100% - 14px));
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat(4, 1fr);
    grid-template-areas:
      "left right"
      "rotL rotR"
      "down down"
      "drop drop";
  }
}

/* Very short windows: give the board what there is. */
@media (orientation: landscape) and (max-height: 360px) {
  #pad { width: clamp(112px, 16vw, 150px); }
  .iconBtn { width: 34px; height: 34px; }
}

/* Short windows, whichever way round. The title panel's content is a fixed
   height, and below about 386px of window it ran past the bottom of the panel:
   Play sat below the fold and had to be scrolled to on the one screen whose
   only job is to start the game. The overflow cap keeps that from ever being
   unreachable, and this makes it not happen in the first place.

   The key list is the bulk of it, so it goes two columns rather than away:
   on a short window it is still a computer that is being played, and those
   six lines are the whole control scheme. */
@media (max-height: 400px) {
  .panel {
    gap: 6px;
    padding: 10px 14px 12px;
  }

  .panel h1 { font-size: clamp(20px, 5vw, 26px); }

  .tagline { font-size: 10px; }

  .hint { font-size: 11px; }

  .keys {
    grid-template-columns: 1fr 1fr;
    gap: 2px 10px;
    margin-top: 0;
    font-size: 10px;
  }

  .keys li { gap: 4px; }

  .bigBtn {
    margin-top: 0;
    padding: 7px 20px;
    min-height: 36px;
  }

  /* The board is real content on a short screen too, so it tightens rather
     than going away. The window height already decides how many rows are
     drawn; this makes each of them cost less. */
  .boardList ol { font-size: 10.5px; gap: 1px; }
  .boardList li { padding: 1px 5px; }
  .nameAsk { padding: 5px 8px 6px; }
  .nameHead, .nameBody { font-size: 9.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .panel { backdrop-filter: none; }
}
