/* Super Seven — card-room identity
   Quiet deep-pine table, warm card-cream surfaces, one vermilion accent held
   in reserve for the active turn / Stop / selection, gold for host + start. */

:root {
  /* ---- chrome: neutral graphite ----
     Deliberately desaturated. The app ships fourteen table themes, from Casino
     Felt to Horror to Space Galaxy, and the chrome used to be fixed dark green —
     so exactly one of the fourteen harmonised with its own frame. Neutral chrome
     never competes with any of them, and it leaves the felt as the only
     saturated surface on screen, which is where the eye should go.

     Hue comes back as --bloom below: a soft wash *behind* content, never under
     it, so contrast is identical on every theme and only has to be checked once.
     The previous green palette is kept in .chrome-classic further down. */
  --bg:      #141516;
  --bg-2:    #1b1d1f;
  --panel:   #212426;
  --panel-2: #2a2d30;
  --line:    #35393c;
  --cream:   #f3ecdc;
  --ink:     #15171a;
  --text:    #e9eaea;
  --muted:   #9aa0a2;
  --accent:  #e8593f;  /* active turn, Stop, danger, selection */
  --gold:    #e6b23c;  /* host badge, Start, confirm */
  --turn:    #57d98a;  /* current player's boundary */
  --felt:    #14302a;

  /* Ambient wash behind the table, set per table theme in themes.css. Neutral
     by default so an unthemed page (or a theme with no bloom yet) still looks
     finished rather than broken. Kept low-alpha on purpose: if you can see
     where the bloom begins, it is too strong. */
  --bloom:   rgba(150, 160, 168, 0.07);
  --radius:  14px;
  --shadow:  0 18px 40px -24px rgba(0, 0, 0, 0.7);
  --display: "Space Grotesk", system-ui, sans-serif;
  --body:    "Inter", system-ui, sans-serif;

  /* ---- page rails ----
     One set of vertical guides for a room page, so the table, the topbar's
     contents and the footer's contents all start and end on the same lines
     instead of each choosing its own inset. --page-max is the normal cap;
     --page-max-wide takes over once the screen is wide enough to also balance
     the side column (see the wide-screen block in table.css). */
  --page-max:      1400px;
  --page-max-wide: 1760px;
  --side-col:      280px;    /* the Scores / Action History column */
  --side-gap:      1.5rem;   /* gap between that column and the felt */
  --page-pad:      1.5rem;   /* inset from the rail to content */

  /* ---- design system tokens ----
     One scale for each kind of decision, so two screens built months apart
     still look like the same product. New and touched CSS uses these; older
     literal values are migrated as each surface is reworked. */

  /* type: a 1.125 scale on a 16px root */
  --fs-2xs: 0.6875rem;  /* 11px — micro labels only */
  --fs-xs:  0.75rem;    /* 12px */
  --fs-sm:  0.8125rem;  /* 13px */
  --fs-md:  0.9375rem;  /* 15px — body in panels */
  --fs-lg:  1.125rem;   /* 18px */
  --fs-xl:  1.375rem;   /* 22px */
  --fs-2xl: 1.75rem;    /* 28px */
  --fs-3xl: 2.375rem;   /* 38px */

  /* spacing: 4px steps */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.25rem;
  --sp-6: 1.5rem;
  --sp-8: 2rem;
  --sp-10: 2.5rem;

  /* radii */
  --r-sm:   8px;
  --r-md:   12px;
  --r-lg:   16px;
  --r-xl:   20px;
  --r-pill: 999px;

  /* elevation: hairline, raised (cards, menus), overlay (dialogs, sheets) */
  --el-1: 0 1px 2px rgba(0, 0, 0, 0.35);
  --el-2: 0 10px 28px -14px rgba(0, 0, 0, 0.75), 0 1px 0 rgba(255, 255, 255, 0.03) inset;
  --el-3: 0 28px 64px -24px rgba(0, 0, 0, 0.85);

  /* motion */
  --ease-out:  cubic-bezier(0.32, 0.72, 0, 1);
  --ease-std:  cubic-bezier(0.4, 0, 0.2, 1);
  --dur-fast:  120ms;
  --dur:       200ms;
  --dur-slow:  320ms;

  /* semantic colour, beside the brand palette above */
  --success: #57d98a;
  --warning: #f5b947;
  --danger:  #ef6450;
  --info:    #7aa7ff;

  /* one focus ring for every interactive element */
  --focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--gold);

  /* layers, lowest first — documented here so a new overlay picks a slot
     instead of guessing a number */
  --z-dock: 61;       /* floating reaction / scores buttons */
  --z-tsheet: 70;     /* phone Scores / History sheet */
  /* Dialogs sit above the floating buttons: at 50 the reaction button drew on
     top of every dialog and covered the round summary's Next round button on
     narrow phones (todos §22). */
  --z-modal: 85;      /* dialogs (.modal-backdrop) */
  --z-sheet: 90;      /* Settings sheet */
  --z-toast: 100;
}

* { box-sizing: border-box; }

/* ---------- icons ----------
   The one icon set (templates/partials/icons.html): thin-line, drawn in the
   surrounding text colour, sized to the text by default. Buttons that hold
   only an icon size it explicitly. */
.ico {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.85;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -0.2em;
}

html, body {
  margin: 0;
  min-height: 100%;
}
/* The canvas colour behind everything — what shows when iOS rubber-bands past
   the end of the page, instead of a white flash. */
html { background: var(--bg); }

body {
  font-family: var(--body);
  /* Inter: open digits and a straight-legged 1 read better at small sizes. */
  font-feature-settings: "cv05", "ss01";
  color: var(--text);
  background:
    radial-gradient(120% 90% at 50% -10%, var(--bg-2) 0%, var(--bg) 60%);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}

/* ---------- theme bloom ----------
   The table theme's hue, washed across the page behind everything.

   Two decisions worth keeping:

   1. It is a *masked solid colour*, not a gradient. CSS cannot interpolate
      between two gradients, so a gradient here would snap harshly when the host
      changes theme — and after this change the host repaints everyone's whole
      interface, not just the felt. background-color does interpolate, so the
      mask gives the same soft shape with a 420ms cross-fade.

   2. z-index: -1 puts it above the page background but behind every panel,
      which is the whole point: panels and text sit on solid --panel / --bg, so
      contrast is constant on all fourteen themes.

   3. It is a real element (#theme-bloom in game.html), not a ::after. Chrome
      resolves var() inside a pseudo-element against the ROOT rather than the
      originating element, so `body.theme-x { --bloom }` never reached a
      body::after — and getComputedStyle on a pseudo reports the same wrong
      value, meaning the bug is invisible to measurement as well as broken in
      some browsers. A real element resolves the variable normally and can be
      asserted against.

   4. There is deliberately NO transition, and it has now been tested twice.
      `transition: background-color` on this element freezes it: the colour comes
      from a var(), the variable updates, the paint does not, and the bloom sticks
      on whichever theme loaded first. Transitioning the registered custom
      property instead (`transition: --bloom` on body) freezes it the same way —
      measured with @property genuinely parsing, so this is not the earlier
      false negative. Either way the value stops tracking the theme.
      At ~10% alpha an instant switch is imperceptible, so the wash simply snaps.
      If you reintroduce a transition here, switch themes and confirm the bloom
      colour actually changes before believing it works.

   --bloom is registered below so `syntax: "<color>"` type-checks it: a malformed
   value falls back to the initial rather than silently breaking the layer.

   Room pages only. The home page has its own felt-textured hero. */
@property --bloom {
  syntax: "<color>";
  inherits: true;
  initial-value: rgba(150, 160, 168, 0.07);
}

#theme-bloom {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-color: var(--bloom);
  -webkit-mask-image: radial-gradient(78% 58% at 50% 0%, #000 0%, transparent 74%);
          mask-image: radial-gradient(78% 58% at 50% 0%, #000 0%, transparent 74%);
}

/* ---------- escape hatch: the original green chrome ----------
   Add `chrome-classic` to <body> in templates/game.html to get the pre-graphite
   look back, for side-by-side comparison or a straight revert. Kept as real
   code rather than a comment so it cannot rot. */
body.chrome-classic {
  --bg:      #0f1f1c;
  --bg-2:    #142925;
  --panel:   #193430;
  --panel-2: #1f3e38;
  --line:    #2c4d46;
  --ink:     #15201d;
  --text:    #e7efe9;
  --muted:   #93a9a1;
  --bloom:   rgba(87, 217, 138, 0.05);
}
/* Home page only: a flex column so the felt-backdrop hero grows to fill the
   viewport and the footer sticks to the bottom on short pages, without
   touching every other page's (game.html) body layout. */
body.home-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ---------- wordmark ---------- */
.wordmark {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: 0.04em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-wrap: nowrap;
  row-gap: 0.3rem;
  column-gap: 0.5rem;
}
.wordmark-title {
  white-space: nowrap;
}
.wordmark .seven {
  color: var(--accent);
}
.wordmark .pip {
  color: var(--gold);
  font-size: 0.7em;
  white-space: nowrap;
}
.logo-inline-symbol {
  height: 1.2em;
  width: auto;
  vertical-align: middle;
  margin-left: 8px;
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.4));
  transition: transform 0.2s ease;
  display: inline-block;
}
.logo-inline-symbol:hover {
  transform: scale(1.1);
}
.logo-inline-symbol.small {
  height: 1.1em;
  margin-left: 6px;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.3));
}

/* The home page's own styles live in home.css. */

label {
  display: block;
  font-size: 0.82rem;
  color: var(--muted);
  margin-bottom: 0.6rem;
}

label {
  display: block;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 0 0 0.4rem;
}

input[type="text"],
input[type="number"] {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  font: inherit;
  padding: 0.7rem 0.85rem;
  transition: border-color 0.15s ease;
}
input:focus {
  outline: none;
  border-color: var(--gold);
}
input.code-input {
  text-transform: uppercase;
  letter-spacing: 0.35em;
  font-family: var(--display);
  font-size: 1.15rem;
  text-align: center;
}

.field { margin-bottom: 1rem; }
.field:last-child { margin-bottom: 0; }

button {
  font: inherit;
  cursor: pointer;
  border: none;
  border-radius: 10px;
  padding: 0.75rem 1rem;
  font-weight: 600;
  transition: transform 0.05s ease, filter 0.15s ease, background 0.15s ease,
              border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
button:active { transform: translateY(1px); }
button:disabled { opacity: 0.45; cursor: not-allowed; }

/* One focus ring for everything a keyboard can reach. :focus-visible only, so
   a mouse click never leaves a ring behind. */
/* Text fields and selects are excluded: they show focus with a gold border
   instead (below), and a ring on top of that reads as an error state. */
button:focus-visible,
a:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ---------- buttons ----------
   .btn-primary  gold, the one way forward on a screen (Start, Create, Next round)
   .btn-secondary quiet filled, for real but secondary actions
   .btn-ghost    outline, for alternatives
   .btn-danger   destructive (Leave, Remove)
   Sizes: default 44px tall; .btn-sm 34px; .btn-lg 52px. Icons inside any of
   them sit on the text's baseline with a consistent gap.
   .is-loading swaps the label for a spinner and blocks clicks. */
.btn-primary,
.btn-secondary,
.btn-ghost,
.btn-danger,
.btn-solo {
  position: relative;
  width: 100%;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  border-radius: var(--r-md);
  letter-spacing: 0.005em;
}
.btn-primary {
  background: linear-gradient(180deg, #f0c255 0%, var(--gold) 100%);
  color: var(--ink);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.35) inset, 0 8px 20px -10px rgba(230, 178, 60, 0.55);
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.05); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.35) inset, 0 10px 24px -10px rgba(230, 178, 60, 0.7); }

.btn-secondary {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--line);
}
.btn-secondary:hover:not(:disabled) { background: #33373a; }

.btn-ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--line);
}
.btn-ghost:hover:not(:disabled) { border-color: color-mix(in srgb, var(--gold) 60%, var(--line)); background: rgba(255, 255, 255, 0.03); }

.btn-danger {
  background: transparent;
  color: #ff8a73;
  border: 1px solid rgba(239, 100, 80, 0.45);
}
.btn-danger:hover:not(:disabled) { background: rgba(239, 100, 80, 0.12); border-color: var(--danger); }
.btn-danger.solid { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-danger.solid:hover:not(:disabled) { filter: brightness(1.06); }

.btn-solo {
  background: transparent;
  color: var(--turn);
  border: 1px solid color-mix(in srgb, var(--turn) 70%, transparent);
  margin-top: 0.6rem;
}
.btn-solo:hover:not(:disabled) { background: rgba(87, 217, 138, 0.08); border-color: var(--turn); }

.btn-sm { min-height: 34px; padding: 0.35rem 0.8rem; font-size: var(--fs-sm); border-radius: 10px; }
.btn-lg { min-height: 52px; padding: 0.85rem 1.4rem; font-size: 1.02rem; border-radius: 14px; }
.btn-primary .ico, .btn-secondary .ico, .btn-ghost .ico, .btn-danger .ico, .btn-solo .ico { width: 18px; height: 18px; }

.is-loading { color: transparent !important; pointer-events: none; }
.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 2px solid rgba(0, 0, 0, 0.25);
  border-top-color: var(--ink);
  animation: btn-spin 0.7s linear infinite;
}
.btn-ghost.is-loading::after, .btn-secondary.is-loading::after { border-color: rgba(255, 255, 255, 0.2); border-top-color: var(--text); }
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* ---------- fields ---------- */
select {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  font-size: var(--fs-md);
  color: var(--text);
  background-color: var(--bg);
  /* chevron drawn inline so no icon font or extra request is needed */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239aa0a2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.55rem 2rem 0.55rem 0.8rem;
  min-height: 40px;
  cursor: pointer;
  transition: border-color 0.15s ease;
}
select:hover { border-color: color-mix(in srgb, var(--gold) 45%, var(--line)); }
select:focus { outline: none; border-color: var(--gold); }
select option { background: var(--panel); color: var(--text); }

/* Numbers in scores, timers and chips keep their width as they change, so
   nothing beside them jitters every second. */
.round-chip, .sb-score, .opp-score, .pile-count, .seat-total, .code, #turn-timer,
.re-score, .timer, .pk-amount { font-variant-numeric: tabular-nums; }

/* collapsible settings */
.settings-toggle {
  background: none;
  border: none;
  color: var(--muted);
  padding: 0;
  font-size: 0.82rem;
  margin-top: 0.85rem;
  width: auto;
}
.settings-toggle:hover { color: var(--text); }
.settings-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin-top: 0.9rem;
}
.settings-grid.hidden { display: none; }
.settings-grid label { margin-bottom: 0.3rem; }

/* ══════════════════════════════════════════════════════════════════════
   First-connect loading screen (core/waking.js)
   ══════════════════════════════════════════════════════════════════════
   The service worker can paint the cached landing page long before the
   sleeping host answers, which leaves a complete-looking UI that cannot
   do anything yet. This covers that window with something to watch. */

#waking {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem calc(1.5rem + env(safe-area-inset-left))
           calc(2rem + env(safe-area-inset-bottom))
           calc(1.5rem + env(safe-area-inset-right));
  background: radial-gradient(120% 90% at 50% -10%, #16302b 0%, var(--bg) 65%);
  animation: waking-fade-in 200ms ease-out;
}
#waking.waking-out {
  animation: waking-fade-out 240ms ease-in forwards;
  pointer-events: none;
}
.waking-inner { max-width: 340px; }

/* Three cards being dealt, on a loop. */
.waking-cards {
  position: relative;
  height: 96px;
  margin-bottom: 1.7rem;
}
.waking-cards i {
  position: absolute;
  top: 6px;
  left: 50%;
  width: 56px;
  height: 80px;
  margin-left: -28px;
  border-radius: 8px;
  background: linear-gradient(160deg, var(--cream) 0%, #dccfb2 100%);
  border: 1px solid rgba(0, 0, 0, 0.28);
  box-shadow: 0 12px 24px -14px rgba(0, 0, 0, 0.95);
  animation: waking-deal 1900ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
/* The gold pip, matching the card artwork's treatment. */
.waking-cards i::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  background: var(--gold);
  transform: rotate(45deg);
  border-radius: 3px;
  opacity: 0.85;
}
.waking-cards i:nth-child(1) { --r: -19deg; animation-delay: 0ms; }
.waking-cards i:nth-child(2) { --r: 0deg;   animation-delay: 190ms; }
.waking-cards i:nth-child(3) { --r: 19deg;  animation-delay: 380ms; }

.waking-title {
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 600;
  margin: 0 0 0.6rem;
  color: var(--text);
}
.waking-tip {
  margin: 0;
  min-height: 2.8em;           /* reserve space so swaps don't jump the layout */
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--muted);
  transition: opacity 200ms ease;
}
.waking-note {
  margin: 1rem 0 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--muted);
  opacity: 0.75;
}
.waking-retry {
  margin-top: 1.3rem;
  padding: 0.6rem 1.6rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  font-family: var(--body);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

@keyframes waking-fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes waking-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes waking-deal {
  0%   { transform: translateY(10px) rotate(0deg) scale(0.95); opacity: 0.3; }
  30%  { opacity: 1; }
  60%  { transform: translateY(-8px) rotate(var(--r)) scale(1); opacity: 1; }
  100% { transform: translateY(10px) rotate(0deg) scale(0.95); opacity: 0.3; }
}

/* Respect a reduced-motion preference: keep the screen, drop the movement. */
@media (prefers-reduced-motion: reduce) {
  .waking-cards i {
    animation: none;
    opacity: 1;
  }
  .waking-cards i:nth-child(1) { transform: translateX(-34px) rotate(-19deg); }
  .waking-cards i:nth-child(3) { transform: translateX(34px) rotate(19deg); }
  #waking, #waking.waking-out { animation: none; }
}
