/*
 * The title screen (assets/scripts/menu/titleScreen.mjs). Two modes on one overlay:
 *  - intro (data-mode="intro"): the first visit on this device. One column: the brand logo and
 *    tape, the pitch, the clock line, the DEMO / DUOS / RANKED ledger, the board and controls
 *    lines, PLAY NOW, the sound hint and the returning line.
 *  - gate (data-mode="gate"): a returning player whose browser holds the menu music until a
 *    gesture: the logo, PLAY NOW, "or press any key", the sound hint.
 * The live attract scene stays visible behind a dark veil (menuEffects.mjs frames the hero under
 * or beside the column); the menu chrome waits underneath and fades in as the screen dissolves.
 * Same kit as the menu: 'Retro Gaming' on the 11 px grid (11 / 22 / 33 px), the brand logo
 * (assets/images/brand/, --title-logo-h tall per tier, width = height x 3.137), the amber
 * quarantine-tape tagline, the kit's primary button, hard shadows in whole --ui-px. Nothing
 * blinks, nothing glows, zero radius.
 */

:root {
  --title-screen-fade-ms: 300ms;
  --title-logo-h: 150px;
  /* The corporate emblem above the logo (assets/images/brand/emblem.svg), about 0.8 x the logo. */
  --title-emblem-h: 120px;
  /* The name under it in plain type, on the 11 px grid. */
  --title-word-size: 66px;
  /* The lockup's shadow step (the wordmark's extrusion step). */
  --title-word-px: calc(2 * var(--ui-px));
  --title-pitch-size: 22px;
  --title-label-size: 22px;
  --title-line-size: 11px;
  --title-play-size: 22px;
  --title-play-width: 352px;
  --title-icon: 16px;
}

/* Menu chrome (shell, footer, dock, drawers) waits under the screen and comes up as it
   dissolves. The live scene (.menu-backdrop) is never hidden. */
html[data-title-screen] body > :not(.menu-backdrop):not(.title-screen) {
  opacity: 0;
  transition: opacity var(--title-screen-fade-ms) ease-out;
}

html[data-title-screen='leaving'] body > :not(.menu-backdrop):not(.title-screen) {
  opacity: 1;
}

/* "pending" (menu/menuMusicBoot.mjs): the short autoplay check before the screen may go up. The
   chrome is hidden at once (no fade-out flash) and out of reach (no tap on a button nobody can
   see); if the music may play on its own, it passes through 'leaving' and the menu fades in. */
html[data-title-screen='pending'] body > :not(.menu-backdrop):not(.title-screen) {
  pointer-events: none;
  transition: none;
}

.title-screen {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  place-items: center;
  padding:
    max(16px, env(safe-area-inset-top))
    max(16px, env(safe-area-inset-right))
    max(16px, env(safe-area-inset-bottom))
    max(16px, env(safe-area-inset-left));
  overflow: hidden;
  color: var(--ui-text);
  font-family: var(--ui-font);
  text-align: center;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
  opacity: 1;
  transition: opacity var(--title-screen-fade-ms) ease-out;
}

/* The dialog root holds the focus for pointer sessions: no ring on it (PLAY NOW earns the kit's
   ring on the first Tab). */
.title-screen:focus,
.title-screen:focus-visible {
  outline: none;
}

.title-screen[data-state='leaving'] {
  opacity: 0;
  pointer-events: auto;
}

/* Tall screens: the column sits above centre, so the attract hero on its turntable stays visible
   under its last line. Never on a short phone (a 360 x 740 Android): the column needs the room,
   and a touch cannot scroll it (the gesture is the screen's). */
@media (min-width: 761px) and (min-height: 700px) {
  .title-screen {
    padding-bottom: calc(max(16px, env(safe-area-inset-bottom)) + 18vh);
  }
}

@media (max-width: 760px) and (min-height: 800px) {
  .title-screen {
    padding-bottom: calc(max(16px, env(safe-area-inset-bottom)) + 10vh);
  }
}

/* Dark veil: deepest at the edges, lighter around the title so the scene reads behind it. */
.title-screen__veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 75% 65% at 50% 48%, rgba(6, 6, 7, 0.6) 0%, rgba(6, 6, 7, 0.74) 55%, rgba(6, 6, 7, 0.9) 100%),
    linear-gradient(180deg, rgba(6, 6, 7, 0.35) 0%, rgba(6, 6, 7, 0) 30%, rgba(6, 6, 7, 0) 70%, rgba(6, 6, 7, 0.55) 100%);
}

/* Scanlines in whole UI pixels: a CRT hint over the scene, never over the type. */
.title-screen__veil::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(180deg, rgba(0, 0, 0, 0.22) 0, rgba(0, 0, 0, 0.22) var(--ui-px), transparent var(--ui-px), transparent calc(2 * var(--ui-px)));
  opacity: 0.5;
}

/* The column. Every direct child shrink-wraps (justify-items: center), so their union is the
   visible column menuEffects.mjs measures to place the hero; the box itself spans the overlay.
   Taller than the screen (a tiny window): it scrolls by wheel and keys. */
.title-screen__content {
  position: relative;
  display: grid;
  justify-items: center;
  gap: calc(5 * var(--ui-px));
  width: 100%;
  max-width: 100%;
  max-height: 100%;
  overflow: hidden auto;
}

.title-screen__logo {
  display: grid;
  justify-items: center;
  gap: calc(5 * var(--ui-px));
  margin: 0;
  line-height: 0;
}

/* The corporate emblem (the menu's .menu-logo__emblem at the title's size): a square vector, the
   kit's two-step hard drop. The <img> has width/height attributes, so menuEffects.mjs measures the
   right box before the file lands. */
.title-screen__emblem {
  display: block;
  height: var(--title-emblem-h);
  width: var(--title-emblem-h);
  image-rendering: auto;
  filter:
    drop-shadow(0 var(--title-word-px) 0 var(--ui-frame))
    drop-shadow(0 calc(2.5 * var(--title-word-px)) 0 rgba(0, 0, 0, 0.5));
}

/* The name under the emblem in plain kit type (--title-word-size per tier, on the 11 px grid), one
   solid colour (--brand-word, game-ui.css), the same two-step hard drop as a text shadow.
   text-indent balances the letter-spacing's trailing space so the word sits centred. */
.title-screen__word {
  display: block;
  color: var(--brand-word);
  font-size: var(--title-word-size);
  font-weight: normal;
  letter-spacing: 6px;
  line-height: 1;
  text-indent: 6px;
  text-transform: uppercase;
  text-shadow:
    0 var(--title-word-px) 0 var(--ui-frame),
    0 calc(2.5 * var(--title-word-px)) 0 rgba(0, 0, 0, 0.5);
}

/* Quarantine tape, like .menu-logo__tag: brand red, light text. */
.title-screen__tag {
  padding: 3px calc(3 * var(--ui-px)) 2px;
  background: var(--ui-amber);
  box-shadow:
    0 0 0 var(--ui-px) var(--ui-frame),
    0 calc(2 * var(--ui-px)) 0 var(--ui-px) rgba(0, 0, 0, 0.45);
  color: var(--ui-amber-ink);
  font-size: 22px;
  line-height: 1;
  letter-spacing: 4px;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Pixel glyphs (the menu's own 16 x 16 crispEdges paths) in a fixed box, brand red unless the
   parent says otherwise (the button's icon takes its ink). */
.title-screen__icon {
  display: inline-flex;
  flex: none;
  width: var(--title-icon);
  height: var(--title-icon);
  color: var(--ui-amber);
}

.title-screen__icon > svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---------------------------------------------------------------- the intro column */

/* Read to screen readers through the dialog's aria-describedby (never aria-hidden). Shrink-wrapped
   (not width: 100%) so its box, like every other child of __content, is the visible column. */
.title-screen__intro {
  display: grid;
  justify-items: center;
  gap: calc(5 * var(--ui-px));
  width: auto;
  max-width: 100%;
}

/* 39ch is the width of the widest balanced line ("Pick a hero and hold out as long as you can."),
   so the box is the text, and the column's measured rect is honest. */
.title-screen__pitch {
  margin: 0;
  max-width: 39ch;
  color: var(--ui-text);
  font-size: var(--title-pitch-size);
  line-height: 1.3;
  text-wrap: balance;
  text-shadow:
    var(--ui-px) var(--ui-px) 0 var(--ui-frame),
    0 calc(2 * var(--ui-px)) 0 rgba(0, 0, 0, 0.5);
}

/* The clock line, right under the pitch: when the game steps up (the tier table's own times). */
.title-screen__clock {
  margin: calc(-3 * var(--ui-px)) 0 0;
  max-width: 100%;
  color: var(--ui-text-muted);
  font-size: var(--title-line-size);
  line-height: 1.4;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-wrap: balance;
}

/* One ledger plate: three rows of icon | label | hint, in the menu's own hint voice ("Solo run ·
   no login"). Flat: a 1-px steel ring in a 2-px black ring and an inset top highlight, no raised
   drop, no per-row frame, so it reads as a table, never as three buttons. */
.title-screen__ledger {
  display: grid;
  grid-template-columns: var(--title-icon) minmax(7.5ch, auto) 1fr;
  justify-items: start;
  gap: calc(3 * var(--ui-px));
  margin: calc(2 * var(--ui-px)) calc(2 * var(--ui-px)) calc(3 * var(--ui-px));
  padding: calc(4 * var(--ui-px)) calc(5 * var(--ui-px));
  min-width: min(100%, 462px);
  max-width: 100%;
  background: var(--ui-grime) 0 0 / var(--ui-grime-size) repeat, rgba(20, 22, 24, 0.93);
  box-shadow:
    inset 0 var(--ui-px) 0 0 rgba(255, 244, 222, 0.05),
    0 0 0 var(--ui-px) var(--ui-steel),
    0 0 0 calc(2 * var(--ui-px)) var(--ui-frame);
  list-style: none;
  color: var(--ui-text);
  text-align: left;
}

/* Each row spans the plate's three columns (subgrid, so the label column is shared and the hints
   line up; browsers without subgrid get a per-row grid of the same columns). */
.title-screen__row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: var(--title-icon) minmax(7.5ch, auto) 1fr;
  grid-template-rows: auto;
  column-gap: calc(3 * var(--ui-px));
  align-items: center;
  width: 100%;
}

@supports (grid-template-columns: subgrid) {
  .title-screen__row {
    grid-template-columns: subgrid;
  }
}

.title-screen__row-label {
  color: var(--ui-text-bright);
  font-size: var(--title-label-size);
  line-height: 1;
  letter-spacing: 2px;
  text-transform: uppercase;
  text-shadow: 0 var(--ui-px) 0 rgba(0, 0, 0, 0.6);
}

.title-screen__row-hint {
  color: var(--ui-text-muted);
  font-size: var(--title-line-size);
  line-height: 1.25;
  white-space: nowrap;
}

/* Facts under the plate, one per row, in reading order: the board line (true on every server;
   upgraded to the prize line only after /api/prizes/current says enabled), the portrait-touch
   "turn it sideways" line, and last, directly above PLAY NOW, the controls line in the reader's
   own input, in --ui-text. One colour per row. */
.title-screen__facts {
  display: grid;
  justify-items: center;
  gap: calc(2 * var(--ui-px));
  margin: 0;
  padding: 0;
  list-style: none;
}

.title-screen__fact {
  display: inline-flex;
  align-items: center;
  gap: calc(2 * var(--ui-px));
  color: var(--ui-text-muted);
  font-size: var(--title-line-size);
  line-height: 1.3;
  letter-spacing: 1px;
  text-shadow: 0 var(--ui-px) 0 rgba(0, 0, 0, 0.6);
}

.title-screen__fact--controls {
  color: var(--ui-text);
}

/* "Turn it sideways" only for touch readers holding a phone upright (the game's rotate card has
   the same gate); the copy names no device. */
.title-screen__fact--sideways {
  display: none;
}

@media (max-width: 760px) and (orientation: portrait) {
  .title-screen[data-input='touch'] .title-screen__fact--sideways {
    display: inline-flex;
  }
}

/* ---------------------------------------------------------------- PLAY NOW */

/* The kit's primary button (amber face, hazard-stripe bumpers), the one call to action. Its press
   is the gesture that starts the music (titleScreen.mjs). Focus: the dialog root holds it for
   pointer sessions; the first Tab moves it here (then :focus-visible is earned). */
.title-screen__play {
  width: min(100%, var(--title-play-width));
  gap: calc(3 * var(--ui-px));
  font-size: var(--title-play-size);
  letter-spacing: 2px;
}

.title-screen__play .title-screen__icon {
  color: inherit;
}

/* The press is swallowed at the window (no native :active), so the leaving state draws it pressed. */
.title-screen[data-state='leaving'] .title-screen__play {
  transform: translateY(var(--ui-px));
}

/* The gate's other way in, right under the button. */
.title-screen__or {
  margin: 0;
  color: var(--ui-text-muted);
  font-size: var(--title-line-size);
  line-height: 1.3;
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* ---------------------------------------------------------------- foot */

.title-screen__foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(3 * var(--ui-px));
}

/* Wide screens: both foot lines on one row, so the column ends above the attract hero. */
@media (min-width: 1100px) and (min-height: 600px) {
  .title-screen__foot {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: calc(2 * var(--ui-px)) calc(7 * var(--ui-px));
  }
}

/* The sound hint: what the player's browser and setting make true right now. */
.title-screen__hint {
  display: inline-flex;
  align-items: center;
  gap: calc(2 * var(--ui-px));
  margin: 0;
  color: var(--ui-text-muted);
  font-size: var(--title-line-size);
  line-height: 1.3;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.title-screen[data-sound='muted'] .title-screen__hint .title-screen__icon {
  color: var(--ui-text-dim);
}

/* The one-tap path for returning players, steady (no blink). */
.title-screen__returning {
  margin: 0;
  color: var(--ui-text-dim);
  font-size: var(--title-line-size);
  line-height: 1.3;
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* ---------------------------------------------------------------- breakpoints */

/* Tablets and small laptops. */
@media (max-width: 1100px), (max-height: 760px) {
  :root {
    --title-logo-h: 128px;
    --title-emblem-h: 80px;
    --title-word-size: 44px;
  }

  /* The lockup is three items here (emblem, name, tape): a tighter gap keeps the column inside a
     720 px tall laptop screen with its 18vh bottom padding. */
  .title-screen__logo {
    gap: calc(3 * var(--ui-px));
  }
}

/* Phones (the kit's 2 px UI pixel) and short landscape screens: 11 px type, tighter ledger. */
@media (max-width: 760px), (max-height: 520px) {
  :root {
    --title-logo-h: 96px;
    --title-emblem-h: 72px;
    --title-word-size: 33px;
    --title-word-px: calc(1.5 * var(--ui-px));
    --title-pitch-size: 11px;
    --title-label-size: 11px;
    --title-play-width: 286px;
  }

  .title-screen__tag {
    font-size: 11px;
    letter-spacing: 3px;
  }

  /* The column takes 2 px of the overlay's 16 px edge on each side: the ledger plate's rings
     (box-shadow, outside its box) need room inside the column, which clips what lies outside its
     own box, and the plate itself keeps the full width that gives the longest hint its one line
     at 375 px. */
  .title-screen__content {
    gap: calc(6 * var(--ui-px));
    width: calc(100% + 4 * var(--ui-px));
    max-width: calc(100% + 4 * var(--ui-px));
    padding-inline: calc(2 * var(--ui-px));
  }

  .title-screen__intro {
    gap: calc(5 * var(--ui-px));
  }

  .title-screen__pitch {
    max-width: 44ch;
    line-height: 1.4;
  }

  /* Full column width (its rings fall in the column's side padding above), lighter side padding
     and a 6.5ch label column, so the longest hint ("1 ticket per run · scores add up") stays on
     one line down to 375 px. */
  .title-screen__ledger {
    grid-template-columns: var(--title-icon) minmax(6.5ch, auto) 1fr;
    margin: calc(2 * var(--ui-px)) 0 calc(4 * var(--ui-px));
    padding: calc(4 * var(--ui-px));
    min-width: 0;
    width: 100%;
  }

  .title-screen__row {
    grid-template-columns: var(--title-icon) minmax(6.5ch, auto) 1fr;
  }

  @supports (grid-template-columns: subgrid) {
    .title-screen__row {
      grid-template-columns: subgrid;
    }
  }

  .title-screen__row-label {
    line-height: 1.3;
    letter-spacing: 1px;
    text-shadow: none;
  }

  /* On phones too narrow for a hint (360 px Androids), it folds into two even lines, so the fold
     lands after a "·" ("1 ticket per run · / scores add up"), never on a lone last word. */
  .title-screen__row-hint {
    white-space: normal;
    text-wrap: balance;
  }
}

/* The narrowest phones (375 px iPhones): a tighter plate (6 px sides, 4 px between the columns,
   no letter-spacing on the labels) gives the longest hint its one line; 360 px Androids fold. */
@media (max-width: 380px) {
  .title-screen__ledger {
    padding: calc(4 * var(--ui-px)) calc(3 * var(--ui-px));
    column-gap: calc(2 * var(--ui-px));
  }

  .title-screen__row {
    column-gap: calc(2 * var(--ui-px));
  }

  .title-screen__row-label {
    letter-spacing: 0;
  }
}

/* Portrait phones: the one sentence that says what Bixel is gets the only big type between the
   wordmark and the button (22 px, full width). */
@media (max-width: 760px) and (orientation: portrait) {
  :root {
    --title-pitch-size: 22px;
  }

  .title-screen__pitch {
    max-width: 100%;
    line-height: 1.3;
  }
}

/* Short portrait phones (a 375 x 667 iPhone SE, a 360 x 740 Android): the column fills the screen,
   so the attract hero cannot stand under it and stays at the menu's stage, behind the pitch
   (menuEffects.mjs resolveTitleFocus). The same veil, deeper, so the type reads over him and the
   scene stays a hint; from 800 px up the column moves up and he stands under it. */
@media (max-width: 760px) and (max-height: 799px) and (orientation: portrait) {
  .title-screen__veil {
    background:
      radial-gradient(ellipse 75% 65% at 50% 48%, rgba(6, 6, 7, 0.8) 0%, rgba(6, 6, 7, 0.86) 55%, rgba(6, 6, 7, 0.94) 100%),
      linear-gradient(180deg, rgba(6, 6, 7, 0.35) 0%, rgba(6, 6, 7, 0) 30%, rgba(6, 6, 7, 0) 70%, rgba(6, 6, 7, 0.55) 100%);
  }
}

/* Landscape phones: everything on one short screen (a 667 x 375 iPhone SE included: tighter
   edges and gaps). The intro's column is kept narrow (<= ~400 px: the pitch and the clock capped
   at 46ch, the ledger takes the intro's width, and the two foot lines stay stacked, since side by
   side they are 434 px) so resolveTitleFocus still finds the 128 px it needs for the hero beside
   the column on a 667 px wide phone; the gate keeps a bigger logo. */
@media (max-height: 520px) and (orientation: landscape) {
  :root {
    --title-logo-h: 72px;
    --title-emblem-h: 36px;
    --title-word-size: 22px;
  }

  .title-screen {
    padding-top: max(8px, env(safe-area-inset-top));
    padding-bottom: max(8px, env(safe-area-inset-bottom));
  }

  .title-screen[data-mode='gate'] {
    --title-logo-h: 88px;
    --title-emblem-h: 44px;
    --title-word-size: 33px;
  }

  .title-screen__content {
    gap: calc(2 * var(--ui-px));
    max-width: 560px;
  }

  .title-screen__logo {
    gap: calc(3 * var(--ui-px));
  }

  .title-screen__intro {
    gap: calc(2 * var(--ui-px));
  }

  .title-screen__pitch,
  .title-screen__clock {
    max-width: 46ch;
    line-height: 1.3;
  }

  .title-screen__clock {
    margin-top: calc(-2 * var(--ui-px));
  }

  .title-screen__ledger {
    gap: calc(2 * var(--ui-px));
    margin-bottom: calc(2 * var(--ui-px));
    padding: calc(3 * var(--ui-px)) calc(4 * var(--ui-px));
  }

  .title-screen__foot {
    gap: calc(2 * var(--ui-px));
  }
}

/* The smallest phones (a 320 x 568 iPhone SE 1st gen / 5s, portrait and landscape): the column
   has to fit a box a touch cannot scroll (titleScreen.mjs keeps every touch for the start), so the
   logo steps down (80 px = 251 wide inside the 288 px the 16 px edges leave), every gap closes to
   the kit's 2 px and the returning line goes (a tap anywhere still starts, and the sound hint
   stays). Measured so the column never overflows at 320 x 568 and 568 x 320. */
@media (max-width: 340px) and (orientation: portrait), (max-height: 340px) and (orientation: landscape) {
  :root {
    --title-logo-h: 80px;
    --title-emblem-h: 56px;
    --title-word-size: 33px;
  }

  .title-screen__tag {
    letter-spacing: 2px;
  }

  .title-screen__content,
  .title-screen__logo,
  .title-screen__intro {
    gap: calc(2 * var(--ui-px));
  }

  .title-screen__ledger {
    margin-bottom: calc(2 * var(--ui-px));
  }

  .title-screen__returning {
    display: none;
  }
}

/* The same phone on its side (568 x 320): the logo one more step down, the plate's rows closer,
   and the overlay's own edges at the kit's 2 px. The gate's own --title-logo-h (set on the
   element in the 520 tier, so it beats every :root step) comes down with it, one step above. */
@media (max-height: 340px) and (orientation: landscape) {
  :root {
    --title-logo-h: 48px;
    --title-word-size: 22px;
  }

  .title-screen[data-mode='gate'] {
    --title-logo-h: 56px;
  }

  /* No room for the emblem on a 320 px tall phone: the column is measured to the pixel there. */
  .title-screen__emblem {
    display: none;
  }

  .title-screen {
    padding-top: max(calc(2 * var(--ui-px)), env(safe-area-inset-top));
    padding-bottom: max(calc(2 * var(--ui-px)), env(safe-area-inset-bottom));
  }

  .title-screen__ledger {
    padding: calc(2 * var(--ui-px)) calc(4 * var(--ui-px));
  }
}

/* 4K: the kit's 4 px UI pixel, type one step up, icons at 2x. */
@media (min-width: 2200px) and (min-height: 1200px) {
  :root {
    --title-logo-h: 240px;
    --title-emblem-h: 192px;
    --title-word-size: 99px;
    --title-pitch-size: 33px;
    --title-label-size: 33px;
    --title-line-size: 22px;
    --title-play-size: 33px;
    --title-play-width: 528px;
    --title-icon: 32px;
  }

  .title-screen__tag {
    font-size: 33px;
  }
}

/* Reduced motion: nothing here moves anyway; the fades, the button's step transition and the
   pressed nudge go too (titleScreen.mjs skips its fade timer). */
@media (prefers-reduced-motion: reduce) {
  .title-screen,
  .title-screen__play,
  .title-screen[data-state='leaving'] .title-screen__play,
  html[data-title-screen] body > :not(.menu-backdrop):not(.title-screen) {
    animation: none;
    transition: none;
    transform: none;
  }
}
