/* WordRails — one hand-written stylesheet.

   Everything is sized in rem so browser zoom scales the whole interface. The
   play screen keeps one complete square that grows with a tall window up to a
   bounded cap. Phones can enlarge the board and pan for precise placement. */

/* Nunito, self-hosted. Copyright 2014 The Nunito Project Authors
   (https://github.com/googlefonts/nunito). Licensed under the SIL Open Font
   License 1.1; the full text ships beside the font files in
   app/assets/stylesheets/fonts/Nunito-OFL.txt. Files are the Latin subsets
   Google Fonts serves for the "Nunito" family, variable weight 200-1000. */
@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 200 1000;
  font-display: swap;
  src: url("/assets/fonts/nunito-latin-a6de09cc.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 200 1000;
  font-display: swap;
  src: url("/assets/fonts/nunito-latin-ext-6e74a3a2.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --button-bevel: inset 0 1px 1px #ffffff66, inset 0 -2px 2px #00000026, 0 2px 0 #0000001a;
  --cream: #fbf3e6;
  --cream-deep: #f2e5d1;
  --paper: #fffcf6;
  --ink: #3b2a45;
  --ink-soft: #6d5b76;
  --plum: #6a3d73;
  --plum-deep: #4d2a56;
  --teal: #2e7d74;
  --teal-soft: #d9ebe7;
  --coral: #b8452f;
  --coral-deep: #9c3823;
  --coral-soft: #fbdfd6;
  --lavender: #7f6fb5;
  --lavender-soft: #e9e3f8;
  --gold: #b8821c;
  --gold-soft: #fbeecb;
  --tile-face: #fffaf0;
  --tile-edge: #e0c9a2;
  --line: #e6d8c6;
  --font-friendly: "Nunito", ui-rounded, "SF Pro Rounded", "Segoe UI", system-ui, sans-serif;

  --radius-lg: 18px;
  --radius: 12px;
  --radius-sm: 8px;

  --shadow-sm: 0 1px 2px rgba(59, 42, 69, 0.12);
  --shadow-md: 0 4px 12px rgba(59, 42, 69, 0.14);
  --shadow-tile: 0 2px 0 var(--tile-edge), 0 3px 6px rgba(59, 42, 69, 0.14);

  --tile: 3.3rem;
}

html {
  font-size: 17px;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  background-color: #f5efe1;
  background-image: linear-gradient(180deg, #fcf9f2 0%, #f9f4ea 55%, #f5efe1 100%);
  background-repeat: no-repeat;
  color: var(--ink);
  font-family: var(--font-friendly);
  font-size: 1rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  margin: 0;
  line-height: 1.25;
}

p {
  margin: 0;
}

ul,
ol,
dl,
dd {
  margin: 0;
}

code {
  background: var(--cream-deep);
  border-radius: 6px;
  padding: 0.1em 0.35em;
}

:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--plum-deep);
  color: #fff;
  padding: 0.6rem 1rem;
  z-index: 100;
}

.skip-link:focus {
  left: 0.5rem;
  top: 0.5rem;
}

/* primitives: shared heading, buttons, fields, icons, and helpers. */

.section-heading {
  font-size: 1.05rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  margin-bottom: 0.6rem;
}

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

.button {
  appearance: none;
  box-shadow: var(--button-bevel);
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.6rem 1.05rem;
  min-height: 2.85rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  cursor: pointer;
  text-decoration: none;
  transition: transform 120ms ease, box-shadow 120ms ease, background-color 120ms ease;
}

.button:hover:not(:disabled) {
  box-shadow: var(--button-bevel), var(--shadow-md);
  transform: translateY(-1px);
}

.button:active:not(:disabled) {
  transform: translateY(0);
  box-shadow: var(--shadow-sm);
}

.button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.button--primary {
  background: var(--plum);
  border-color: var(--plum-deep);
  color: #fff;
}

.button--secondary {
  background: var(--paper);
  border-color: var(--line);
  color: var(--ink);
}

.button--danger {
  background: var(--coral);
  border-color: var(--coral-deep);
  color: #fff;
}

.button--quiet {
  box-shadow: none;
  background: transparent;
  border-color: transparent;
  color: var(--plum);
  min-height: 2.3rem;
  padding: 0.35rem 0.6rem;
}

.button--quiet:hover:not(:disabled) {
  background: var(--cream-deep);
  box-shadow: none;
}

.button--wide {
  width: 100%;
}

.button--letter {
  background: var(--paper);
  border-color: var(--line);
  min-height: 2.9rem;
  min-width: 2.9rem;
  padding: 0.4rem;
  font-size: 1.1rem;
}

.button--play {
  background: var(--coral);
  border-color: var(--coral-deep);
  color: #fff;
  font-size: 1.2rem;
  padding: 0.9rem 1.6rem;
  min-height: 3.6rem;
  width: 100%;
  max-width: 28rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.icon {
  width: 1.15rem;
  height: 1.15rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: 0 0 auto;
}

.field {
  display: grid;
  gap: 0.35rem;
}

.field__label {
  font-weight: 700;
  color: var(--ink-soft);
}

.input {
  font: inherit;
  padding: 0.65rem 0.8rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--paper);
  min-height: 2.85rem;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ui icons: the few reused decorative glyphs, sized in rem and inert to the
   pointer so a glyph never steals a tap from the control it sits in. */

.ui-icon {
  width: 1.15rem;
  height: 1.15rem;
  flex: none;
  display: block;
  color: inherit;
  pointer-events: none;
}
i.ui-icon { font-size: 1.15rem; line-height: 1; text-align: center; }

/* header: the site header shell and brand, the lobby/board/onboarding header
   variants, the signed-in nav row, the account panel, and notifications. */

.site-header {
  position: relative;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  max-width: 68rem;
  margin: 0 auto;
  padding: 0.85rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  color: var(--plum-deep);
}

.brand__icon {
  width: 2.6rem;
  height: 2.1rem;
  flex: none;
  display: block;
}

.brand__name {
  font-size: 1.4rem;
  font-weight: 850;
  letter-spacing: 0;
}

.site-main {
  max-width: 68rem;
  margin: 0 auto;
  padding: 1.5rem 1.5rem 3rem;
}

.site-footer {
  max-width: 68rem;
  margin: 0 auto;
  padding: 0 1.5rem 2.5rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

:is(.home-page, .game-page) .site-header { background: transparent; --plum-deep: #4d2a56; --ink-soft: #6d5b76; --paper: #fffcf6; --line: #e6d8c6; }

.onboarding .site-header {
  background: transparent;
  border-bottom-color: #eadcc4;
}

.onboarding .site-header__inner {
  max-width: 58rem;
}

.onboarding--entry .site-header { border: 0; }
.onboarding--entry .site-header__inner {
  justify-content: center;
  padding: 2.4rem 1rem 1.6rem;
}
.onboarding--entry .brand { gap: 1.25rem; }
.onboarding--entry .brand__name { font-size: clamp(2rem, 4vw, 3.15rem); }
.onboarding--entry .brand__icon { width: 5.5rem; height: 4.7rem; }

@media (max-width: 600px) {
  .onboarding .site-header__inner { padding-inline: 1rem; }
  .onboarding--entry .site-header__inner { padding-block: 1.5rem 0.75rem; }
  .onboarding--entry .brand { gap: 0.65rem; }
  .onboarding--entry .brand__icon { width: 3.5rem; height: 3rem; }
}

/* The signed-in header is the same chrome in the lobby and on the board. */

/* The lobby header and the lobby main share one outer grid: the same horizontal
   gutter, and a max width wide enough that the header content, the game
   rows/section and the Start panel all share one left/right edge. The fallbacks
   keep the board and every other signed-in page at the old 82rem/1.5rem. */
:is(.home-page, .game-page) .site-header__inner { max-width: calc(var(--lobby-max, 79rem) + 2 * var(--lobby-gutter, 1.5rem)); gap: 1rem; padding: 0.9rem var(--lobby-gutter, 1.5rem); }
:is(.home-page, .game-page) .brand { color: #4d2a56; }
:is(.home-page, .game-page) .brand__icon { width: 44px; height: 44px; }
:is(.home-page, .game-page) .brand__name { font-size: 1.5rem; }
:is(.home-page, .game-page) .button--quiet { min-height: 44px; }

/* Notification menu overlays header instead of changing header height. */
.notification-menu { position: relative; flex: 0 0 auto; font-size: .95rem; }
.notification-menu .notification-menu__toggle { border: 0; background: transparent; font: inherit; display: flex; align-items: center; min-height: 2.4rem; padding: .35rem .5rem; cursor: pointer; list-style: none; color: var(--plum-deep); font-weight: 750; white-space: nowrap; border-radius: var(--radius-sm); }
.notification-menu .notification-menu__toggle::after { content: "▾"; margin-left: .35rem; font-size: .8em; }
.notification-menu[open] .notification-menu__toggle { background: var(--cream-deep); }
.notification-menu:not([open]) .notification-menu__content, .notification-menu__content[hidden] { display: none; visibility: hidden; pointer-events: none; }
.notification-menu__content { position: absolute; z-index: 40; top: calc(100% + .35rem); right: 0; width: min(22rem, calc(100vw - 1rem)); padding: .65rem .75rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); box-shadow: var(--shadow-md); }
.notification-list { margin: 0; padding: 0; list-style: none; }
.notification-menu .notification-list { max-height: min(18rem, 50vh); overflow: auto; }
.notification-list li { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .65rem 0; border-bottom: 1px solid var(--line); }
.notification-list li:last-child { border-bottom: 0; }
.notification-list li.is-read { color: var(--ink-soft); }
.notification-list p { min-width: 0; overflow-wrap: anywhere; }
.notification-list__open { flex: 0 0 auto; min-height: 44px; padding: .2rem .45rem; font-size: .9rem; white-space: nowrap; }
.notification-menu__links { display: flex; gap: .75rem; padding-top: .55rem; border-top: 1px solid var(--line); font-size: .9rem; }
.notification-menu__links a { display: inline-flex; align-items: center; gap: .4rem; min-height: 44px; color: var(--plum); font-weight: 700; }
.notification-update:not([hidden]) { position: fixed; z-index: 80; top: auto; bottom: calc(max(1rem, env(safe-area-inset-bottom)) + var(--flash-banner-height, 0px)); left: auto; right: max(1rem, env(safe-area-inset-right)); width: min(28rem, calc(100% - 2rem)); margin: 0; padding: 1.1rem 1.25rem; display: flex; gap: .75rem; align-items: center; background: #176f63; border: 1px solid #11584f; border-radius: var(--radius); box-shadow: var(--shadow-md); color: #fffdf7; font-size: 1rem; font-weight: 700; }
.notification-update > span { min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; }
.notification-update[hidden], .notification-update__message { display: none; }
.notification-update form { margin: 0; }
.notification-update__open { min-height: 44px; padding: .4rem .6rem; background: #fff7e9; border-color: #d9c7a5; color: #14584f; white-space: nowrap; }
.notification-update__dismiss { flex: 0 0 44px; min-height: 44px; padding: 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: inherit; font: inherit; font-size: 1.5rem; cursor: pointer; }
.notification-update__dismiss:hover { background: #ffffff24; }
.notification-update__dismiss:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }
.game-page .notification-update:not([hidden]) {
  position: absolute;
  top: auto;
  right: auto;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  box-shadow: none;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  pointer-events: none;
}
@media (max-width: 600px) {
  body:not(.game-page) .notification-update:not([hidden]) {
    position: fixed; flex: none; margin: 0; padding: 6px 10px;
    display: grid; grid-template-columns: minmax(0, 1fr) 44px; gap: 8px;
    background: #edf7f3; border-color: #b7d9ce; color: #17574a;
    border-radius: 10px; box-shadow: none; font-size: 1rem; line-height: 1.35;
  }
  body:not(.game-page) .notification-update__copy, .notification-update__action-label { display: none; }
  .notification-update__message { display: inline; }
  .notification-update form { min-width: 0; }
  .notification-update .notification-update__open {
    width: 100%; padding: 0; border: 0; border-radius: 4px; background: none;
    color: inherit; box-shadow: none; font-size: 1rem; font-weight: 650; line-height: 1.35;
    text-align: left; white-space: normal; justify-content: start; overflow-wrap: anywhere;
  }
  .notification-update .notification-update__open:hover:not(:disabled) { box-shadow: none; transform: none; text-decoration: underline; }
  .notification-update__dismiss { width: 44px; }
  .notification-update__dismiss:focus-visible { outline-color: #17574a; }
}
.notification-page { max-width: 38rem; margin: 2rem auto; font-size: 1.15rem; }
.notification-page h1 { font-size: 2rem; }
.notification-page h2 { font-size: 1.4rem; }
.notification-settings-actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.notification-settings-actions .button { min-height: 56px; font-size: 1.15rem; }
.notification-note { font-size: 1rem; }
.notification-menu .notification-menu__toggle:focus-visible { outline: 3px solid #267e74; outline-offset: 3px; border-radius: .3rem; }

.notification-settings-actions [hidden] { display: none; }

.notification-page p { margin: .85rem 0; }

.notification-menu__summary { display: inline-flex; align-items: center; gap: .35rem; }

.notification-page__action { display: inline-flex; align-items: center; gap: .4rem; }

/* ------------------------------------------------------ shared header nav
   The signed-in header is three clear groups on one row at every width:
   the brand on the left, and a right-aligned cluster of the standalone My Games
   link, Notifications disclosure and compact Account disclosure. Settings and
   Sign out always live inside that account panel, so there is one DOM node and
   no mode to switch between: the panel is a dropdown at every width, opened by
   the existing 44px icon trigger. Nothing is rendered twice, so the
   notifications controller keeps its single set of targets. The panel sits
   out of flow so opening it cannot shift the row, and the header keeps its
   own z-index to stay above the positioned board squares it drops over. */
.header-menu.site-header {
  z-index: 50;
}

.header-menu .site-header__inner {
  position: relative;
  max-width: calc(var(--lobby-max, 79rem) + 2 * var(--lobby-gutter, 1.5rem));
  padding: 0.9rem var(--lobby-gutter, 1.5rem);
  flex-wrap: nowrap;
  align-items: center;
}

.header-menu .brand__icon { width: 44px; height: 44px; }

.header-menu .brand {
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 44px;
}

.header-menu .brand__name {
  font-size: 1.5rem;
  white-space: nowrap;
}

.site-header__games {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: 44px;
  flex: none;
  margin-left: auto;
  min-width: 44px;
  justify-content: center;
  color: var(--plum-deep);
  font-size: 1.05rem;
  font-weight: 750;
  text-decoration: none;
  white-space: nowrap;
}
.site-header__games:hover { text-decoration: underline; }
.site-header__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: var(--plum-deep);
  color: #fffdf7;
  font-size: 1rem;
  line-height: 1.2;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.site-header__games:focus-visible { outline: 3px solid var(--teal); outline-offset: 2px; border-radius: 4px; }

/* The Notifications disclosure is a sibling of the account panel, not one of
   its rows, so the bell stays on the row and rides with the account trigger on
   the right. Making it static hands its popover's absolute coordinates to the
   header row, which keeps the popover right-aligned and viewport-bounded at
   every width without a container query. */
.header-menu .notification-menu {
  position: static;
}

.header-menu .notification-menu__content {
  right: .75rem;
  left: auto;
  width: min(22rem, calc(100% - 1.5rem));
}

.header-menu .notification-menu .notification-menu__toggle {
  position: relative;
  min-height: 44px;
  min-width: 44px;
  justify-content: center;
  font-size: 1.05rem;
}
.header-menu .notification-menu .notification-menu__toggle::before {
  content: "";
  position: absolute;
  left: -.5rem;
  height: 28px;
  width: 1px;
  background: var(--line);
}
.header-menu .notification-menu .notification-menu__toggle::after { display: none; }

.header-menu__toggle {
  position: relative;
  display: inline-flex;
  flex: none;
  gap: .65rem;
  margin-left: .75rem;
  font: inherit;
  font-size: 1.05rem;
  font-weight: 750;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--plum-deep);
  cursor: pointer;
}

.header-menu__toggle::before {
  content: "";
  position: absolute;
  left: -1rem;
  height: 28px;
  width: 1px;
  background: var(--line);
}
.header-menu__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid #b6ded2;
  background: #daf3e9;
  color: #17574a;
  font-size: 1.35rem;
  font-weight: 800;
}
.header-menu__label { max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.header-menu__chevron { font-size: .75rem; }

.header-menu__toggle:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}

/* Account panel: one compact, right-aligned cream card, the same at every
   width. It is off flow, so opening it cannot move the row beneath it, and it
   never spans a desktop viewport. */
.header-menu .site-header__who {
  display: none;
  position: absolute;
  z-index: 60;
  top: calc(100% + .4rem);
  right: .75rem;
  left: auto;
  width: min(20rem, calc(100vw - 1.5rem));
  max-height: calc(100dvh - 5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: .35rem;
  margin: 0;
  padding: .7rem;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  color: var(--ink-soft);
  font-size: 1rem;
}

.header-menu.is-open .site-header__who {
  display: flex;
}

.header-menu .site-header__who > form {
  margin: 0;
}

.header-menu .site-header__who .button {
  justify-content: flex-start;
  width: 100%;
  min-height: 44px;
}

/* Narrow screens keep the train-only brand, the 44px icon-only bell and the 44px
   account trigger so the standalone My Games link still fits beside them. The
   "Notifications" word stays in the DOM for screen readers, so the summary
   keeps its accessible name. The compact row also fits browser zoom. */
@media (max-width: 950px) {
  .site-header__games-label { display: none; }
  .header-menu__label { display: none; }
  .header-menu__toggle { margin-left: 6px; gap: 4px; }
  .header-menu__toggle::before { left: -7px; }
  .header-menu__avatar { width: 36px; height: 36px; font-size: 1.1rem; }
  .header-menu .brand__name { display: none; }
  .header-menu .site-header__inner { padding: 8px var(--lobby-gutter, 12px); gap: 6px; }
  .header-menu .brand { gap: 6px; }
  .header-menu .brand__icon { width: 40px; height: 40px; }
  .site-header__games { font-size: 1rem; gap: .3rem; }
  .header-menu .notification-menu .notification-menu__toggle { padding-inline: 6px; }
  .header-menu .notification-menu .notification-menu__toggle::before { left: -3px; }
  .header-menu .notification-menu .ui-icon,
  .header-menu__toggle .ui-icon { width: 22px; height: 22px; font-size: 22px; }
  .notification-menu__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Very narrow phones need the last few pixels: a slightly smaller brand mark
   buys room for the My Games link, the bell and the account trigger without
   touching the row's target sizes. Lobby and board share the same chrome. */
@media (max-width: 380px) {
  .header-menu .site-header__inner { gap: .25rem; padding-inline: var(--lobby-gutter, 8px); }
  .site-header__games { font-size: .9rem; }
  .header-menu .notification-menu .notification-menu__toggle { padding-inline: 2px; }
  .header-menu .brand { gap: .35rem; }
  :is(.home-page, .game-page) .brand__icon { width: 32px; height: 32px; }
}

/* game: board-first play screen for older eyes. The board is the only
   responsive piece and stays one complete square: it takes the smaller of the
   available width and a bounded maximum that grows with the window's height,
   about 42px squares on a short window and larger on a tall one. The gaps
   between the major groups are deliberate whitespace, and nothing scrolls
   sideways, so the board overview stays whole. */

/* Reserve the scrollbar without adding an empty strip on the left edge. */
html:has(.game-page) { overflow-y: scroll; }
.game-page {
  --cream: #f9f5ec;
  --paper: #fffdf8;
  --ink: #2f2b41;
  --ink-soft: #5f5b71;
  --plum-deep: #33304a;
  --teal: #1f7a66;
  --teal-soft: #e2f2ea;
  --line: #e8dfcd;
  --tile-face: #fffdf6;
  --tile-edge: #d9c096;
  --tile-merged-face: #f7d96f;
  --tile-merged-edge: #c8a83f;
  --tile-latest-face: #f3b45b;
  --board-gap: 2px;
  /* 15 squares of about 42px plus their 2px gaps at the short-desktop floor.
     A tall window grows the square with the available height, but only up to a
     bounded ceiling, so the scores, rack, and actions stay beside the board and
     nothing is stretched to fill a window it does not need. */
  --board-max: clamp(660px, calc(100dvh - 26rem), 740px);
  --frame-pad: 3px;
  --frame-edge: 1px;
  --frame-extra: calc(2 * (var(--frame-pad) + var(--frame-edge)));
  --cluster-width: calc(var(--board-max) + var(--frame-extra) + 2.5rem);
  font-family: var(--font-friendly);
}

.game-page .site-main { max-width: var(--cluster-width); padding: 0.85rem 1.25rem 1.5rem; }
.game-page .flash:not(:has(p)) { display: none; }

/* Open page composition: no enclosing panel. The board frame, the rack tray,
   and the controls keep their own shapes; deliberate gaps do the separating:
   header 14 / scores 14 / board 18 / rack 18 / actions 24 / history. */
.game {
  position: relative;
  -webkit-user-select: none;
  user-select: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  width: min(100%, calc(var(--board-max) + var(--frame-extra)));
  margin: 0 auto;
}
.game input, .game textarea, .game [contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
}
.game > turbo-cable-stream-source { display: none; }
.game-page .flash .flash__message {
  padding: .55rem .75rem;
  border-radius: 10px;
  box-shadow: none;
  font-size: 1rem;
}
.game-page .flash__icon { flex-basis: 1.5rem; height: 1.5rem; font-size: 1rem; }
.game-scoreboard {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.85rem;
  width: 100%;
}
/* Phone-only route back to the lobby once the site header is hidden. */
.game-back { display: none; }
.players { display: contents; }
.player {
  grid-row: 1;
  justify-self: center;
  text-align: center;
  display: flex;
  align-items: center;
  width: 190px;
  max-width: 100%;
  height: calc(2.598rem + 2px);
  padding: 0 0.5rem;
}
.player--you { grid-column: 1; justify-self: start; }
.player--opponent { grid-column: 3; justify-self: end; }
.player__identity { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 0.9rem; }
.player--opponent .player__identity { flex-direction: row-reverse; }
.player__name { font-size: 1.25rem; font-weight: 650; line-height: 1.1; color: #46414f; white-space: nowrap; }
.player__score { display: flex; align-items: baseline; gap: 0.25rem; margin: 0; line-height: 1; white-space: nowrap; }
.player__number { font-size: 2.1rem; font-weight: 850; font-variant-numeric: tabular-nums; }
.player--you .player__number { color: #2b607f; }
.player--opponent .player__number { color: #a2543f; }
.game-status { grid-column: 2; grid-row: 1; justify-self: center; display: flex; flex-direction: column; align-items: center; gap: .6rem; min-width: 0; }
.game .game-scoreboard { min-height: 0; margin-bottom: .6rem; }
.game .board-tools { align-items: start; }
.tile-bag-count { margin: 0; text-align: center; white-space: nowrap; font-size: .8rem; line-height: 1.3; color: var(--ink-soft); }
.tile-bag-count strong { color: var(--plum-deep); font-variant-numeric: tabular-nums; }
.status-banner {
  position: relative;
  justify-self: center;
  grid-column: 2;
  grid-row: 1;
  display: inline-grid;
  justify-items: center;
  gap: 0.05rem;
  text-align: center;
  padding: 0.4rem 1.15rem;
  border-radius: 999px;
  border: 1px solid #e7ddc8;
  background: linear-gradient(#fffefb, #f5efe2);
  box-shadow: inset 0 1px 0 #fff, 0 1px 0 #e6dac3;
  color: var(--ink-soft);
}
.status-banner--turn {
  background: linear-gradient(#eaf8f1, #d9efe4);
  border-color: #b3dcc7;
  box-shadow: inset 0 1px 0 #fff, 0 1px 0 #b3dcc7;
  color: #17574a;
}
.status-banner--over { background: transparent; border: 0; box-shadow: none; border-radius: 0; padding: 0; }
.player--winner { background: #dcefe3; border: 1px solid #92c6aa; border-radius: 12px; height: auto; min-height: 52px; padding: .4rem .6rem; }
.player--winner .player__number { color: #17574a; }
.status-banner__headline { font-size: 1.25rem; font-weight: 800; line-height: 1.15; }
.status-banner__direction { position: absolute; right: calc(100% + 0.5rem); top: 50%; transform: translateY(-50%); font-size: 1.4rem; font-weight: 800; line-height: 1; }
.status-banner__direction--opponent { right: auto; left: calc(100% + 0.5rem); }
.status-banner__detail { font-size: 0.95rem; font-weight: 650; margin: 0; color: #4b4761; }

/* Board down to the rack band. */
.board-region { width: 100%; min-width: 0; margin-bottom: 1.05rem; }
.board-tools { display: grid; align-items: center; height: 3rem; margin-bottom: 6px; }
.board-tools > p { grid-area: 1 / 1; justify-self: center; max-width: 100%; min-width: 0; margin: 0; padding: .35rem .9rem; border-radius: 999px; font-size: 1.1rem; line-height: 1.4rem; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.board-tools > [hidden] { display: none; }
.board-latest-play { background: #e2eff8; box-shadow: inset 0 0 0 1px #afcadf; color: #285874; font-weight: 700; }
.board-word-error { background: #f7d7cf; box-shadow: inset 0 0 0 1px #d18e80; color: #7c2925; font-weight: 800; }
.board-zoom {
  display: none;
  font: inherit; font-size: 0.8rem; font-weight: 750; color: var(--teal);
  background: var(--paper); border: 1px solid var(--teal); border-radius: 8px;
  min-height: 44px; padding: 6px 10px; cursor: pointer;
}
.board-zoom:focus-visible { outline: 3px solid var(--teal); outline-offset: 2px; }
.board-viewport { width: 100%; aspect-ratio: 1; overflow: hidden; }
.board-viewport.is-zoomed { overflow: auto; overscroll-behavior: contain; }
.board-viewport.is-zoomed .board { width: 200%; }
.board-scroll {
  position: relative;
  overflow: visible;
  width: 100%;
  padding: var(--frame-pad);
  border: var(--frame-edge) solid #ceb98e;
  border-radius: 10px;
  background: linear-gradient(#eedfbe, #dfcba1);
  box-shadow: inset 0 1px 0 #fffdf4, inset 0 -2px 0 #d6c5a1, 0 2px 0 #d3c29c,
    0 8px 18px rgba(101, 83, 52, 0.16), 0 22px 40px rgba(101, 83, 52, 0.07);
}
.board {
  display: grid;
  grid-template-columns: repeat(15, 1fr);
  grid-template-rows: repeat(15, 1fr);
  gap: var(--board-gap);
  width: 100%;
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  background: #e2d3b4;
  border-radius: calc(10px - var(--frame-pad) - var(--frame-edge));
  container-type: inline-size;
}
.board__row { display: contents; }
.move-score {
  position: absolute; z-index: 8; pointer-events: auto; white-space: nowrap;
  padding: 2px 6px; border: 1px solid #b3dcc7; border-radius: 6px;
  background: #e2f2ea; color: #17574a; font-size: 18px; line-height: 20px;
  font-weight: 800; box-shadow: 0 2px 5px #14523f24;
}
.move-score[hidden] { display: none; }
.game.is-dragging .move-score,
.game:has(.tile.is-selected) .move-score { pointer-events: none; }

.square {
  appearance: none;
  font: inherit;
  padding: 0;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 7px;
  background: #fbf4e3;
  box-shadow: inset 1px 1px 0 #fffdf7, inset -1px -1px 0 #8e785322, inset 0 1px 2px #8e78531c;
  color: #46546a;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  cursor: pointer;
  transition: box-shadow 120ms ease, background-color 120ms ease;
}
.square:focus-visible { box-shadow: inset 0 0 0 3px #1f7a66; z-index: 3; }
@media (hover: hover) and (pointer: fine) {
  .square:hover:not(:disabled) { box-shadow: inset 0 0 0 3px #1f7a66; z-index: 3; }
}
.square:disabled { cursor: default; }
.square--double_letter { background: #d2e4f0; color: #305a75; box-shadow: inset 1px 1px 0 #ffffffb3, inset -1px -1px 0 #4d759020, inset 0 2px 3px #4d759012; }
.square--triple_letter { background: #b6d9ca; color: #23574c; box-shadow: inset 1px 1px 0 #ffffffb3, inset -1px -1px 0 #2f6d5d24, inset 0 2px 3px #2f6d5d12; }
.square--double_word { background: #f1d3c7; color: #8a4b3e; box-shadow: inset 1px 1px 0 #ffffffb3, inset -1px -1px 0 #a2604a20, inset 0 2px 3px #a2604a12; }
.square--triple_word { background: #e8a08c; color: #6b2a1d; box-shadow: inset 1px 1px 0 #ffffff9e, inset -1px -1px 0 #8d3f2c26, inset 0 2px 3px #8d3f2c14; }
.square--center { background: #f6e3ac; color: #7d5410; }
.square__premium, .square__star { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
/* cqw keeps the labels and the star in proportion at every board size; the
   clamps hold them near 17px on a full-size board and keep them legible when
   the board shrinks. */
.square__premium { font-size: clamp(14px, 2.6cqw, 18px); font-weight: 800; letter-spacing: 0.01em; text-shadow: 0 1px 0 #ffffff8c; }
.square__star { font-size: clamp(14px, 3.4cqw, 24px); text-shadow: 0 1px 0 #ffffff8c; }
.square.has-draft .square__premium, .square.has-draft .square__star { visibility: hidden; }
/* The square the tile would land on, and the square that already holds a
   tentative tile. Both are louder than a hover so an older player can see
   where the tile is about to go. */
.square.is-drop-target { box-shadow: inset 0 0 0 4px #15695a, 0 0 0 2px #ffffffcc; background: #cfeade; }
/* The destination square fills with a cell-sized ghost carrying the held
   letter, so the player sees both WHAT is going down and exactly WHERE. It is
   a real element (not a pseudo) so its letter and size can be asserted, and it
   renders above a tentative tile when the drop is a replacement. */
.square .tile--drop-ghost {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  background: linear-gradient(166deg, #f4f0ff, #ded3f6);
  border: 2px solid #6b53a8;
  border-bottom-color: #503b8c;
  box-shadow: inset 0 1px 0 #fff, 0 3px 0 #6d5aa8, 0 6px 10px #3d2f5c33;
  opacity: 0.92;
  pointer-events: none;
}
.square.is-drop-target .square__premium, .square.is-drop-target .square__star { visibility: hidden; }
/* A committed square under the finger is a clear "no", never a silent hop. */
.square.is-drop-invalid { box-shadow: inset 0 0 0 4px #b65246, 0 0 0 2px #ffffffcc; background: #f2d7d0; }
/* A committed tile fills its square (merged tiles fill it edge to edge), which
   hides the inset shadow above. Paint the invalid "no" as an overlay so it
   stays visible on top of the letter and tile, without redirecting the drop. */
.square.is-drop-invalid::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 4;
  border-radius: inherit;
  border: 4px solid #b65246;
  box-shadow: 0 0 0 2px #ffffffcc;
  background: #b6524626;
  pointer-events: none;
}
.square.has-draft { background: #e3d9f4; }

.tile {
  width: var(--tile);
  height: var(--tile);
  flex-shrink: 0;
  font: inherit;
  border-radius: 10px;
  background: linear-gradient(166deg, #fffdf7, #fff2d8);
  border: 1px solid var(--tile-edge);
  border-top-color: #fffef9;
  border-bottom: 2px solid #cdae74;
  box-shadow: inset 1px 1px 0 #ffffffd9, inset -1px -1px 0 #bc965b29, 0 2px 0 #c3a771, 0 5px 8px #5c492229;
  color: var(--plum-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  font-weight: 700;
}
.tile__letter { font-size: 1.9rem; font-weight: 700; line-height: 1; }
.tile__points { position: absolute; right: 5px; bottom: 2px; font-size: 0.85rem; font-weight: 750; line-height: 1; color: #3f4053; }
/* Board tiles are sized by their square; rack tiles keep a fixed size. */
.board .tile { width: 88%; height: 88%; }
.board .tile__letter { font-size: 4.1cqw; transform: translate(-2px, -2px); }
.board .tile__points { right: 5%; bottom: 3%; font-size: clamp(12px, 2.15cqw, 15px); }
/* touch-action: none belongs on the draggable tile itself and must be present
   from the start of a touch: the browser decides gesture ownership before any
   JS drag threshold runs, so it cannot be applied later. This suppresses
   native scrolling only for a gesture that begins on a tile; page scrolling
   and board panning stay available everywhere else. The .is-dragging class
   does not own scrolling. */
.tile--rack { appearance: none; cursor: grab; touch-action: none; }
.tile--rack:hover:not(:disabled) { transform: translateY(-4px); box-shadow: inset 1px 1px 0 #ffffffd9, inset -1px -1px 0 #bc965b29, 0 4px 0 #c3a771, 0 9px 14px #5c492233; }
.tile--rack:disabled { cursor: default; }
/* Choosing a tile has to be unmistakable: a thick ring, a tinted face, and a
   clear lift, not a one-pixel colour change. */
.tile--rack.is-selected {
  outline: 4px solid #10695a;
  outline-offset: 3px;
  transform: translateY(-6px);
  background: linear-gradient(166deg, #dff3e6, #c6e8d3);
  border-color: #1c7d69;
  box-shadow: inset 0 1px 0 #fff, 0 6px 0 #1a705f, 0 12px 18px #1b5f4d3d;
}
.tile--rack.is-lifted, .tile--rack.is-drag-source { visibility: hidden; }
.tile--played {
  z-index: 1;
  background: linear-gradient(166deg, #ffed9c, #f2d363);
  border-color: #c8aa43;
  border-top-color: #fff7ce;
  border-bottom-color: #b39432;
  box-shadow: inset 1px 1px 0 #fff9dccc, inset -1px -1px 0 #b3943233, 0 2px 0 #b39432, 0 5px 8px #69502529;
}
.tile--latest-play {
  background: var(--tile-latest-face);
  outline: none;
  filter: none;
}
.tile--latest-play.is-word-settling {
  animation: word-settle 480ms cubic-bezier(.22, 1, .36, 1) var(--word-delay, 0ms) both;
}
@keyframes word-settle {
  0% { transform: translateY(-18%) scale(.88); filter: brightness(1.22); }
  62% { transform: translateY(0) scale(1.045); filter: brightness(1.12); }
  100% { transform: none; filter: none; }
}
/* A committed tile that touches another committed tile joins it into one gold
   surface. The tile keeps its letter and points but swaps its raised face for a
   flat one, drops the bevel and outline on the sides it shares, and grows by
   half the board gap so the faces meet with no seam. Neighbour classes are
   rendered by the server, one per shared side and never on a diagonal. */
#game-board .tile--played.tile--merged {
  position: absolute;
  inset: calc(var(--board-gap) * -0.5);
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  background: var(--tile-merged-face);
  box-shadow: none;
  outline: none;
}
#game-board .tile--merged:not(.tile--join-up) { border-top: 1px solid var(--tile-merged-edge); }
#game-board .tile--merged:not(.tile--join-down) { border-bottom: 1px solid var(--tile-merged-edge); }
#game-board .tile--merged:not(.tile--join-left) { border-left: 1px solid var(--tile-merged-edge); }
#game-board .tile--merged:not(.tile--join-right) { border-right: 1px solid var(--tile-merged-edge); }
#game-board .tile--merged:not(.tile--join-up):not(.tile--join-left) { border-top-left-radius: 10px; }
#game-board .tile--merged:not(.tile--join-up):not(.tile--join-right) { border-top-right-radius: 10px; }
#game-board .tile--merged:not(.tile--join-down):not(.tile--join-left) { border-bottom-left-radius: 10px; }
#game-board .tile--merged:not(.tile--join-down):not(.tile--join-right) { border-bottom-right-radius: 10px; }
/* The latest word uses a warm orange face while keeping the joined geometry. */
#game-board .tile--latest-play.tile--merged {
  background: var(--tile-latest-face);
  filter: none;
}
/* Played blanks keep their zero-point label without breaking the word outline. */
#game-board .tile--played.tile--merged.tile--blank { border-style: solid; }
#game-board .tile--played.tile--merged.tile--blank::after { content: none; }
/* A tentative tile is tinted, outlined, and raised, so it never reads as a
   committed board tile. */
.tile--draft {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  cursor: grab;
  touch-action: none;
  background: linear-gradient(166deg, #f2edff, #ded3f6);
  border: 2px solid #6b53a8;
  border-bottom-color: #503b8c;
  box-shadow: inset 0 1px 0 #fff, 0 3px 0 #6d5aa8, 0 7px 11px #3d2f5c33;
}
.tile--draft.is-selected { outline: 4px solid #10695a; outline-offset: 2px; transform: translate(-50%, -50%) translateY(-3px); box-shadow: inset 0 1px 0 #fff, 0 5px 0 #6d5aa8, 0 10px 16px #3d2f5c45; }
.tile--draft.is-invalid {
  background: linear-gradient(166deg, #fff0eb, #f3c7bf);
  border-color: #b65246; border-bottom-color: #953e35;
  box-shadow: inset 0 1px 0 #fff, 0 3px 0 #ad574b, 0 7px 11px #66322933;
}
.square:has(.tile--draft.is-invalid) { background: #f2d7d0; }
.tile--blank { border-style: dashed; }
.tile--blank::after { content: ""; position: absolute; left: 3px; top: 3px; width: 4px; height: 4px; border-radius: 50%; background: #8a719c; }
.tile--small { width: 2.6rem; height: 2.6rem; }
.tile--small .tile__letter { font-size: 1.55rem; }
/* The lifted preview floats above a touch finger purely for visibility, or at
   the mouse pointer on desktop. Targeting and release use the finger, never
   this point. Desktop mouse keeps the familiar lighter ghost; a touch finger
   gets a nearly solid tile so the held letter reads over the board. The
   destination ghost, not this preview, communicates precision. */
.tile--ghost { position: fixed; width: 3.4rem; height: 3.4rem; transform: translate(-50%, -50%) rotate(-2deg) scale(1.06); pointer-events: none; z-index: 60; opacity: 0.5; box-shadow: inset 0 1px 0 #fff, 0 4px 0 #b89d6b, 0 16px 26px #35283b52; }
.tile--ghost.tile--ghost--touch { opacity: 0.95; }
.tile--ghost .tile__letter { font-size: 2.3rem; }
/* The original slot stays visible but faded, so the tile reads as being moved. */
.tile--draft.is-drag-source { opacity: 0.5; }
.tile__letter--blank { color: #8c7751; }

/* minmax(0, 1fr) plus min-width: 0 on the spanning items keeps the play area,
   the rack band, and the action row exactly as wide as the board frame. */
.play-area { width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; justify-items: center; }
/* The rack sits in its own band under the board; the 18px gap above it keeps
   the tray from reading as part of the board frame. The band is named for
   assistive technology with a visually hidden heading, not an on-screen one. */
.rack-action-row { grid-column: 1 / -1; grid-row: 2; display: flex; justify-content: center; align-items: stretch; gap: 1rem; width: 100%; min-width: 0; }
.rack-region { display: flex; justify-content: center; flex: 1 1 0; min-width: 0; }
.rack {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 0.5rem;
  justify-content: center;
  align-items: center;
  width: 100%;
  padding: 6px 0.9rem 8px;
  border-radius: 16px;
  border: 1px solid #cdb488;
  border-top-color: #e4cda2;
  background: linear-gradient(#e9cd9c, #f2ddb9);
  box-shadow: inset 0 1px 0 #fff3da, inset 0 4px 8px #8a623026, inset 0 -4px 0 #d3b07a, 0 2px 0 #bf9c6b, 0 5px 10px #493c2422;
  container-type: inline-size;
}
/* Tiles fill the tray, so the rack hugs its seven letters at any size. */
.rack .tile { width: 100%; height: auto; aspect-ratio: 1 / 1; }
.rack .tile__letter { font-size: clamp(28px, 7.5cqw, 34px); }
.rack .tile__points { right: 7%; bottom: 5%; font-size: clamp(14px, 3.3cqw, 16px); }
.rack.is-drop-target { outline: 3px solid var(--teal); outline-offset: 2px; }
.rack .is-insert-before::before, .rack .is-insert-after::before {
  content: ""; position: absolute; top: 3px; bottom: 3px; width: 4px;
  border-radius: 2px; background: #10695a; box-shadow: 0 0 0 1px #fffdf6;
  pointer-events: none;
}
.rack .is-insert-before::before { left: -7px; }
.rack .is-insert-after::before { right: -7px; }

.rack__empty { grid-column: 1 / -1; text-align: center; }
/* Utility actions stay in a compact row below the rack and GO. */
.action-bar { grid-column: 1 / -1; grid-row: 4; margin-top: 1.05rem; display: flex; width: 100%; max-width: 100%; min-width: 0; justify-content: center; align-items: center; gap: 1.3rem; flex-wrap: wrap; }
.controls { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); align-items: stretch; gap: 0.5rem; width: 100%; min-width: 0; }
.game:not(.is-your-turn) .controls { display: none; }
/* Soft filled capsules with a lower edge, so the row reads as game pieces
   rather than a toolbar of outlined product buttons. Icons accompany labels. */
.controls .button, .game-options > .button, .game-chat--floating .game-chat__panel:not([open]) .game-chat__summary {
  width: 100%;
  font-size: 1.2rem;
  font-weight: 800;
  line-height: 1.25;
  min-height: 62px;
  min-width: 5.3rem;
  padding: 0.55rem 0.7rem;
  gap: 0.45rem;
  border-radius: 14px;
  border: 1px solid #e7dcc6;
  border-bottom: 2px solid #dbcdb1;
  background: linear-gradient(#fffdf7, #f7efdd);
  color: var(--ink);
  box-shadow: inset 0 1px 0 #fff, 0 3px 0 #ddccaa, 0 5px 9px #6b583514;
}
.button__icon { display: block; flex: 0 0 auto; width: 22px; height: 22px; pointer-events: none; }
.controls .button:hover:not(:disabled) {
  background: linear-gradient(#fffefb, #fbf4e6);
  box-shadow: inset 0 1px 0 #fff, 0 4px 0 #e3d6bb, 0 8px 14px #6b583518;
  transform: translateY(-1px);
}
.controls .button:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: inset 0 2px 3px #b8a58338, 0 1px 0 #e5d6b9;
}
.game-page .button:disabled { opacity: 1; cursor: default; }
.controls .button:disabled {
  color: #6f6a58;
  border-color: #e7dfd0;
  border-bottom-color: #e3dbca;
  background: linear-gradient(#f5f2e9, #eeeadf);
  box-shadow: inset 0 1px 0 #fffaf0, 0 2px 0 #e6e0d2;
  transform: none;
}
/* Primary play action. */
.preview { position: relative; display: flex; align-items: stretch; flex: 0 0 auto; }
.game-page .button--play {
  flex: 0 0 auto;
  margin-left: 0;
  width: auto;
  max-width: none;
  min-width: 8rem;
  min-height: 56px;
  gap: 0.45rem;
  padding: 0.7rem 1.05rem;
  border-radius: 18px;
  border: 1px solid #08644e;
  background: linear-gradient(#08795e, #056149);
  color: #fff;
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.25;
  box-shadow: inset 0 0 0 1px #ffffff26, 0 3px 7px #075a4626;
  white-space: nowrap;
}
.game-page .button--play:hover:not(:disabled) {
  background: linear-gradient(#078667, #056d52);
  transform: none;
  box-shadow: inset 0 0 0 1px #ffffff30, 0 4px 9px #075a4633;
}
.game-page .button--play:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: inset 0 1px 3px #0c3d3329, 0 1px 3px #075a4626;
}
.game-page .button--play:disabled {
  background: #e3e7e2;
  color: #929a93;
  border-color: #c9d0c9;
  border-bottom-color: #c9d0c9;
  box-shadow: none;
  cursor: not-allowed;
  transform: none;
}

.game-secondary { grid-column: 1 / -1; grid-row: 5; margin-top: 0.25rem; display: flex; gap: 0.5rem; align-items: center; width: 100%; color: var(--ink-soft); }
.game-play-dock .game-options:not([hidden]) { display: contents; }
.game-options > .button { grid-row: 3; min-width: 0; }
.game-options__back { grid-column: 1; }
.game-options__chat { grid-column: 2; }
.game-sound-toggle { grid-column: 3; }
.game-resign { grid-column: 4; }
.game-nudge__button { min-height: 44px; font-size: .85rem; padding: 6px 10px; }
.game-nudge__button > span { width: 4em; flex-shrink: 0; text-align: center; }
.game-options > .button .ui-icon { width: 22px; height: 22px; font-size: 22px; }
.game-options > .game-options__back { background: linear-gradient(#edf6fc, #dcecf7); border-color: #b7d1e3; color: #285b76; }
.game-options > .game-sound-toggle { background: linear-gradient(#f0f8ed, #deeedb); border-color: #bcd3b5; color: #345d2d; }
.game-options > .game-resign { background: linear-gradient(#fbefea, #f5e3de); border-color: #dab4a9; color: #843e30; }

/* Rematch call to action: an empty, hidden target while the game is live, filled
   in place by the finishing response for both players. */
.game-rematch { width: 100%; display: flex; justify-content: center; margin: 0; }
.game-rematch[hidden], .game-rematch:empty { display: none; }
.game-rematch__button { min-height: 52px; padding-inline: 2rem; font-size: 1.2rem; }

/* Private chat opens from its action-row button; pending and finished notices stay in flow. */
.game-chat { width: 100%; min-width: 0; margin-top: 0.5rem; }
.game-chat__panel { border: 1px solid var(--plum-deep); border-radius: 12px; background: #fffdf8; overflow: hidden; }
.game-chat__summary { display: flex; align-items: center; gap: 0.5rem; justify-content: center; min-width: 9rem; min-height: 56px; padding: 0 1.1rem; font-weight: 750; color: #fffdf7; background: var(--plum-deep); cursor: pointer; list-style: none; }
.game-chat__summary::-webkit-details-marker { display: none; }
.game-chat__summary-title { display: inline-flex; align-items: center; gap: 0.5rem; }
.game-chat__unread { display: inline-flex; align-items: center; justify-content: center; min-width: 1.5rem; padding: 0.1rem 0.45rem; border-radius: 999px; background: #fffdf7; color: var(--plum-deep); font-size: 1rem; line-height: 1.2; font-weight: 800; font-variant-numeric: tabular-nums; }
.game-chat__unread[hidden] { display: none; }
.game-chat__panel:not([open]) .game-chat__summary { min-width: 11rem; min-height: 64px; font-size: 1.4rem; }
.game-chat__close-icon { display: none; }
.game-chat__panel[open] .game-chat__summary { justify-content: space-between; }
.game-chat__panel[open] .game-chat__close-icon { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; font-size: 1.3rem; }
.game-chat__summary .ui-icon { width: 1.4rem; height: 1.4rem; font-size: 1.4rem; }
@media (max-width: 600px) {
  .game-chat__panel:not([open]) .game-chat__summary { min-width: 6rem; min-height: 48px; padding-inline: .75rem; font-size: 1.06rem; }
  .game-chat__panel:not([open]) .game-chat__summary .ui-icon { width: 1.1rem; height: 1.1rem; font-size: 1.1rem; }
}
/* The panel clips its overflow, so a positive outline-offset would leave the
   summary focus ring half-hidden. An inset ring stays fully inside the bounds. */
.game-chat__summary:focus-visible { outline: 3px solid #267e74; outline-offset: -3px; }
.game-chat__body { display: grid; gap: 0.6rem; padding: 0.9rem; min-width: 0; }
.game-chat__note { margin: 0; color: var(--ink-soft); font-size: 1rem; overflow-wrap: anywhere; }
.game-chat__messages { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; max-height: 16rem; overflow-y: auto; overflow-wrap: anywhere; }
.game-chat__message { display: grid; gap: 0.1rem; min-width: 0; max-width: 100%; padding: 0.35rem 0.55rem; border-radius: 10px; background: #f4f0e6; }
.game-chat__author { font-weight: 750; color: var(--plum-deep); font-size: 1rem; }
.game-chat__text { white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; }
.game-chat__form { display: grid; gap: 0.5rem; min-width: 0; }
.game-chat__input { width: 100%; min-width: 0; max-width: 100%; min-height: 3rem; padding: 0.5rem 0.65rem; border: 1px solid var(--line); border-radius: 10px; font: inherit; resize: none; overflow-y: auto; box-sizing: border-box; }
.game-chat__input:focus-visible { outline: 3px solid #267e74; outline-offset: 2px; }
.game-chat__error { margin: 0; color: #7d2f1e; font-weight: 600; }
.game-chat__send { justify-self: end; min-height: 44px; font-size: inherit; }

/* Chat shares the secondary action row. The open panel floats so
   opening it never shifts the board or replaces a draft. */
.game:has(.game-chat--floating) { padding-bottom: 0; }
.game-chat--floating {
  position: relative;
  font-size: 1.2rem;
  grid-column: 2; grid-row: 3; align-self: stretch;
  width: 100%; min-width: 0; margin: 0; z-index: 60;
  display: flex; flex-direction: column;
}
.game-chat--floating .game-chat__panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  width: fit-content;
  max-width: 100%;
  max-height: min(var(--chat-room, calc(100dvh - 16px)), calc(100dvh - 16px));
}
.game-chat--floating .game-chat__panel[open] {
  position: absolute; left: 0; bottom: 0;
  width: min(22rem, calc(100vw - 32px)); max-width: none;
  transform-origin: bottom right;
  animation: chat-open 160ms ease-out;
}
.game-chat--floating .game-chat__panel[open].game-chat__panel--below {
  top: 0; bottom: auto; transform-origin: top right;
  animation-name: chat-open-below;
}
@keyframes chat-open {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes chat-open-below {
  from { opacity: 0; transform: translateY(-16px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .game-chat--floating .game-chat__panel[open] { animation: none; }
}
.game-chat--floating .game-chat__summary { flex: 0 0 auto; }
.game-chat--floating .game-chat__body {
  min-height: 0;
  max-height: min(calc(var(--chat-room, 100dvh) - 58px), calc(100dvh - 74px));
  /* A short viewport scrolls the whole body so the note and the reply controls
     can both be reached; the messages list keeps its own scroll on tall ones. */
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  align-content: start;
}
/* Cap the thread against the visible viewport so the input and Send stay on
   screen at 320px wide, short landscape, or high zoom. The 28rem reserve leaves
   room for the note, the form, and the panel's header/gutter chrome before the
   body itself has to scroll; 16rem remains the ceiling on a tall window. */
.game-chat--floating .game-chat__messages {
  max-height: min(16rem, max(2.5rem, calc(100dvh - 28rem)));
  min-height: 2.5rem;
}


/* While typing, reserve the composer and let only message history scroll. */
.game-chat--floating .game-chat__panel--composing .game-chat__body {
  height: min(24rem, calc(var(--chat-room) - 58px));
  grid-template-rows: minmax(0, 1fr) auto; padding: .6rem; overflow: hidden;
}
.game-chat__panel--composing .game-chat__note { display: none; }
.game-chat--floating .game-chat__panel--composing .game-chat__messages { min-height: 0; max-height: none; }

/* Chat stays outside the Turbo-replaced play area to preserve its draft. */
.game-play-dock { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; width: 100%; }
.game-play-dock .action-bar,
.game .game-play-dock .controls { display: contents; }
.game-play-dock .controls .button { grid-row: 2; }
.game-play-dock .play-area:not([hidden]) { display: contents; }
.game-play-dock .rack-action-row { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 1fr); grid-column: 1 / -1; grid-row: 1; gap: 8px; }
.game-play-dock .rack-region { grid-column: 1; grid-row: 1; }
.game-play-dock .preview { grid-column: 2; grid-row: 1; min-width: 0; width: 100%; }
.game-play-dock .button--play { width: 100%; min-width: 0; min-height: 64px; }
.game-play-dock .action-bar { grid-column: 1 / -1; grid-row: 2; margin-top: 0; }
.game-chat--floating .game-chat__panel:not([open]) { width: 100%; border: 0; background: transparent; overflow: visible; }
.game-chat--floating .game-chat__panel:not([open]) .game-chat__summary {
  position: relative; min-width: 0; width: 100%; min-height: 62px; padding: .55rem .7rem; font-size: 1.2rem;
  background: #e9e3f8; border-color: #cbbbe0; color: var(--plum-deep);
}

.game-chat--floating .game-chat__panel:not([open]) .game-chat__summary .ui-icon { width: 22px; height: 22px; font-size: 22px; }

@media (max-width: 950px) {
  .game-scoreboard { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 0.5rem; }
  .controls { justify-content: center; }
  .action-bar { justify-content: center; }
  .game-page .button--play { margin-left: 0; }
  .rack { gap: 0.45rem; padding-inline: 0.75rem; }
}
@media (max-width: 600px), (max-width: 950px) and (max-height: 500px) {
  .game-page .site-main { padding: 8px 12px 16px; }
  .game-scoreboard { gap: 8px; margin-bottom: 8px; }
  /* Phones stack each player's name over their score inside its own column,
     with the turn pill alone in the centre column and a clear gap between. */
  .player { width: 100%; min-width: 0; height: auto; padding-inline: 0; }
  .player__identity {
    min-width: 0; gap: 2px;
    flex-direction: column; align-items: stretch; justify-content: center;
  }
  .player--you .player__identity { text-align: left; }
  .player--opponent .player__identity { flex-direction: column; text-align: right; }
  .player__name {
    width: 100%; max-width: 100%; min-width: 0;
    overflow: hidden; text-overflow: ellipsis;
    font-size: clamp(0.8rem, 3.6vw, 1rem);
  }
  .player__score { flex-shrink: 0; }
  .player--you .player__score { justify-content: flex-start; }
  .player--opponent .player__score { justify-content: flex-end; }
  .player__number { font-size: 1.6rem; }
  .status-banner { max-width: 34vw; min-width: 0; padding: 6px 8px; }
  .status-banner__headline { max-width: 100%; font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .status-banner__direction { display: none; }
  .board-region { margin-bottom: 6px; }
  .board-zoom { display: inline-flex; position: absolute; top: 6px; right: 6px; z-index: 4; }
  .board-tools > p { font-size: 1rem; }
  .board .tile__points { display: none; }
  .board .tile__letter { font-size: 4.5cqw; transform: none; }
  .board .square__premium { font-size: clamp(8px, 2.6cqw, 14px); }
  .move-score { font-size: 12px; line-height: 14px; padding: 1px 3px; }
  .rack-action-row { flex-wrap: wrap; gap: 8px; }
  .rack-region { flex-basis: 100%; }
  .rack { gap: 5px; padding-inline: 6px; }
  .rack .tile__letter { font-size: clamp(22px, 7.5cqw, 30px); transform: translateY(-2px); }
  .rack .tile__points { font-size: clamp(10px, 3cqw, 14px); }
  .preview { width: 100%; }
  .game-page .button--play { min-width: 0; width: 100%; min-height: 56px; padding: 4px 12px; font-size: 1.5rem; }
  .action-bar { margin-top: 8px; }
  .controls { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
  .controls .button, .game-options > .button { flex-direction: column; gap: 3px; padding: 6px 2px; min-width: 0; font-size: 0.9rem; }
  /* Chat sits below the controls/options on phones, matching the desktop order
     it gets from the DOM; without this the flex default (0) floats it up. */
  .game-chat { order: 5; }
  .game-chat__messages { max-height: 12rem; }
  .preview__message:has(.preview__error:not(:empty)) {
    position: static; width: 100%; height: auto; clip: auto; white-space: normal;
    overflow: visible; order: 3; margin: 8px 0 0; padding: 10px 12px;
    border: 1px solid var(--line); border-radius: 10px; background: var(--paper);
  }
}

@media (max-width: 950px) and (max-height: 500px) and (orientation: landscape) {
  .game { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px 16px; width: 100%; align-items: start; }
  .game-scoreboard, .game > .flash { grid-column: 1 / -1; }
  .game-scoreboard { margin: 0; }
  .board-region { grid-column: 1; grid-row: 2 / span 3; margin: 0; }
  .board-scroll { width: min(100%, calc(100dvh - 156px)); margin: auto; }
  .game-play-dock, .preview__message, .game-options { grid-column: 2; }
}

/* Compact mobile game header and rack controls. */
@media (max-width: 600px) {
  html:has(.game-page) { scrollbar-gutter: auto; scrollbar-width: none; }
  .game-page .site-header { display: none; }
  .game-page .site-main {
    padding: max(0px, env(safe-area-inset-top, 0px)) max(6px, env(safe-area-inset-right, 0px))
      calc(12px + env(safe-area-inset-bottom, 0px)) max(6px, env(safe-area-inset-left, 0px));
  }

  .game-scoreboard {
    grid-template-columns: 44px minmax(0, 1fr) auto minmax(0, 1fr) 44px;
    column-gap: 4px;
    align-items: center;
    min-height: 60px;
    margin-bottom: 8px;
  }
  .player--you { grid-column: 2; }
  .game-status { grid-column: 3; }
  .status-banner { grid-column: 3; max-width: 30vw; padding: 4px 6px; }
  .status-banner--over { padding: 0; }
  .status-banner .game-rematch__button { min-height: 44px; padding: .45rem .6rem; font-size: .9rem; }
  .player--winner { padding: .3rem .4rem; }
  .player--opponent { grid-column: 4; }
  .game-back { grid-column: 1; }
  .player__number { font-size: 1.5rem; }

  .game-back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    min-width: 44px;
    height: 44px;
    min-height: 44px;
    padding: 0;
    border: 0;
    border-radius: 10px;
    background: none;
    color: var(--plum-deep);
    text-decoration: none;
    cursor: pointer;
  }
  .game-back .ui-icon { width: 1.4rem; height: 1.4rem; }
  .game-back:focus-visible { outline: 3px solid var(--teal); outline-offset: 2px; }

  .game-play-dock .button--play { min-height: 56px; }
  .game-chat--floating .game-chat__panel:not([open]) .game-chat__summary { min-height: 62px; padding: 6px 2px; font-size: .9rem; }
  .game-chat--floating .game-chat__panel:not([open]) .game-chat__summary-title { flex-direction: column; gap: 3px; }
  .game-chat--floating .game-chat__panel[open] {
    width: calc(100vw - 12px - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px));
  }
  .game-chat--floating .game-chat__summary-title { gap: 5px; }
  .game-chat--floating .game-chat__panel:not([open]) .game-chat__unread { position: absolute; top: 2px; right: 2px; background: var(--plum-deep); color: white; min-width: 1.1rem; padding: 0 3px; font-size: .8rem; }

}

/* ----------------------------------------------------------------- dialogs */

dialog.dialog {
  border: none;
  border-radius: var(--radius-lg);
  padding: 0;
  max-width: min(38rem, calc(100vw - 2rem));
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 18px 40px rgba(59, 42, 69, 0.3);
}

dialog.dialog::backdrop {
  background: rgba(59, 42, 69, 0.45);
}

.dialog__inner {
  padding: 1.5rem;
  display: grid;
  gap: 1rem;
}

.dialog__title {
  font-size: 1.4rem;
  color: var(--plum-deep);
}

.dialog__text {
  color: var(--ink-soft);
}

.dialog__actions {
  display: flex;
  gap: 0.75rem;
  justify-content: flex-end;
  flex-wrap: wrap;
}

@media (min-width: 900px) {
  #confirm-dialog[data-kind="play"] { width: 40rem; max-width: calc(100vw - 4rem); }
  #confirm-dialog[data-kind="play"] .dialog__inner { padding: 2.25rem; gap: 1.5rem; }
  #confirm-dialog[data-kind="play"] .dialog__title { font-size: 2rem; }
  #confirm-dialog[data-kind="play"] .dialog__text { font-size: 1.25rem; }
  #confirm-dialog[data-kind="play"] .button { min-height: 56px; font-size: 1.2rem; }
}

.letter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(2.9rem, 1fr));
  gap: 0.45rem;
}

.swap-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  padding: 0.5rem 0;
}

.swap-choice {
  position: relative;
  cursor: pointer;
}
.swap-choice .tile { width: 3.5rem; height: 3.5rem; }
.swap-choice .tile__letter { font-size: 2rem; }
.swap-choice input:checked + .tile {
  background: #d8eee4;
  border-color: #15695a;
  outline: 3px solid #15695a;
  outline-offset: 2px;
}
.swap-choice input:focus-visible + .tile {
  outline: 3px solid #2b607f;
  outline-offset: 5px;
}

/* ------------------------------------------------------------------- flash */

.flash-stack, .game > .flash {
  position: fixed;
  top: auto;
  left: auto;
  right: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 90;
  width: min(28rem, calc(100% - 2rem));
  max-height: 50dvh;
  overflow-y: auto;
  display: grid;
  gap: 0.4rem;
  pointer-events: none;
}

.game > .flash { bottom: calc(max(1rem, env(safe-area-inset-bottom)) + var(--flash-banner-height, 0px)); }

.flash {
  position: relative;
  z-index: 90;
  display: grid;
  gap: 0.4rem;
}

.flash:not(:has(.flash__message)) {
  display: none;
}

.flash .flash__message {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1.1rem 1.25rem;
  background: #1d6259;
  color: #fff;
  border: 2px solid #124c44;
  border-radius: 16px;
  box-shadow: 0 8px 28px #3b2a4538;
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.45;
  pointer-events: auto;
}
.flash .flash__alert { background: #873928; border-color: #692619; }
.flash__message p { align-self: center; overflow-wrap: anywhere; min-width: 0; }
.flash__icon {
  flex: 0 0 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  border: 2px solid currentColor;
  border-radius: 50%;
  font-size: 1.25rem;
  line-height: 1;
}
.flash__dismiss {
  flex: 0 0 44px;
  margin-left: auto;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 1.5rem;
  cursor: pointer;
}
.flash__dismiss:hover { background: #ffffff24; }
.flash__dismiss:focus-visible { outline: 3px solid white; outline-offset: 2px; }

@media (max-width: 600px) {
  .flash .flash__message {
    padding: 10px 12px; gap: 8px; font-size: 1rem; line-height: 1.35;
    border-width: 1px; border-radius: 12px; box-shadow: var(--shadow-sm);
  }
  .flash__icon { display: none; }
}

.is-pending {
  cursor: progress;
}

.is-pending .rack,
.is-pending .controls,
.is-pending .board-scroll {
  opacity: 0.72;
}

/* sign-in and onboarding: the shared card plus the onboarding, entry, and
   invitation variants and the miniature welcome board. */

.signin {
  max-width: 30rem;
  margin: 2rem auto;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 2rem;
  box-shadow: var(--shadow-md);
  display: grid;
  gap: 1rem;
}

.signin__title {
  font-size: 1.8rem;
  color: var(--plum-deep);
}

.signin__text {
  color: var(--ink-soft);
}

.signin__list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}

/* Sign-in form. */

.signin__form {
  display: grid;
  gap: 1rem;
}

.signin__text--quiet {
  font-size: 0.95rem;
}

/* --------------------------------------------------------------- onboarding */

.onboarding {
  min-height: 100vh;
}

.onboarding:not(.home-page) {
  background:
    radial-gradient(circle at 12% 15%, #fffdf7 0 7rem, transparent 19rem),
    linear-gradient(155deg, #f8eedb 0%, #fbf5e9 50%, #e8f0e9 100%);
}

.onboarding .site-main {
  max-width: 32rem;
  padding-top: clamp(2.5rem, 10vh, 6rem);
}

.onboarding .signin {
  max-width: 31rem;
  margin: 0 auto;
  padding: 0;
  gap: 1.15rem;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.onboarding .signin__title {
  font-size: clamp(1.875rem, 4vw, 2.25rem);
  overflow-wrap: anywhere;
}

.onboarding .signin__text {
  color: #57475e;
  font-size: 1.15rem;
  overflow-wrap: anywhere;
}

.onboarding .signin__text--quiet {
  color: #6d5b4b;
  font-size: 1rem;
  display: grid;
  gap: 0.1rem;
}

/* Shared welcome text and form grouping. */
.onboarding__intro,
.onboarding__signin {
  display: grid;
  gap: 1.15rem;
  justify-items: center;
  min-width: 0;
}

.onboarding__intro {
  gap: 0.75rem;
  max-width: 29rem;
  margin-inline: auto;
  text-align: center;
}

.onboarding .field {
  gap: 0.45rem;
  min-width: 0;
}

.onboarding .field__label {
  color: #493852;
  font-size: 1.1rem;
}

.onboarding .input {
  width: 100%;
  min-height: 3.45rem;
  padding: 0.75rem 0.9rem;
  border-color: #bfa878;
  background: #fffdf8;
  box-shadow: inset 0 1px 2px rgba(91, 66, 45, 0.08);
  font-size: 1.15rem;
}

.onboarding .signin__form {
  min-width: 0;
}

.onboarding__button {
  min-height: 3.45rem;
  background: linear-gradient(#287b72, #1e7068);
  border-color: #175b55;
  border-bottom-width: 3px;
  box-shadow: inset 0 1px 0 #ffffff4d, 0 3px 0 #175b55, 0 5px 9px rgba(31, 90, 84, 0.2);
  font-size: 1.18rem;
}

.onboarding__button:hover:not(:disabled) {
  background: linear-gradient(#27776f, #216f68);
}

.onboarding__button:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: inset 0 1px 3px rgba(16, 61, 57, 0.4), 0 1px 0 #175b55;
}

/* A miniature board fragment: the real board's ivory squares, premium
   colours, centre star, and raised tiles at a small decorative size. Scoped
   under .onboarding so the play board itself never changes. It is a picture,
   not a control: the markup marks it aria-hidden and the copy above it says
   what the game is. */
.onboarding__preview {
  display: grid;
  grid-template-columns: repeat(5, 2.05rem);
  gap: 2px;
  width: fit-content;
  max-width: 100%;
  margin: 0.15rem auto;
  padding: 5px;
  border: 1px solid #ceb98e;
  border-radius: 10px;
  background: linear-gradient(#eedfbe, #dfcba1);
  box-shadow: inset 0 1px 0 #fffdf4, inset 0 -2px 0 #d6c5a1, 0 2px 0 #d3c29c,
    0 8px 16px rgba(101, 83, 52, 0.16);
}

.onboarding__preview-square {
  display: grid;
  aspect-ratio: 1 / 1;
  place-items: center;
  border-radius: 5px;
  background: #fbf4e3;
  box-shadow: inset 1px 1px 0 #fffdf7, inset -1px -1px 0 #8e785322, inset 0 1px 2px #8e78531c;
  color: #46546a;
}

.onboarding__preview-square--double-letter { background: #d2e4f0; color: #305a75; }
.onboarding__preview-square--triple-letter { background: #b6d9ca; color: #23574c; }
.onboarding__preview-square--double-word { background: #f1d3c7; color: #8a4b3e; }
.onboarding__preview-square--triple-word { background: #e8a08c; color: #6b2a1d; }
.onboarding__preview-square--center { background: #f6e3ac; color: #7d5410; }

.onboarding__preview-tile {
  display: grid;
  width: 88%;
  height: 88%;
  place-items: center;
  border: 1px solid #d9c096;
  border-top-color: #fffef9;
  border-bottom: 2px solid #cdae74;
  border-radius: 6px;
  background: linear-gradient(166deg, #fffdf7, #fff2d8);
  box-shadow: inset 1px 1px 0 #ffffffd9, inset -1px -1px 0 #bc965b29, 0 2px 0 #c3a771,
    0 4px 6px #5c492229;
  color: var(--plum-deep);
}

.onboarding__preview-letter {
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1;
  transform: translate(-1px, -1px);
}

.onboarding__preview-premium {
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  text-shadow: 0 1px 0 #ffffff8c;
}

.onboarding__preview-star { font-size: 0.9rem; text-shadow: 0 1px 0 #ffffff8c; }

@media (min-width: 64rem) {
  .onboarding .site-main { max-width: 62rem; }

  /* The 194px board fragment grows to about 348px on the invitation and
     magic-link screens, with the squares, letters, and premium labels scaled
     to match it. */
  .onboarding__preview {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    width: min(100%, 20.5rem);
    gap: 3px;
    padding: 7px;
    margin: 0.35rem auto;
  }

  .onboarding__preview-square { border-radius: 8px; }
  .onboarding__preview-tile { border-radius: 9px; }
  .onboarding__preview-letter { font-size: 1.8rem; }
  .onboarding__preview-premium { font-size: 1rem; }
  .onboarding__preview-star { font-size: 1.5rem; }
}

@media (max-width: 600px) {
  .onboarding .site-main { padding: 1.5rem 1rem 2.5rem; }
  .onboarding .signin { margin: 0; }
  .onboarding__preview { margin-top: 0; }
}

/* Entry sign-in: one centered welcome, with the real game's tiles. */

.onboarding--entry {
  background: radial-gradient(ellipse at 50% 25%, #fffdf8 0%, #fbf3e5 65%, #f4e5ce 100%);
}

.onboarding--entry .site-main { max-width: 72rem; padding: 1rem 1.5rem 3rem; }
.onboarding--entry .signin { max-width: none; gap: 2.3rem; }
.onboarding--entry .onboarding__intro { max-width: 40rem; gap: 0.9rem; }
.onboarding--entry .signin__title { font-size: clamp(1.9rem, 3.3vw, 2.8rem); font-weight: 800; }
.onboarding--entry .signin__text { font-size: clamp(1.15rem, 2vw, 1.55rem); }
.onboarding--entry .onboarding__signin { width: min(100%, 40rem); margin-inline: auto; gap: 1.5rem; }
.onboarding--entry .signin__form { width: 100%; gap: 1.2rem; }
.onboarding--entry .field__label { font-size: clamp(1.1rem, 2vw, 1.5rem); }
.onboarding--entry .input,
.onboarding--entry .onboarding__button { min-height: 4.4rem; font-size: clamp(1.15rem, 2.2vw, 1.7rem); border-radius: 16px; }
.onboarding--entry .input { padding-inline: 1.25rem; border: 2px solid #d1b483; }
.onboarding--entry .input::placeholder { color: #756e68; opacity: 1; }
.onboarding--entry .signin__text--quiet { display: block; font-size: clamp(1rem, 1.7vw, 1.25rem); text-align: center; color: #6d5b76; }

.signin-confirmation {
  width: min(100%, 40rem);
  margin: clamp(1rem, 4vh, 3rem) auto 0;
  padding: clamp(1.5rem, 4vw, 3rem);
  display: grid;
  justify-items: center;
  gap: 1.2rem;
  text-align: center;
  background: #e4f2e9;
  border: 2px solid #9bcabb;
  border-radius: 22px;
  box-shadow: 0 6px 18px #235e4912;
}
.signin-confirmation__check {
  display: grid;
  place-items: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: #1e7068;
  color: white;
  font-size: 2.4rem;
  font-weight: 800;
}
.signin-confirmation__help { color: #425b51; font-size: 1.1rem; line-height: 1.6; }
.signin-confirmation__back { min-height: 56px; font-size: 1.15rem; background: #fffdf7; }

.welcome-board {
  --frame-pad: 8px;
  --frame-edge: 1px;
  --board-gap: 3px;
  --plum-deep: #33304a;
  --tile-edge: #d9c096;
  width: min(100%, 40rem);
  margin-inline: auto;
  pointer-events: none;
  user-select: none;
}
.welcome-board__grid { grid-template-columns: repeat(9, 1fr); grid-template-rows: repeat(2, 1fr); aspect-ratio: 9 / 2; }
.welcome-board .tile__letter { font-size: 4.85cqw; }

@media (max-width: 600px) {
  .onboarding--entry .site-main { padding: 1rem 1rem 2rem; }
  .onboarding--entry .signin { gap: 1.6rem; }
  .onboarding--entry .input, .onboarding--entry .onboarding__button { min-height: 3.6rem; }
  .welcome-board { --frame-pad: 5px; --board-gap: 2px; }
  .welcome-board__grid { grid-template-columns: repeat(7, 1fr); aspect-ratio: 7 / 2; }
  .welcome-board .square:nth-child(9n + 1),
  .welcome-board .square:nth-child(9n + 9) { display: none; }
  .welcome-board .tile__letter { font-size: 7cqw; }
  .welcome-board .square__premium { font-size: 12px; }
}

/* lobby: the shared .home base plus the signed-in home-page composition,
   cards, invites, artwork, and their responsive rules. */

.home {
  display: grid;
  gap: 2rem;
  max-width: 46rem;
}

.game-list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 1rem;
}

.game-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.25rem;
  display: grid;
  gap: 0.9rem;
  box-shadow: var(--shadow-sm);
}

.game-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.game-card__title {
  font-size: 1.15rem;
}

.score-line {
  display: flex;
  gap: 1.5rem;
}

.score-line__item dt {
  color: var(--ink-soft);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.score-line__item dd {
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--plum-deep);
}

/* Lobby composition: the page column fills the viewport so the tagline can
   rest at the bottom edge of a short lobby, and the games and invitation panels
   share one bounded frame. */
.home-page .site-main { max-width: none; padding: 3.5rem var(--lobby-gutter, 1.5rem) 3rem; width: 100%; flex: 1 1 auto; display: flex; flex-direction: column; }
.home-page .home { --lobby-control: 64px; max-width: none; min-width: 0; gap: 1.5rem; font-size: 1.2rem; color: var(--ink-soft); overflow-wrap: break-word; flex: 1 1 auto; display: flex; flex-direction: column; }
.home-page .home__frame { display: grid; gap: 1.75rem; min-width: 0; width: 100%; max-width: var(--lobby-max, 79rem); margin-inline: auto; }
/* Sticky lobby footer: the page column fills the viewport, so the tagline
   rests near the bottom edge when the lobby is short and is simply pushed
   below the content when the lobby is long. --lobby-gutter is the shared
   header/main horizontal gutter: 40/28/18 CSS px at the 17px root, kept in rem
   so it still scales with the reader's font size and browser zoom. */
body.home-page { isolation: isolate; display: flex; flex-direction: column; min-height: 100dvh; --lobby-gutter: 2.35rem; --lobby-max: 80rem; }
/* The tagline and the closing art share one bounded footer. The negative
   inline and bottom margins let that band reach the page edges and the
   viewport bottom without ever using 100vw, so no scrollbar overflow. */
.home-page .home__footer { margin-top: auto; margin-inline: calc(-1 * var(--lobby-gutter, 1.5rem)); margin-bottom: -3rem; }

.home-page .section-heading { margin: 0; text-transform: none; letter-spacing: 0; color: var(--plum-deep); }
.home-page .home__title { font-size: clamp(1.8rem, 3vw, 2.45rem); font-weight: 800; line-height: 1.15; }
.home__welcome { display: flex; justify-content: space-between; align-items: center; gap: 2rem; }
.home__welcome #player-search-help { font-size: 1.1rem; margin-top: .5rem; }
.home__search-help--mobile { display: none; }
.home__welcome .home__train-accent { display: block; flex: none; width: 5.75rem; height: auto; transform: translateX(-1rem) scale(1.6) rotate(-8deg); opacity: .9; pointer-events: none; }
@media (prefers-reduced-motion: no-preference) {
  html:has(.home-page) { scroll-behavior: smooth; }
}
.home-page .lobby-card { background: #fdf7ec; border: 1px solid #f0e2cb; border-radius: var(--radius-lg); padding: 1.75rem; min-width: 0; }
.home__active { display: grid; gap: 1rem; }
.home__invite { display: grid; gap: 1.5rem; }
.home__choices { display: grid; grid-template-columns: minmax(0, 2fr) auto minmax(0, 1fr); align-items: center; gap: 1rem; }
.home__search { position: relative; min-width: 0; }
.home__search-results { position: absolute; top: calc(100% + .5rem); left: 0; right: 0; z-index: 20; max-height: min(24rem, 50vh); overflow-y: auto; overscroll-behavior: contain; border: 1px solid var(--line); border-radius: 16px; background: var(--paper); box-shadow: 0 8px 22px #35202224; }
.home__search-results[hidden],
.home__search-results:not(:has(.start-game__outcome:not([hidden]) > *, .start-game__status:not(.visually-hidden):not(:empty), #new-game-error:not(:empty))) { display: none; }
.home__search-results .player-results, .home__search-results .player-result { border: 0; border-radius: 0; }
.home__search-results .start-game__outcome > .start-game__state,
.home__search-results .start-game__status:not(.visually-hidden),
.home__search-results #new-game-error:not(:empty) { padding: 1rem; margin: 0; }
.home-page .start-game { width: 100%; min-width: 0; }
.home-page .field__row { position: relative; }
.home-page .input { min-height: var(--lobby-control); height: var(--lobby-control); font-size: 1.35rem; padding-left: 4.5rem; border-color: #d7cdbf; background: #fffefd; box-shadow: 0 3px 7px #35202208; }
.home-page .input:focus { border-color: var(--teal); outline: 3px solid var(--teal); outline-offset: 2px; box-shadow: 0 0 0 6px var(--teal-soft); }
.home-page .start-game__search { position: absolute; inset: 0 auto 0 0; width: 4.2rem; border: 0; background: transparent; color: var(--teal); cursor: pointer; border-radius: var(--radius); }
.home-page .start-game__search svg { width: 1.85rem; height: 1.85rem; }
.home__or { display: grid; justify-items: center; gap: .4rem; font-size: 1rem; }
.home__or::before, .home__or::after { content: ""; width: 1px; height: 1.4rem; background: #e3d2b3; }
.home__computer { display: flex; align-items: center; min-width: 0; }
.home__computer form { width: 100%; }
.home-page .home__computer .button { display: inline-flex; align-items: center; justify-content: center; gap: .7rem; width: 100%; min-height: var(--lobby-control); height: var(--lobby-control); padding: .4rem 1.35rem; font-size: 1.2rem; background: #e0eff8; color: var(--plum-deep); border-color: #a7cde5; box-shadow: inset 0 1px 0 #ffffffb3, 0 2px 4px #305a7512; }
.computer-icon { width: 3.4rem; height: 3.4rem; flex-shrink: 0; color: var(--plum-deep); }
.home-page .home__computer .computer-icon { width: 2.5rem; height: 2.5rem; }
.home__robot-label { font-weight: 750; white-space: nowrap; }
.home__robot-copy { display: inline; }
.home__robot-note, .home__robot-chevron { display: none; }
.home__tagline { display: flex; align-items: center; justify-content: center; gap: .7rem; margin: 0; color: var(--ink-soft); font-size: 1.05rem; font-weight: 650; }
.home__tagline-rule { flex: none; width: 2.5rem; height: 1px; background: #dcc9a2; }
.home__tagline .ui-icon { flex: none; width: 1.15rem; height: 1.15rem; color: #c39a4a; fill: currentColor; stroke: none; }
/* Keep the mountain silhouettes intact. The source's top half is transparent;
   this band trims that empty space without cropping or fading the hills. */
body { isolation: isolate; }
.site-backdrop {
  position: fixed; left: 0; bottom: 0; z-index: -1;
  width: 100%; height: clamp(90px, 16.67vw, 300px);
  object-fit: cover; object-position: 50% 100%;
  opacity: .18; pointer-events: none;
}
@media (min-width: 1101px) {
  /* Keep the existing art visible at the viewport edge, behind the lobby. */
  .home-page .home__footer { padding-bottom: max(6rem, 8vw); }
}
.home-page .start-game__status:empty, .home-page .start-game__outcome:empty, .home-page .start-game__outcome[hidden] { display: none; }
.home-page .start-game__outcome { margin: 0; }
.home-page .start-game__state { margin: 0; color: var(--ink-soft); }
.home-page .player-results { list-style: none; padding: 0; margin: 0; border: 1px solid var(--line); border-radius: 16px; overflow: hidden; background: #fffdf899; }
.home-page .player-result { display: flex; align-items: center; gap: 1.2rem; min-width: 0; padding: .85rem 1.25rem; }
.home-page .player-results .player-result + .player-result { border-top: 1px solid var(--line); }
.home-page .player-result--invite, .home-page .player-result--none { border: 1px solid var(--line); border-radius: 16px; background: #fffdf899; }
.home-page .player-result__avatar, .game-card__avatar { display: grid; place-items: center; width: 3.5rem; height: 3.5rem; flex-shrink: 0; border-radius: 50%; background: #d0e8de; color: #23574c; font-weight: 800; font-size: 1.3rem; }
.home-page .player-result__avatar--1 { background: #d2e4f0; color: #305a75; }
.home-page .player-result--invite .player-result__avatar { background: #f1d3c7; color: #8a4b3e; }
.home-page .player-result--none .player-result__avatar { background: #eee9e4; color: var(--ink-soft); }
.home-page .player-result__avatar svg { width: 1.7rem; height: 1.7rem; }
.home-page .player-result__name { font-weight: 750; color: var(--plum-deep); }
.home-page .player-result__copy { min-width: 0; }
.home-page .player-result form { margin-left: auto; flex-shrink: 0; }
.home-page .onboarding__button { min-height: 58px; font-size: 1.15rem; }
.home-page .player-result .onboarding__button { min-width: 12rem; }
.home-page .player-result--invite { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .5rem 1rem; }
.home-page .player-result--invite > .player-result__name { grid-column: 1 / -1; overflow-wrap: anywhere; }
.home-page .player-result--invite > .player-result__copy { grid-column: 1; grid-row: 2; }
.home-page .player-result--invite > form { grid-column: 2; grid-row: 2; align-self: center; }
.home-page .player-result--invite .onboarding__button { min-width: 0; }
@media (max-width: 600px) {
  .home-page .player-result.player-result--invite { padding: .65rem; column-gap: .5rem; }
  .home-page .player-result--invite > form { max-width: 4.25rem; }
  .home-page .player-result--invite .onboarding__button { flex-direction: column; gap: .2rem; padding: .5rem; font-size: .85rem; line-height: 1.2; }
}

.home-page .home__games { display: grid; gap: 1.25rem; min-width: 0; }
.home-page .home__games-header { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.home-page .home__games-title { font-size: clamp(2rem, 4.8vw, 4rem); font-weight: 800; margin: 0; }
.home-page .home__new-game { display: inline-flex; align-items: center; gap: .6rem; min-height: 76px; padding: .65rem 1.75rem; font-size: 1.6rem; font-weight: 800; white-space: nowrap; }
.home-page .home__empty { margin: 0; padding: 1.2rem 0; }
.home-page .home__empty-art { width: 100%; max-width: 17rem; height: 6rem; object-fit: cover; object-position: 50% 60%; }
.home-page .game-list { margin: 0; }

/* Active lobby rows: identity, paired scores, status pill, then Nudge and one
   chevron link to the board. The row itself is not a link, so the status pill
   and Nudge stay separate controls and nothing interactive nests. */
.home-page .game-card { position: relative; min-width: 0; padding: .85rem 1.25rem; background: var(--cream); border: 1px solid #ecdcc0; border-radius: 16px; box-shadow: 0 2px 4px #35202210; }
.home-page .game-card--active { grid-template-columns: minmax(20rem, 1fr) minmax(10rem, 1fr) minmax(10rem, 16rem) minmax(11rem, 13rem); grid-template-areas: "identity scores status actions"; align-items: center; gap: .75rem 1.25rem; min-height: 144px; }
.home-page .game-card--turn { background: #eaf6ee; border-color: #bcded0; }
.home-page .game-card--waiting { background: var(--cream); border-color: #ecdcc0; }
.home-page .game-card--over { border-color: #e1dbe7; }
.home-page .game-card--invitation { background: #e2eff8; border-color: #afcadf; }
.game-card__accept { grid-area: status; margin: 0; width: 100%; }
.game-card__status--accept { background: #2b607f; border-color: #204960; color: #fff; }
.game-card__invitation-error { grid-column: 1 / -1; margin: 0; color: #8c3e2f; }
.game-card__invitation-error:empty { display: none; }

.game-card__identity { grid-area: identity; display: flex; align-items: center; gap: .85rem; min-width: 0; }
.game-card__who { min-width: 0; }
.home-page .game-card__title { font-size: 1.6rem; margin: 0; color: var(--plum-deep); overflow-wrap: anywhere; }
.game-card__meta { display: block; margin-top: .15rem; font-size: 1.15rem; font-weight: 600; color: var(--ink-soft); white-space: nowrap; }
.game-card__avatar { width: 5rem; height: 5rem; background: #f7d1c9; color: #8d332e; font-size: 2rem; }
.game-card:nth-child(even) .game-card__avatar { background: #e5d9ee; color: var(--plum-deep); }
.home-page .game-card__avatar--computer { background: #d0e8de; }
.home-page .game-card__avatar .computer-icon { width: 3.5rem; height: 3.5rem; }

/* Paired lobby scores keep the board's .score-line untouched: a new grid puts
   your score first, a divider, then the opponent's. */
.game-card__scores { grid-area: scores; justify-self: center; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: center; gap: 1.4rem; width: 100%; max-width: 12rem; margin: 0; }
.game-card__score { min-width: 0; text-align: center; }
.game-card__score dt { max-width: 7rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-bottom: .15rem; font-size: 1rem; line-height: 1.3; font-weight: 650; color: var(--ink-soft); }
.game-card__score + .game-card__score { position: relative; }
.game-card__score + .game-card__score::before { content: "|"; position: absolute; left: -.7rem; top: calc(50% + .72rem); transform: translate(-50%, -50%); font-size: 1.5rem; font-weight: 700; color: #c9b9a4; }

.game-card__score dd { margin: 0; font-size: 2.8rem; line-height: 1.1; font-weight: 800; color: var(--plum-deep); font-variant-numeric: tabular-nums; }
.home-page .game-card--turn .game-card__score:first-child dd { color: #185637; }

.game-card__status { position: relative; z-index: 1; grid-area: status; justify-self: center; min-width: 0; display: inline-flex; align-items: center; justify-content: center; width: 100%; max-width: 16rem; min-height: 58px; padding: .7rem 1.1rem; border: 1px solid; border-radius: 14px; box-shadow: var(--button-bevel); font-size: 1.3rem; font-weight: 800; text-align: center; overflow-wrap: anywhere; }
.game-card__status--turn { background: var(--teal); border-color: #175d53; color: #fff; gap: .55rem; }
.game-card__status--turn::before { content: ""; width: .6rem; height: .6rem; border-radius: 50%; background: currentColor; flex: none; }
.game-card__status--waiting { background: var(--plum); border-color: var(--plum-deep); color: #fff; }

.game-card__actions { grid-area: actions; display: grid; grid-template-columns: minmax(0, 1fr) 44px; align-items: center; gap: 1.25rem; min-width: 0; }
.game-card__actions .game-nudge { position: relative; z-index: 1; justify-self: center; }
.game-card__actions .game-card__open { grid-column: 2; }
.game-card__actions .game-nudge, .game-card__actions form { display: grid; min-width: 0; }
.home-page .game-card .game-nudge__button { min-height: 58px; gap: .2rem; padding: .45rem .75rem; font-size: 1.3rem; background: #2b607f; border-color: #204960; color: #fff; box-shadow: var(--button-bevel); }

.game-card__open { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex: none; border-radius: .4rem; background: transparent; border: 0; color: var(--plum-deep); font-size: 1.9rem; line-height: 1; font-weight: 800; text-decoration: none; }
.game-card__open::after { content: ""; position: absolute; inset: 0; border-radius: 16px; }
.game-card:has(.game-card__open:focus-visible) { outline: 3px solid var(--teal); outline-offset: 3px; }
.lobby-chevron { display: inline-block; flex: none; width: 1em; font-size: 1.1rem; line-height: 1; text-align: center; }

/* Finished rows: identity with an explicit result, paired scores, the finished
   date, then the same chevron that opens the post-game page (where Rematch
   already lives). */
.home-page .game-card--finished { grid-template-columns: minmax(0, 1fr) 10rem minmax(10rem, .8fr) 44px; grid-template-areas: "identity scores finished-at open"; align-items: center; gap: .6rem 1.1rem; min-height: 90px; padding: .6rem 1.1rem; background: #fffdfa; border: 0; border-bottom: 1px solid #e8dfd3; border-radius: 0; box-shadow: none; }
.home-page .game-card--finished .game-card__avatar { width: 3.5rem; height: 3.5rem; font-size: 1.4rem; }
.home-page .game-card--finished .game-card__avatar .computer-icon { width: 1.8rem; height: 1.8rem; }
.home-page .game-card--finished .game-card__title { font-size: 1.35rem; }
.home-page .game-card--finished .game-card__score dd { font-size: 1.85rem; }
.game-card__result { display: block; margin-top: .15rem; font-size: 1.1rem; color: var(--ink-soft); }
.game-card__result--won { color: #17574a; }
.game-card__result--lost { color: #843e30; }
.game-card__finished-at { grid-area: finished-at; justify-self: end; font-size: 1.1rem; font-weight: 700; color: var(--ink-soft); white-space: nowrap; }
.game-card--finished > .game-card__open { grid-area: open; }

.finished-games { display: block; }
:is(.finished-games__summary, .pending-invitations__summary) { display: flex; align-items: center; gap: .65rem; min-height: 44px; cursor: pointer; font-size: 1.65rem; font-weight: 800; line-height: 1.2; color: var(--plum-deep); list-style: none; }
:is(.finished-games__summary, .pending-invitations__summary) > .ui-icon { width: 1em; height: 1em; font-size: 1em; flex-shrink: 0; }
:is(.finished-games__summary, .pending-invitations__summary) > span:not(.site-header__count) { min-width: 0; }
:is(.finished-games__summary, .pending-invitations__summary)::-webkit-details-marker { display: none; }
:is(.finished-games__summary, .pending-invitations__summary) > .lobby-chevron { margin-left: auto; }
details[open] > :is(.finished-games__summary, .pending-invitations__summary) > .lobby-chevron { transform: rotate(90deg); }
:is(.finished-games__summary, .pending-invitations__summary):focus-visible { outline: 3px solid #267e74; outline-offset: 3px; border-radius: .3rem; }

/* Compact cream disclosure cards for Finished Games and Pending Invitations,
   with a pale lavender count beside the title and the chevron at the right. */
.home-page details.finished-games, .home-page #lobby-invites { padding: .8rem 1.1rem; }
.home-page :is(.finished-games__summary, .pending-invitations__summary) { min-height: 56px; }
.home-page :is(.finished-games__count, .pending-invitations__count) { background: var(--lavender-soft); color: var(--plum-deep); font-size: 1.05rem; }

.finished-games .game-list { margin: .6rem 0 0; gap: 0; border: 1px solid #e8dfd3; border-radius: 12px; overflow: hidden; }
.home-page .game-list--finished > :last-child { border-bottom: 0; }
.home-page .game-list--finished > [hidden] { display: none; }
.finished-games__more { display: flex; align-items: center; justify-content: center; gap: .7rem; width: fit-content; min-width: 15rem; max-width: 100%; min-height: 44px; margin: .8rem auto 0; padding: .4rem 1rem; font: inherit; font-weight: 750; color: var(--plum-deep); background: #fffdf7; border: 1px solid #ecdcbe; border-radius: .65rem; box-shadow: var(--button-bevel); cursor: pointer; }
.finished-games__more[hidden] { display: none; }
.finished-games__more:hover { background: #fff; }
.home-page .pending-invites__item { border-style: solid; min-width: 0; }
.home-page .pending-invites__item strong { min-width: 0; max-width: 100%; }
.home-page .home__invite-error { color: #7d2f1e; font-weight: 600; margin-top: 1rem; }
.home-page .home__invite-error:empty, .home-page #lobby-invites[hidden] { display: none; }
@media (max-width: 1100px) {
  body.home-page { --lobby-gutter: 1.65rem; }
  .home-page .site-main { padding: 1.5rem var(--lobby-gutter, 1.25rem) 2rem; }
  .home-page .home__footer { margin-inline: calc(-1 * var(--lobby-gutter, 1.25rem)); margin-bottom: -2rem; }
  .home-page .lobby-card { padding: 1.35rem; }
  .home__welcome { display: block; }
  .home__welcome .home__train-accent { display: none; }
  .home__choices { grid-template-columns: 1fr; gap: .7rem; }
  .home__or { display: flex; justify-content: center; align-items: center; }
  .home__or::before, .home__or::after { height: 1px; width: 2rem; }
  .home-page .input { font-size: 1.1rem; padding-left: 3rem; }
  .home-page .start-game__search { width: 2.8rem; }
  .home__computer, .home__computer form { width: 100%; }
  .home-page .home__computer .button { width: 100%; }
  .home-page .player-result { gap: .75rem; padding: 1rem; flex-wrap: wrap; }
  .home-page .player-result__name, .home-page .player-result__copy { flex: 1; }
  .home-page .player-result form { width: 100%; }
  .home-page .player-result .onboarding__button { width: 100%; min-width: 0; }
  .home-page .game-card__actions { gap: 1rem; }
  /* Tablet and below: two coherent rows so the name/scores and the
     status/actions never squeeze one another. */
  .home-page .game-card--active {
    grid-template-columns: minmax(0, 1fr) minmax(0, 12rem);
    grid-template-areas:
      "identity scores"
      "status   actions";
    gap: .6rem 1rem;
    min-height: 0;
    padding: .75rem .9rem;
  }
  .home-page .game-card--finished {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas:
      "identity    identity    open"
      "scores      finished-at finished-at";
    gap: .5rem .9rem;
    min-height: 0;
    padding: .65rem .9rem;
  }
  .home-page .game-card__avatar { width: 44px; height: 44px; font-size: 1.15rem; }
  .home-page .game-card__avatar .computer-icon { width: 30px; height: 30px; }
  .home-page .game-card__title { font-size: 1.1rem; }
  .home-page .game-card__score dd { font-size: 1.6rem; }
  .home-page .game-card__status { justify-self: start; font-size: 1.05rem; }
  .home-page .game-card__finished-at { grid-area: finished-at; }
}

@media (max-width: 600px) {
  body.home-page { --lobby-gutter: 1.06rem; }
  .home-page .home__footer { margin-inline: 0; margin-bottom: 0; }
  .home-page .lobby-card { padding: .85rem; }
  .home__invite { gap: 1rem; }
  .home-page .home__games-title { font-size: 1.85rem; }
  .home-page .home__title { font-size: 1.8rem; }
  .home__welcome #player-search-help { margin-top: .8rem; font-size: 1.05rem; }
  .home__search-help--desktop { display: none; }
  .home__search-help--mobile { display: inline; }
  .home-page .home__empty-art { height: 5rem; }

  /* Search: a full-width 56px field with a 48px icon target. */
  .home-page .input { height: 56px; min-height: 56px; font-size: 1.06rem; padding-left: 3.4rem; }
  .home-page .start-game__search { width: 48px; }
  .home-page .start-game__search svg { width: 1.5rem; height: 1.5rem; }

  /* RailBot: one calm secondary row with a small mark and a chevron. The
     single-column choices grid already stacks it under the field; an .82rem
     gap is the only beat between them, so no extra computer margin. */
  .home__or { display: none; }
  .home__choices { gap: .82rem; }
  .home__computer { margin-top: 0; }
  .home-page .home__computer .button { height: 60px; min-height: 56px; justify-content: flex-start; gap: .8rem; padding: .5rem 1rem; box-shadow: var(--button-bevel); }
  .home-page .home__computer .computer-icon { width: 2rem; height: 2rem; }
  .home__robot-copy { display: flex; flex: 1 1 auto; min-width: 0; flex-direction: column; align-items: flex-start; text-align: left; line-height: 1.15; }
  .home__robot-label { font-size: 1.1rem; }
  .home__robot-note { display: block; font-size: 1rem; font-weight: 650; line-height: 1.2; color: var(--ink-soft); }
  .home__robot-chevron { display: block; flex: none; font-size: 1.4rem; font-weight: 800; line-height: 1; color: var(--plum); }

  /* Phones stack identity and centered scores above the game actions. */
  .home-page .game-card--active { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-areas: "identity identity" "scores scores" "status actions"; gap: .55rem .7rem; padding: .7rem .8rem; border-radius: 14px; }
  .home-page .game-card--finished {
    grid-template-columns: minmax(0, 1fr) 44px;
    grid-template-areas:
      "identity open"
      "scores scores"
      "finished-at finished-at";
    gap: .4rem .7rem;
    padding: .65rem .8rem;
    border-radius: 14px;
  }
  .home-page .game-card--finished > .game-card__open { align-self: center; }
  .home-page .home__games-header { gap: .5rem; }
  .home-page .home__new-game { min-height: 44px; font-size: 1rem; padding: .45rem .7rem; }
  .home-page .game-card__identity { gap: .65rem; }
  .home-page .game-card__avatar { width: 40px; height: 40px; font-size: 1.15rem; }
  .home-page .game-card__avatar .computer-icon { width: 28px; height: 28px; }
  .home-page .game-card__title { font-size: 1.1rem; overflow-wrap: anywhere; }
  .home-page .game-card__meta { font-size: .95rem; }
  .home-page .game-card__score dd { font-size: 1.7rem; }
  .home-page .game-card__score + .game-card__score::before { font-size: 1.3rem; }
  .home-page .game-card__status { justify-self: center; width: auto; max-width: 100%; min-height: 44px; padding: .35rem .7rem; }
  .home-page .game-card--active .game-card__scores { justify-self: center; }
  .home-page .game-card__actions { gap: .7rem; }
  .home-page .game-card .game-nudge__button { min-height: 44px; padding: 6px 8px; font-size: 1rem; }
  .home-page .game-card__finished-at { justify-self: end; font-size: .85rem; }
  .home-page .game-card--finished .game-card__title { font-size: 1.1rem; }
  .home-page .game-card--finished .game-card__score dd { font-size: 1.45rem; }
  .home-page .game-card--finished .game-card__avatar { width: 40px; height: 40px; }
  .home-page .game-card--finished .game-card__scores { justify-self: start; }
  .finished-games .game-list { margin-top: .5rem; }
  :is(.finished-games__summary, .pending-invitations__summary) { font-size: 1.25rem; gap: .5rem; }
}

@media (max-width: 380px) {

  /* Keep the heading and shortcut on one line on the smallest phones. */
  .home-page .home__games-title { font-size: 1.6rem; }
  .home-page .home__new-game { font-size: .94rem; padding-inline: .5rem; gap: .25rem; }
  /* Keep the avatar on the smallest phones, just a touch smaller. */
  .home-page .game-card__avatar { width: 36px; height: 36px; font-size: 1.05rem; }
  .home-page .game-card__avatar .computer-icon { width: 24px; height: 24px; }
  .home-page .game-card__title { font-size: 1.05rem; }
}

@media (max-width: 600px) {
  .home-page .game-card--active .game-card__status { width: 100%; max-width: none; }
  .home-page .game-card--active .game-card__actions { display: block; }
  .home-page .game-card--active .game-card__open { position: absolute; grid-area: auto; z-index: 0; inset: 0; width: auto; height: auto; display: block; }
  .home-page .game-card--active .game-card__open .lobby-chevron { display: none; }
  .home-page .game-card--active .game-nudge { position: relative; z-index: 2; }
  .home-page .game-card--active .game-nudge,
  .home-page .game-card--active .game-nudge__button { width: 100%; }
  .home-page .game-card--active:not(:has(.game-nudge)) {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "identity" "scores" "status";
  }
  .home-page .game-card--active:not(:has(.game-nudge)) .game-card__actions { display: contents; }
}

/* Pending invitations and their resend controls. */

.home-page #lobby-invites { display: block; }
.home-page #lobby-invites > .pending-invites { margin-top: .75rem; }
.pending-invites {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.pending-invites__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.5rem 1.1rem;
  background: #fffdf6;
  border: 1px solid #ecdcbe;
  border-radius: 16px;
  padding: 0.85rem 1.1rem;
}

.pending-invites__icon { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; flex: none; border-radius: 50%; background: #f0e9fb; color: var(--plum); }
.pending-invites__icon .ui-icon { width: 1.5rem; height: 1.5rem; }
.pending-invites__message { min-width: 0; margin: 0; overflow-wrap: anywhere; }
.pending-invites__mobile, .pending-invites__label-short { display: none; }
.pending-invites__actions { display: flex; align-items: center; justify-self: end; gap: .5rem; }
.pending-invites__actions form { flex-shrink: 0; }

@media (max-width: 600px) {
  .home-page #lobby-invites > .pending-invites { margin-top: .6rem; }
  /* Recipient, waiting state, then the resend/cancel actions on their own row. */
  .pending-invites { gap: .5rem; }
  .pending-invites__item {
    /* Keep long recipient names within the card. */
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-rows: auto auto;
    align-items: center;
    column-gap: .55rem;
    row-gap: .15rem;
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: .55rem 0;
  }
  .pending-invites__icon { grid-area: 1 / 1 / 2 / 2; width: auto; height: auto; border-radius: 0; background: transparent; color: var(--plum); }
  .pending-invites__icon .ui-icon { width: 1.15rem; height: 1.15rem; }
  .pending-invites__desktop { display: none; }
  .pending-invites__message, .pending-invites__mobile { display: contents; }
  .pending-invites__recipient { grid-area: 1 / 2 / 2 / 3; display: block; min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 750; color: var(--plum-deep); }
  .pending-invites__state { grid-area: 2 / 2 / 3 / 3; display: block; min-width: 0; font-size: 1.05rem; color: var(--ink-soft); }
  .pending-invites__item--received > .button { grid-column: 2; justify-self: start; }
  .pending-invites__item--received > p { min-width: 0; overflow-wrap: anywhere; }
  .pending-invites__actions { grid-area: 3 / 2 / 4 / 3; justify-self: end; }
  .pending-invites__label-full { display: none; }
  .pending-invites__label-short { display: inline; }
  /* The envelope already identifies the invitation on mobile. */
  .pending-invites__actions .button { min-height: 48px; min-width: 48px; padding: .4rem .8rem; font-size: 1.06rem; gap: .35rem; }
  .pending-invites__actions .button .ui-icon { display: none; }
}

/* local sign-in and outbox (development only). */

.empty-state {
  background: var(--paper);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 1.1rem;
  color: var(--ink-soft);
}

.outbox {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}

.outbox__item {
  display: grid;
  gap: 0.35rem;
  justify-items: start;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.8rem;
}

.outbox__subject {
  font-weight: 700;
}

.outbox__meta {
  color: var(--ink-soft);
  font-size: 0.95rem;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
