/* =========================================================================
   PHONE UI FOUNDATIONS — the screen template (2026-09-19, Session 4)
   =========================================================================
   Plan + approved mock-ups: docs/Design/ui-foundations-plan.md,
   docs/Design/ui-foundations/board-1…3.png.

   Loaded ONLY by client/index.html (the phone page), after tokens.css, so
   nothing here can reach the TV (client/tv.html) or the iPad (ipad.html) —
   tokens.css is shared with both.

   Every migrated screen is:
     .screen-top   — ‹ back button (44 pt) + title, always the same height
     .screen-body  — the content; fills what's left, never scrolls itself
     .action-bar   — the main button, full width, at the bottom

   Sizes: 16 px side margins; main button 56 pt; buttons in cards 48 pt;
   anything tappable at least 44 pt (Apple's minimum).

   REAL SAFARI (measured 2026-09-19, iOS 26.5): the visible page is 402×714
   (iPhone 17), 390×699 (390-wide), 440×796 (Pro Max), while `100vh` is 40 px
   MORE than that — and `min-height` beats `height`. So a migrated screen must
   never keep `min-height: 100vh` (Tailwind's `min-h-screen`): it would sit
   40 px under Safari's toolbar. Headless browsers cannot show this; check with
   tests/manual/safari/sim-snapshots.mjs in Simulator Safari.
   ========================================================================= */

/* ---- The template ------------------------------------------------------ */

.screen-top {
  flex: none;
  min-height: 56px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 6px;
}
.screen-top--center { justify-content: center; }

.btn-back {
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 999px;
  background: var(--lobby-paper-warm);
  border: 3px solid var(--lobby-ink);
  box-shadow: 0 3px 0 0 var(--lobby-ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.btn-back:active {
  transform: translateY(3px);
  box-shadow: 0 0 0 0 var(--lobby-ink);
}
.btn-back svg { pointer-events: none; }

/* `.screen-top` prefix: tokens.css colours every h1–h3 inside a phone stage
   ink-black, and that selector is more specific than a bare class. */
.screen-top .screen-title {
  font-family: 'Fredoka One', cursive;
  font-size: 25px;
  line-height: 1.1;
  letter-spacing: 0.01em;
  color: var(--lobby-paper-warm);
  -webkit-text-stroke: 2px var(--lobby-ink);
  paint-order: stroke fill;
  text-shadow: 0 3px 0 var(--lobby-ink);
  margin: 0;
}

.screen-body {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 8px;
}

.action-bar {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 0 16px;
}
/* Beats `:is(…) .btn-chunky:not(.hidden)` in tokens.css on source order
   (same specificity, this file loads later). */
.action-bar .btn-chunky:not(.hidden) {
  width: 100%;
  min-height: 56px;
  padding: 0 24px;
  font-size: 24px;
  box-shadow:
    0 6px 0 0 var(--lobby-ink),
    0 10px 18px rgb(26 22 19 / 0.25);
}
.action-bar .btn-chunky[disabled] { opacity: 0.55; }

/* Long-press on character art must not open Safari's image menu. */
.character-tile img,
.player-paper-card__photo img {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* ---- Entry screens: landing, join, name -------------------------------- */

html:has(#screen-landing:not(.hidden)),
body:has(#screen-landing:not(.hidden)),
html:has(#screen-join:not(.hidden)),
body:has(#screen-join:not(.hidden)),
html:has(#screen-name-character:not(.hidden)),
body:has(#screen-name-character:not(.hidden)) {
  height: 100dvh;
  min-height: 0;
  max-height: 100dvh;
  overflow: hidden;
  box-sizing: border-box;
}

#screen-landing[data-slot="landing"]:not(.hidden),
#screen-join[data-slot="join-code"]:not(.hidden),
#screen-name-character[data-slot="name-character"]:not(.hidden) {
  display: flex;
  flex-direction: column;
  height: calc(100dvh - var(--app-safe-top, 0px) - var(--app-safe-bottom, 0px));
  min-height: 0;
  max-height: none;
  overflow: hidden;
  padding: 0 16px;
}

.screen-body--center {
  justify-content: center;
  align-items: center;
  gap: 24px;
}
/* Typing screens: the main button lives right under the field, because iOS
   Safari's keyboard covers the bottom of the screen. */
.screen-body--form {
  justify-content: center;
  align-items: center;
  gap: 16px;
}
.screen-body--form .btn-chunky:not(.hidden) {
  width: 100%;
  max-width: 22rem;
  min-height: 56px;
  padding: 0 24px;
  font-size: 24px;
  box-shadow:
    0 6px 0 0 var(--lobby-ink),
    0 10px 18px rgb(26 22 19 / 0.25);
}
/* `.screen-body` prefix: tokens.css colours every <p> inside a phone stage
   ink-black, which is unreadable on the brick. */
.screen-body .form-error {
  margin: 0;
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 15px;
  color: var(--lobby-paper-warm);
  text-shadow: 0 1px 3px rgb(26 22 19 / 0.8);
  text-align: center;
}

/* Name screen: the character photo gives up height first so the field and
   GO TO LOBBY always fit (including an iPhone SE). */
#screen-name-character .player-paper-card--featured .player-paper-card__photo {
  width: clamp(96px, calc(100dvh - 350px), 210px);
  height: clamp(96px, calc(100dvh - 350px), 210px);
}
#screen-name-character .player-paper-card--featured { margin: 0; }

/* ---- Lobby -------------------------------------------------------------
   The self-card photo simply gives up height until everything fits, so there
   are no magic numbers to re-tune when the content changes. */

html:has(#screen-lobby[data-stage="lobby"]:not([data-stage-variant]):not(.hidden)),
body:has(#screen-lobby[data-stage="lobby"]:not([data-stage-variant]):not(.hidden)) {
  height: 100dvh;
  min-height: 0;
  max-height: 100dvh;
  overflow: hidden;
  box-sizing: border-box;
}

#screen-lobby[data-stage="lobby"]:not([data-stage-variant]):not(.hidden) {
  display: flex;
  flex-direction: column;
  height: calc(100dvh - var(--app-safe-top, 0px) - var(--app-safe-bottom, 0px));
  min-height: 0;
  max-height: none;
  overflow: hidden;
  padding: 0 16px;
}
#screen-lobby .screen-body--lobby {
  align-items: center;
  gap: 12px;
}
#screen-lobby .lobby-sign {
  flex: none;
  font-size: 1.25rem;
  text-align: center;
}
/* The ready tally lives in the sign; the big counter block and the separate
   "All players ready!" line are gone from the phone lobby. */
#screen-lobby[data-stage="lobby"]:not([data-stage-variant]) .lobby-sign-tally {
  display: block;
  font-size: 0.8em;
  text-align: center;
}
#screen-lobby[data-stage="lobby"]:not([data-stage-variant]) .ready-counter,
#screen-lobby[data-stage="lobby"]:not([data-stage-variant]) #ready-status {
  display: none;
}
#screen-lobby .room-ticket { flex: none; margin: 0; }
#screen-lobby .player-paper-card--featured {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  max-width: 320px;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 14px 16px;
}
/* Only the photo gives up height — the name and character label keep theirs,
   otherwise a squeezed card clips the name on an iPhone SE. */
#screen-lobby .player-paper-card--featured .player-paper-card__photo {
  flex: 0 1 auto;
  min-height: 56px;
  width: auto;
  height: auto;
  max-height: 210px;
  max-width: 100%;
  aspect-ratio: 1;
  align-self: center;
}
#screen-lobby .player-paper-card--featured .player-paper-card__name,
#screen-lobby .player-paper-card--featured .player-paper-card__sub {
  flex: none;
}
#screen-lobby .player-paper-card--featured .player-paper-card__photo img {
  width: 100%;
  height: 100%;
}
/* The name keeps its full size here (fitOneLine shrinks it only when a long
   name would not fit the card). */
#screen-lobby[data-stage="lobby"]:not([data-stage-variant]) .player-paper-card--featured .player-paper-card__name {
  font-size: min(3rem, var(--name-max, 3rem));
}

/* ---- Character picker: all 20 characters, no scrolling ----------------- */

/* While a rebuilt screen is up the page itself cannot move — the screen is
   already exactly the visible height. Screens not yet rebuilt keep the old
   "scroll rather than clip" behaviour, so nothing gets stranded. */
html:has(#screen-pick-character:not(.hidden)),
body:has(#screen-pick-character:not(.hidden)) {
  height: 100dvh;
  min-height: 0;
  max-height: 100dvh;
  overflow: hidden;
  box-sizing: border-box;
}

#screen-pick-character[data-slot="pick-character"]:not(.hidden) {
  display: flex;
  flex-direction: column;
  height: calc(100dvh - var(--app-safe-top, 0px) - var(--app-safe-bottom, 0px));
  min-height: 0;
  max-height: none;
  overflow: hidden;
  padding: 0 16px;
}
#screen-pick-character .screen-body { padding-bottom: 0; }

#screen-pick-character #pick-character-grid {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: repeat(5, minmax(0, 1fr));
  gap: 8px;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
  overflow: visible; /* tile tilt + drop shadows must not be clipped */
}
#screen-pick-character .character-tile {
  min-height: 0;
  height: 100%;
  padding: 6px 3px 5px;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  align-items: center;
  justify-items: center;
  gap: 1px;
}
#screen-pick-character .character-tile__emoji {
  height: 100%;
  min-height: 0;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px; /* emoji fallback when a character has no art */
}
/* renderCharacter writes width/height inline (64 px), so this needs
   !important to make the art fill its tile. */
#screen-pick-character .character-tile__emoji img,
#screen-pick-character .character-tile__emoji video {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain;
}
#screen-pick-character .character-tile__label {
  font-size: 12px;
  line-height: 1.05;
  max-width: 100%;
}
#screen-pick-character .character-tile__taken-badge { font-size: 9px; }
@media (max-width: 395px) {
  #screen-pick-character .character-tile__label { font-size: 11px; }
}

/* ---- Round screen: the same shape on every phone ----------------------
   Plan step 4 + board 1. Timer, ONE big red button (SUS? / HOST TOOLS),
   a fixed-size task card, the evidence card, and the Group chat / DMs
   bar. Nothing here may differ by role except the words. */

html:has(#screen-round-active:not(.hidden)),
body:has(#screen-round-active:not(.hidden)) {
  height: 100dvh;
  min-height: 0;
  max-height: 100dvh;
  overflow: hidden;
  box-sizing: border-box;
}

#screen-round-active[data-stage="phone-round-active"]:not(.hidden) {
  /* The task box is sized from THIS, not from its own font-size: the host's
     placeholder is set in a smaller italic face, so a height in `em` made
     the host's card 20 px shorter than everyone else's — a glance tell. */
  --task-text-size: 1.35rem;
  --task-text-lines: 3;
  display: flex;
  flex-direction: column;
  height: calc(100dvh - var(--app-safe-top, 0px) - var(--app-safe-bottom, 0px));
  min-height: 0;
  max-height: none;
  overflow: hidden;
  padding: 0 16px;
}

#screen-round-active .screen-body--round {
  align-items: stretch;
  gap: 10px;
  padding-top: 4px;
  padding-bottom: 0;
}

/* The big red button keeps its own slot so the cards below always start
   at the same height on every phone. */
#screen-round-active .round-action-column {
  flex: none;
  padding: 0;
  position: relative;
}
#screen-round-active .btn-chunky.sus-button-chunky:not(.hidden) {
  width: 100%;
  min-width: 0;
  min-height: 64px;
  padding: 0 1.5rem;
  font-size: clamp(1.6rem, 6vw, 2.1rem);
  position: relative;
}

/* Badge on HOST TOOLS — this is how the host learns the Odd One Out has
   claimed their task. It must never pop up by itself: a box appearing
   right after someone taps their phone points straight at them. */
.round-badge {
  position: absolute;
  top: -8px;
  right: -6px;
  min-width: 28px;
  height: 28px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--lobby-mango);
  color: var(--lobby-ink);
  border: 3px solid var(--lobby-ink);
  font-family: 'Fredoka One', cursive;
  font-size: 15px;
  line-height: 22px;
  text-align: center;
}

/* Task + evidence cards: equal share of what is left, and the same size
   for the host, a player and the Odd One Out. */
#screen-round-active .task-paper {
  flex: none;
  min-height: 0;
  margin: 0;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#screen-round-active .task-paper__label { margin-bottom: 0; }

/* THE PARITY RULE. The text box is exactly three lines tall whatever it
   holds — the Detective briefing, a secret task, or the host's hidden
   placeholder — so nobody can be spotted by the height of their card.
   A task longer than the cap scrolls inside the box instead of growing
   it (that also keeps a long custom task readable). */
#screen-round-active #my-task-text {
  flex: none;
  height: calc(var(--task-text-lines) * 1.2 * var(--task-text-size));
  font-size: var(--task-text-size);
  line-height: 1.2;
  overflow-y: auto;
  overscroll-behavior: contain;
  min-height: 0;
}
#screen-round-active .evidence-card .evidence-card__text {
  flex: none;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* Every role's green button is the same size in the same place, and it
   never greys out — a greyed "Awaiting Host…" is a give-away. */
#screen-round-active .task-paper .btn-chunky:not(.hidden),
#screen-round-active .evidence-card .btn-chunky.evidence-card__btn:not(.hidden) {
  flex: none;
  width: 100%;
  min-height: 48px;
  margin-top: 0;
  padding: 0 1rem;
  font-size: 1.05rem;
}
#screen-round-active .evidence-card .paper-chip.evidence-card__btn {
  align-self: stretch;
  justify-content: center;
  margin-top: 0;
  min-height: 48px;
}

/* ---- Round screen bottom bar: Group chat (teal) vs DMs (orange) ------ */

/* Read by the chat + DM sheets, which sit directly under <body> and so
   cannot see a variable set on the round screen. */
:root { --round-bar-h: 74px; }
@media (max-height: 700px) { :root { --round-bar-h: 68px; } }
@media (max-height: 600px) { :root { --round-bar-h: 60px; } }

.round-bottom-bar {
  flex: none;
  display: flex;
  gap: 10px;
  padding: 10px 0 16px;
}
.round-tab {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  min-height: 48px;
  padding: 0 8px;
  border: 3px solid var(--lobby-ink);
  border-radius: 16px;
  box-shadow: 0 4px 0 0 var(--lobby-ink);
  font-family: 'Fredoka One', cursive;
  font-size: 15px;
  letter-spacing: 0.01em;
  color: var(--lobby-ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}
.round-tab:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 0 var(--lobby-ink);
}
.round-tab--chat { background: var(--lobby-teal); }
.round-tab--dm { background: var(--lobby-mango); }
.round-tab .chip-unread-badge {
  position: absolute;
  top: -8px;
  right: -6px;
  min-width: 26px;
  height: 26px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--lobby-coral);
  color: var(--lobby-paper-warm);
  border: 3px solid var(--lobby-ink);
  font-size: 14px;
  line-height: 20px;
  text-align: center;
}

/* Short screens (a 390-wide iPhone is 699 px, an SE 548): give up the
   paddings, never a button. */
@media (max-height: 700px) {
  #screen-round-active .screen-top { min-height: 48px; padding-top: 2px; }
  #screen-round-active .screen-body--round { gap: 8px; }
  #screen-round-active .btn-chunky.sus-button-chunky:not(.hidden) { min-height: 58px; }
  #screen-round-active .task-paper { padding: 11px 14px; gap: 6px; }
  .round-bottom-bar { padding: 8px 0 12px; }
}
@media (max-height: 600px) {
  #screen-round-active .screen-top { min-height: 40px; }
  #screen-round-active .btn-chunky.sus-button-chunky:not(.hidden) { min-height: 50px; font-size: 1.5rem; }
  #screen-round-active[data-stage="phone-round-active"]:not(.hidden) {
    --task-text-size: 1.1rem;
    --task-text-lines: 2;
  }
  #screen-round-active .task-paper__text { font-size: var(--task-text-size); }
  #screen-round-active .task-paper .btn-chunky:not(.hidden),
  #screen-round-active .evidence-card .btn-chunky.evidence-card__btn:not(.hidden) { min-height: 44px; font-size: 0.95rem; }
  .round-tab { min-height: 46px; font-size: 14px; }
}

/* ---- Sheets ------------------------------------------------------------
   Everything that used to open inside the round screen now slides up from
   the bottom. The shells live directly under <body> (a `position: fixed`
   child of a screen breaks the moment that screen is transformed) and
   carry `data-stage="phone-sheet"`, so the paper-cutout styling in
   tokens.css still reaches the markup inside them. */

.sheet-scrim {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: rgb(26 22 19 / 0.55);
  opacity: 0;
  transition: opacity 0.28s ease;
}
.sheet-scrim.is-open { opacity: 1; }

.sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 120;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 86dvh;
  padding: 8px 16px calc(16px + var(--app-safe-bottom, 0px));
  background: var(--lobby-paper);
  border-top: 4px solid var(--lobby-ink);
  border-radius: 26px 26px 0 0;
  box-shadow: 0 -10px 34px rgb(26 22 19 / 0.45);
  color: var(--lobby-ink);
  transform: translateY(100%);
  transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
}
.sheet.is-open { transform: none; }

.sheet__grabber {
  flex: none;
  align-self: center;
  width: 44px;
  height: 5px;
  border-radius: 999px;
  background: var(--lobby-ink);
  opacity: 0.25;
}
/* `.sheet` prefix: tokens.css colours every <p> inside a phone stage, and
   that selector out-ranks a bare class. */
.sheet .sheet__title {
  flex: none;
  margin: 0;
  font-family: 'Fredoka One', cursive;
  font-size: 20px;
  line-height: 1.15;
  color: var(--lobby-ink);
}
.sheet .sheet__title-sub {
  display: block;
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 0.04em;
  opacity: 0.7;
}
.sheet .sheet__sub {
  flex: none;
  margin: 0;
  font-family: 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 14px;
  opacity: 0.8;
}
.sheet .sheet__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.sheet .sheet__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.sheet .sheet__actions {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.sheet .sheet__actions .btn-chunky:not(.hidden),
.sheet .btn-chunky.sheet__close:not(.hidden) {
  width: 100%;
  min-height: 52px;
  font-size: 1.1rem;
}
.sheet .sheet__close { flex: none; }
.sheet .sheet__peek {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: 10px;
  background: rgb(26 22 19 / 0.06);
  font-weight: 800;
  font-size: 1.05rem;
}
.sheet .sheet__peek.hidden { display: none; }
/* Sheets are their own surface — the paper-modal inside no longer needs
   the floating-card margins or the tilt. */
.sheet .paper-modal {
  margin: 0;
  transform: none;
}
/* Every tap target in a sheet clears Apple's 44 pt minimum. */
.sheet .paper-chip,
.sheet .timer-stepper-btn {
  min-height: 44px;
  padding-left: 1rem;
  padding-right: 1rem;
  font-size: 0.8rem;
}
.sheet .paper-modal__actions .btn-chunky:not(.hidden) { min-height: 48px; }

/* Group chat = teal, DMs = orange, so you always know which one you're in.
   Step 5 turns these into two full screens; the colours carry over. */
.sheet--chat { border-top-color: var(--lobby-teal); }
.sheet--dm { border-top-color: var(--lobby-mango); }
.sheet--chat .sheet__title { color: var(--lobby-teal); }
.sheet--dm .sheet__title { color: var(--lobby-mango); }
/* Chat and DMs stop just above the bottom bar, and the bar stays on top of
   the scrim while they are open: one tap switches between the two, one tap
   on the one you're in closes it. The modal sheets (SUS, Host tools) still
   cover the bar — there's nothing to switch to from those. */
.sheet--chat,
.sheet--dm {
  height: 72dvh;
  bottom: var(--round-bar-h, 0px);
  border-radius: 26px 26px 18px 18px;
}
.sheet--chat .sheet__body,
.sheet--dm .sheet__body { justify-content: flex-end; }
body:has(.sheet--chat.is-open) .sheet-scrim,
body:has(.sheet--dm.is-open) .sheet-scrim { bottom: var(--round-bar-h, 0px); }
body:has(.sheet--chat.is-open) .round-bottom-bar,
body:has(.sheet--dm.is-open) .round-bottom-bar {
  position: relative;
  z-index: 130;
}
.sheet--chat .chat-panel__composer,
.sheet--dm .dm-panel__composer {
  flex: none;
  align-items: flex-end;
}
.sheet .chat-send-btn,
.sheet .dm-send-btn {
  flex: none;
  min-height: 44px;
  padding: 0 1rem;
  font-size: 0.95rem;
}
.sheet .paper-input { min-height: 44px; }

/* A sheet covers the bottom bar, so the button that opened it can't be the
   way back out: every sheet carries its own ✕. */
.sheet__x {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  background: none;
  font-size: 22px;
  line-height: 1;
  color: var(--lobby-ink);
  opacity: 0.55;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.sheet__x:active { opacity: 1; }
.sheet .sheet__title { padding-right: 48px; }

/* Host tools rows — board 1: what each tool does, then the button. */
.sheet .tool-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 3px solid var(--lobby-ink);
  border-radius: 14px;
  background: var(--lobby-paper-warm);
}
.sheet .tool-row--stack {
  flex-direction: column;
  align-items: stretch;
}
.sheet .tool-row__text {
  flex: 1 1 auto;
  min-width: 0;
  display: block;
}
.sheet .tool-row__text b {
  display: block;
  font-family: 'Fredoka One', cursive;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.15;
}
.sheet .tool-row__text small {
  display: block;
  font-family: 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 12px;
  line-height: 1.2;
  opacity: 0.65;
}
.sheet .tool-row .paper-chip { flex: none; }
.sheet .tool-row--stack .paper-chip { align-self: flex-start; }

/* ---- Group chat + DMs: two full screens (step 5, board 2) -------------
   Teal is everyone, orange is private — you can tell which one you're in
   from across the room. They slide in from the right over whatever was
   there. The chat/DM bar underneath is what opened them, so ‹ is the way
   back out.

   KEYBOARD (proved in real iOS 26.5 Safari before this was built):
   phone.js sizes .msg-screen to `visualViewport.height` and slides it down
   by `visualViewport.offsetTop`, so the type box sits right on top of the
   keyboard. Do NOT try to do it with padding-bottom — on iOS
   `window.innerHeight` shrinks with the keyboard too, so
   `innerHeight - visualViewport.height` is always about zero. While the
   keyboard slides away the box is briefly shorter than the screen, so
   `body` is painted the same cream underneath (see .msg-open below) and
   there is never a dark strip. */

.msg-screen {
  position: fixed;
  inset: 0;
  z-index: 200;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  height: 100dvh;
  background: var(--lobby-paper-warm);
  color: var(--lobby-ink);
  transform: translateX(100%);
  transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1);
  overflow: hidden;
}
.msg-screen.is-open { transform: none; }
/* While a message screen is up, the page behind it is the same cream, so
   the strip under the box during the keyboard's slide-away is invisible. */
body.msg-open { background: var(--lobby-paper-warm); }

.msg-top {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px calc(10px);
  padding-top: calc(10px + var(--app-safe-top, 0px));
  border-bottom: 4px solid var(--lobby-ink);
}
.msg-screen--chat .msg-top { background: var(--lobby-teal); }
.msg-screen--dm .msg-top { background: var(--lobby-mango); }
.msg-top .btn-back { width: 40px; height: 40px; }

.msg-faces {
  flex: none;
  display: flex;
  align-items: center;
}
.msg-faces img,
.msg-faces video {
  width: 30px;
  height: 30px;
  border-radius: 999px;
  border: 2px solid var(--lobby-ink);
  object-fit: cover;
  background: var(--lobby-paper-warm);
  margin-left: -10px;
}
.msg-faces > :first-child img { margin-left: 0; }

/* `.msg-top` prefix: tokens.css colours text inside a phone stage. */
.msg-top .msg-title {
  flex: 1 1 auto;
  min-width: 0;
  font-family: 'Fredoka One', cursive;
  font-size: 19px;
  line-height: 1.1;
  color: var(--lobby-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.msg-top .msg-title small {
  display: block;
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 11px;
  letter-spacing: 0.04em;
  opacity: 0.7;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msg-top .msg-timer {
  flex: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-weight: 700;
  font-size: 15px;
  padding: 5px 10px;
  border-radius: 999px;
  border: 2.5px solid var(--lobby-ink);
  background: var(--lobby-paper-warm);
  color: var(--lobby-ink);
}

/* Said on the inbox AND inside every conversation — Juvian's wording. */
.msg-screen .msg-note {
  flex: none;
  margin: 0;
  padding: 5px 12px;
  text-align: center;
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 12px;
  color: var(--lobby-ink);
  background: color-mix(in srgb, var(--lobby-mango) 45%, var(--lobby-paper-warm));
  border-bottom: 2px solid var(--lobby-ink);
}

.msg-screen .msg-body {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 16px;
}

.msg-screen .msg-composer {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 10px 12px calc(10px + var(--app-safe-bottom, 0px));
  border-top: 3px solid var(--lobby-ink);
  background: var(--lobby-paper-warm);
}
.msg-screen .msg-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  max-height: 96px;
  font-size: 16px; /* under 16px iOS zooms the page on focus */
}
.msg-screen .msg-send {
  flex: none;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 3px solid var(--lobby-ink);
  border-radius: 999px;
  box-shadow: 0 3px 0 0 var(--lobby-ink);
  font-size: 19px;
  line-height: 1;
  color: var(--lobby-ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.msg-screen--chat .msg-send { background: var(--lobby-teal); }
.msg-screen--dm .msg-send { background: var(--lobby-mango); }
.msg-screen .msg-send:active { transform: translateY(3px); box-shadow: none; }

/* My own bubbles take the screen's colour, so the two never look alike.
   `.msg-screen` prefix beats `:is([data-stage^="phone-"]) .paper-card--mine`
   in tokens.css. */
.msg-screen--chat .paper-card.paper-card--mine { background: var(--lobby-teal); }
.msg-screen--dm .paper-card.paper-card--mine { background: var(--lobby-mango); }
/* "Seen" under my last DM once they have read it (2026-10-18). */
.msg-screen--dm .dm-seen {
  align-self: flex-end;
  margin: -2px 6px 4px 0;
  font-family: 'Nunito', sans-serif;
  font-size: 0.75rem;
  color: var(--lobby-paper-warm);
  opacity: 0.85;
}
/* Messages sit at the BOTTOM of an empty screen, like any messages app —
   this still scrolls normally once they fill it. */
.msg-screen .msg-body { justify-content: flex-end; }
.msg-screen .msg-body > * { flex: none; }

/* ---- The DM inbox ----------------------------------------------------- */

.msg-screen .dm-inbox {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0;
}
.msg-screen .dm-inbox .dm-chip {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 64px;
  margin: 0;
  padding: 10px 14px;
  border: none;
  border-bottom: 2px solid color-mix(in srgb, var(--lobby-ink) 18%, transparent);
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  text-align: left;
  transform: none;
}
.msg-screen .dm-inbox .dm-chip:active { background: color-mix(in srgb, var(--lobby-mango) 25%, transparent); }
.msg-screen .dm-inbox .dm-chip__photo { width: 44px; height: 44px; flex: none; }
.msg-screen .dm-inbox .dm-chip__name {
  flex: 1 1 auto;
  min-width: 0;
  font-family: 'Fredoka One', cursive;
  font-size: 16px;
  letter-spacing: 0;
}
.msg-screen .dm-inbox .dm-chip__sub {
  display: block;
  font-family: 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 13px;
  opacity: 0.65;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msg-screen .dm-inbox .dm-chip__badge { flex: none; position: static; }

/* Inbox or conversation — never both. */
.msg-screen[data-dm-view="inbox"] #dm-messages,
.msg-screen[data-dm-view="inbox"] #dm-composer { display: none; }
.msg-screen[data-dm-view="thread"] .dm-inbox { display: none; }

.msg-screen .dm-panel__tabs {
  flex: none;
  display: flex;
  gap: 8px;
  padding: 8px 12px;
}
.msg-screen .dm-panel__tabs.hidden { display: none; }

/* ---- Host checklist (step 6) ------------------------------------------
   On the template: title, the cards, NOTIFY PLAYERS in the bottom bar.
   The task list is the one thing allowed to scroll, inside its own box. */

html:has(#screen-host-checklist:not(.hidden)),
body:has(#screen-host-checklist:not(.hidden)) {
  height: 100dvh;
  min-height: 0;
  max-height: 100dvh;
  overflow: hidden;
  box-sizing: border-box;
}
#screen-host-checklist[data-stage="phone-host-checklist"]:not(.hidden) {
  display: flex;
  flex-direction: column;
  height: calc(100dvh - var(--app-safe-top, 0px) - var(--app-safe-bottom, 0px));
  min-height: 0;
  max-height: none;
  overflow: hidden;
  padding: 0 16px;
}
#screen-host-checklist .screen-body--checklist {
  gap: 10px;
  padding-top: 4px;
}
#screen-host-checklist .checklist-subhead {
  flex: none;
  margin: 0;
  text-align: center;
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 13px;
  color: var(--lobby-paper-warm);
  text-shadow: 0 1px 3px rgb(26 22 19 / 0.8);
}
#screen-host-checklist .checklist-card {
  margin: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* The task card takes whatever is left; the timer card keeps its size. */
#screen-host-checklist [data-slot="checklist-task-card"] { flex: 1 1 auto; }
#screen-host-checklist [data-slot="checklist-timer-card"] { flex: none; }
#screen-host-checklist #checklist-ooo-card { flex: none; }
#screen-host-checklist .checklist-card__step { flex: none; }
#screen-host-checklist .checklist-options {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#screen-host-checklist .checklist-options .character-tile {
  width: 100%;
  min-height: 44px;
  text-align: left;
}
#screen-host-checklist .checklist-options button { min-height: 44px; }
#screen-host-checklist .checklist-options textarea { min-height: 44px; }

/* One row of times, not two. */
#screen-host-checklist .checklist-timer-row {
  display: flex;
  gap: 6px;
}
#screen-host-checklist .checklist-timer-row .checklist-timer-preset {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  padding: 0 4px;
}
#screen-host-checklist .checklist-custom-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}
#screen-host-checklist .checklist-custom-row .timer-stepper-field { flex: 1 1 auto; }
#screen-host-checklist .checklist-custom-row .timer-stepper-btn { min-width: 44px; min-height: 44px; }
#screen-host-checklist .checklist-custom-row #btn-checklist-custom-timer { flex: none; min-height: 44px; }
#screen-host-checklist #checklist-custom-mins {
  border: none;
  background: none;
  text-align: center;
  width: 3.5ch;
}
#screen-host-checklist .checklist-notify-hint {
  margin: 0;
  text-align: center;
  font-family: 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 12px;
  color: var(--lobby-paper-warm);
  text-shadow: 0 1px 3px rgb(26 22 19 / 0.8);
}

/* The stepper primitives in tokens.css are scoped to the Adjust Timer
   stage, so the checklist needs its own row. */
#screen-host-checklist .checklist-custom-row .timer-stepper-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0;
  border: 3px solid var(--lobby-ink);
  border-radius: 12px;
  background: var(--lobby-paper-warm);
  overflow: hidden;
}
#screen-host-checklist .checklist-custom-row .timer-stepper-btn {
  flex: none;
  border: none;
  background: transparent;
  font-family: 'Fredoka One', cursive;
  font-size: 22px;
  line-height: 1;
  color: var(--lobby-ink);
  cursor: pointer;
}
#screen-host-checklist .checklist-custom-row .timer-stepper-readout {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 4px;
  min-width: 0;
}
#screen-host-checklist #checklist-custom-mins {
  width: 3ch;
  padding: 0;
  font-family: 'Fredoka One', cursive;
  font-size: 19px;
  color: var(--lobby-ink);
}
#screen-host-checklist .checklist-custom-row .timer-stepper-unit {
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 13px;
  opacity: 0.7;
}

/* The "who is the Odd One Out" card is a reminder, not the subject — keep
   it small so the task list gets the room. */
#screen-host-checklist #checklist-ooo-card { padding: 10px 12px; }
#screen-host-checklist #checklist-ooo-card img {
  width: 48px !important;
  height: 48px !important;
}

/* The Odd One Out reminder folds into one compact row, so the task list
   gets the room instead. (Its inner layout is written inline by
   renderChecklistOooCard, hence the !important overrides.) */
#screen-host-checklist #checklist-ooo-card { padding: 8px 12px; gap: 0; }
#screen-host-checklist #checklist-ooo-card .checklist-card__step {
  margin-bottom: 4px !important;
  font-size: 11px;
}
#screen-host-checklist #checklist-ooo-card > div:last-child { gap: 0.5rem !important; }
#screen-host-checklist #checklist-ooo-card > div:last-child > div:last-child > div:first-child {
  font-size: 1.05rem !important;
}
#screen-host-checklist #checklist-ooo-card > div:last-child > div:last-child > div:last-child {
  font-size: 0.72rem !important;
  margin-top: 0 !important;
}
/* Task rows: enough for three plus Shuffle and "write my own". */
#screen-host-checklist .checklist-options .character-tile {
  padding: 7px 10px;
  font-size: 13px;
  line-height: 1.2;
}
#screen-host-checklist .checklist-options .divider { margin: 2px 0 !important; }

/* ---- Step 6: the rest of the screens ----------------------------------- */

/* "Picking your host" and the 5-second countdown were plain black while
   every other screen is the brick wall. */
[data-stage="phone-host-reveal-waiting"],
[data-stage="phone-round-start-countdown"],
[data-stage="phone-role-reveal"] {
  background:
    url('/assets/images/brick-phone.webp') center / cover no-repeat,
    var(--lobby-ink);
}

/* Voting: the grid goes to four across from 10 players, so 20 fit without
   scrolling, and LOCK IT IN sits in the bottom bar like every other main
   button. */
html:has(#screen-voting:not(.hidden)),
body:has(#screen-voting:not(.hidden)),
html:has(#screen-normal-gather:not(.hidden)),
body:has(#screen-normal-gather:not(.hidden)),
html:has(#screen-emergency-gather:not(.hidden)),
body:has(#screen-emergency-gather:not(.hidden)),
html:has(#screen-between-rounds:not(.hidden)),
body:has(#screen-between-rounds:not(.hidden)),
html:has(#screen-spectator:not(.hidden)),
body:has(#screen-spectator:not(.hidden)) {
  height: 100dvh;
  min-height: 0;
  max-height: 100dvh;
  overflow: hidden;
  box-sizing: border-box;
}

#screen-voting[data-stage="phone-voting"]:not(.hidden),
#screen-normal-gather[data-stage="phone-gather"]:not(.hidden),
#screen-emergency-gather[data-stage="phone-gather"]:not(.hidden),
#screen-between-rounds[data-stage="phone-between-rounds"]:not(.hidden),
#screen-spectator[data-stage="phone-spectator"]:not(.hidden) {
  height: calc(100dvh - var(--app-safe-top, 0px) - var(--app-safe-bottom, 0px));
  min-height: 0;
  max-height: none;
  overflow: hidden;
  padding: 12px 16px 16px;
}

#screen-voting .vote-grid {
  flex: 1 1 auto;
  min-height: 0;
  align-content: start;
  overflow-y: auto;
  overscroll-behavior: contain;
  gap: 10px 10px;
}
/* 10 players or more: four across. `:has(> :nth-child(10))` is how the TV
   page picks its column count too. */
#screen-voting .vote-grid:has(> :nth-child(10)) {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  max-width: none;
}
#screen-voting .btn-chunky:not(.hidden) {
  flex: none;
  width: 100%;
  max-width: 24rem;
  min-height: 56px;
}
#screen-voting .vote-headline { flex: none; }

/* The main button on these screens goes to the bottom, in the same place
   as everywhere else. */
#screen-normal-gather .btn-chunky:not(.hidden),
#screen-emergency-gather .btn-chunky:not(.hidden) {
  width: 100%;
  min-height: 56px;
}
#screen-normal-gather .gather-grid,
#screen-emergency-gather .gather-grid {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  align-content: start;
}
#screen-between-rounds .between-action-column .btn-chunky:not(.hidden) {
  width: 100%;
  min-height: 56px;
}
#screen-between-rounds #between-ready-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Spectators get Group chat from their own screen (DMs stay off — the
   brain rejects spectator DMs). */
.spectator-bottom-bar { margin-top: auto; align-self: stretch; width: 100%; }
#screen-spectator { display: flex; flex-direction: column; }

/* Big rooms: the tiles give up size so 20 players fit on one screen,
   the same trick the picker uses. renderCharacter writes 52 px inline,
   hence the !important. */
#screen-voting .vote-grid:has(> :nth-child(10)) {
  grid-auto-rows: minmax(0, 1fr);
  overflow: hidden;
}
#screen-voting .vote-grid:has(> :nth-child(10)) .paper-tile-sm {
  min-height: 0;
  height: 100%;
  padding: 4px 3px;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  align-items: center;
  justify-items: center;
  gap: 2px;
}
#screen-voting .vote-grid:has(> :nth-child(10)) .paper-tile-sm__avatar {
  height: 100%;
  min-height: 0;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
#screen-voting .vote-grid:has(> :nth-child(10)) .paper-tile-sm__avatar img,
#screen-voting .vote-grid:has(> :nth-child(10)) .paper-tile-sm__avatar video {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain;
}
#screen-voting .vote-grid:has(> :nth-child(10)) .paper-tile-sm__name {
  font-size: 10px;
  line-height: 1.05;
  max-width: 100%;
}
#screen-voting .vote-sub { flex: none; }

/* The main button belongs at the bottom, under your thumb, on these
   screens too — not floating in the middle of the brick. */
#screen-normal-gather[data-stage="phone-gather"]:not(.hidden),
#screen-emergency-gather[data-stage="phone-gather"]:not(.hidden) {
  display: flex;
  flex-direction: column;
}
#screen-normal-gather .gather-grid,
#screen-emergency-gather .gather-grid { order: 5; }
#screen-normal-gather #btn-normal-at-tv,
#screen-emergency-gather #btn-at-tv { order: 10; margin-top: auto; }
#screen-normal-gather #normal-gather-status,
#screen-emergency-gather #at-tv-status { order: 11; flex: none; }

#screen-between-rounds[data-stage="phone-between-rounds"]:not(.hidden) {
  display: flex;
  flex-direction: column;
}
#screen-between-rounds .between-action-column {
  margin-top: auto;
  width: 100%;
  flex: none;
}
#screen-between-rounds #round-recap { flex: none; }

/* iPhone SE (548 tall): the two cards plus the Odd One Out reminder cannot
   all keep full size. The task list keeps a usable minimum and the middle
   of the screen may scroll as a last resort — the bottom bar never does.
   (Without the minimum the list collapsed to nothing and the card's own
   "1 · Pick a task" header sat on top of the first task.) */
#screen-host-checklist .checklist-options { min-height: 96px; }
#screen-host-checklist .screen-body--checklist {
  overflow-y: auto;
  overscroll-behavior: contain;
}
@media (max-height: 620px) {
  #screen-host-checklist .screen-top { min-height: 42px; }
  #screen-host-checklist .checklist-subhead { display: none; }
  #screen-host-checklist .checklist-card { padding: 8px 10px; gap: 6px; }
  #screen-host-checklist .checklist-timer-row .checklist-timer-preset { font-size: 12px; }
  #screen-host-checklist .checklist-notify-hint { display: none; }
}

/* ---- Step 7: pop-ups become messages on the page ----------------------- */
.checklist-inline-error {
  flex: none;
  margin: 4px 0 0;
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 12px;
  line-height: 1.25;
  color: var(--lobby-coral);
}
.checklist-inline-error.hidden { display: none; }
.checklist-char-count {
  margin: 2px 0 0;
  text-align: right;
  font-family: 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 11px;
  opacity: 0.6;
}

/* Bug 52: the host's way back into their end-of-round question from
   "Head to the TV". Sits above the main button, only when there is
   something to answer. */
.gather-host-chip {
  position: relative;
  order: 9;
  align-self: center;
  min-height: 44px;
  margin-top: auto;
  margin-bottom: 8px;
  padding: 0 1rem;
  font-size: 0.8rem;
}
.gather-host-chip.hidden { display: none; }
#screen-normal-gather .gather-host-chip + #btn-normal-at-tv { margin-top: 0; }

/* Bug 49: Leave game sits in the lobby's top-left corner, where ‹ lives on
   every other screen. Absolute so it can't push the wordmark off centre. */
#screen-lobby .lobby-top { position: relative; }
/* The wordmark is centred and decorative — without this it sits on top of
   the Leave button and swallows the tap. */
#screen-lobby .lobby-top .wordmark { pointer-events: none; }
#screen-lobby .lobby-leave {
  position: absolute;
  z-index: 2;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
}
#screen-lobby .lobby-leave:active { transform: translateY(calc(-50% + 3px)); box-shadow: 0 0 0 0 var(--lobby-ink); }

/* ---- TV13: a phone that dropped looks dropped, on both lobby screens ----
   Matched to the TV half (tv-fit.css, `player-paper-card--dropped`): the same
   opacity .45 + grayscale(.85) + dashed border that `paper-tile-lg--disconnected`
   uses on the round and gather grids, and the same word — DROPPED, not
   "disconnected" (too long, and not what a person says) or "offline" (technical).

   The rule the two chats agreed: the number and the card move together. A
   dropped player stops being counted AND is visibly out. Never one without
   the other — "3/3 ready · Everyone's ready!" next to four identical cards is
   confidently wrong, and worse than a visibly stuck "3/4".

   The phone lobby has no cards for other players (only `#lobby-self-card`), so
   there the sign carries both halves: the tally drops them, and `· N dropped`
   in coral says so. Between rounds the phone DOES have a tile per player, and
   that gets the card treatment. */
#screen-lobby .lobby-sign-dropped {
  color: var(--lobby-coral, #E86B6B);
  white-space: nowrap;
}
#screen-lobby .lobby-sign-dropped.hidden { display: none; }

/* THE FADE GOES ON THE CONTENTS, NOT THE TILE. `opacity` on a parent
   composites its whole subtree, so `opacity:.45` here with `opacity:1` on the
   status line inside it does not spare the word — it cannot, there is nothing
   to undo it with. The first version of this rule did exactly that and made
   the one element that has to be read the same grey as everything else. (The
   TV chat hit it too, on the card that carries their DROPPED badge.)
   So: the tile keeps its own opacity, takes tokens.css's empty-seat look
   (`player-paper-card--empty`, line 942) and fades its children — leaving a
   ghost of the person's picture in a seat that is visibly vacant. */
#screen-between-rounds .between-ready-tile--dropped {
  background: rgba(244, 233, 206, 0.45);
  border-color: rgba(26, 22, 19, 0.4);
  border-style: dashed;
  box-shadow: none;
}
#screen-between-rounds .between-ready-tile--dropped > :not(.between-ready-tile__status) {
  opacity: 0.4;
  filter: grayscale(0.9);
}
#screen-between-rounds .between-ready-tile--dropped .between-ready-tile__avatar {
  border-style: dashed;
}
/* The word is what the screen is for, so it is the one thing at full strength
   — and coral, the same colour as the lobby's "· 1 dropped" and the TV's
   badge. One word, one colour, everywhere. */
#screen-between-rounds .between-ready-tile--dropped .between-ready-tile__status {
  color: var(--lobby-coral, #E86B6B);
  opacity: 1;
}

/* ---- SAFETY (App Store guideline 1.2) ---------------------------------- */

/* The agreement screen. Deliberately plain and short: the full rules are a
   tap away, and a wall of text on a phone is a wall nobody reads. */
/* Every other screen's title sits next to a 44 pt back button, which is what
   holds it off the edge. This one has no back button (there is nowhere to go
   back to) so it needs the gutter itself, and the stroke on the type means
   flush-left actually clips the B. */
#screen-terms .screen-top--center { padding-left: 4px; padding-right: 4px; }
#screen-terms .terms-rule {
  font-size: 0.95rem;
  text-align: center;
  line-height: 1.35;
}
#screen-terms .terms-list {
  list-style: none;
  padding: 0;
  margin: 4px 0 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}
#screen-terms .terms-list li {
  font-family: 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--lobby-paper);
  padding-left: 1.2em;
  position: relative;
  line-height: 1.35;
}
#screen-terms .terms-list li::before {
  content: '✕';
  position: absolute;
  left: 0;
  color: var(--lobby-coral, #E86B6B);
  font-weight: 900;
}
#screen-terms .terms-note {
  font-family: 'Nunito', sans-serif;
  font-size: 0.85rem;
  line-height: 1.35;
  color: var(--lobby-paper-warm);
  opacity: 0.9;
  text-align: center;
  margin: 4px 0 0;
}
#screen-terms .terms-links,
.landing-links {
  font-family: 'Nunito', sans-serif;
  font-size: 0.85rem;
  color: var(--lobby-paper-warm);
  text-align: center;
  margin: 0;
  display: flex;
  gap: 10px;
  justify-content: center;
  align-items: center;
}
/* 44 pt is Apple's minimum and these are the links a reviewer taps. The row
   stays visually small; the tap target does not. */
#screen-terms .terms-links a,
.landing-links a {
  color: var(--lobby-paper);
  text-decoration: underline;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 0 4px;
}
.landing-links { margin-top: 2px; }

/* The rejoin screen's way out. Quiet on purpose: it is on screen during every
   healthy rejoin, so it must not read as the way in. Still a full 44px tap. */
.reconnect-exit-link {
  margin-top: 1.75rem;
  background: none;
  border: 0;
  font-family: 'Nunito', sans-serif;
  font-size: 0.9rem;
  color: var(--lobby-paper);
  text-decoration: underline;
  min-height: 44px;
  padding: 0 12px;
  cursor: pointer;
}

/* A sender's name in group chat is the way in to report or block them, so it
   is a button. It has to keep looking exactly like the name it replaced. */
.paper-card__name--actionable {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
  /* The bubble is small, so the 44 pt target is the row, not the glyphs. */
  min-height: 24px;
  display: block;
}
.paper-card__name--actionable::after {
  content: ' ⋯';
  opacity: 0.55;
  font-weight: 900;
}

/* The ⋯ in a DM thread's top bar. */
.msg-actions {
  flex: none;
  min-width: 44px;
  min-height: 44px;
  background: none;
  border: 0;
  color: inherit;
  font-size: 1.4rem;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
}
.msg-actions.hidden { display: none; }

/* The sheet opens OVER a full-screen chat / DM (z-index 200), which every
   other sheet never does — openMessageScreen closes them. So while a message
   screen is up, this one and the scrim have to clear it. */
body.msg-open #sheet-player-actions { z-index: 220; }
body.msg-open #sheet-player-actions.is-open ~ #sheet-scrim,
body.msg-open #sheet-scrim { z-index: 210; }

#sheet-player-actions .pa-reason-label {
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 0.9rem;
  color: var(--lobby-ink);
  margin: 0 0 8px;
  text-align: center;
}
#sheet-player-actions .pa-reasons {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#sheet-player-actions .pa-reason {
  font-family: 'Nunito', sans-serif;
  font-weight: 800;
  font-size: 0.95rem;
  min-height: 48px;
  padding: 0 14px;
  border: 2.5px solid var(--lobby-ink);
  border-radius: 12px;
  background: var(--lobby-paper);
  color: var(--lobby-ink);
  box-shadow: 0 3px 0 0 var(--lobby-ink);
  cursor: pointer;
}
#sheet-player-actions .pa-reason:active {
  transform: translateY(3px);
  box-shadow: 0 0 0 0 var(--lobby-ink);
}
#sheet-player-actions .pa-done {
  font-family: 'Nunito', sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.4;
  color: var(--lobby-ink);
  text-align: center;
  margin: 0;
}
