/* The house kit's structure (docs/design-language.md, "Using the house kit";
   ADR 0025): sheets, the result sheet, toasts, banners, the splash, Options
   rows, key caps, focus rings and the motion tokens. Structure only: every
   color, face and edge comes from the tokens the game's root declares. The
   kit reads its own names (--house-*), each falling back to the room's
   (docs/design-system.md, "The room kit"), so a room game needs nothing
   new; a game with other names (the puzzle kit, Hashi, The Register)
   declares the --house-* ones it needs. The only colors written here are
   black shadows and scrims. Load it after the game's own stylesheet. */

/* ── motion tokens (motion.js MOTION; tools/house checks they agree) ──── */
:where(:root) {
  --m-press: 120ms;
  --m-lift: 150ms;
  --m-quick: 150ms;
  --m-glide: 250ms;
  --m-stagger: 22ms;
  --m-reflow: 220ms;
  --m-flight: 380ms;
  --m-flight-long: 580ms;
  --m-deal: 250ms;
  --m-deal-gap: 40ms;
  --m-flip: 240ms;
  --m-sweep-hold: 900ms;
  --m-sweep-hold-relaxed: 1350ms;
  --m-sweep: 350ms;
  --m-arrive: 350ms;
  --m-pop: 200ms;
  --m-nope: 360ms;
  --m-pulse: 1200ms;
  --m-sheet-in: 150ms;
  --m-sheet-out: 150ms;
  --m-banner: 2000ms;
  --m-announce: 2000ms;
  --m-toast: 4500ms;
  --m-toast-action: 6000ms;
  --m-splash: 3400ms;
  --m-prompt: 2600ms;
  --m-beckon: 1600ms;
  --m-beckon-idle: 3000ms;
  --m-celebrate: 1000ms;
  --m-hold: 1200ms;
  --m-hold-key: 2000ms;
  --m-catch-up: 1500ms;
  --m-emote: 3200ms;
  --ease-out: cubic-bezier(.2, .7, .3, 1);
  --ease-flight: cubic-bezier(.3, .7, .2, 1);
}
/* guide:start reduced-motion */
/* Reduced motion: nothing travels, every change lands at once; fades of
   150ms or less stay; a celebration is a still picture (celebrate.js). A game that times its motion
   with these tokens gets this for nothing. */
@media (prefers-reduced-motion: reduce) {
  :where(:root) {
    --m-glide: 0ms; --m-stagger: 0ms; --m-reflow: 0ms; --m-flight: 0ms; --m-flight-long: 0ms;
    --m-deal: 0ms; --m-deal-gap: 0ms; --m-flip: 0ms; --m-sweep: 0ms; --m-arrive: 0ms;
    --m-pop: 0ms; --m-nope: 0ms; --m-celebrate: 0ms;
  }
}
/* guide:end reduced-motion */

/* ── layout and type (docs/design-language.md, "Layout and type") ────── */
/* The page's skeleton, the same in every game: how far in its words start,
   how wide its column runs, how tall its bar is, and the size of each type
   role, each button and each panel. A game re-skins them (its faces, its
   colors, its radii, its display weight) but doesn't resize them: only the
   ones marked "a game's" below are a game's to set. `npm run check:tokens`
   holds every root to the rest; `npm run check:layout` measures the pages. */
/* guide:start scale */
:where(:root) {
  /* space: where the page's words start from the window's edge (the gutter),
     the frame round a table (the felt's margin, inside the gutter), the bar's
     top and the room under it, the column a home or lobby runs in */
  --gutter: max(24px, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  --frame: 10px;
  --bar-h: 44px;
  --bar-top: 12px;
  --bar-gap: 24px;
  --page-max: 960px;
  --page-max-wide: 1180px;
  /* type: each role's size and line height (its face and color are the
     game's; --t-display's size is too, for its one title) */
  --t-title: 28px;
  --t-bar: 17px;
  --t-lead: 16px;
  --t-tool: 15px;
  --t-small: 14px;
  --t-kicker: 12px;
  --t-figure: 20px;
  --lh-display: 1.1;
  --lh-heading: 1.2;
  --lh-body: 1.45;
  --lh-note: 1.4;
  --w-label: 600;
  --w-tool: 700;
  --w-figure: 800;
  --kicker-spacing: .14em;
  /* buttons: a move's height and side padding; a tool's (the bar's quiet
     ones, a dock's small ones); a finger's on a touch screen */
  --btn-h: 44px;
  --btn-pad: 16px;
  --tool-h: 36px;
  --tool-pad: 10px;
  /* panels and sheets */
  --panel-pad: 16px;
  --panel-gap: 16px;
  --panel-radius: 12px;
  --sheet-pad: 24px;
}
@media (max-width: 640px) {
  :where(:root) { --gutter: max(16px, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); --frame: 0px; --bar-top: 8px; --bar-gap: 16px; --t-bar: 15px; --t-figure: 18px; --btn-pad: 12px; }
}
@media (max-width: 400px) {
  :where(:root) { --tool-pad: 8px; }
}
/* (a phone on its side: the table needs every pixel of height, so the bar
   is as short as its tools allow) */
@media (max-height: 520px) {
  :where(:root) { --bar-h: 30px; }
}
@media (max-width: 560px) {
  :where(:root) { --sheet-pad: 16px; }
}
@media (pointer: coarse) {
  :where(:root) { --tool-h: 44px; }
}
/* guide:end scale */

/* ── the tokens the kit reads, with the room's names to fall back on ──── */
/* guide:start fallbacks */
:where(.house-scrim, .house-toasts, .house-banner, .house-splash, .house-announce, .house-cheer, .house-options, .house-section, .house-setting, .house-seg) {
  --_surface: var(--house-surface, var(--sheet));
  --_ink: var(--house-ink, var(--ink));
  --_soft: var(--house-soft, var(--soft));
  --_edge: var(--house-edge, var(--rail));
  --_radius: var(--house-radius, var(--rail-radius, 14px));
  --_line: var(--house-line, color-mix(in srgb, var(--_ink) 14%, transparent));
  --_field-edge: var(--house-field-edge, var(--field-edge, 1.5px solid color-mix(in srgb, currentColor 50%, transparent)));
  --_btn-radius: var(--house-btn-radius, var(--btn-radius, 8px));
  --_display: var(--house-display, var(--display));
  --_display-weight: var(--house-display-weight, var(--display-weight, 400));
  --_font: var(--house-font, var(--ui-font));
  --_focus: var(--house-focus, var(--focus, var(--_ink)));
  --_turn: var(--house-turn, var(--turn, var(--_ink)));
  --_turn-ink: var(--house-turn-ink, var(--turn-ink, var(--_surface)));
  --_toast-edge: var(--house-toast-edge, var(--chip-edge, var(--_edge)));
  --_scrim: var(--house-scrim, rgba(0, 0, 0, .55));
  --_shadow: var(--house-shadow, 0 24px 64px rgba(0, 0, 0, .45));
}
/* guide:end fallbacks */

/* ── focus, key caps, the page while a sheet is up ─────────────────── */
/* One ring everywhere, never removed: 2px in the ink with a 2px gap. (No
   specificity: a game drawing its own ring keeps it.) Yellow is never focus. */
:where(:focus-visible) { outline: 2px solid var(--house-focus, var(--focus, currentColor)); outline-offset: 2px; }
:where(.house-scrim, .house-toasts, .house-setting, .house-seg) :focus-visible { outline: 2px solid var(--_focus); outline-offset: 2px; }

/* ── the way up: the arrow at the top left of every bar ────────────────
   One component for every game (house/nav.js, templates/house/back.html):
   always the same place (the bar's first thing, at the gutter), a finger
   wide and tall, the same arrow and ring. It's the page's ink, so a game
   re-skins it with the tokens it already has. In a bar only 30px tall (a
   phone on its side) its margins give back what its 44px takes. */
.house-back {
  flex: none; display: inline-grid; place-items: center; box-sizing: border-box;
  width: 44px; height: 44px; margin: calc((var(--bar-h) - 44px) / 2) 0; padding: 0;
  border: 0; border-radius: var(--house-btn-radius, var(--btn-radius, 8px)); background: transparent;
  color: var(--house-ink, var(--ink, currentColor)); font: inherit; text-decoration: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* (over what's beside or under it: in a bar only 30px tall its square reaches past the bar) */
  position: relative; z-index: 1;
}
.house-back svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; }
@media (hover: hover) { .house-back:hover { background: color-mix(in srgb, currentColor 12%, transparent); } }
.house-back:focus-visible { outline: 2px solid var(--house-focus, var(--focus, currentColor)); outline-offset: 2px; }

/* Key caps show only while shortcuts are on and there's a mouse (keys.js
   showKeyCaps); hidden, they keep their space, so the button holds its size.
   A disabled button keeps its cap, dimmed with it: a cap hidden in its
   space would push the button's words off its middle. On a touch screen,
   where caps never show, they take no space at all. Its letter sits in the
   cap's middle in any face: the cap is trimmed to the cap height and the
   baseline (.house-glyph, "fine details" below), padded evenly round it.
   Shown, a cap inherits its button's visibility rather than setting its
   own: a button hidden in its space (a dock's empty slot, a switch moved
   aside) takes its cap with it. Never give a cap `visibility: visible`. */
kbd.house-key {
  font: 700 12px/1 var(--house-font, var(--ui-font, inherit)); padding: 3.5px 5px; margin-left: 4px;
  border: 1px solid currentColor; border-radius: 4px; visibility: hidden;
  text-box: trim-both cap alphabetic;
}
:root[data-house-keys="on"] kbd.house-key { visibility: inherit; }
@media (pointer: coarse) { kbd.house-key { display: none; } }

/* ── fine details (docs/design-language.md, "Fine details") ─────────── */
/* A glyph in a box (a badge, a token, a count, a seat's initials): its
   capitals and figures in the box's middle whatever the face's ascent and
   descent, its line trimmed to the cap height and the baseline. Put it on
   the box itself when that's a block, an inline-block or a button (a fixed
   height centers it with align-content: center; otherwise pad it evenly),
   or on the glyph's own span inside a flex or grid box. Where text-box
   isn't supported it's as it was. */
:where(.house-glyph) { text-box: trim-both cap alphabetic; }
/* A finger's reach: on a touch screen, a control drawn smaller than 44px
   (a link in a line, a compact switch) is pressed anywhere in the
   44px round its middle, without growing (an invisible ::before; not for
   a control that draws its own ::before). */
@media (pointer: coarse) {
  :where(.house-reach, .house-post a) { position: relative; }
  :where(.house-reach, .house-post a)::before { content: ''; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: max(100%, 44px); translate: -50% -50%; }
}

html.house-locked { overflow: hidden; }
.house-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ── sheets ─────────────────────────────────────────────────────────── */
.house-scrim {
  position: fixed; inset: 0; z-index: 70; display: grid; place-items: center;
  padding: var(--s3, 16px); background: var(--_scrim);
  animation: house-fade var(--m-sheet-in) ease-out both;
}
.house-scrim.house-going { animation: house-fade-out var(--m-sheet-out) ease-in both; pointer-events: none; }
.house-sheet {
  position: relative; display: flex; flex-direction: column; box-sizing: border-box;
  width: min(var(--house-sheet-width, 600px), 100%); max-height: calc(100dvh - 2 * var(--s3, 16px));
  background: var(--_surface); color: var(--_ink); border: var(--_edge); border-radius: var(--_radius);
  box-shadow: var(--_shadow); font-family: var(--_font); outline: none; overflow: hidden;
  animation: house-rise var(--m-sheet-in) var(--ease-out) both;
}
.house-sheet.house-wide { --house-sheet-width: 860px; }
/* How to play's last line: how the game works, in the technical guide
   (nav.js guideLink(), docs/adr/0035). Quiet, under a rule, across both
   columns of a two-column sheet; a finger tall on a touch screen. */
.house-guide { column-span: all; clear: both; margin: var(--s4, 24px) 0 0; padding-top: var(--s2, 8px); border-top: 1px solid var(--_line); font-size: var(--t-note, 14px); line-height: var(--lh-note); color: var(--_soft); }
.house-body .house-guide { margin-top: var(--s4, 24px); }  /* (over a body's own p { margin: 0 }) */
.house-guide a { color: inherit; text-underline-offset: 3px; }
@media (pointer: coarse) { .house-guide a { display: inline-flex; align-items: center; min-height: 44px; } }
.house-head { display: flex; align-items: flex-start; gap: var(--s2, 8px); padding: var(--sheet-pad) var(--sheet-pad) var(--s2, 8px); }
.house-titles { flex: 1; min-width: 0; }
.house-kicker { margin: 0 0 var(--s1, 4px); font: 700 var(--t-kicker)/1.3 var(--_font); letter-spacing: var(--kicker-spacing); text-transform: uppercase; color: var(--_soft); }
/* A figure (docs/design-language.md, "The glance"): the number that says how
   near the end is, or the score. Bold, in ink, in figures that don't jump as
   they change; its noun beside it, smaller and soft, names it. The face is
   whatever it sits in. */
.house-figure { font-size: var(--t-figure, 20px); font-weight: var(--w-figure, 800); line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--house-ink, var(--ink)); white-space: nowrap; }
.house-figure-noun { margin-left: .3em; font-size: var(--t-note, 14px); font-weight: 600; color: var(--house-soft, var(--soft)); }
.house-title { margin: 0; font-family: var(--_display); font-weight: var(--_display-weight); font-size: var(--t-title); line-height: 1.15; }
/* ✕ ("Close"): a quiet button, a finger wide and tall (whatever a game's
   quiet buttons are), at the top right; its ✕ is drawn (nav.js closeIcon),
   so it sits in the middle of the button in every game's face. */
.house-sheet .house-x {
  flex: none; display: inline-grid; place-items: center; box-sizing: border-box; min-width: 44px; min-height: 44px;
  margin: calc(-1 * var(--s2, 8px)) calc(-1 * var(--s3, 16px)) 0 0; padding: 0; font-size: 18px; line-height: 1; text-decoration: none;
}
svg.house-close { display: block; width: 1.35em; height: 1.35em; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
/* A table's clock still running under the sheet, in a turn-yellow pill. */
.house-sheetclock {
  flex: none; align-self: center; margin: 0; padding: 3px 10px; border-radius: 99px;
  background: var(--_turn); color: var(--_turn-ink); font: 800 13px/1.3 var(--_font); font-variant-numeric: tabular-nums;
}
.house-body { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: var(--s2, 8px) var(--sheet-pad) var(--s3, 16px); }
.house-body > :first-child { margin-top: 0; }
.house-body h3 { font-family: var(--_display); font-weight: var(--_display-weight); font-size: var(--t-heading, 20px); line-height: var(--lh-heading); margin: var(--s4, 24px) 0 var(--s2, 8px); }
/* The foot: the primary at the right end, secondaries to its left, quiet
   ones at the far left (sheet.js actionRow puts them in that order). */
.house-foot {
  display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--s2, 8px);
  padding: var(--s3, 16px) var(--sheet-pad) var(--sheet-pad); border-top: 1px solid var(--_line);
}
.house-foot > [data-weight="quiet"] + :not([data-weight="quiet"]) { margin-left: auto; }
/* (every action in a foot is a button a finger tall, quiet ones too, whatever a game's quiet buttons are elsewhere) */
.house-sheet .house-foot > :is(button, a) { min-height: 44px; }

/* The result sheet rises over the lower part of the board, on a lighter
   scrim, so the celebration above stays in view. */
.house-scrim-result { place-items: end center; background: var(--house-result-scrim, rgba(0, 0, 0, .3)); }
.house-scrim-result .house-sheet { --house-sheet-width: 480px; max-height: min(78dvh, calc(100dvh - 2 * var(--s3, 16px))); }
.house-result .house-head { text-align: center; }
.house-result .house-x { position: absolute; top: var(--s3, 16px); right: var(--s3, 16px); margin: 0; }
.house-result .house-titles { padding-inline: 36px; }
.house-result-body { display: flex; flex-direction: column; align-items: center; gap: var(--s2, 8px); text-align: center; }
.house-emblem { display: grid; place-items: center; }
/* A game's own milestone ("New best"), a tag in the turn color (ink on the
   sheet where a game has none) that pops in as the sheet opens, a beat
   late so the eye's already there; still under reduced motion. */
.house-news { margin: 0; display: flex; justify-content: center; }
.house-news > span {
  padding: 3px 12px; border-radius: 999px; font-weight: 700; font-size: var(--t-small, 14px); letter-spacing: .02em;
  background: var(--_turn); color: var(--_turn-ink);
  animation: house-news calc(var(--m-pop, 200ms) * 2) cubic-bezier(.3, .7, .3, 1.4) var(--m-sheet-in, 150ms) both;
}
@keyframes house-news { from { opacity: 0; transform: scale(.6); } }
@media (prefers-reduced-motion: reduce) { .house-news > span { animation: none; } }
.house-facts { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2, 8px) var(--s4, 24px); }
.house-fact { display: flex; flex-direction: column; align-items: center; }
.house-fact b { font-family: var(--_display); font-weight: var(--_display-weight); font-size: 32px; line-height: 1.1; font-variant-numeric: lining-nums tabular-nums; }
.house-fact span, .house-compare p { font-size: var(--t-note, 14px); color: var(--_soft); }
.house-compare p { margin: 0; }
/* The post line keeps its two lines, so a message arriving moves nothing. */
.house-post { margin: 0; min-height: 2.9em; max-width: 30em; font-size: var(--t-note, 14px); color: var(--_soft); }

/* ── Options ────────────────────────────────────────────────────────── */
.house-section + .house-section { margin-top: var(--s4, 24px); }
.house-section > h3 { margin: 0 0 var(--s1, 4px); }
.house-note { margin: 0 0 var(--s2, 8px); font-size: var(--t-note, 14px); color: var(--_soft); }
/* The house setting pattern (house rule 8): words at the left, a short
   control at the right; the controls in a column share an edge and a width,
   so the rows line up; a long one (.house-under) goes under the words. */
.house-setting {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2, 8px) var(--s3, 16px);
  padding: 12px 0; border-bottom: 1px solid var(--_line); color: var(--_ink);
}
.house-setting:last-child { border-bottom: 0; }
.house-setting-text { display: flex; flex-direction: column; flex: 1 1 12em; min-width: 0; }
.house-setting-label { font-size: var(--t-label, 16px); font-weight: 600; line-height: 1.3; }
.house-setting-hint { font-size: var(--t-note, 14px); line-height: 1.4; color: var(--_soft); }
.house-setting > .house-seg { flex: none; width: var(--house-control-width, 12em); }
.house-setting.house-under { flex-direction: column; align-items: stretch; }
.house-setting.house-under > .house-seg { width: 100%; }
/* (in a column the words' flex basis would be a height: they keep their own) */
.house-setting.house-under > .house-setting-text { flex: none; }

/* Choosing isn't doing (house rule 3): a pick is a tint, an inner ring and
   bold, never the fill; every choice as wide as the widest in bold, so a
   pick never nudges its neighbors. */
.house-seg {
  display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 2px; padding: 3px; box-sizing: border-box;
  border: var(--_field-edge); border-radius: var(--_btn-radius); color: var(--_ink);
}
.house-seg > button {
  appearance: none; min-width: 0; min-height: 38px; padding: 6px 12px; border: 0; cursor: pointer;
  border-radius: max(0px, calc(var(--_btn-radius) - 3px)); background: transparent; color: inherit;
  font: inherit; font-size: 15px; font-weight: 500; line-height: 1.2; text-wrap: balance;
}
/* (a choice too long for its share of the row wraps in it, rather than running into its neighbor) */
.house-seg > button::after { content: attr(data-label); display: block; height: 0; overflow: hidden; visibility: hidden; font-weight: var(--pick-weight, 700); }
.house-seg > button:hover { background: color-mix(in srgb, currentColor 8%, transparent); }
.house-seg > button[aria-pressed="true"] { background: var(--pick-tint); box-shadow: var(--pick-ring); font-weight: var(--pick-weight); }

/* The Home Screen row at the end of Options (install.js): a button where
   the other rows have a choice, as wide as their controls. */
.house-setting > .house-action { flex: none; width: var(--house-control-width, 12em); }
@media (max-width: 560px) { .house-setting > .house-action { width: var(--house-control-width-phone, 10em); } }
@media (max-width: 360px) { .house-setting > .house-action { width: 100%; } }

/* ── Feedback (feedback.js, docs/adr/0038) ─────────────────────────── */
/* The footer's "Feedback", for a signed-in player: a word in the line, like
   the links beside it, though it opens a sheet. */
.house-feedback {
  appearance: none; margin: 0; padding: 0; border: 0; background: none; color: inherit; cursor: pointer;
  font: inherit; text-decoration: underline; text-underline-offset: 3px;
}
/* The sheet: a few words, the box, Dictate where there's speech recognition,
   the screenshot's checkbox, and a line for what went wrong. */
.house-fb .house-body { display: flex; flex-direction: column; gap: var(--s2, 8px); }
.house-fb .house-body > p { margin: 0; }
.house-fb .house-body > .house-fb-lead { margin-bottom: var(--s2, 8px); font-size: var(--t-note, 14px); line-height: var(--lh-note, 1.4); color: var(--_soft); }
.house-fb-label { font-size: var(--t-label, 16px); font-weight: var(--w-label, 600); }
.house-fb-text {
  display: block; width: 100%; box-sizing: border-box; min-height: 8.5em; max-height: 40vh; resize: vertical; margin: 0;
  padding: 10px 12px; border: var(--_field-edge); border-radius: var(--_btn-radius); background: transparent; color: var(--_ink);
  font: 16px/1.45 var(--_font); /* (16px: iOS doesn't zoom in on it) */
}
.house-fb-tools { display: flex; justify-content: flex-start; }
.house-fb-mic { display: inline-flex; align-items: center; gap: 6px; }
.house-fb-mic[aria-pressed="true"] { background: var(--pick-tint); box-shadow: var(--pick-ring); font-weight: var(--pick-weight, 700); }
.house-fb-check { display: flex; align-items: center; gap: 10px; min-height: 44px; font-size: var(--t-body, 16px); cursor: pointer; }
.house-fb-check input { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--_turn); }
.house-fb-status { font-size: var(--t-note, 14px); line-height: var(--lh-note, 1.4); color: var(--_ink); }

/* ── the Home Screen sheet (install.js) ──────────────────────────────── */
.house-install .house-body { display: flex; flex-direction: column; gap: var(--s3, 16px); }
.house-install .house-body > * { margin: 0; }
.house-install .house-lead { font-size: var(--t-lead, 16px); line-height: var(--lh-body, 1.45); color: var(--_ink); }
/* the app as it will sit on the Home Screen: its icon, its name, what it's for */
.house-install-top { display: flex; align-items: center; gap: var(--s3, 16px); }
.house-install-intro { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.house-install-icon { flex: none; width: 60px; height: 60px; border-radius: 14px; box-shadow: 0 0 0 1px color-mix(in srgb, var(--_ink) 22%, transparent), 0 6px 14px rgba(0, 0, 0, .3); }
.house-install-name { margin: 0; font: 600 var(--t-label, 16px)/1.3 var(--_font); color: var(--_ink); }
/* the steps: a number, then the words, with iOS's own glyphs inline */
.house-steps { display: flex; flex-direction: column; gap: var(--s3, 16px); margin: 0; padding: 0; list-style: none; counter-reset: house-step; }
.house-step { display: flex; align-items: flex-start; gap: var(--s3, 16px); font-size: var(--t-body, 16px); line-height: var(--lh-body, 1.45); counter-increment: house-step; }
.house-step::before {
  content: counter(house-step); flex: none; display: grid; place-items: center; width: 28px; height: 28px; margin-top: -1px;
  border-radius: 50%; border: 1.5px solid currentColor; font: 700 14px/1 var(--_font); font-variant-numeric: tabular-nums;
}
.house-step b { font-weight: 700; }
.house-glyph { display: inline-block; width: 1.2em; height: 1.2em; vertical-align: -.25em; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }

/* ── toasts, banners, the splash ───────────────────────────────────── */
/* Toasts: at the top of the play area, just under the page's top bar
   (toast.js measures it), out of the middle where banners, prompts and
   announcements play and clear of the dock; at the window's top while a
   sheet is open. Only a toast's one action takes clicks. */
.house-toasts {
  position: fixed; left: var(--house-toast-x, 50%); top: var(--house-toast-top, calc(var(--s2, 8px) + env(safe-area-inset-top, 0px))); translate: -50% 0; z-index: 80; pointer-events: none;
  width: max-content; max-width: min(460px, calc(100% - 2 * var(--s3, 16px)));
}
html.house-locked .house-toasts { top: calc(var(--s2, 8px) + env(safe-area-inset-top, 0px)); left: 50%; }
.house-toast {
  display: flex; align-items: center; justify-content: center; gap: var(--s2, 8px) var(--s3, 16px); flex-wrap: wrap;
  padding: 10px 18px; border: var(--_toast-edge); border-radius: 14px; background: var(--_surface); color: var(--_ink);
  font: 15px/1.4 var(--_font); text-align: center; box-shadow: 0 10px 28px rgba(0, 0, 0, .4);
  animation: house-rise var(--m-sheet-in) var(--ease-out) both;
}
.house-toast:empty { display: none; }
.house-toast.house-going { animation: house-fade-out var(--m-sheet-out) ease-in both; }
.house-toast-action { pointer-events: auto; }

/* A banner: a game moment over the middle of the table, taking no clicks. */
.house-banner {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%; z-index: 45; pointer-events: none;
  padding: var(--s2, 8px) var(--s4, 24px); border: var(--_edge); border-radius: var(--_radius);
  background: var(--_surface); color: var(--_ink); box-shadow: inset 0 -4px 0 var(--_turn), var(--_shadow);
  font-family: var(--_display); font-weight: var(--_display-weight); font-size: clamp(26px, 5vw, 44px); line-height: 1.1; white-space: nowrap;
}
body > .house-banner { position: fixed; }

/* The splash at a new hand: over the table, never in the way of a click. */
.house-splash { position: absolute; inset: 0; z-index: 45; display: grid; place-items: center; pointer-events: none; background: rgba(0, 0, 0, .25); }
body > .house-splash { position: fixed; }
.house-splash-card {
  max-width: min(620px, calc(100% - 24px)); padding: 20px 30px 26px; text-align: center;
  border: var(--_edge); border-radius: var(--_radius); background: var(--_surface); color: var(--_ink); box-shadow: var(--_shadow);
  font-family: var(--_font);
}
/* The strong announcement (announce.js): a band in the turn color across
   the table, over everything but toasts, never in the way of a click. */
.house-announce { position: fixed; inset: 0; z-index: 75; pointer-events: none; background: var(--house-announce-scrim, rgba(0, 0, 0, .28)); }
.house-announce-band {
  position: absolute; left: 0; right: 0; top: 50%; transform: translate(0, -50%);
  display: flex; align-items: center; justify-content: center; gap: var(--s3, 16px);
  padding: 18px var(--gutter) 22px; background: var(--_turn); color: var(--_turn-ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--_turn-ink) 22%, transparent), var(--_shadow); text-align: center; font-family: var(--_font);
}
.house-announce-text { display: grid; justify-items: center; gap: 4px; min-width: 0; }
.house-announce-kicker { margin: 0; font-size: var(--t-kicker, 12px); letter-spacing: var(--kicker-spacing, .14em); text-transform: uppercase; font-weight: 700; opacity: .85; }
.house-announce-title {
  margin: 0; font-family: var(--_display); font-weight: var(--_display-weight); font-size: clamp(34px, 8.5vw, 68px); line-height: var(--lh-display, 1.1);
  text-wrap: balance;
}
.house-announce-word { display: inline-block; }
.house-announce-sub { margin: 0; max-width: 40ch; font-size: var(--t-lead, 16px); line-height: var(--lh-note, 1.4); text-wrap: pretty; }
.house-announce-art { flex: none; display: grid; place-items: center; }

/* A celebration (celebrate.js): one canvas, taking no clicks. With a result
   sheet it's inside the sheet's scrim, under the sheet; on a page, over it. */
.house-cheer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.house-scrim > .house-sheet { position: relative; }
.house-cheer-page { position: fixed; z-index: 65; }
/* On a phone, where the sheet covers the board: a sheet held below the
   window while its celebration's first moments play (celebrate.js), and a
   celebration's copy over a sheet already up, for a moment. */
.house-scrim > .house-sheet.house-held { animation: none; }
.house-scrim > .house-cheer-over { z-index: 1; }

/* Where news landed lights up once (a highlight, the same with reduced motion). */
.house-pulse { animation: house-pulse var(--m-pulse, 1200ms) ease-out; }

@keyframes house-fade { from { opacity: 0; } }
@keyframes house-fade-out { to { opacity: 0; } }
@keyframes house-rise { from { opacity: 0; transform: translateY(8px); } }
/* Your move (cue.js): what to press, ringed in the turn color. It breathes
   three times and then holds still until the player acts; under reduced
   motion it's the still ring from the start (the status line says it too).
   An outline, not a shadow, and !important: the ring is a passing state on
   someone else's control, so it must show over whatever the control draws
   (a hand already outlined in the turn color, a button that's `all: unset`).
   It breathes through a registered property, which an animation can move
   even under !important. */
@property --house-breath { syntax: '<length>'; inherits: false; initial-value: 2px; }
.house-beckon {
  outline: 3px solid color-mix(in srgb, var(--house-turn, var(--turn, currentColor)) 75%, transparent) !important;
  outline-offset: var(--house-breath) !important;
  animation: house-beckon var(--m-beckon, 1600ms) ease-in-out 3;
}
@keyframes house-beckon { 50% { --house-breath: 7px; } }
@media (prefers-reduced-motion: reduce) { .house-beckon { animation: none; } }

/* The prompt's card (cue.js): the splash's card saying what's yours to do. */
.house-prompt { display: grid; justify-items: center; gap: 6px; }
.house-prompt-kicker {
  margin: 0; font-size: var(--t-kicker, 12px); letter-spacing: .12em; text-transform: uppercase; font-weight: 700;
  color: var(--_soft);
}
.house-prompt-title { margin: 0; font-family: var(--_display); font-weight: var(--_display-weight); font-size: clamp(26px, 6vw, 40px); line-height: 1.1; text-wrap: balance; }
.house-prompt-sub { margin: 0; max-width: 34ch; color: var(--_soft); font-size: var(--t-lead, 16px); line-height: 1.35; text-wrap: pretty; }

@keyframes house-pulse {
  20%, 45% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--house-turn, var(--turn, currentColor)) 40%, transparent); }
}

/* ── phones: sheets come up from the bottom; a foot's buttons stack ── */
@media (max-width: 560px) {
  .house-scrim { place-items: end stretch; padding: env(safe-area-inset-top, 0px) 0 0; }
  .house-sheet, .house-scrim-result .house-sheet {
    width: 100%; max-height: calc(100dvh - var(--s5, 40px)); border-bottom: 0;
    border-radius: var(--_radius) var(--_radius) 0 0;
  }
  .house-foot { flex-direction: column-reverse; align-items: stretch; padding-bottom: calc(var(--sheet-pad) + env(safe-area-inset-bottom, 0px)); }
  .house-foot > * { width: 100%; }
  .house-foot > [data-weight="quiet"] + :not([data-weight="quiet"]) { margin-left: 0; }
  .house-setting > .house-seg { width: var(--house-control-width-phone, 10em); }
}
@media (max-width: 360px) {
  .house-setting > .house-seg { width: 100%; }
}
/* (on a phone a choice's share of the row is narrow: its words keep to its middle with less room each side, rather than running past it) */
@media (max-width: 640px) {
  .house-seg > button { padding-inline: 8px; }
}
/* (and on the narrowest, the choices share the row by their words, not
   equally, so "Medium" in bold has its room beside "Easy" and "Hard": each
   is still as wide as its own words in bold, so a pick moves nothing) */
@media (max-width: 360px) {
  .house-seg { grid-auto-columns: auto; }
  .house-seg > button { padding-inline: 6px; }
}
@media (pointer: coarse) {
  .house-seg > button { min-height: 44px; }
}

/* Reduced motion: fades of 150ms stay; nothing rises or travels. */
@media (prefers-reduced-motion: reduce) {
  .house-sheet, .house-toast { animation-name: house-fade; }
  .house-toast.house-going { animation-name: house-fade-out; }
}
