/*
 * The shared pieces of every game page (ui.js binds them): icons, buttons,
 * the brand bar, the price strip, the link readout, the stage stepper and
 * result pill, the stake controls, the game menu, the first-run card, toasts,
 * the terminal notice, the demo notch and the win-confetti layer.
 * wisdom-games' web/ui values, written out. Phones are below 640px.
 */

/* ---- icons: an SVG from /core/icons as a mask, painted in currentColor ---- */
.icon {
  display: inline-block;
  flex-shrink: 0;
  width: 1em;
  height: 1em;
  background: currentColor;
  mask: var(--icon-url) center / contain no-repeat;
  -webkit-mask: var(--icon-url) center / contain no-repeat;
}
.icon-chevron { --icon-url: url(icons/chevron.svg); }
.icon-dots { --icon-url: url(icons/dots.svg); }
.icon-flag { --icon-url: url(icons/flag.svg); }
.icon-home { --icon-url: url(icons/home.svg); }
.icon-lock { --icon-url: url(icons/lock.svg); }
.icon-minus { --icon-url: url(icons/minus.svg); }
.icon-music { --icon-url: url(icons/music.svg); }
.icon-plus { --icon-url: url(icons/plus.svg); }
.icon-shield { --icon-url: url(icons/shield.svg); }
.icon-speaker-on { --icon-url: url(icons/speaker-on.svg); }
.icon-speaker-off { --icon-url: url(icons/speaker-off.svg); }
.icon-target { --icon-url: url(icons/target.svg); }
.icon-x { --icon-url: url(icons/x.svg); }
.icon-zap { --icon-url: url(icons/zap.svg); }

/* ---- buttons: shadcn's Button, secondary variant ---- */
.btn {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  gap: 8px;
  white-space: nowrap;
  border-radius: var(--radius-md);
  padding: 8px 16px;
  font-weight: 700;
  background: var(--secondary);
  color: var(--secondary-foreground);
  box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  cursor: pointer;
  outline: none;
  transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
.btn:hover {
  background: var(--accent);
}
.btn:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--ring) 50%, transparent);
}
.btn .icon {
  width: 16px;
  height: 16px;
}

/* ---- demo notch, above the header (layout.css reserves its height) ---- */
.fun-mode-notch {
  position: fixed;
  z-index: 30;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 132px;
  height: var(--fun-mode-height);
  padding-top: env(safe-area-inset-top, 0px);
  border-radius: 0 0 20px 20px;
  background: var(--attention);
  color: var(--attention-foreground);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  pointer-events: none;
}

/* ---- the brand bar ---- */
.topbar {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 14px;
}
/* A flex child's floor is its content, so the brand block -- which carries the
   connection tooltip -- could push the balance and the menu button off a 320px
   screen when the tooltip opened. The tooltip is positioned and should
   not size its row at all. */
.topbar__brand {
  min-width: 0;
}
.topbar__right {
  flex-shrink: 0;
}

/* The "Demo mode" notch is a fixed 132px tab centred at the top, hanging over
   the bar below it. On a 320px frame it reached the balance's "BALANCE"
   caption, which is pinned right, and the caption read "...ALANCE" from under
   the tab (seen on the iPhone SE frame). Narrower screens get a narrower
   tab -- it only carries one short word -- so the two stop meeting and nothing
   has to be hidden. */
/* In a band the shell reserves no row for the notch (layout.css gives the
   board that space), so the tab overlaps the bar it hangs over. It moves to
   the left edge, where the brand name is short and nothing else sits. */
@media (orientation: landscape) and (max-height: 320px) {
  .fun-mode-notch {
    left: auto;
    right: 8px;
    translate: none;
    border-radius: 0 0 10px 10px;
    height: 16px;
    font-size: 9px;
  }
}

@media (max-width: 400px), (orientation: landscape) and (max-height: 320px) {
  .fun-mode-notch {
    width: auto;
    min-width: 96px;
    max-width: 44vw;
    padding-left: 10px;
    padding-right: 10px;
    font-size: 10px;
    letter-spacing: 0.04em;
  }
}
.topbar__brand {
  display: flex;
  align-items: center;
  gap: 10px;
}
.topbar__name {
  font-size: 16px;
  line-height: 24px;
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--accent-color);
}
.topbar__right {
  display: flex;
  align-items: center;
  gap: 12px;
}
.topbar__balance {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.1;
}
/* The label also names what is on its way ("+3.00 processing"), in its own
   place: the header's height never depends on it. */
.topbar__balance-label {
  white-space: nowrap;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1.4px;
  color: var(--icon);
}
.topbar__balance-value {
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 28px;
  font-weight: 700;
  color: var(--foreground);
  white-space: nowrap;
}
/* the wallet has not answered: a pulsing bar in the number's own line */
.topbar__balance-value:empty::before {
  content: "";
  display: inline-block;
  height: 0.8em;
  width: 6ch;
  border-radius: 9999px;
  background: var(--secondary-hover);
  animation: kit-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@media (max-width: 639.98px) {
  .topbar__balance-value {
    font-size: 16px;
    line-height: 24px;
  }
}

/* ---- the price strip ---- */
.price-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 18px 0 12px;
}
.price-header__asset {
  display: flex;
  align-items: center;
  gap: 10px;
}
/* BTC brand orange on purpose: asset identity, not the UI palette */
.asset-badge {
  display: flex;
  width: 32px;
  height: 32px;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background-image: linear-gradient(to bottom right, #f7931a, #ffb84d);
  font-size: 16px;
  font-weight: 900;
  color: #fff;
  box-shadow: 0 3px 10px rgba(247, 147, 26, 0.35);
}
.price-header__name {
  font-size: 14px;
  line-height: 1.2;
  font-weight: 800;
  color: var(--foreground);
}
.price-header__price {
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 1;
  font-weight: 500;
  color: var(--muted-foreground);
}
@media (max-width: 639.98px) {
  .price-header {
    gap: 8px;
    margin: 12px 0 8px;
  }
  .price-header__asset {
    gap: 8px;
  }
  .asset-badge {
    width: 28px;
    height: 28px;
    font-size: 14px;
  }
  .price-header__name {
    font-size: 13px;
  }
  .price-header__price {
    font-size: 16px;
  }
}

/* ---- the link readout: absent while healthy, a tinted pill when not ---- */
.link-status {
  position: relative;
  display: inline-flex;
}
.link-pill {
  display: flex;
  cursor: pointer;
  align-items: center;
  gap: 6px;
  border-radius: 9999px;
  padding: 5px 10px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  outline: none;
}
.link-pill.is-attention {
  background: color-mix(in oklab, var(--attention) 15%, transparent);
  color: var(--attention);
}
.link-pill.is-destructive {
  background: color-mix(in oklab, var(--destructive) 15%, transparent);
  color: var(--destructive);
}
/* three bars, lit from the shortest up; unlit ones stay a faint --icon */
.link-bars rect {
  fill: var(--icon);
  fill-opacity: 0.28;
}
.link-bars[data-lit="1"] rect:nth-child(-n + 1),
.link-bars[data-lit="2"] rect:nth-child(-n + 2) {
  fill: currentColor;
  fill-opacity: 1;
}
.link-tip {
  position: absolute;
  top: 100%;
  z-index: 50;
  /* the width ui.js sets is the box it occupies, padding and border included:
     on a 320px screen the difference is the whole overflow */
  box-sizing: border-box;
  max-width: calc(100vw - 16px);
  margin-top: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--secondary);
  padding: 12px;
  text-align: left;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.link-tip__caret {
  position: absolute;
  top: -4px;
  width: 8px;
  height: 8px;
  transform: rotate(45deg);
  border-left: 1px solid var(--border);
  border-top: 1px solid var(--border);
  background: var(--secondary);
}
.link-tip__title {
  font-size: 12px;
  font-weight: 700;
  color: var(--secondary-foreground);
}
.link-tip__body {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted-foreground);
}
/* ---- the stage stepper: a track, one live segment carrying the timer ---- */
.stages {
  position: relative;
  margin-bottom: 12px;
  display: flex;
  height: 48px;
  width: 100%;
  align-items: center;
  border-radius: var(--radius-xl);
  background: var(--card);
  padding: 4px;
}
.stages__track {
  display: flex;
  height: 100%;
  width: 100%;
  align-items: center;
  gap: 1px;
}
/* one soft entrance for the result; dismissal is immediate */
.stages__track.is-covered,
.stages__result.is-on {
  transition: opacity 1000ms cubic-bezier(0.45, 0.05, 0.25, 1);
}
.stages__track.is-covered {
  opacity: 0;
}
.stage {
  position: relative;
  display: flex;
  height: 40px;
  min-width: 0;
  flex: 1 1 0%;
  align-items: center;
  justify-content: center;
  gap: 8px;
  overflow: hidden;
  border-radius: calc(var(--radius-xl) - 0.25rem);
  padding: 0 8px;
  font-size: 16px;
  line-height: 24px;
  color: var(--foreground);
  opacity: 0.5;
}
.stage.is-active {
  background: #141416;
  opacity: 1;
}
.stage-timer {
  pointer-events: none;
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
}
.stage-timer > span {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 0;
  background: var(--secondary-hover);
}
.stage__label {
  position: relative;
  z-index: 10;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.stage__time {
  position: relative;
  z-index: 10;
  font-family: var(--font-mono);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.stage__time:empty {
  display: none;
}
/* the betting clock's last seconds */
.stage.is-active.is-urgent .stage__time {
  animation: stage-urgent 0.7s ease-in-out infinite;
}
@keyframes stage-urgent {
  50% { opacity: 0.5; }
}
/* a tap after bets closed: lift the dim tab, flash the label white, shake */
.stage.is-nudged {
  overflow: visible;
  animation: stage-nudge-in 0.42s ease-in-out;
}
.stage.is-nudged .stage__label {
  animation: stage-nudge 0.42s ease-in-out;
}
@keyframes stage-nudge-in {
  0%, 100% { opacity: 0.5; }
  12%, 88% { opacity: 1; }
}
@keyframes stage-nudge {
  0%, 100% { transform: translateX(0); color: inherit; }
  16% { transform: translateX(-6px); color: #fff; }
  32% { transform: translateX(6px); color: #fff; }
  48% { transform: translateX(-4px); color: #fff; }
  64% { transform: translateX(4px); color: #fff; }
  80% { transform: translateX(-2px); color: #fff; }
}
@keyframes stage-nudge-flash {
  0%, 100% { color: inherit; }
  20%, 80% { color: #fff; }
}
.stages__result {
  position: absolute;
  inset: 4px;
  display: flex;
  pointer-events: none;
  opacity: 0;
}
.stages__result.is-on {
  pointer-events: auto;
  opacity: 1;
}
.result-pill {
  display: flex;
  flex: 1 1 0%;
  align-items: center;
  justify-content: center;
  gap: 10px;
  overflow: hidden;
  white-space: nowrap;
  border-radius: calc(var(--radius-xl) - 0.25rem);
  padding: 0 8px;
  font-size: 16px;
}
.result-pill.is-win {
  background: rgba(214, 255, 77, 0.14);
}
.result-pill.is-loss,
.result-pill.is-missed {
  background: rgba(242, 79, 232, 0.14);
}
/* a zero-return notice: the destructive surface's text colour */
.result-pill.is-missed .result-pill__text {
  color: var(--destructive-foreground);
}
.result-pill.is-flat {
  background: color-mix(in oklab, #fff 6%, transparent);
}
/* a payment the wallet has not answered (ui.js paymentFace): no amount, a
   slow pulse until the final face replaces it */
.result-pill.is-pending {
  background: color-mix(in oklab, var(--attention) 14%, transparent);
}
.result-pill.is-pending .result-pill__text {
  color: var(--attention);
  animation: kit-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.result-pill.is-voided {
  background: color-mix(in oklab, #fff 6%, transparent);
}
.result-pill.is-voided .result-pill__text {
  color: var(--muted-foreground);
}
.result-pill__text {
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--foreground);
}
.result-pill__tag {
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--success);
}
.result-pill__mult {
  font-family: var(--font-mono);
  font-weight: 500;
  color: var(--success);
  font-variant-numeric: tabular-nums;
}
.result-pill__amount {
  font-family: var(--font-mono);
  font-size: 13.5px;
  color: color-mix(in oklab, var(--foreground) 90%, transparent);
  font-variant-numeric: tabular-nums;
}
.result-pill__text:empty,
.result-pill__tag:empty,
.result-pill__mult:empty,
.result-pill__amount:empty {
  display: none;
}
@media (max-width: 639.98px) {
  .stage {
    gap: 4px;
    padding: 0 4px;
    font-size: 13px;
  }
  .result-pill {
    gap: 8px;
    font-size: 13px;
  }
}

/* ---- the money buttons docked beside the plot (Pulse, Dash): a bet in
   the side's colour, or the cashout with its amount; success surfaces carry
   dark text, destructive ones white ---- */
.action {
  position: relative;
  display: flex;
  min-width: 0;
  cursor: pointer;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: 16px;
  font-family: var(--font-sans);
  transition-property: transform, box-shadow, filter;
  transition-duration: 150ms;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.action:enabled:hover {
  transform: translateY(-2px);
  filter: brightness(1.05);
}
.action:enabled:active {
  transform: scale(0.98);
}
.action:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
.action--up {
  background: linear-gradient(to bottom right, var(--success), var(--success-deep));
  color: var(--success-foreground);
  box-shadow: 0 8px 24px rgba(214, 255, 77, 0.34);
}
.action--up:enabled:hover {
  box-shadow: 0 12px 32px rgba(214, 255, 77, 0.5);
}
.action--down {
  background: linear-gradient(to bottom right, var(--destructive), var(--destructive-deep));
  color: var(--destructive-foreground);
  box-shadow: 0 8px 24px rgba(242, 79, 232, 0.34);
}
.action--down:enabled:hover {
  box-shadow: 0 12px 32px rgba(242, 79, 232, 0.5);
}
.action--bet {
  gap: 5px;
  padding: 16px 12px;
}
.action--cashout {
  gap: 6px;
  padding: 14px 12px;
}
.cashout__row {
  display: flex;
  height: 36px;
  width: 100%;
  min-width: 0;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
}
.cashout__big {
  display: block;
  flex-shrink: 0;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 36px;
  font-weight: 800;
  line-height: 1;
}
.cashout__amount {
  font-variant-numeric: tabular-nums;
}
.cashout__note {
  flex-shrink: 0;
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.3;
  opacity: 0.9;
}
@media (max-width: 639.98px) {
  .action--bet {
    gap: 3px;
    padding: 12px 8px;
  }
  .cashout__row {
    height: 21px;
  }
  .cashout__big {
    font-size: 21px;
  }
  .cashout__note {
    font-size: 11px;
  }
}

/* ---- the stake controls: −/amount/+ over the quick chips ---- */
.stake-rack {
  margin-bottom: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.stake-stepper {
  display: flex;
  align-items: stretch;
  gap: 6px;
}
.stake-step {
  min-width: 56px;
  flex: 1 1 0%;
  border-radius: var(--radius-xl);
  padding: 8px 12px;
  font-size: 24px;
  line-height: 32px;
  font-weight: 800;
  color: var(--primary-hover);
}
.stake-step:hover {
  color: var(--primary);
}
.stake-step:active {
  scale: 0.93;
}
.stake-field {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 8px;
  border-radius: var(--radius-xl);
  background: var(--secondary);
  padding: 10px 8px;
}
.stake-field input {
  width: 100%;
  min-width: 0;
  flex: 1 1 0%;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 28px;
  font-weight: 700;
  color: var(--foreground);
  outline: none;
}
.stake-field__currency {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 700;
  color: var(--foreground);
}
.stake-chips {
  display: grid;
  grid-template-columns: repeat(var(--chips, 4), minmax(0, 1fr));
  gap: 6px;
}
.stake-chip {
  min-height: 42px;
  border-radius: var(--radius-xl);
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 700;
  color: var(--muted-foreground);
}
.stake-chip:hover {
  color: var(--primary-hover);
}
.stake-chip:active {
  scale: 0.95;
}
@media (max-width: 639.98px) {
  .stake-stepper {
    gap: 4px;
  }
  /* fixed 44px −/+ tap targets; the freed width goes to the amount */
  .stake-step {
    min-width: 0;
    width: 44px;
    flex: none;
    font-size: 18px;
    line-height: 28px;
  }
  .stake-field {
    padding: 6px 8px;
  }
  .stake-field input {
    font-size: 16px;
    line-height: 24px;
  }
  .stake-field__currency {
    font-size: 13px;
  }
  .stake-chips {
    gap: 5px;
  }
  .stake-chip {
    min-height: 32px;
    font-size: 13px;
  }
}

/* ---- the game menu: a ⋯ that opens a bottom sheet ---- */
.menu-trigger {
  display: flex;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  font-size: 18px;
  color: var(--icon);
  transition: color 150ms, background-color 150ms;
}
.menu-trigger:hover {
  background: var(--secondary);
  color: var(--foreground);
}
.menu-trigger:active {
  scale: 0.93;
}
.menu {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.menu__backdrop {
  position: absolute;
  inset: 0;
  background: rgb(0 0 0 / 0.65);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.menu__sheet {
  position: relative;
  display: flex;
  max-height: 86dvh;
  width: 100%;
  max-width: 600px;
  flex-direction: column;
  overflow: hidden;
  border-radius: 16px 16px 0 0;
  background: #17181d;
  box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.55);
  transition: transform 0.18s ease-out;
}
.menu__sheet.is-dragging {
  transition: none;
}
.menu__handle {
  display: flex;
  justify-content: center;
  padding: 10px 0 4px;
}
.menu__handle::before {
  content: "";
  height: 4px;
  width: 36px;
  border-radius: 9999px;
  background: rgb(255 255 255 / 0.22);
}
.menu__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 20px 12px;
}
.menu__back {
  display: flex;
  cursor: pointer;
  align-items: center;
  gap: 4px;
  font-size: 15px;
  font-weight: 600;
  color: var(--accent-color);
}
.menu__back .icon {
  font-size: 18px;
  rotate: 180deg;
}
.menu__title {
  flex: 1 1 0%;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.025em;
  color: #fff;
}
.menu__close {
  display: flex;
  width: 28px;
  height: 28px;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: rgb(255 255 255 / 0.08);
  color: var(--icon);
  transition: color 150ms, background-color 150ms;
}
.menu__close:hover {
  background: rgb(255 255 255 / 0.16);
  color: #fff;
}
.menu__body {
  position: relative;
  min-height: 0;
  flex: 1 1 0%;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: calc(18px + env(safe-area-inset-bottom));
}
/* More to scroll to. A row cut by the sheet's edge looked like the end of the
   list, so players never learned that "Sounds" was under "Music". A
   gradient alone cannot say it -- the sheet and its rows are within a few
   percent of the same dark, so a fade between them is invisible. This is a
   hairline plus an arrow sitting ON the sheet's own footer row, so nothing
   paints over it: the line separates "cut off" from "finished", the arrow
   names the direction. ui.js adds the class, and only while rows really are
   hidden below. */
.menu__more {
  pointer-events: none;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 26px;
  display: grid;
  place-items: center;
  border-top: 1px solid rgb(255 255 255 / 0.14);
  background: #1d1f26;
  color: #cfd3de;
  font-size: 12px;
  line-height: 1;
  opacity: 0;
  transition: opacity 0.15s ease-out;
}
.menu.has-more-below .menu__more {
  opacity: 1;
}
.menu__rows {
  border-top: 1px solid rgb(255 255 255 / 0.08);
}
.menu-row {
  display: flex;
  width: 100%;
  cursor: pointer;
  align-items: center;
  gap: 14px;
  border-bottom: 1px solid rgb(255 255 255 / 0.08);
  padding: 16px 20px;
  text-align: left;
  font-size: 17px;
  font-weight: 600;
  color: #fff;
  transition: background-color 150ms;
}
.menu-row:hover {
  background: rgb(255 255 255 / 0.05);
}
.menu-row:active {
  background: rgb(255 255 255 / 0.08);
}
div.menu-row {
  cursor: auto;
}
div.menu-row:hover,
div.menu-row:active {
  background: transparent;
}
/* the glyph at its size, centred in a 24px slot (a mask fills its box) */
.menu-row > .icon:first-child {
  font-size: 17px;
  margin: 0 calc((24px - 1em) / 2);
  color: var(--accent-color);
}
.menu-row > .icon-music:first-child,
.menu-row > [data-speaker] {
  font-size: 19px;
}
.menu-row__label {
  flex: 1 1 0%;
}
.menu-row > .icon-chevron {
  font-size: 18px;
  color: var(--icon);
}
.menu-switch {
  position: relative;
  height: 28px;
  width: 48px;
  flex-shrink: 0;
  cursor: pointer;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.16);
  transition: background-color 150ms;
}
.menu-switch[aria-checked="true"] {
  background: var(--accent-color);
}
.menu-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  border-radius: 9999px;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  transition: transform 150ms;
}
.menu-switch[aria-checked="true"]::after {
  transform: translateX(20px);
}
/* the language picker: a native select, sized like wisdom-games' EN/RU trigger */
.menu-lang {
  height: 28px;
  width: 74px;
  flex-shrink: 0;
  cursor: pointer;
  border: 1px solid rgb(255 255 255 / 0.16);
  border-radius: 6px;
  background: rgb(255 255 255 / 0.08);
  padding: 0 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  color-scheme: dark;
}
.menu-howto {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 8px 20px 12px;
  counter-reset: step;
}
.menu-howto > li {
  counter-increment: step;
  display: flex;
  flex-direction: column;
}
.menu-howto p {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding-top: 2px;
  font-size: 15px;
  line-height: 1.625;
  color: #fff;
}
.menu-howto p::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-mono);
  font-size: 22px;
  line-height: 1;
  font-weight: 900;
  padding-top: 2px;
  color: var(--accent-color);
}
.menu-rules {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 4px 20px 8px;
  counter-reset: step;
}
.menu-rules > li {
  counter-increment: step;
  display: flex;
  gap: 12px;
  font-size: 15px;
  line-height: 1.625;
  color: #d7dae3;
}
.menu-rules > li::before {
  content: counter(step, decimal-leading-zero);
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  color: var(--accent-color);
}
.menu__panel {
  padding: 4px 20px 8px;
}
.menu-limits {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 16px;
  font-size: 15px;
}
.menu-limits dt,
.menu-limits dd {
  border-bottom: 1px solid rgb(255 255 255 / 0.08);
  padding: 12px 0;
}
.menu-limits dt {
  color: #d7dae3;
}
.menu-limits dd {
  text-align: right;
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--accent-color);
}

/* ---- the first-run card over a softened game ---- */
.shell.is-intro .stages,
.shell.is-intro .shell-board,
.shell.is-intro .shell-controls {
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  filter: blur(6px) brightness(0.7) saturate(0.75);
}
/* over the board and the controls, whichever way the layout puts them; the
   card is centred out of flow so it never sizes the grid rows */
.ftue {
  grid-row: 2 / -1;
  grid-column: 1 / -1;
  position: relative;
  z-index: 30;
  min-height: 0;
}
/* The card is bounded by the frame it opens in, and lays itself out as a
   column: the title and the Play button keep their place, the steps take what
   is left and scroll if they do not fit. Without the bound the card simply
   grew past both edges of a short frame -- its own overflow: hidden then cut
   the Play button off, and in a landscape band the button was not on screen at
   all, which left the player unable to close the card . */
.ftue__card {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  width: calc(100% - 24px);
  max-width: 540px;
  max-height: calc(100% - 12px);
  overflow: hidden;
  border-radius: 16px;
  background: var(--card);
  padding: 20px;
  box-shadow: 0 0 0 1px rgb(255 255 255 / 0.25), 0 24px 64px rgba(0, 0, 0, 0.55);
}
.ftue__card > .ftue__title,
.ftue__card > .ftue__cta {
  flex: 0 0 auto;
}
.ftue__card::before {
  content: "";
  pointer-events: none;
  position: absolute;
  inset: 0 0 auto;
  height: 96px;
  background-image: linear-gradient(to bottom, rgb(255 255 255 / 0.12), transparent);
}
.ftue__title {
  position: relative;
  margin-bottom: 16px;
  text-align: center;
  font-size: 20px;
  line-height: 28px;
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--heading);
}
.ftue__steps {
  position: relative;
  margin-bottom: 20px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  /* the one part of the card that may scroll, so the button never leaves */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.ftue__steps > li {
  min-width: 0;
  text-align: center;
}
.ftue__steps p {
  font-size: 13px;
  line-height: 1.375;
  color: var(--foreground);
}
.ftue__cta {
  position: relative;
  height: 48px;
  width: 100%;
  border-radius: var(--radius-xl);
  font-size: 16px;
  font-weight: 800;
  background: #fff;
  color: #000;
}
.ftue__cta:hover {
  background: rgb(255 255 255 / 0.9);
}
@media (max-width: 639.98px) {
  .ftue__card {
    width: calc(100% - 16px);
    padding: 16px 12px;
  }
  .ftue__title {
    margin-bottom: 12px;
    font-size: 18px;
  }
  .ftue__steps {
    margin-bottom: 16px;
    gap: 8px;
  }
  .ftue__steps p {
    font-size: 11px;
  }
}

/* ---- the first-run card in a short frame ----
 * The card has to fit the frame the operator gave the game, and the Play
 * button is what the player needs most: it is the only way out of the card.
 * So the trimming goes title, art, padding -- and the steps scroll. */
@media (max-height: 560px) {
  .ftue__card {
    max-height: calc(100% - 8px);
    padding: 12px;
  }
  .ftue__title {
    margin-bottom: 8px;
    font-size: 16px;
    line-height: 22px;
  }
  .ftue__steps {
    margin-bottom: 10px;
    gap: 8px;
  }
  .ftue__cta {
    height: 42px;
  }
}

/* A landscape band: three columns of steps leave no height for anything, and
   the art is the first thing that can go. The button keeps its full size --
   it is a tap target, and the one that closes the card. */
@media (orientation: landscape) and (max-height: 420px) {
  .ftue__card {
    max-height: calc(100% - 6px);
    padding: 10px 12px;
  }
  .ftue__title {
    margin-bottom: 6px;
    font-size: 15px;
    line-height: 20px;
  }
  .ftue__steps {
    margin-bottom: 8px;
    gap: 6px;
  }
  .ftue__steps .art {
    display: none;
  }
  .ftue__steps p {
    font-size: 11px;
  }
  .ftue__cta {
    height: 40px;
  }
}

/* ---- toasts: sonner's dark card ---- */
/* A page without a header (none of the games) shows a notice as a toast. */
.toaster {
  position: fixed;
  z-index: 100;
  top: 24px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  width: 356px;
  flex-direction: column;
  gap: 14px;
}

/* ---- the notice row: the header's last row, one line, always reserved ----
   Its height never changes, with a notice or without: the board and the
   controls under the header do not move when one comes or goes. */
.notice-row {
  display: block;
  width: 100%;
  height: 24px;
  margin-top: 4px;
  border: 0;
  border-radius: 8px;
  background: none;
  padding: 0 12px;
  color: var(--foreground);
  font: inherit;
  font-size: 12px;
  line-height: 24px;
  text-align: center;
  cursor: pointer;
}
.notice-row:disabled { visibility: hidden; }
.notice-row > span {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.notice-row.is-standing { background: var(--popover); }
/* the panel a tap on the row opens: every notice in full */
.notices { text-align: left; font-size: 13px; font-weight: 500; }
.notices ul { margin: 0 0 16px; padding: 0; list-style: none; max-height: 60vh; overflow-y: auto; }
.notices li + li { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 12px; }
.notices p { margin: 0; overflow-wrap: anywhere; }
.toast {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--popover);
  color: var(--popover-foreground);
  padding: 16px;
  font-size: 13px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  animation: toast-in 400ms ease;
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-100%); }
}
@media (max-width: 639.98px) {
  .toaster {
    top: 16px;
    width: calc(100% - 32px);
  }
}

/* ---- terminal notice: the credential is dead, relaunch from the lobby ---- */
.terminal {
  margin: auto;
  width: calc(100% - 32px);
  max-width: 448px;
  border: 1px solid color-mix(in srgb, var(--primary) 30%, transparent);
  border-radius: 24px;
  background: var(--card);
  color: var(--heading);
  padding: 28px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
  text-align: center;
  font-size: 15px;
  line-height: 1.5;
  font-weight: 600;
}
.terminal::backdrop {
  background: rgb(0 0 0 / 0.6);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.terminal p::first-letter {
  text-transform: uppercase;
}
.terminal .btn {
  margin-top: 16px;
}

/* ---- the win burst over the board ---- */
.win-confetti {
  pointer-events: none;
  position: absolute;
  inset: 0;
  z-index: 4;
}

@media (prefers-reduced-motion: reduce) {
  .shell.is-intro .stages,
  .shell.is-intro .shell-board,
  .shell.is-intro .shell-controls {
    filter: brightness(0.9);
  }
  .stage.is-active.is-urgent .stage__time { animation: none; }
  .stage.is-nudged .stage__label { animation: stage-nudge-flash 0.42s ease-in-out; }
  .toast { animation: none; }
  .result-pill.is-pending .result-pill__text { animation: none; }
}
