/* Nibbles theme - the shared cuteness: palette, cards, chips, buttons,
   floaties, toasts. Every game page loads this before its own stylesheet.
   Kit rule: nothing game-specific lives here.

   Colour doctrine: pink is the game, mint is you, lavender helps, gold
   celebrates, red objects, sky explains. A colour never means two of those
   on one screen. Every colour lives in these two :root blocks - the wiring
   test fails any hex or rgb() that strays into a component rule. */

/* ================================================================= Nibbles
   A soft, candy-coloured theme. Mobile first; everything scales off the board
   width so the same layout works on a phone and on a desktop browser.
   ========================================================================= */

:root {
  --pink:        #ff8fbe;
  --pink-deep:   #f0619a;
  --pink-soft:   #ffdcec;
  --pink-press:  #d9548c;                    /* the 3D under-edge of pink toys */
  --mint:        #8fe3cc;
  --mint-deep:   #3fbfa2;
  --mint-press:  #2fa88c;
  --gold:        #ffe27a;                    /* celebration: unique, leader, streak */
  --gold-soft:   #ffe9a3;
  --gold-deep:   #ffc93c;
  --gold-press:  #d99a00;                    /* amber text on gold washes */
  --gold-ink:    #7a4c00;                    /* ink on bright gold fills, both themes */
  --lavender:    #c3b1ff;
  --lavender-soft: #ded2ff;
  --lavender-deep: #a78bff;
  --lavender-press:#8a6ce0;                  /* purple text on lavender washes */
  --sky:         #a5d8ff;                    /* the trail and confetti pastel */
  --peach:       #ffb27a;                    /* the epic word tier */
  --peach-deep:  #e8722a;
  --cream:       #fffaf6;
  --ink:         #5c4657;
  --ink-soft:    #786675;
  --ink-faint:   #847082;                    /* placeholders and empty states: 4.5 on white */
  --danger:      #ff7a7a;
  --danger-soft: #ff8f8f;
  --danger-deep: #e05a5a;

  /* Glow triplets: rgb components for shadows and halos, alpha at the use
     site. --glow is the neutral mauve every card casts; the accent glows
     keep their hue in both themes. */
  --glow:          190, 140, 170;
  --pink-glow:     230, 100, 160;
  --mint-glow:     45, 160, 135;
  --lavender-glow: 150, 120, 220;

  /* Surfaces and edges. Everything below paints through these, so a theme
     is a palette swap and never a second copy of the rules. */
  --page-1:      #fff1f8;
  --page-2:      #f4f0ff;
  --page-3:      #eafaf6;
  --surface:     rgba(255, 255, 255, .78);   /* a card, over the page */
  --surface-2:   rgba(255, 255, 255, .5);    /* the quieter card */
  --surface-3:   #ffffff;                    /* solid: chips, inputs, pills */
  --edge:         #ffffff;                   /* the card's own rim */
  --edge-soft:   #ddc7d6;                    /* hairlines; never ink (that is --ink-faint) */
  /* White on a pastel is a deliberate choice, not an oversight: it reads
     1.50 on mint and 2.12 on pink, well under WCAG's 4.5. The alternatives
     were mocked up and measured, and the candy look won. */
  --on-accent:   #ffffff;                    /* ink on a pink or mint fill */
  --on-bright:   #402e3d;                    /* ink on gold and lavender, which
                                                stay light in both themes */
  --on-dark:     #ffffff;                    /* ink on the toast, always dark */
  --emboss:      #ffffff;                    /* the little raised text shadow */
  --card-shadow: rgba(190, 140, 170, .14);
  --tint-gold:   #fffaeb;                    /* a gold wash: best words, leaders */
  --veil:        rgba(255, 245, 250, .88);   /* pause and countdown, over the board */
  --scrim:       rgba(48, 34, 45, .55);      /* the dimmer behind every modal */
  --toast-bg:    rgba(92, 70, 87, .94);
  --tint-pink:   #fff5fa;                    /* the sudoku grid's quiet washes */
  --tint-pink-2: #ffeaf4;
  --cell-peer:   var(--tint-pink-2);          /* the selected row, column and box */
  --cell-match:  var(--pink-soft);            /* cells sharing the selected digit */
  /* The selected cell. It used to be the brightest thing on the board and
     carried white, which read 2.12. Now it is a calm pink, and the digit
     keeps the colour that says whose it is; only pencil marks take the
     cell's ink, dark at 6.99. */
  --cell-sel:    #ffc2dc;
  --cell-sel-2:  #ffa8cb;
  --cell-sel-ink:  var(--on-bright);
  --tint-lavender: #ece3ff;
  --tint-mint:   #eafff7;
  --tint-sky:    #eaf4ff;

  /* The semantic layer: what a feeling paints with, in both games. */
  --me:        var(--mint-deep);
  --correct:   var(--mint-deep);
  --wrong:     var(--danger);
  --hint:      var(--lavender);
  --evidence:  var(--tint-sky);              /* the lesson's "because of these" wash */

  /* The fills, written once. Built from tokens that flip with the theme,
     so they need no dark values of their own. */
  --pink-fill:  linear-gradient(160deg, var(--pink), var(--pink-deep));   /* a chosen thing */
  --gold-fill:  linear-gradient(160deg, var(--gold), var(--gold-deep));   /* a celebrated one */
  --pink-wash:  linear-gradient(160deg, var(--surface-3), var(--pink-soft));   /* a lit surface */
  --gold-wash:  linear-gradient(160deg, var(--surface-3), var(--tint-gold));   /* a celebrated surface */
  --hint-fill:  linear-gradient(160deg, var(--lavender), var(--lavender-deep));   /* a hint */
  --card-lift:  0 10px 24px var(--card-shadow);   /* the shadow a card and a dropdown float on */
  --brand-text: linear-gradient(100deg, var(--pink-deep), var(--lavender) 55%, var(--mint-deep));

  --tile-face:   #ffffff;
  --tile-edge:   #f3d9e6;

  /* The radius scale: the same kind of control wears the same corner. */
  --r-xs:   8px;                             /* badges, marks, calendar days */
  --r-sm:   12px;                            /* small word chips, tower scores */
  --r-md:   16px;                            /* chips, keys, inputs, foot buttons */
  --r-lg:   22px;                            /* cards, boards, the big button */
  --r-pill: 999px;                           /* identity pills */
  --radius: var(--r-lg);
  --shadow:      0 8px 0 rgba(206, 160, 186, .28), 0 14px 28px rgba(190, 130, 165, .18);

  /* The play column: what a board, a HUD, a pad and a foot row are wide.
     The viewport minus the app's side padding, capped; each game moves
     the cap where its screens need it. One cap for both games (the sudoku
     used to stop at 420): its 9x9 wears the extra 20px as slightly larger
     cells, and the two games line up on a tablet. */
  --play-w: min(100vw - 32px, 440px);

  /* What the browser paints around the page; prefs.ts mirrors it into
     the theme-color metas whenever the cog overrides the OS. */
  --browser-chrome: #ffdcec;

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* ------------------------------------------------------------------- dark
   Only the tokens move, so every rule above keeps working untouched. The
   page head resolves "auto" against the phone before the first frame and
   stamps data-theme, so there is exactly one dark block to keep in step
   and nothing ever flashes the wrong palette. */

:root[data-theme="dark"] {
  color-scheme: dark;

  --pink-soft:   #4b2f41;
  --gold:        #f5d06a;
  --gold-soft:   #55482a;
  --gold-press:  #f5b93c;                    /* amber text brightens on dark washes */
  --lavender:    #a892f0;
  --lavender-soft: #3d3260;
  --lavender-press:#b7a2f5;                  /* purple text brightens on dark washes */
  --peach-deep:  #f0854a;
  --cream:       #2c2431;
  --ink:         #f3e9f0;
  --ink-soft:    #b7a5b4;
  --ink-faint:   #a8959f;                    /* 4.6 on the dark input */

  --tile-face:   #3b3040;
  --tile-edge:   #56414f;
  --shadow:      0 8px 0 rgba(0, 0, 0, .34), 0 14px 28px rgba(0, 0, 0, .42);

  --page-1:      #251b28;
  --page-2:      #1f1b2e;
  --page-3:      #16242a;
  --surface:     rgba(58, 47, 63, .82);
  --surface-2:   rgba(58, 47, 63, .52);
  --surface-3:   #382e3d;
  --edge:        rgba(255, 255, 255, .09);
  --edge-soft:   #6a5566;
  --emboss:      rgba(0, 0, 0, .35);
  --on-bright:   #2b1f2a;
  --card-shadow: rgba(0, 0, 0, .45);
  --glow:        0, 0, 0;
  --tint-gold:   #3e3524;
  --veil:        rgba(28, 22, 32, .9);
  --scrim:       rgba(0, 0, 0, .6);
  --toast-bg:    rgba(112, 90, 106, .96);
  --tint-pink:   #322530;
  --tint-pink-2: #402c3a;
  /* Dark highlights lighten toward pink rather than darken: a lit cell
     should glow out of the board, not sink into it. Gently, though. At 45%
     the match wash was bright enough to swallow what stood on it: a mint
     digit read 2.34 and a pencil mark 2.30. At 25% the same digit reads
     3.46 and the wash still glows. */
  --cell-peer:   color-mix(in srgb, var(--surface-3), var(--pink) 10%);
  --cell-match:  color-mix(in srgb, var(--surface-3), var(--pink) 25%);
  /* Dark runs the selection the other way: a deep pink, with white for
     the pencil marks at 5.51 where the bright pink read 2.12. */
  --cell-sel:    #b0416b;
  --cell-sel-2:  #93325a;
  --cell-sel-ink:  var(--on-accent);
  --tint-lavender: #2f2747;
  --tint-mint:   #1f342f;
  --tint-sky:    #22303f;
  --browser-chrome: #251b28;
}

/* Nunito rides with the site (one variable woff2, latin subset), so every
   OS gets the same rounded face. The old stack named fonts it never
   shipped, and the brand's typeface depended on which phone opened it. */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/fonts/nunito-latin.ba344451.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;
}

/* The drifting snacks are decoration, and the cog can switch them off. */
:root.no-sky .sky { display: none; }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Several elements below set `display`, which would otherwise beat the browser
   default for [hidden] and leave them stuck on screen. */
[hidden] { display: none !important; }

/* For the keyworded page h1 crawlers read and players never see; the
   visible hero heading is an h2 wearing .title. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  overscroll-behavior: none;
  overflow-x: clip;   /* decorative bleed must never cause sideways scroll */
}

body {
  font-family: "Nunito", ui-rounded, "SF Pro Rounded", "Segoe UI",
               system-ui, -apple-system, sans-serif;
  color: var(--ink);
  background: linear-gradient(170deg, var(--page-1) 0%, var(--page-2) 45%, var(--page-3) 100%);
  background-attachment: fixed;
  -webkit-user-select: none;
  user-select: none;
}

/* --------------------------------------------------------- background fluff */

/* The snacks drift behind the app, but the cards above them are
   translucent, so near the top and bottom they read as sitting on the HUD
   and the button row. Fading them out of those bands keeps them off the
   clock a player is racing without taking the charm away. */
.sky {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 15%, #000 85%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 15%, #000 85%, transparent 100%);
}

.floaty {
  position: absolute;
  left: var(--x);
  top: 100%;
  font-size: calc(26px * var(--s, 1));
  opacity: .5;
  animation: drift 22s linear infinite;
  animation-delay: var(--d, 0s);
}

@keyframes drift {
  from { transform: translateY(0) rotate(0deg); }
  to   { transform: translateY(-118vh) rotate(340deg); }
}

/* ------------------------------------------------------------------ layout */

#app {
  position: relative;
  z-index: 1;
  max-width: 520px;
  margin: 0 auto;
  padding: calc(14px + var(--safe-top)) 16px calc(20px + var(--safe-bottom));
}

.screen { display: none; }
/* Screens cut, they do not slide: a fade on the way in only made the
   page read as slow. */
.screen.is-active { display: flex; flex-direction: column; gap: 14px; }

/* -------------------------------------------------------------------- hero */

.hero { text-align: center; padding: 6px 0 0; }
.hero-tight { padding-top: 0; }

.mascot {
  font-size: 58px;
  line-height: 1;
  animation: bob 2.6s ease-in-out infinite;
  filter: drop-shadow(0 6px 10px rgba(var(--glow), .3));
}

@keyframes bob {
  0%, 100% { transform: translateY(0) rotate(-3deg); }
  50%      { transform: translateY(-8px) rotate(3deg); }
}

.title {
  margin: 6px 0 2px;
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -.5px;
  background: var(--brand-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.tagline { margin: 0; font-size: 14px; color: var(--ink-soft); }

/* ------------------------------------------------------------------- cards */

.card {
  background: var(--surface);
  backdrop-filter: blur(6px);
  border: 2px solid var(--edge);
  border-radius: var(--radius);
  padding: 16px;
  box-shadow: var(--card-lift);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.card-quiet { background: var(--surface-2); gap: 8px; }

.field { display: flex; flex-direction: column; gap: 8px; }

.field-label {
  font-size: 13px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .8px;
  color: var(--ink-soft);
}

.hint-text { margin: 0; font-size: 13px; color: var(--ink-soft); line-height: 1.45; }
.hint-text.error { color: var(--danger); font-weight: 700; }

/* ------------------------------------------------------------------- chips */

.chips { display: flex; flex-wrap: wrap; gap: 8px; }

.chip {
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-md);
  padding: 9px 14px;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, box-shadow .18s ease;
}

/* Grow to fill the row so a wrapped last option looks deliberate, not stranded. */
.chips .chip:not(.chip-tall) { flex: 1 1 auto; }

.chip:active { transform: scale(.94); }

.chip.is-on {
  background: var(--pink-fill);
  border-color: var(--pink-deep);
  color: var(--on-accent);
  box-shadow: 0 4px 0 rgba(var(--pink-glow), .35);
}

.chip-tall {
  flex: 1 1 0;
  min-width: 72px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 10px 6px;
}

.chip-tall b { font-size: 22px; line-height: 1.1; }
.chip-tall span { font-size: 13px; }
.chip-tall em { font-style: normal; font-size: 11px; opacity: .65; }

/* ----------------------------------------------------------------- toggles */

.toggles { display: flex; gap: 8px; }

.toggle {
  flex: 1;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px;
  border-radius: var(--r-md);
  border: 2px solid var(--pink-soft);
  background: var(--surface-3);
  color: var(--ink-soft);
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}

.toggle[aria-pressed="true"] {
  background: var(--pink-wash);
  border-color: var(--pink);
  color: var(--ink);
}

.toggle[aria-pressed="false"] .toggle-emoji { filter: grayscale(1); opacity: .5; }
.toggle:active { transform: scale(.96); }

/* The app's row on the play-together card: nearby parties in range. */
.nearby-hosts { display: flex; flex-direction: column; gap: 8px; }
.nearby-host {
  font: inherit;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-md);
  padding: 9px 12px;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.nearby-host:active { transform: scale(.98); }
.nearby-host .p-emoji { font-size: 22px; }
.nearby-host .p-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nearby-host .p-code { font-size: 12px; letter-spacing: 2px; color: var(--ink-soft); }

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

.big-button {
  font: inherit;
  font-size: 19px;
  font-weight: 800;
  color: var(--on-accent);
  background: var(--pink-fill);
  border: none;
  border-radius: var(--r-lg);
  padding: 17px;
  cursor: pointer;
  box-shadow: 0 6px 0 var(--pink-press), 0 14px 24px rgba(var(--pink-glow), .35);
  transition: box-shadow .1s ease;
}

.big-button:active {
  transform: translateY(4px);
  box-shadow: 0 2px 0 var(--pink-press), 0 8px 14px rgba(var(--pink-glow), .3);
}

.mini-button {
  font: inherit;
  font-size: 14px;
  font-weight: 800;
  color: var(--on-accent);
  background: linear-gradient(160deg, var(--mint), var(--mint-deep));
  border: none;
  border-radius: var(--r-md);
  padding: 11px 18px;
  cursor: pointer;
  box-shadow: 0 4px 0 rgba(var(--mint-glow), .55);
  transition: box-shadow .1s ease;
}

.mini-button:active { transform: translateY(3px); box-shadow: 0 1px 0 rgba(var(--mint-glow), .55); }

.mini-button.ghost {
  background: var(--surface-3);
  color: var(--ink-soft);
  box-shadow: 0 4px 0 var(--pink-soft);
}

.text-button {
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-soft);
  background: none;
  border: none;
  padding: 8px;
  cursor: pointer;
  text-decoration: underline dotted;
}

.join-row { display: flex; gap: 8px; }

.code-input {
  flex: 1;
  font: inherit;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 3px;
  text-align: center;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-md);
  padding: 10px;
  min-width: 0;
}

.code-input:focus { outline: none; border-color: var(--pink); }
.code-input::placeholder { color: var(--ink-faint); letter-spacing: 2px; }

/* ------------------------------------------------------------------ toast */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + var(--safe-bottom));
  transform: translate(-50%, 20px);
  background: var(--toast-bg);
  color: var(--on-dark);
  font-size: 14px;
  font-weight: 700;
  padding: 11px 18px;
  border-radius: var(--r-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease, transform .25s ease;
  z-index: 50;
  max-width: 86vw;
  text-align: center;
}

.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.happy { background: linear-gradient(160deg, var(--mint-deep), var(--mint-press)); }
.toast.sad { background: linear-gradient(160deg, var(--danger-soft), var(--danger-deep)); }

/* ------------------------------------------------------------ modal veil
   The one dimmer behind every modal: the settings panel, a word's story
   card, the report, the sudoku's win and daily cards. Modals never stack
   except the word card over the report, and those sit in DOM order, so
   one z-index serves them all.

   No backdrop blur: a full-screen blur over the still-animating screens
   behind (bobbing towers, the floaty sky) makes opening a modal visibly
   stutter. The tint and a solid card do the job. Particle layers (the
   word game's confetti) sit under 40, so nothing falls over a modal. */
.modal-veil {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: var(--scrim);
}

/* The card on the dimmer is solid. A plain .card is 78% surface with a
   backdrop blur, which over the scrim reads grey with the screen showing
   through; here the blur would be of a flat tint, for nothing. */
.modal-veil > .card {
  background: linear-gradient(160deg, var(--surface-3), var(--cream));
  backdrop-filter: none;
}

/* ------------------------------------------------------------ board veil
   The frosted panel that sits over the board itself while it cannot be
   played: paused, counting down, rolling a fresh puzzle. Absolute, so the
   board's wrapper positions it; each game only tunes the inset and radius
   to its own board. */
.board-veil {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--veil);
  backdrop-filter: blur(6px);
  border-radius: var(--r-lg);
  font-weight: 800;
}

/* 3.. 2.. 1.. GO! The countdown before a shared round, run by
   src/kit/countdown.ts over either game's board. */
.count-veil { pointer-events: none; }   /* input is gated by game state, not by this veil */

.count-num {
  font-size: 120px;
  font-weight: 800;
  color: var(--pink-deep);
  text-shadow: 0 6px 0 var(--emboss), 0 14px 30px rgba(var(--pink-glow), .4);
  /* Invisible until a number fires; .pop is re-added per number so the
     animation actually restarts for 3, 2, 1 AND go. */
  opacity: 0;
}

.count-num.pop { animation: count-pop .9s ease both; }
.count-num.go { font-size: 84px; color: var(--mint-deep); }

@keyframes count-pop {
  0%   { opacity: 0; transform: scale(2.2); }
  25%  { opacity: 1; transform: scale(1); }
  80%  { opacity: 1; transform: scale(1.05); }
  100% { opacity: 0; transform: scale(.8); }
}

/* ----------------------------------------------------------- settings cog
   Per-device preferences, built by src/kit/settings.ts. It opens from a
   real button rather than a floating cog: none of this is something a
   player changes often, so it does not need to follow them around. */

.set-panel { width: min(340px, 100%); max-height: 88vh; overflow-y: auto; }

.set-title {
  margin: 0;
  font-size: 19px;
  font-weight: 800;
  text-align: center;
}

.set-done { margin-top: 2px; }

/* The hub gives it a proper button; a game's setup screen a quiet link. */
.set-open { align-self: center; }

/* ------------------------------------------------------------ preferences */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .floaty { display: none; }
  /* The countdown's numbers live inside their animation, which ends at
     opacity 0: played in a frame, they were never seen. Without motion
     each number simply shows. */
  .count-num.pop { animation: none; opacity: 1; }
}

/* -------------------------------------------------------------- site nav
   The bento nav worn by the hub, the content pages and each game setup
   screen; never over a running round, the lobby or the results. Each game tab is a native details dropdown: zero JS, works on
   touch, and closes by tapping its tab again. */

.site-nav { display: flex; gap: 6px; justify-content: center; position: relative; z-index: 20; }
.site-nav > a, .site-nav summary {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  width: 82px;
  font-size: 11px;
  font-weight: 800;
  color: var(--ink-soft);
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-md);
  padding: 8px 4px 6px;
  text-decoration: none;
  cursor: pointer;
  list-style: none;
}
.site-nav summary::-webkit-details-marker { display: none; }
.site-nav > a b, .site-nav summary b { font-size: 21px; line-height: 1; }
.site-nav summary i { font-style: normal; font-size: 12px; opacity: .7; }
.site-nav > a.here, .site-nav summary.here, .site-nav details[open] summary {
  border-color: var(--pink);
  color: var(--ink);
  background: var(--pink-wash);
}
.site-nav details { position: relative; }
.site-nav .drop {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  min-width: 172px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-md);
  padding: 6px;
  box-shadow: var(--card-lift);
}
.site-nav .drop a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border-radius: var(--r-sm);
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.site-nav .drop a.here { background: var(--pink-soft); }

/* ------------------------------------------------------- foot buttons
   The side padding and the row gap ride --foot-fit, which src/kit/foot.ts
   sets to 1 whenever the row fits and lowers only as far as a narrow
   phone demands. */

.foot-button {
  font: inherit;
  font-size: 14px;
  font-weight: 800;
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-md);
  padding: 10px calc(14px * var(--foot-fit, 1));
  color: var(--ink);
  cursor: pointer;
  box-shadow: 0 4px 0 var(--pink-soft);
  transition: box-shadow .1s ease, opacity .2s ease;
}

.foot-button:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--pink-soft); }
.foot-button:disabled { opacity: .4; cursor: default; }
.foot-emoji { font-size: 19px; }

/* ------------------------------------------------------------ party look
   The identity, lobby and invite widgets every Nibbles game shares -
   each game's stylesheet only adds its own flavour on top. */

.name-input {
  text-transform: none;
  letter-spacing: .5px;
  font-size: 16px;
}
.name-input::placeholder { text-transform: none; letter-spacing: .5px; }

.emoji-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
}

.emoji-btn {
  font-size: 22px;
  line-height: 1;
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-sm);
  padding: 6px 8px;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.emoji-btn:active { transform: scale(.9); }
.emoji-btn.sel {
  border-color: var(--pink-deep);
  background: var(--pink-soft);
  transform: scale(1.12);
}

.lobby-code-card { text-align: center; }

/* The lobby's is a button (tap or Enter copies the invite); the invite
   card's is a plain block. Both wear this. */
.party-code-big {
  display: block;
  width: 100%;
  font: inherit;
  font-size: 44px;
  font-weight: 800;
  letter-spacing: 10px;
  padding: 0 0 0 10px;   /* optically recentre the tracked text */
  color: var(--pink-deep);
  text-shadow: 0 3px 0 var(--emboss);
  background: none;
  border: none;
}
/* Only the lobby's code does anything on tap; the invite card's and the
   guides' examples are plain blocks. */
button.party-code-big { cursor: pointer; }

.lobby-players { display: flex; flex-direction: column; gap: 8px; }

.lobby-player {
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-md);
  padding: 9px 12px;
  font-size: 14px;
  font-weight: 700;
}
.lobby-player .p-emoji {
  font-size: 22px;
  animation: bob 2.6s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
.lobby-player .p-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lobby-player .p-tag {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .5px;
  color: var(--on-bright);
  background: var(--gold);
  border-radius: var(--r-xs);
  padding: 2px 7px;
}
.lobby-player .p-total { font-size: 12px; color: var(--ink-soft); }
.lobby-player.away { opacity: .45; }
.lobby-player.away .p-emoji { filter: grayscale(1); }
/* The same row on a results card, wearing its crown. */
.lobby-player.winner { border-color: var(--gold); background: var(--tint-gold); }

.kick-btn {
  font: inherit;
  font-size: 13px;
  font-weight: 800;
  color: var(--ink-soft);
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-xs);
  width: 32px;    /* as much finger as a lobby row has room for */
  height: 32px;
  line-height: 1;
  cursor: pointer;
  flex: none;
}
.kick-btn:active { color: var(--danger); border-color: var(--danger); }

/* The winstreak badge (src/kit/party-client.ts): a star with the count
   inside, on a lobby row, a party pill or a results tower. */
.streak-star {
  position: relative;
  display: inline-block;
  font-size: 24px;
  line-height: 1;
  filter: drop-shadow(0 2px 3px rgba(var(--glow), .4));
}

.streak-star b {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-top: 3px;
  font-size: 10px;
  font-weight: 800;
  color: var(--gold-ink);
  text-shadow: 0 1px 0 color-mix(in srgb, var(--on-accent) 50%, transparent);
}

.lobby-player .streak-star { font-size: 20px; }
.lobby-player .streak-star b { font-size: 9px; padding-top: 2px; }
.party-pill .streak-star { font-size: 16px; }
.party-pill .streak-star b { font-size: 8px; padding-top: 2px; }

.lobby-wait { text-align: center; font-size: 14px; }

.invite-card { text-align: center; align-items: center; }
.invite-emoji { font-size: 46px; line-height: 1.1; }
.invite-heading { font-size: 22px; margin: 0; }

/* An invite link strips the setup screen to the join essentials: no nav,
   no play button, no hosting, no code to type. The kit builds all of
   these (src/kit/screens.ts), so the theme hides them; each game hides
   only its own settings card. */
body.inviting .site-nav,
body.inviting .setup-play,
body.inviting .card-quiet > .field-label,
body.inviting .card-quiet > .hint-text:not(.error),
body.inviting .card-quiet > .mini-button,
body.inviting .join-row .code-input { display: none; }
body.inviting .join-row .mini-button { flex: 1; }

/* Live counts for everyone in the round, in a strip above the board. */
.party-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
}

.party-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 2px solid var(--edge);
  border-radius: var(--r-pill);
  padding: 4px 11px;
  font-size: 13px;
  font-weight: 800;
}
.party-pill.me { border-color: var(--me); }
.party-pill b { color: var(--pink-deep); }
.party-pill.is-out { opacity: .5; }
.party-pill.is-done { border-color: var(--correct); background: var(--tint-mint); }

/* A muted sound or music foot button dims until tapped back on. */
.foot-button.is-off { opacity: .55; }

/* ------------------------------------------------------------- game HUD
   The score pill, round clock ring and stat pill both games wear, plus
   the footer button row. */

.hud { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

.hud-pill {
  flex: 1;
  background: var(--surface);
  border: 2px solid var(--edge);
  border-radius: var(--r-md);
  padding: 8px 10px;
  text-align: center;
  box-shadow: 0 6px 14px var(--card-shadow);
}

.hud-label {
  display: block;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .8px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.hud-pill strong { font-size: 22px; font-weight: 800; }

/* ----------------------------------------------------------------- timer */

.timer { position: relative; width: 84px; height: 84px; flex: none; }
.timer svg { width: 100%; height: 100%; transform: rotate(-90deg); }

.ring-bg { fill: var(--surface-3); stroke: var(--pink-soft); stroke-width: 8; }

.ring-fg {
  fill: none;
  stroke: var(--mint-deep);
  stroke-width: 8;
  stroke-linecap: round;
  stroke-dasharray: 276.5;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset .3s linear, stroke .6s ease;
}

.timer.warn .ring-fg { stroke: var(--gold); }
.timer.danger .ring-fg { stroke: var(--danger); }
.timer.danger { animation: heartbeat 1s ease-in-out infinite; }

@keyframes heartbeat {
  0%, 100% { transform: scale(1); }
  15% { transform: scale(1.09); }
  30% { transform: scale(1); }
}

.timer-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -.5px;
}

.game-foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(10px * var(--foot-fit, 1));
}

/* Short phones: the hero and the clock ring give the board its room. A
   laptop window is short too, and its hub keeps the hero the about page
   keeps beside it, so the shrink is for narrow screens alone. */
@media (max-height: 700px) and (max-width: 939px) {
  .mascot { font-size: 44px; }
  .title { font-size: 27px; }
}
@media (max-height: 700px) {
  .timer { width: 72px; height: 72px; }
}

/* A settings card a lobby guest may read but never edit. */
.is-locked { pointer-events: none; opacity: .8; }

/* ------------------------------------------------------------ play pieces
   The looks the games paint with and the guides show, so a guide's picture
   of a hint bubble is the hint bubble: a letter tile, a word pill, the
   candy hint bubble, a finger's trace. Layout stays with whoever uses them. */

/* A letter tile: the face, the under-edge, and what it lights up with.
   --tile-size drives the type, the radius and the edge, so the playing
   board, the reveal's mini board and a guide's example are one tile at
   three sizes; a state sets --tile-fill, --tile-ink and --tile-under and
   the piece paints. The scale springs stay with whoever uses it. */
.letter-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(var(--tile-size) * .40);
  font-weight: 800;
  color: var(--tile-ink, var(--ink));
  background: var(--tile-fill, var(--tile-face));
  border-radius: calc(var(--tile-size) * .24);
  box-shadow: 0 calc(var(--tile-size) * .055) 0 var(--tile-under, var(--tile-edge));
}

/* On the results a pill is a button (it opens the word's card); in the
   guide it is a span. Both wear this. */
.word-pill {
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .5px;
  color: inherit;
  background: var(--surface-3);
  border: 2px solid var(--pink-soft);
  border-radius: var(--r-sm);
  padding: 4px 9px;
}
button.word-pill { cursor: pointer; }
.word-pill.big { border-color: var(--gold); background: var(--tint-gold); }

.candy-bubble {
  background: var(--hint-fill);
  color: var(--on-accent);
  font-size: 14px;
  font-weight: 700;
  padding: 9px 14px;
  border-radius: var(--r-md);
  box-shadow: 0 8px 18px rgba(var(--lavender-glow), .35);
}
/* The sudoku's bubble is the quiet one: ink on the face, a hint-coloured
   rim, so its teaching lines read at length. Its guide shows the same. */
.candy-bubble.quiet {
  background: var(--surface-3);
  color: var(--ink);
  border: 2px solid var(--hint);
  padding: 10px 14px;
  box-shadow: 0 6px 16px rgba(var(--lavender-glow), .25);
}

.trace-line {
  fill: none;
  stroke: color-mix(in srgb, var(--on-accent) 85%, transparent);
  stroke-width: 9;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 6px rgba(var(--pink-glow), .55));
}

/* ------------------------------------------------------------ game screen
   The one layout template both games play on, phone or desktop: HUD at
   the top, the game area floating in the screen's slack, the button row
   docked at the bottom. A game's area holds whatever it plays with - a
   letter grid, or a number grid with its pad. */
.game-screen.is-active { min-height: calc(100dvh - 34px - var(--safe-top) - var(--safe-bottom)); }
.game-area { margin-block: auto; }

/* Scaffold chrome (src/kit/screens.ts): the more-games foot link and
   the lobby settings region, shared by both games. */
.foot-link { text-align: center; }
.lobby-settings { display: flex; flex-direction: column; gap: 8px; }
.result-actions { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }

/* Folded away for a guest: one line of what the host picked, and a tap to
   see the rest. Nobody needs 640px of chips they are not allowed to touch. */
.lobby-settings.is-folded > div,
.lobby-settings.is-folded > .lobby-wait { display: none; }
.lobby-peek { align-self: center; }
