/* ==========================================================================
   layout.css — Game table, score bar, deck area, hands area, header, footer
   Blackjack Solitaire
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Page Wrapper / Game Table
   -------------------------------------------------------------------------- */

main[role="main"] {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  padding: var(--padding-page);
  /* Notched devices (viewport-fit=cover): keep content out of the sensor
     housing / home-indicator areas; insets are 0 elsewhere. */
  padding-top:    max(var(--padding-page), env(safe-area-inset-top));
  padding-right:  max(var(--padding-page), env(safe-area-inset-right));
  padding-bottom: max(var(--padding-page), env(safe-area-inset-bottom));
  padding-left:   max(var(--padding-page), env(safe-area-inset-left));
  gap: var(--space-6); /* 24px between sections */
}

/* Living surface: corner suit watermarks — the third ambient layer, alongside
   the weave and motes painted on body::after / body::before (theme.css §3b).
   Every theme that declares `--surface-watermark` gets them; the token carries
   the per-theme tint, so adding a theme is a one-line change over there rather
   than another copy of this block.

   These are `position: absolute` inside `main`, which is a flex container —
   that is load-bearing. A static pseudo-element would become a flex ITEM and
   shove the whole board sideways.

   The vertical offsets clear the chrome rather than bleeding past it. `main`
   holds the header and footer as its own first and last children, so the
   design's -10px/-30px overhang — which it could afford because its demo tile
   clipped them against nothing — parked both glyphs underneath the two bars
   that are always painted. They now sit inside the open table band. */
body.theme-refined-felt    main[role="main"]::before,
body.theme-crimson-classic main[role="main"]::before,
body.theme-neon-arcade     main[role="main"]::before,
body.theme-neon-navy       main[role="main"]::before {
  content: '♠';
  position: absolute;
  left: 4%;
  top: 100px;
  font-size: 120px;
  line-height: 1;
  color: var(--surface-watermark);
  pointer-events: none;
  z-index: 0;
}
body.theme-refined-felt    main[role="main"]::after,
body.theme-crimson-classic main[role="main"]::after,
body.theme-neon-arcade     main[role="main"]::after,
body.theme-neon-navy       main[role="main"]::after {
  content: '♦';
  position: absolute;
  right: 4%;
  bottom: 105px;
  font-size: 120px;
  line-height: 1;
  color: var(--surface-watermark);
  pointer-events: none;
  z-index: 0;
}

/* Centre content, constrain max-width */
.game-table,
main[role="main"] > * {
  width: 100%;
  max-width: var(--max-width);
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   2. Game Header
   -------------------------------------------------------------------------- */

.game-header {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  padding: 14px 22px;
  background: var(--header-bg);
  border: 1px solid var(--header-border);
  border-radius: 12px;
  gap: var(--space-4);
  flex-shrink: 0;
  position: relative;
}

/* .game-title is now an animation hook only (animateHeaderWink targets it).
   Its typography lives in .brand-wordmark — theme.css §8. */

/* --------------------------------------------------------------------------
   Header nav and burger menu
   -------------------------------------------------------------------------- */

.header-nav {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

/* Shared icon+label molecule for all header nav items */
.navitem {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 40px;
  padding: 0 var(--space-3);
  border-radius: 9px;
  background: transparent;
  border: 1.5px solid transparent;
  color: var(--text-accent);
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}

.navitem__icon {
  display: inline-flex;
  width: 17px;
  height: 17px;
  flex-shrink: 0;
}

.navitem__icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* Quiet (non-primary) items: gold-tinted hover */
.navitem:not(.navitem--primary):hover {
  background: rgba(var(--accent-rgb), 0.16);
  color: var(--text-primary);
  border-color: var(--color-accent);
}

.navitem:active {
  transform: scale(0.97);
}

/* Primary CTA — New Game. Pill-shaped with an accent bloom, per the design mockup. */
.navitem--primary {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--text-inverse);
  font-size: 0.875rem; /* 14px */
  font-weight: 700;
  border-radius: 99px;
  padding: 0 20px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    0 2px 8px rgba(0, 0, 0, 0.25),
    0 0 18px var(--glow-accent);
}

.navitem--primary:hover {
  filter: brightness(1.07);
}

/* Burger button — hidden on desktop, shown on mobile */
.burger-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: transparent;
  border: var(--border-width) solid var(--border-btn-help);
  border-radius: 9px;
  color: var(--text-accent);
  cursor: pointer;
  flex-shrink: 0;
  margin-left: auto;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.burger-icon {
  width: 22px;
  height: 22px;
}

.burger-btn:hover {
  background: var(--color-accent);
  color: var(--text-inverse);
}

/* --------------------------------------------------------------------------
   3. Score Bar
   -------------------------------------------------------------------------- */

.score-bar {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  gap: var(--score-gap);
  flex-wrap: wrap;
  flex-shrink: 0;
}

.score-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 9px 18px;
  background: var(--score-bg);
  border: 1px solid var(--score-border);
  border-radius: 10px;
  min-width: 86px;
  box-shadow: var(--shadow-score);
  position: relative;
  overflow: hidden;
}

/* Beat-the-Score tracker: accent-emphasised score-boxes (target + tries) */
.score-box.beat-banner {
  border-color: var(--color-accent);
}
.score-box.beat-banner .score-label,
.score-box.beat-banner .score-value {
  color: var(--color-accent);
}
.score-box.beat-banner[hidden] {
  display: none;
}

/* Face, weight, tracking and uppercasing come from .score-label in theme.css §8
   (they are theme-dependent); only size, colour and rhythm live here. */
.score-label {
  font-size: var(--type-label);
  color: var(--score-label);
  line-height: 1;
}

.score-value {
  font-size: 1.375rem; /* 22px */
  font-weight: var(--weight-label);
  color: var(--score-text);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   4. Deck Area
   -------------------------------------------------------------------------- */

.deck-area {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: var(--deck-gap);
  flex-shrink: 0;
}

/* Deck area label (optional helper text) */
.deck-area__label {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--text-muted);
  text-align: center;
  margin-top: var(--space-1);
}

/* Deck slot — visual container matching hand-slot scale, no border */
.deck-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
  min-height: 200px;
  min-width: calc(var(--deck-card-width) + var(--space-6));
  overflow: visible;
}

/* Draw pile area wrapper — for label + card */
.draw-pile-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}

/* --------------------------------------------------------------------------
   5. Hands Area
   -------------------------------------------------------------------------- */

.hands-area {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: var(--hand-gap);
  min-height: 200px;
  flex: 1;
}

/* --------------------------------------------------------------------------
   6. Hand Slot
   -------------------------------------------------------------------------- */

.hand-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  min-width: 0; /* allow flex to shrink */
  min-height: 214px;
  padding: var(--space-4) var(--space-3);
  border: var(--border-width) dashed var(--hand-border);
  border-radius: 12px;
  background: var(--hand-bg);
  position: relative;
  transition:
    border-color var(--duration-normal) var(--ease-out),
    background-color var(--duration-normal) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out);
  cursor: default;
}

/* Bust state: desaturate the slot */
.hand-slot--busting {
  filter: grayscale(0.6) brightness(0.92);
  transition: filter 400ms ease-out;
}

/* Bust label: "BUST · NN" floating above the slot */
.bust-label {
  position: absolute;
  top: -28px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-alert);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 2px 8px;
  border-radius: 4px;
  pointer-events: none;
  z-index: 20;
  white-space: nowrap;
  animation: bustLabelFade 1400ms ease-out forwards;
}

/* Empty slot label */
.hand-slot:empty::after,
.hand-slot--empty .hand-empty-label {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--text-secondary);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  white-space: normal;
  text-align: center;
  width: 90%;
}

.hand-slot:not(:has(.card-stack)):not(:has(.card)) .hand-slot__placeholder {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--text-secondary);
  text-align: center;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  white-space: normal;
  width: 90%;
}

/* Explicit empty label element rendered by JS */
.hand-empty-label {
  font-family: var(--font-mono);
  font-size: 0.78125rem; /* 12.5px */
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  white-space: normal;
  text-align: center;
  width: 90%;
}

/* ---- Hand slot states ---- */

/* Has cards — solid border */
.hand-slot--has-cards {
  border-style: solid;
  border-color: var(--border-hand-empty);
}

/* Valid: card can be placed here without busting */
.hand-slot--valid {
  border-style: solid;
  border-color: var(--hand-border-valid);
  box-shadow: 0 0 0 1px var(--hand-border-valid) inset;
}

/* Invalid: placing card would bust (>21) */
.hand-slot--invalid {
  border-style: solid;
  border-color: var(--hand-border-invalid);
}

/* Drag-over: card hovering above this slot (legacy — keep for backward compat) */
.hand-slot--dragover {
  border-style: solid;
  border-color: var(--border-hand-dragover) !important;
  background: var(--bg-dragover);
  box-shadow: 0 0 0 1px var(--hand-border-dragover) inset;
  animation: dragoverPulse 800ms ease-in-out infinite;
}

/* Drag affordance: valid drop target — green glow + pulse */
.hand-slot--drag-valid {
  border-style: solid;
  border-color: var(--border-hand-valid);
  box-shadow: 0 0 12px 2px var(--border-hand-valid);
  animation: dragoverPulse 800ms ease-in-out infinite;
}

/* Drag affordance: bust-risk drop target — red glow, no pulse */
.hand-slot--drag-bust {
  border-style: solid;
  border-color: var(--border-hand-invalid);
  box-shadow: 0 0 8px 2px var(--border-hand-invalid);
}

.card--dragging {
  opacity: 0.5;
  cursor: grabbing;
}

#draw-pile .card {
  cursor: grab;
  width: var(--deck-card-width, 74px);
  height: var(--deck-card-height, 110px);
}

#draw-pile .card:active {
  cursor: grabbing;
}

/* ---- Locked hand slot (app-only feature) ---- */

.hand-slot--locked {
  border-style: dashed;
  border-color: var(--border-hand-locked);
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: auto; /* Keep pointer events so we can show tooltip/CTA */
}

.hand-slot__lock-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  background: var(--bg-overlay-lock);
  border-radius: inherit;
  z-index: 5;
  padding: var(--space-3);
}

.hand-slot__lock-icon {
  font-size: 1.25rem;
  color: var(--text-muted);
  line-height: 1;
}

.hand-slot__lock-text {
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--text-muted);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1.3;
}

.hand-slot__lock-cta {
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  color: var(--text-accent);
  text-decoration: underline;
  text-align: center;
  cursor: pointer;
}

/* ---- Hand total display ---- */

.hand-total {
  /* face + tabular numerals from theme.css §8 */
  font-size: 0.875rem; /* 14px */
  font-weight: var(--weight-label);
  color: var(--hand-value-color);
  text-align: center;
  line-height: 1;
  min-height: 1rem;
  letter-spacing: -0.02em;
  flex-shrink: 0;
  margin-top: auto;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--surface-line);
  border-radius: 999px;
  padding: 3px 13px;
}

.hand-total--empty {
  background: transparent;
  border-color: transparent;
}

/* Dual soft/hard ace total — "7 (17)" carries ~3× the glyphs of a plain total and
   burst out of the pill on narrow slots (issue #84). Scale the text down and squeeze
   the side padding so the bubble stays inside its hand slot. */
.hand-total--dual {
  font-size: 0.75rem;
  padding-inline: 6px;
  letter-spacing: -0.03em;
  white-space: nowrap;
}

.hand-total--21 {
  color: var(--border-hand-valid);
}

.hand-total--bust {
  color: var(--color-alert);
}

/* Validity indicators (colour + text, not colour alone) */
.hand-status-badge {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  border-radius: 3px;
  padding: 1px 4px;
}

.hand-status-badge--valid {
  color: var(--border-hand-valid);
}

.hand-status-badge--invalid {
  color: var(--color-alert);
}

/* ---- Locked slot tooltip ---- */
.locked-tooltip {
  position: absolute;
  bottom: calc(100% + var(--space-2));
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-secondary);
  border: 1px solid var(--border-modal);
  border-radius: var(--border-radius);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--text-primary);
  white-space: nowrap;
  z-index: 20;
}

.locked-tooltip a {
  color: var(--text-accent);
  text-decoration: underline;
}

/* ---- Deck draw-blocked hint (drawRule: block_when_playable) ----
   Viewport-fixed and horizontally centred so a long message wraps within the
   screen instead of overflowing a narrow mobile deck (issue #62). `top` is set
   in JS (showDeckHint) to sit just below the deck, clamped into the viewport.
   Same z-index tier as #score-fx-layer: above the board, below the open header
   dropdown (70) and the modal overlay (100). */
.deck-hint {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  max-width: min(88vw, 340px);
  background: var(--color-secondary);
  border: 1px solid var(--border-modal);
  border-radius: var(--border-radius);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--text-primary);
  text-align: center;
  z-index: 65;
  pointer-events: none;
  animation: deckHintFade 2500ms ease-out forwards;
}

@keyframes deckHintFade {
  0%   { opacity: 0; transform: translateX(-50%) translateY(4px); }
  12%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  80%  { opacity: 1; }
  100% { opacity: 0; }
}

/* --------------------------------------------------------------------------
   7. Footer
   -------------------------------------------------------------------------- */

.game-footer {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-footer);
  border-radius: var(--border-radius);
  margin-top: auto;
  flex-shrink: 0;
}

.footer-cta {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--text-secondary);
  text-align: right;
}

.footer-link {
  color: var(--text-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--duration-fast) var(--ease-out);
}

.footer-link:hover {
  color: var(--text-primary);
}

#kofi-widget-container {
  display: flex;
  align-items: center;
}

/* Ko-fi + Get the App, always on one line (issue #153). The Ko-fi widget is a
   third-party <a> of a width we do not control, so the row — not either button —
   owns the sizing: nowrap keeps them together, and both children may shrink
   (min-width:0) so a 320px phone squeezes them rather than wrapping one under
   the other or pushing a scrollbar. */
.footer-cta-row {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--space-2);
  min-width: 0;
}

.footer-cta-row > * {
  min-width: 0;
}

.footer-get-app-btn {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text-inverse);
  background: var(--color-accent);
  border: none;
  border-radius: 4px;
  padding: 5px 10px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background var(--duration-fast) var(--ease-out);
}

.footer-get-app-btn:hover {
  background: var(--cta-hover);
}

.footer-get-app-btn:focus-visible {
  outline: 2px solid var(--text-accent);
  outline-offset: 2px;
}

.lang-select {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid var(--border-subtle, rgba(255,255,255,0.15));
  border-radius: 4px;
  padding: 2px 6px;
  cursor: pointer;
  flex-shrink: 0;
}

.lang-select:focus {
  outline: 2px solid var(--text-accent);
  outline-offset: 2px;
}

.lang-select option {
  background: var(--bg-surface, #1a1a2e);
  color: var(--text-primary);
}

.playtester-login-btn {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
  flex-shrink: 0;
  opacity: 0.7;
}

.playtester-login-btn:hover,
.playtester-login-btn:focus {
  color: var(--text-primary);
  opacity: 1;
  outline: none;
}

.playtester-login-btn:focus-visible {
  outline: 2px solid var(--text-accent);
  outline-offset: 2px;
}

.footer-privacy-link {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--text-secondary);
  text-decoration: underline;
  text-underline-offset: 2px;
  flex-shrink: 0;
  opacity: 0.7;
}

.footer-privacy-link:hover,
.footer-privacy-link:focus {
  color: var(--text-primary);
  opacity: 1;
  outline: none;
}

.footer-privacy-link:focus-visible {
  outline: 2px solid var(--text-accent);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   8. Responsive — Mobile (max-width: 768px)
   -------------------------------------------------------------------------- */

@media (max-width: 768px) {

  /* Reduce overall page padding */
  main[role="main"] {
    padding: var(--space-3);
    gap: var(--space-4);
  }

  /* ---- Score bar: sticky top on mobile ----
     No wash and no rule under it. The bar used to carry a translucent
     `--bg-table-solid` fill plus a bottom border to separate it from content
     scrolled underneath, and Neon Arcade and Refined Felt opted out of both
     because their radial `--bg-table` is much lighter at the top than the solid
     it is mixed from, so the wash painted a mismatched box across the head of
     the table instead of blending in.

     Every theme's `--bg-table` is that same top-lit radial (theme.css §3), so
     Claret Table and Midnight Electric had exactly the same mismatched
     container — issue #145. The opt-out is now the rule: the score boxes' own
     backgrounds and accent borders are what separate the bar from whatever
     scrolls beneath it, on all four themes. */
  .score-bar {
    position: sticky;
    top: 0;
    z-index: 10;
    /* Tighter than the 16px desktop token. A timed mode puts four boxes in this
       nowrap row (Hands, Points, Time, Tempo) and at 360px the desktop gap left
       each box 2px short of its own value — "00:00" clipped. Set on .score-bar
       rather than :root so it cannot be confused with the component aliases
       css/CLAUDE.md warns about. */
    --score-gap: var(--space-2);
    padding: var(--space-2) 0;
    margin-inline: calc(-1 * var(--space-3));
    padding-inline: var(--space-3);
    width: calc(100% + var(--space-3) * 2);
    max-width: none;
    flex-wrap: nowrap;
  }

  /* Compact score boxes on mobile — share the row width instead of forcing a
     horizontal scrollbar when the Beat-the-Score boxes are visible.
     Horizontal padding is 4px, not 8px: a timed mode puts four boxes in this row
     and at 360px each gets ~72px, of which "00:00" in the real Space Grotesk
     needs most. The 8px inset overflowed it by 11px in CI — where the webfont
     actually loads — while measuring clean locally against the system fallback. */
  .score-box {
    padding: var(--space-1);
    min-width: 0;
    flex: 1 1 0;
  }

  /* Tracking is what makes an uppercase label wide, and it is the label — not the
     value — that overflowed the Points box. */
  .score-label {
    font-size: 0.75rem;
    letter-spacing: 0.02em;
  }

  .score-value {
    font-size: 1rem;
  }

  /* ---- Mobile card dimensions ---- */
  :root {
    --card-width:  48px;
    --card-height: 72px;
    --card-stack-offset: 22px;
    --deck-card-width:  58px;
    --deck-card-height: 84px;
    --padding-page: 12px;
    --hand-gap: 8px;
    --deck-gap: 16px;
    --section-gap: 20px;
  }

  /* ---- Wordmark smaller on mobile (retune the token, don't fight it) ---- */
  .brand-wordmark {
    --brand-size-bar: 18px;
  }

  /* ---- Burger menu: show burger, hide inline nav ---- */
  .burger-btn {
    display: flex;
  }

  /* Floating dropdown panel — gold border, navy background, rounded.
     z-index sits ABOVE the transient board-overlay tier (65: .deck-hint,
     #score-fx-layer, .tutorial-target / .tutorial-coach) and below the modal
     overlay (100). The panel drops down over the deck area, so at the old 50
     a tutorial-highlighted deck and its coach panel painted straight through
     the open menu and hid the items behind them (issue #124). A menu the
     player deliberately opened outranks anything decorating the board; a
     modal still wins if one opens over it. */
  .header-nav {
    display: none;
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    left: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--color-secondary);
    border: 1.5px solid var(--color-accent);
    border-radius: 14px;
    z-index: 70;
    padding: 0;
    box-shadow: 0 22px 50px rgba(0, 0, 0, 0.55);
    margin-left: 0;
  }

  .header-nav--open {
    display: flex;
  }

  /* Items become full-width rows with dividers inside the dropdown */
  .header-nav .navitem {
    width: 100%;
    height: auto;
    border-radius: 0;
    border: none;
    border-bottom: 1px solid rgba(var(--accent-rgb), 0.14);
    padding: var(--space-3) var(--space-4);
    font-size: 0.9375rem;
    justify-content: flex-start;
  }

  .header-nav .navitem:last-child {
    border-bottom: none;
  }

  .header-nav .navitem--primary {
    border-radius: 0;
  }

  .header-nav .navitem__icon {
    width: 20px;
    height: 20px;
  }

  /* ---- Deck slots on mobile ---- */
  .deck-slot {
    min-height: 120px;
    padding: var(--space-2);
  }

  /* ---- Hands area: allow horizontal scroll ---- */
  .hands-area {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    /* Negative margin + padding to bleed to edges */
    margin-inline: calc(-1 * var(--space-3));
    padding-inline: var(--space-3);
    width: calc(100% + var(--space-3) * 2);
    max-width: none;
    padding-bottom: var(--space-2); /* room for scrollbar */
  }

  .hand-slot {
    scroll-snap-align: start;
    flex: 0 0 calc(var(--card-width) + var(--space-3));
    min-width: calc(var(--card-width) + var(--space-3));
    min-height: 160px;
    padding: var(--space-1) var(--space-1);
  }

  /* Hand-total bubble on mobile — the slot is only ~56-60px wide here, so both the
     dual ace total and Beginner Assistance's enlarged face need their own step-down
     to stay inside it (issue #84). Measured at 360px and 390px viewports. */
  .hand-total--dual {
    font-size: 0.625rem;
    padding-inline: 4px;
  }

  body.beginner-assist .hand-total {
    font-size: 0.95rem;
  }

  body.beginner-assist .hand-total--dual {
    font-size: 0.625rem;
  }

  /* ---- Card font sizes scale down ---- */
  .card-rank {
    font-size: 0.6875rem;
  }

  .card-suit-small {
    font-size: 0.5625rem;
  }

  .card-center {
    font-size: 1.125rem;
  }

  /* ---- Footer: wrap and centre items so they flow together instead of
     stacking as full-width rows ---- */
  .game-footer {
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    padding: var(--space-2) var(--space-3);
  }

  .footer-cta {
    font-size: 0.75rem;
  }

  /* ---- Deck area ---- */
  .deck-area {
    gap: var(--space-4);
  }

  /* ---- Ko-fi widget: hide on mobile when a modal is open ---- */
  body:has(#modal-overlay) #kofi-widget-container {
    display: none !important;
  }

}

/* --------------------------------------------------------------------------
   9. Very small screens (max-width: 360px)
   -------------------------------------------------------------------------- */

@media (max-width: 360px) {
  :root {
    --card-width:  44px;
    --card-height: 66px;
    --card-stack-offset: 18px;
  }

  .brand-wordmark {
    --brand-size-bar: 17px;
  }
}

/* --------------------------------------------------------------------------
   10. Large screens — extra breathing room
   -------------------------------------------------------------------------- */

@media (min-width: 1200px) {
  main[role="main"] {
    padding: var(--space-8);
    gap: var(--space-8);
  }
}

/* Mode selection */
.mode-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
  padding: 12px 0;
}
.mode-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 14px 10px;
  border: 2px solid var(--border-hand, #444);
  border-radius: 10px;
  background: var(--bg-card, #1a1a2e);
  color: var(--text-primary, #e0d6c2);
  cursor: pointer;
  font-family: inherit;
  text-align: center;
  transition: border-color 0.2s, transform 0.15s;
}
.mode-card:hover, .mode-card:focus-visible {
  border-color: var(--color-accent, #d4a843);
  transform: translateY(-2px);
  outline: none;
}
.mode-card--current {
  border-color: var(--color-accent, #d4a843);
  box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.3);
}
.mode-card__icon { font-size: 1.4rem; }
.mode-card__name { font-weight: 700; font-size: 0.9rem; }
.mode-card__desc { font-size: 0.72rem; opacity: 0.7; line-height: 1.3; }
.mode-card__label { font-size: 0.62rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.5; margin-top: 3px; }
.mode-card--challenges { position: relative; border-color: var(--color-accent); box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.25); }
.mode-card--challenges .badge { position: absolute; top: -8px; right: -8px; background: #e0524a; color: #fff; font-size: 0.62rem; font-weight: 800; border-radius: 999px; padding: 1px 7px; line-height: 1.3; }
.mode-select-modal { max-width: 480px; }
.mode-btn {
  background: var(--bg-card, #1a1a2e);
  color: var(--text-primary, #e0d6c2);
  border: 1px solid var(--border-hand, #444);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 0.8rem;
  cursor: pointer;
  font-family: inherit;
}
.mode-btn:hover { border-color: var(--color-accent, #d4a843); }

/* Mode UI area */
.mode-ui-area { display: flex; justify-content: center; gap: 14px; padding: 4px 16px; flex-wrap: wrap; }
/* --------------------------------------------------------------------------
   Burn pile — the right-hand end of the deck row.

   The row reads left-to-right as the card's life: deck · draw ······ burn, and
   all three piles are the SAME SIZE, because they are the same kind of thing.
   The container is a bare column — no border, no padding, no background of its
   own — so the card-sized slot inside it lines up with the deck and draw pile
   rather than sitting shrunken inside a box.

   One caption, one count, one row of pips, and never more than that:
     · the slot names itself "Burn" only while EMPTY, exactly as the draw pile
       does — once cards are in it, the count says what it is
     · the count sits CENTRED on the card, the same place and type as the deck's
       own remaining figure
     · the pips below are the only allowance indicator; lit = still available
   -------------------------------------------------------------------------- */
.burn-pile-container {
  margin-left: auto;
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs, 6px);
  cursor: pointer;
  transition:
    transform var(--duration-fast, 150ms) var(--ease-out, ease-out),
    opacity var(--duration-fast, 150ms) var(--ease-out, ease-out);
}

/* The slot itself is a card, at deck size. */
.burn-pile-slot {
  position: relative;
  width: var(--deck-card-width, 74px);
  height: var(--deck-card-height, 110px);
  border-radius: var(--border-radius-card);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--duration-normal, 250ms) var(--ease-out, ease-out);
}

/* Empty: a card-sized dashed outline that names itself, mirroring
   .draw-pile--empty. NOT breathing — the draw pile animates because it is
   asking for the next action; the burn pile only ever moves on impact. */
.burn-pile--empty .burn-pile-slot {
  border: var(--border-width, 1px) dashed var(--color-alert);
}

.burn-pile--empty .burn-pile-slot::after {
  content: attr(data-label);
  font-family: var(--font-mono);
  font-size: 0.6875rem; /* 11px, matching the draw pile's label */
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.35;
  color: var(--color-alert);
  text-align: center;
  padding: 6px;
  opacity: 0.9;
}

.burn-pile--empty { opacity: 0.62; }
.burn-pile--empty:hover,
.burn-pile--empty:focus-visible { opacity: 1; }

/* Live: cards in it, allowance left. Lifts to answer a hover. */
.burn-pile--live:hover,
.burn-pile--live:focus-visible { transform: translateY(-3px); }

/* Spent: still a destination for busted cards, dead as an affordance. Hatched
   rather than dimmed — a faded pile reads as "loading", a hatch reads as
   "closed". The click handler answers a tap here with a reason, not silence. */
.burn-pile--spent { cursor: not-allowed; }
.burn-pile--spent:hover { transform: none; }
.burn-pile--spent .burn-stack__card {
  background-image: repeating-linear-gradient(
    45deg,
    transparent 0 5px,
    rgba(255, 255, 255, 0.07) 5px 10px
  );
}

/* --- The stack -----------------------------------------------------------
   Face-down and anonymous: the player's own deck back (.card--back, so the
   chosen skin still shows) run through a dead colour profile plus a cold red
   wash. Not crushed to black — the pattern has to stay legible on every skin.
   -------------------------------------------------------------------------- */
.burn-stack {
  position: relative;
  width: 100%;
  height: 100%;
}

.burn-stack__card {
  position: absolute;
  inset: 0;
  /* Above the depth edges below. Without this the stack's ::before/::after
     paint AFTER the card (same stacking context, no z-index on either), so a
     three-deep pile covered its own card with a near-black rectangle and the
     deck pattern vanished — the pile read as a black hole rather than as a
     darkened version of the player's own deck back. */
  z-index: 1;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  border-radius: var(--border-radius-card);
  /* A DARKENED version of the player's own deck back, not a black card: the
     pattern has to stay legible on every skin, which is what makes the pile
     read as "your cards, spent" rather than as a void. */
  filter: saturate(0.3) brightness(0.72) contrast(1.04);
  box-shadow:
    inset 0 0 0 999px rgba(128, 36, 36, 0.14),
    0 1px 3px rgba(0, 0, 0, 0.5);
}

/* Depth: an offset edge per extra card, to two, so the pile has visible mass
   without redrawing every card in it. */
.burn-stack--depth-2::before,
.burn-stack--depth-3::before,
.burn-stack--depth-3::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;                 /* behind .burn-stack__card, which is z-index 1 */
  border-radius: var(--border-radius-card);
  background: var(--bg-card-back);
  filter: saturate(0.14) brightness(0.5);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.burn-stack--depth-2::before { transform: translate(3px, -3px); }
.burn-stack--depth-3::before { transform: translate(3px, -3px); }
.burn-stack--depth-3::after  { transform: translate(6px, -6px); }

/* Everything gone, centred on the card — same position and type as the deck's
   own count, so the two piles are read the same way. */
.burn-stack__count {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1;
  color: var(--text-primary, #fff);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* --- The allowance -------------------------------------------------------
   Lit while still AVAILABLE, going dark as it is spent, so the row counts down
   like "burns left" rather than filling up like a progress bar. This is the
   only allowance indicator on the pile — the "1/3" caption that used to sit
   beside it was a third reading of the same two facts.
   -------------------------------------------------------------------------- */
.burn-pile-pips { display: flex; gap: 4px; }

.burn-pip {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-alert);
  border: 1px solid var(--color-alert);
  transition: background-color var(--duration-fast, 150ms) var(--ease-out, ease-out);
}

.burn-pip--spent {
  background: transparent;
  opacity: 0.35;
}

/* --- Impact ---------------------------------------------------------------
   The pile moves only when something lands in it. Never idles. */
.burn-stack--jolt { animation: burnJolt 260ms var(--ease-out, ease-out); }
.burn-stack__count--kick { animation: badgeKick 240ms var(--ease-out, ease-out); }
.burn-pip--spending { animation: pipSpend 280ms var(--ease-out, ease-out); }

@keyframes burnJolt {
  0%   { transform: translateY(-4px) scale(1.06); }
  55%  { transform: translateY(1px)  scale(0.98); }
  100% { transform: translateY(0)    scale(1); }
}
@keyframes badgeKick {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.35); }
  100% { transform: scale(1); }
}
@keyframes pipSpend {
  0%   { transform: scale(1.35); background: var(--color-alert); box-shadow: 0 0 0 0 var(--color-alert); }
  60%  { transform: scale(0.85); box-shadow: 0 0 0 5px rgba(192, 57, 43, 0); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(192, 57, 43, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .burn-stack--jolt,
  .burn-stack__count--kick,
  .burn-pip--spending { animation: none; }
  .burn-pile-container,
  .burn-pile-slot,
  .burn-pip { transition: none; }
}

/* #timer-container / #timer-display carry .score-box / .score-value now — the
   clock moved into the score bar beside Hands and Points. No shell rules of
   their own: a second border/padding here would double the box. */
.deck-counter-container { display: flex; align-items: center; gap: 4px; padding: 4px 12px; font-size: 0.85rem; }
.deck-counter-label { opacity: 0.6; }
.deck-counter-value { font-weight: 700; }
.reshuffle-counter { font-size: 0.72rem; text-align: center; opacity: 0.7; margin-top: 4px; }
.finish-btn {
  display: inline-flex;
  align-items: center;
  height: 40px;
  background: var(--color-accent);
  color: var(--text-inverse);
  border: none;
  border-radius: 9px;
  padding: 0 var(--space-3);
  font-size: 0.8125rem;
  font-weight: 700;
  cursor: pointer;
  font-family: var(--font-sans);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 2px 8px rgba(0, 0, 0, 0.25);
}
.finish-btn:hover { filter: brightness(1.07); }
.finish-btn:active { transform: scale(0.97); }

/* --------------------------------------------------------------------------
   Score build-up toast (issue #73)

   Explains how a completed hand's points were reached. Deliberately laid out in
   normal flow *below* .hands-area rather than floated over the board, so it can
   never cover the deck, draw pile or a hand slot. The slot reserves its own
   height so a toast appearing/disappearing doesn't shift the hands.

   Component tokens are consumed via var() with fallbacks to the shared base, so
   this needs no per-theme block (see CLAUDE.md on the :root alias trap).
   -------------------------------------------------------------------------- */

/* Sits in the band between the deck row and the hands. It reserves a toast
   line's height so showing one never reflows the board — but it must not ALSO
   add a gap of its own, or the band reads as two stacked empty containers
   instead of one space. The negative top margin cancels `main`'s 24px gap above
   it, and the padding puts the breathing room back INSIDE the reserved band, so
   the whole thing costs one gap rather than two. */
.score-toast-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 34px;
  margin-top: calc(-1 * var(--space-6));
  padding-top: var(--space-2);
  pointer-events: none;  /* purely informational — never intercepts a placement click */
}

.score-toast {
  max-width: 100%;
  padding: 6px var(--space-3);
  border-radius: 9px;
  background: var(--score-bg, var(--bg-score));
  border: 1px solid var(--score-border, var(--border-score));
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: var(--type-caption);
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
  text-align: center;
  /* Long breakdowns (five bonuses + a streak multiplier) must stay readable
     rather than stretching the board: wrap instead of overflowing. */
  overflow-wrap: anywhere;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 180ms ease-out, transform 180ms ease-out;
}

.score-toast--in {
  opacity: 1;
  transform: translateY(0);
}

/* Penalty variant ("Wasted an Ace") — same toast, alert colour. */
.score-toast--penalty {
  border-color: var(--color-alert);
  color: var(--color-alert);
}

/* Coach-mark variant — a just-in-time rule explanation (coachMarks.js). It used
   to borrow the penalty's alert red, which made an explanation read as an error
   report (issue #141), and it is not one: nothing has gone wrong when the player
   meets their first Joker. Dressed as the tutorial panel instead — same accent
   border, same body face, same text colour — because that is what it is. */
.score-toast--coach {
  border-color: color-mix(in srgb, var(--color-accent) 55%, transparent);
  color: var(--text-primary);
  font-family: inherit;
}

@media (prefers-reduced-motion: reduce) {
  .score-toast { transition: none; transform: none; }
  .score-toast--in { transform: none; }
}

/* ── Speed Run tempo box ──────────────────────────────────────────────────
   Lives in .score-bar as a .score-box beside Hands and Points, so the run's
   speed reads as one of its headline numbers. Everything below is what the
   score-box shell does not already provide: the drain bar on its bottom edge
   and the per-move flash over its value. */

/* The chain multiplier rides in the label slot. Accented only while a
   multiplier above x1 is live, so "you are on something" is visible without
   another element competing for the row. */
.score-box--tempo .score-label--chained {
  color: var(--color-accent);
}

/* The drain: time remaining before the move goes Cold and the chain breaks.
   Absolutely placed on the box's own bottom edge — .score-box is already
   position:relative and overflow:hidden, so it clips to the rounded corners
   with nothing extra. */
.tempo-hud__bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
}
.tempo-hud__fill {
  height: 100%;
  width: 100%;
  transform-origin: left center;   /* drains right-to-left */
  background: var(--border-hand-valid, #2ecc71);
}
.tempo-hud__fill[data-tier="fast"]   { background: var(--text-accent, #d4a843); }
.tempo-hud__fill[data-tier="steady"] { background: var(--text-secondary); }
.tempo-hud__fill[data-tier="cold"]   { background: var(--border-hand-invalid, #8b1a2b); }

/* Tier boundaries marked on the bar, so "under 1.2s is a Blitz" is a position
   on screen rather than a number to remember. */
.tempo-hud__tick {
  position: absolute;
  top: 0;
  width: 1px;
  height: 100%;
  background: var(--score-bg);
  opacity: 0.9;
}
.score-box--tempo--broke { animation: tempo-shatter 400ms ease-out; }

/* The per-move gain, shown in the value slot for a moment (see flash() in
   tempoUI.js for why this is not an overlay). Colour only — the text swap is
   what carries it, so there is nothing to restore if animation is off. */
.tempo-value--blitz  { color: var(--border-hand-valid, #2ecc71); }
.tempo-value--fast   { color: var(--text-accent, #d4a843); }
.tempo-value--steady { color: var(--text-secondary); }
.tempo-value--cold   { color: var(--border-hand-invalid, #8b1a2b); }
/* A word, not a number, so it cannot ride the value's 22px. nowrap because a
   second line makes this box taller than the three beside it in the row. */
.tempo-value--cold {
  font-size: var(--type-label, 11px);
  letter-spacing: var(--track-label, 0.12em);
  text-transform: uppercase;
  white-space: nowrap;
}

@keyframes tempo-shatter {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-2px); }
  75%      { transform: translateX(2px); }
}

/* Both animations are pure feedback — nothing is communicated only by motion,
   so they can be dropped outright rather than slowed. The flash must not be
   left visible: it covers the value it sits over. */
/* The shake is pure emphasis — the value already says "chain lost" in words, so
   dropping the motion outright loses nothing. */
@media (prefers-reduced-motion: reduce) {
  .score-box--tempo--broke { animation: none; }
}
