/* game.css — Klondike board for solitaire-online.com */

* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --felt-1: #0e5c3f;
  --felt-2: #063a26;
  --gold: #d4af37;
  --ink: #f5f0e6;
  --panel: rgba(0, 0, 0, 0.28);
}

html { scroll-behavior: smooth; }

html, body {
  min-height: 100%;
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}

body {
  overflow-x: hidden;
  overscroll-behavior-y: contain;
  background: radial-gradient(ellipse at 50% 30%, var(--felt-1), var(--felt-2) 80%);
  background-attachment: fixed;
}

/* The game itself fills the viewport exactly; page content scrolls below it.
   Real visible height on mobile (dvh excludes the browser address bar). */
.play-area {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
}

/* ---------- header ---------- */

.game-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  padding: 8px 16px;
  flex: 0 0 auto;
  background: var(--panel);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid rgba(212, 175, 55, 0.25);
}

.brand {
  display: flex;
  align-items: center;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: 0.3px;
  white-space: nowrap;
}
.brand-logo { height: 28px; width: 28px; display: block; flex: none; margin-right: 8px; }
.brand-mark { color: var(--gold); margin-right: 2px; }
.brand-accent { color: var(--gold); font-weight: inherit; }

.hud { display: flex; gap: 18px; margin-left: auto; }
.hud-item { display: flex; flex-direction: column; align-items: center; min-width: 52px; }
.hud-label { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 1px; opacity: 0.65; }
.hud-value { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; }

.controls { display: flex; gap: 8px; align-items: center; margin-left: auto; }

.ctl-btn {
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.08);
  color: var(--ink);
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 0.85rem;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
  white-space: nowrap;
}
.ctl-btn:hover { background: rgba(255, 255, 255, 0.18); }
.ctl-btn:active { transform: scale(0.96); }
.ctl-btn.primary { background: var(--gold); border-color: var(--gold); color: #2a2005; font-weight: 700; }
.ctl-btn.muted { opacity: 0.55; }
.ctl-btn.primary:hover { background: #e6c34c; }
.ctl-btn.big { font-size: 1.05rem; padding: 12px 28px; }

.draw-toggle { display: flex; border: 1px solid rgba(255,255,255,0.25); border-radius: 8px; overflow: hidden; }
.toggle-btn {
  border: none; background: transparent; color: var(--ink);
  padding: 7px 10px; font-size: 0.8rem; cursor: pointer;
}
.toggle-btn.active { background: var(--gold); color: #2a2005; font-weight: 700; }

/* ---------- image control buttons (solitaire-button-images) ---------- */
/* English pages only — the artwork's text is baked in as English, so the
   German mirror keeps the plain text .ctl-btn/.toggle-btn styling above. */

.img-btn {
  border: none;
  background: transparent;
  color: inherit;
  padding: 0;
  border-radius: 0;
  flex-shrink: 0;
  cursor: pointer;
  line-height: 0;
  transition: transform 0.1s, filter 0.15s, opacity 0.15s;
}
.ctl-btn.img-btn, .toggle-btn.img-btn {
  border: none;
  background: transparent;
  padding: 0;
}
.img-btn > img {
  display: block;
  width: auto;
  height: 38px;
  max-width: none;
  pointer-events: none;
  user-select: none;
}
.img-btn:hover { filter: brightness(1.12); }
.img-btn:active { transform: scale(0.94); }
.img-btn.muted { filter: grayscale(0.9) brightness(0.75); }

.draw-toggle.img-mode { border: none; border-radius: 0; overflow: visible; gap: 6px; }
.toggle-btn.img-btn { opacity: 0.5; }
.toggle-btn.img-btn:hover { opacity: 0.75; }
.toggle-btn.img-btn.active { opacity: 1; filter: drop-shadow(0 0 5px rgba(212, 175, 55, 0.55)); }
.toggle-btn.img-btn.active:hover { filter: drop-shadow(0 0 5px rgba(212, 175, 55, 0.55)) brightness(1.1); }


/* ---------- board ---------- */

#board {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* The layer spans the whole board and sits above the placeholders, so it must
   let clicks fall through to them (stock recycle, onPileClick). Cards opt back in. */
#card-layer { position: absolute; inset: 0; pointer-events: none; }

.placeholder {
  position: absolute;
  border: 2px dashed rgba(255, 255, 255, 0.22);
  border-radius: 8%/6%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.3);
  font-size: 1.6rem;
}
.stock-ph { cursor: pointer; }
.stock-ph span { font-size: 2rem; }

/* The fixed slots along the top (stock, waste, free cells, reserve,
   foundations) share one filled-panel look, so that row reads as a single
   band. The tableau placeholders keep the dashed outline: they are a landing
   spot for a run rather than a permanent slot. */
.stock-ph, #ph-waste, .cell-ph, .reserve-ph, .foundation-ph {
  border: none;
  background: rgba(255, 255, 255, 0.09);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    inset 0 -10px 24px rgba(0, 0, 0, 0.10);
}

/* Empty foundations carry a large suit mark instead of four identical letters,
   so the row reads as four distinct targets at a glance.
   The club glyph is several overlapping shapes, so the fade has to sit on the
   element rather than the fill: a translucent fill double-composites where
   they overlap and leaves seams through the mark. */
.foundation-ph .suit-mark {
  width: calc(var(--cw) * 0.44);
  height: calc(var(--cw) * 0.44);
  fill: #ffffff;
  opacity: 0.26;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.22));
}
.foundation-ph.ph-red .suit-mark { fill: #ffc2c2; opacity: 0.32; }

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

.card {
  position: absolute;
  width: var(--cw);
  height: var(--ch);
  top: 0; left: 0;
  will-change: transform;
  cursor: pointer;
  perspective: 900px;
  pointer-events: auto;
}
.card.anim { transition: transform 0.25s cubic-bezier(0.25, 0.9, 0.3, 1.1); }
.card.dragging { cursor: grabbing; }
.card.dragging .card-face { box-shadow: 0 12px 24px rgba(0, 0, 0, 0.45); }

.card-inner {
  position: relative;
  width: 100%; height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.3s ease;
  transform: rotateY(180deg);
}
.card.faceup .card-inner { transform: rotateY(0deg); }

.card-face {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 8%/6%;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.35);
  display: block;
}
.card-face.back { transform: rotateY(180deg); }

/* backface-visibility is unreliable for SVG <image> content, so swap
   faces explicitly at the flip animation's midpoint (0.15s of 0.3s) */
.card-face.front { visibility: hidden; transition: visibility 0s 0.15s; }
.card.faceup .card-face.front { visibility: visible; }
.card-face.back { visibility: visible; transition: visibility 0s 0.15s; }
.card.faceup .card-face.back { visibility: hidden; }

@keyframes deal-in {
  from { opacity: 0.4; transform: translateY(-14px) scale(0.94); }
  to { opacity: 1; transform: none; }
}
.card.dealt .card-inner { animation: deal-in 0.3s ease both; }

/* The hint glow is deliberately NOT a `filter: drop-shadow()` animation.
   `.card` is promoted to its own compositing layer (`will-change: transform`)
   and wraps a `preserve-3d` subtree, and iOS Safari runs filter animations on
   such a layer through the accelerated path, which has no drop-shadow support:
   it drops the whole filter instead, so the glow never paints on iPhone even
   though the computed value interpolates correctly. Desktop Safari and
   software-rendered WebKit both paint it fine, which is why it kept looking
   fixed. So the halo is a box-shadow on a flat pseudo-element and only
   `opacity` animates, which every mobile browser composites reliably. */
@keyframes hint-pulse {
  0%, 100% { opacity: 0; }
  35%, 70% { opacity: 1; }
}
.card.hint::after, .placeholder.hint::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 8%/6%;
  /* the wash stands in for the brightness() the filter used to add, so a card
     showing only a sliver above its neighbour still reads as picked out */
  background: rgba(212, 175, 55, 0.14);
  box-shadow: 0 0 14px 3px var(--gold);
  opacity: 0;
  pointer-events: none;
  animation: hint-pulse 1.2s ease;
}

/* ---------- extra pile types (multi-game) ---------- */

/* the page's <h1>, kept visually subtle inside the game header */
.game-name {
  font-size: 0.85rem;
  font-weight: 600;
  opacity: 0.75;
  letter-spacing: 0.5px;
  white-space: nowrap;
}
.game-name a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px dotted rgba(245, 240, 230, 0.35);
}
.game-name a:hover { color: var(--gold); border-bottom-color: var(--gold); }

.reserve-ph span { font-family: Georgia, serif; font-size: 1.2rem; }
.done-ph { border-color: rgba(212, 175, 55, 0.4); color: rgba(212, 175, 55, 0.5); }

.card.selected .card-face {
  outline: 3px solid var(--gold);
  outline-offset: -1px;
  box-shadow: 0 0 16px rgba(212, 175, 55, 0.7);
  border-radius: 8%/6%;
}

/* ---------- auto-complete ---------- */

.auto-btn {
  position: absolute;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%) translateY(80px);
  opacity: 0;
  pointer-events: none;
  background: var(--gold);
  color: #2a2005;
  border: none;
  font-size: 1rem;
  font-weight: 700;
  padding: 12px 26px;
  border-radius: 999px;
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.4);
  transition: transform 0.3s, opacity 0.3s;
  z-index: 3000;
}
.auto-btn.show { transform: translateX(-50%); opacity: 1; pointer-events: auto; }

/* ---------- scroll hint ---------- */

.scroll-hint {
  flex: 0 0 auto;
  display: block;
  text-align: center;
  padding: 5px 0 9px;
  font-size: 0.74rem;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.4;
  text-decoration: none;
  transition: opacity 0.18s;
}
.scroll-hint:hover { opacity: 0.85; color: var(--gold); }

/* ---------- content below the board ---------- */

.game-content {
  max-width: 760px;
  margin: 0 auto;
  padding: 40px 5vw 20px;
  line-height: 1.65;
  border-top: 1px solid rgba(212, 175, 55, 0.25);
}

.game-content h2 {
  font-size: 1.42rem;
  margin: 38px 0 12px;
  letter-spacing: -0.2px;
}
.game-content h2:first-child { margin-top: 0; }
.game-content h2::after {
  content: '';
  display: block;
  width: 44px;
  height: 2px;
  background: var(--gold);
  margin-top: 10px;
  opacity: 0.8;
}

.game-content h3 { font-size: 1.02rem; margin: 0 0 6px; }
.game-content p { margin-bottom: 15px; opacity: 0.9; }
.game-content ul, .game-content ol { margin: 0 0 18px 22px; }
.game-content li { margin-bottom: 9px; opacity: 0.9; }
.game-content li::marker { color: var(--gold); }
.game-content strong { color: var(--ink); font-weight: 700; }
.game-content a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }
.game-content a:hover { color: #e8cc63; }

.game-content .faq-item {
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  padding: 15px 0;
}
.game-content .faq-item p { margin: 0; font-size: 0.95rem; opacity: 0.86; }

.guide-link { margin-top: 26px; font-weight: 600; }

/* ---------- footer ---------- */

.game-footer {
  text-align: center;
  padding: 40px 5vw 34px;
  margin-top: 30px;
  border-top: 1px solid rgba(212, 175, 55, 0.25);
  opacity: 0.85;
}
.game-footer .footer-games {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
  gap: 26px;
  max-width: 780px;
  margin: 0 auto 34px;
  text-align: left;
}
.game-footer .footer-col h4 {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--gold);
  margin-bottom: 10px;
}
.game-footer .footer-col ul { list-style: none; margin: 0; padding: 0; }
.game-footer .footer-col li { margin-bottom: 6px; }
.game-footer .footer-col a {
  color: var(--ink);
  text-decoration: none;
  font-size: 0.86rem;
  opacity: 0.78;
}
.game-footer .footer-col a:hover { opacity: 1; color: var(--gold); text-decoration: underline; }
.game-footer .footer-brand { font-size: 1.05rem; font-weight: 700; margin-bottom: 6px; }
.game-footer .footer-brand a { color: var(--ink); text-decoration: none; }
.game-footer .footer-brand a:hover { color: var(--gold); }
.game-footer .brand-mark { color: var(--gold); }
.game-footer p { font-size: 0.86rem; }
.game-footer .copyright { margin-top: 12px; opacity: 0.6; font-size: 0.8rem; }

/* ---------- win overlay ---------- */

.win-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s;
  z-index: 5000;
}
.win-overlay.show { opacity: 1; pointer-events: auto; }

.win-card {
  background: linear-gradient(160deg, #14322a, #0a1f18);
  border: 1px solid rgba(212, 175, 55, 0.5);
  border-radius: 18px;
  padding: 36px 44px;
  text-align: center;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  transform: translateY(12px) scale(0.96);
  transition: transform 0.35s;
  max-width: 92vw;
}

/* Only the win card grows: the daily calendar and the achievement banner are
   injected into it at runtime, so it has to survive being tall on a short
   screen. The pause and lose cards share .win-card and stay compact. */
#win-overlay .win-card, .daily-card {
  width: 420px;
  max-height: 88dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.win-overlay.show .win-card { transform: none; }

.win-title { font-size: 2rem; font-weight: 800; color: var(--gold); margin-bottom: 20px; }
.win-grid { display: flex; gap: 30px; justify-content: center; margin-bottom: 18px; }
.win-grid > div { display: flex; flex-direction: column; }
.win-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 1.5px; opacity: 0.6; }
.win-value { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.win-stats { font-size: 0.85rem; opacity: 0.75; margin-bottom: 24px; }

.lose-title { color: #e0916b; }
.lose-msg {
  max-width: 400px;
  margin: -8px auto 22px;
  font-size: 0.94rem;
  opacity: 0.8;
  line-height: 1.5;
}
.win-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ---------- achievements ---------- */

.ach-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
  margin: 0 0 20px;
  padding: 12px 14px;
  border: 1px solid rgba(212, 175, 55, 0.45);
  border-radius: 12px;
  background: rgba(212, 175, 55, 0.1);
}
.ach-icon { font-size: 1.7rem; line-height: 1; flex: none; }
.ach-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ach-text strong { font-size: 0.98rem; color: var(--gold); }
.ach-text span { font-size: 0.8rem; opacity: 0.72; line-height: 1.35; }
.ach-flag {
  align-self: flex-start;
  font-size: 0.56rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #2a2005;
  background: var(--gold);
  border-radius: 20px;
  padding: 3px 8px;
  margin-bottom: 4px;
}

.ach-progress { font-size: 0.8rem; opacity: 0.7; margin-bottom: 12px; }
.ach-grid { display: grid; gap: 8px; grid-template-columns: 1fr 1fr; }
.ach-item {
  display: flex;
  align-items: center;
  gap: 9px;
  text-align: left;
  padding: 8px 10px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.04);
  opacity: 0.38;
}
.ach-item.got { opacity: 1; background: rgba(212, 175, 55, 0.1); }
.ach-item .ach-icon { font-size: 1.15rem; }
.ach-item .ach-text strong { font-size: 0.82rem; }
.ach-item .ach-text span { font-size: 0.7rem; }

/* ---------- daily challenge ---------- */

.daily-panel {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  text-align: left;
}
.dc-title {
  font-size: 1.02rem;
  font-weight: 800;
  color: var(--gold);
  margin-bottom: 12px;
}
.dc-title-sub { margin-top: 22px; }

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

.dc-hero { text-align: center; margin-bottom: 20px; }

.dc-medallion {
  position: relative;
  width: 84px;
  height: 84px;
  margin: 0 auto 12px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 50% 32%, #23503d, #102b20);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.12), 0 8px 22px rgba(0, 0, 0, 0.4);
}
/* The trophy is a soft watermark behind the count, so the number stays the
   thing you read first. */
.dc-medallion-icon {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.16;
}
.dc-medallion-icon svg { width: 54px; height: 54px; }
.dc-medallion-n {
  position: relative;
  font-size: 2.1rem;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.72);
}
.dc-medallion[data-tier="bronze"] {
  background: radial-gradient(circle at 50% 32%, #7a4a2b, #2c1a10);
  box-shadow: inset 0 0 0 2px #c8834f, 0 8px 22px rgba(0, 0, 0, 0.45);
}
.dc-medallion[data-tier="silver"] {
  background: radial-gradient(circle at 50% 32%, #5b6570, #232a31);
  box-shadow: inset 0 0 0 2px #c9d1d9, 0 8px 22px rgba(0, 0, 0, 0.45);
}
.dc-medallion[data-tier="gold"] {
  background: radial-gradient(circle at 50% 32%, #8a6f1c, #3a2c07);
  box-shadow: inset 0 0 0 2px var(--gold), 0 8px 26px rgba(212, 175, 55, 0.3);
}
.dc-medallion[data-tier="bronze"] .dc-medallion-n { color: #f0c19c; }
.dc-medallion[data-tier="silver"] .dc-medallion-n { color: #eef2f6; }
.dc-medallion[data-tier="gold"] .dc-medallion-n { color: #ffe9a8; }

.dc-hero-count {
  font-size: 1.12rem;
  font-weight: 800;
  letter-spacing: -0.2px;
  margin-bottom: 2px;
}
.dc-hero-sub { font-size: 0.8rem; opacity: 0.6; }

/* The trophies sit on the track, so it needs room above and below them. */
.dc-track {
  position: relative;
  height: 6px;
  margin: 6px 14px 34px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.13);
}
.dc-fill {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: 4px;
  background: linear-gradient(90deg, #c8834f, #c9d1d9 55%, var(--gold));
  transition: width 0.4s ease;
}
.dc-trophy {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #17392b;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.3);
}
.dc-trophy svg { width: 16px; height: 16px; }
/* The threshold sits under the trophy rather than inside it, so the icon is
   never competing with a number in 30px. */
.dc-trophy i {
  position: absolute;
  top: 32px;
  font-style: normal;
  font-size: 0.62rem;
  font-weight: 700;
  opacity: 0.5;
  color: #fff;
}
.dc-trophy.earned { color: #2a2005; }
.dc-trophy.earned.bronze { background: #c8834f; box-shadow: 0 0 0 3px rgba(200, 131, 79, 0.22); }
.dc-trophy.earned.silver { background: #c9d1d9; box-shadow: 0 0 0 3px rgba(201, 209, 217, 0.22); }
.dc-trophy.earned.gold { background: var(--gold); box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.28); }
.dc-trophy.earned i { opacity: 0.85; }

/* ---------- month nav ---------- */

.dc-cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.dc-cal-month { font-size: 0.86rem; font-weight: 700; letter-spacing: 0.2px; }
.dc-nav {
  background: rgba(255, 255, 255, 0.07);
  border: 0;
  border-radius: 7px;
  color: inherit;
  width: 28px;
  height: 26px;
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s;
}
.dc-nav:hover:not(:disabled) { background: rgba(255, 255, 255, 0.16); }
.dc-nav:disabled { opacity: 0.22; cursor: default; }

/* table-layout: fixed keeps the seven columns equal, otherwise the marked
   days are wider than the empty ones and the grid goes ragged. */
.dc-cal {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.dc-cal th {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  opacity: 0.5;
  font-weight: 600;
  padding-bottom: 5px;
}
.dc-cal td { padding: 2px; }
/* The pill is the span, so it can be a fixed square inside a fixed cell. */
.dc-cal td > span {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  border-radius: 7px;
  font-size: 0.8rem;
}
.dc-cal td > span {
  background: rgba(255, 255, 255, 0.045);
  transition: background 0.15s;
}
.dc-cal td.dc-pad > span, .dc-cal td.dc-pad { background: none; }
.dc-cal td.future > span { opacity: 0.25; background: none; }
.dc-cal td.won > span {
  background: linear-gradient(160deg, #2f8f5c, #1d6b42);
  color: #eafff2;
  font-weight: 700;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}
.dc-cal td.today > span {
  box-shadow: inset 0 0 0 2px var(--gold);
  font-weight: 800;
  color: var(--gold);
}
.dc-cal td.today.won > span {
  color: #eafff2;
  box-shadow: inset 0 0 0 2px var(--gold), 0 2px 6px rgba(0, 0, 0, 0.25);
}

.dc-board { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.dc-board th {
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  opacity: 0.5;
  font-weight: 600;
  text-align: left;
  padding-bottom: 4px;
}
.dc-board td { font-size: 0.85rem; padding: 5px 0; }
.dc-board tbody tr { background: rgba(212, 175, 55, 0.1); }
.dc-empty { font-size: 0.8rem; opacity: 0.6; margin: 2px 0 0; }

/* Entry point at the foot of the play area. The header control row is full at
   390px, so this sits beside the rules link instead. */
.play-foot {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}
.play-foot .scroll-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding: 0 12px;
  border: 1px solid rgba(212, 175, 55, 0.45);
  border-radius: 16px;
  background: rgba(212, 175, 55, 0.12);
  color: var(--gold);
  opacity: 1;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.65px;
  transition: background 0.15s, border-color 0.15s;
}
.play-foot .scroll-hint:hover {
  background: rgba(212, 175, 55, 0.24);
  border-color: var(--gold);
  color: var(--gold);
  opacity: 1;
}
.play-foot .scroll-hint:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Deliberately styled as a control rather than a caption: as plain text next
   to the rules link it read as a label and went unnoticed. */
.daily-entry {
  background: rgba(212, 175, 55, 0.12);
  border: 1px solid rgba(212, 175, 55, 0.45);
  border-radius: 20px;
  padding: 6px 15px;
  margin: 2px 0 4px;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--gold);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.daily-entry:hover { background: rgba(212, 175, 55, 0.24); border-color: var(--gold); }
.daily-entry:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.bookmark-entry {
  width: 112px;
  height: 39px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: 20px;
  overflow: hidden;
  background: transparent;
  cursor: pointer;
  line-height: 0;
  transition: transform 0.15s, filter 0.15s;
}
.bookmark-entry img { display: block; width: 100%; height: 100%; }
.bookmark-entry:hover { transform: translateY(-1px); filter: brightness(1.08); }
.bookmark-entry:active { transform: scale(0.97); }
.bookmark-entry:focus-visible { outline: 2px solid #fff3b0; outline-offset: 2px; }

/* A pulsing dot while today is unplayed. */
.daily-entry.todo::after {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-left: 7px;
  border-radius: 50%;
  background: var(--gold);
  vertical-align: 1px;
  animation: dc-pulse 2.4s ease-in-out infinite;
}
@keyframes dc-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.45; transform: scale(0.82); }
}
@media (prefers-reduced-motion: reduce) {
  .daily-entry.todo::after { animation: none; }
}

.daily-card { position: relative; text-align: left; }
.daily-card .daily-panel { margin-top: 0; padding-top: 0; border-top: 0; }
.dc-close {
  position: absolute;
  top: 10px;
  right: 12px;
  background: none;
  border: 0;
  color: inherit;
  opacity: 0.5;
  font-size: 1.6rem;
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
}
.dc-close:hover { opacity: 1; }

.dc-play { width: 100%; margin-top: 16px; }
.dc-done { font-size: 0.76rem; opacity: 0.7; margin-top: 8px; text-align: center; }

/* ---------- leaderboard ---------- */

.lb-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.lb-table th {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  opacity: 0.5;
  font-weight: 600;
  text-align: left;
  padding-bottom: 4px;
}
.lb-table th:first-child, .lb-table td:first-child { width: 26px; opacity: 0.75; }
.lb-table td {
  font-size: 0.82rem;
  padding: 5px 6px 5px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
/* A long name must not push the figures off the card. */
.lb-table td:nth-child(2) {
  max-width: 130px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lb-you td { background: rgba(212, 175, 55, 0.13); font-weight: 700; }
.lb-outside td { border-top: 1px dashed rgba(255, 255, 255, 0.25); }
.lb-tag {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--gold);
  opacity: 0.9;
  font-weight: 700;
}
.lb-total { font-size: 0.72rem; opacity: 0.55; margin-top: 7px; }
.lb-empty { font-size: 0.8rem; opacity: 0.6; margin: 4px 0 0; }

.lb-form { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.lb-field { flex: 1; min-width: 0; }
.lb-field input {
  width: 100%;
  padding: 9px 11px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  background: rgba(0, 0, 0, 0.28);
  color: inherit;
  font: inherit;
  font-size: 0.88rem;
}
.lb-field input:focus { outline: 2px solid var(--gold); outline-offset: 1px; }
.lb-form button { flex: none; }
.lb-hint { flex-basis: 100%; font-size: 0.7rem; opacity: 0.55; margin: 0; }
.lb-warn { opacity: 1; color: #f0b48a; }
.lb-sr {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.lb-remove {
  margin-top: 10px;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 0.72rem;
  opacity: 0.5;
  color: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.lb-remove:hover { opacity: 0.85; }

/* ---------- achievements strip ---------- */

.ach-strip {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.ach-strip-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.ach-strip-head .dc-title-sub { margin: 0; }
.ach-count {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
/* A grid rather than a wrapping flex row: at 400px a flex row orphans the
   "+N" counter onto a line of its own, which reads as a bug. */
.ach-row {
  display: grid;
  /* Capped rather than 1fr so the chips are the same size on a phone and on
     a desktop instead of stretching to fill the card. */
  grid-template-columns: repeat(auto-fit, minmax(34px, 42px));
  justify-content: start;
  gap: 7px;
  margin-top: 10px;
}
.ach-chip {
  aspect-ratio: 1;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05rem;
  background: rgba(212, 175, 55, 0.13);
  box-shadow: inset 0 0 0 1px rgba(212, 175, 55, 0.3);
}
.ach-more {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.76rem;
  opacity: 0.6;
  font-weight: 700;
}
.ach-none { grid-column: 1 / -1; }
.ach-none { font-size: 0.8rem; opacity: 0.55; margin: 0; }
.ach-toggle {
  margin-top: 12px;
  width: 100%;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 9px;
  color: inherit;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
}
.ach-toggle:hover { background: rgba(255, 255, 255, 0.12); }
.ach-strip .ach-list { margin-top: 12px; }

#confetti {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 6000;
}

/* ---------- responsive ---------- */

@media (max-width: 760px) {
  .game-header { gap: 6px 8px; padding: 6px 10px; }
  .brand { font-size: 1rem; }
  .brand-logo { height: 24px; width: 24px; }
  .hud { gap: 12px; margin-left: auto; }
  .hud-item { min-width: 44px; }
  .hud-value { font-size: 0.9rem; }
  .controls { margin-left: 0; width: 100%; justify-content: space-between; gap: 5px; flex-wrap: wrap; }
  .ctl-btn { padding: 6px 8px; font-size: 0.75rem; }
  .toggle-btn { padding: 6px 7px; font-size: 0.72rem; }
  .img-btn > img { height: 32px; }
}

/* phones: icon-only buttons, one compact control row, no game name */
@media (max-width: 600px) {
  .game-header { gap: 4px 8px; padding: 5px 8px; }
  .game-name { display: none; }
  .brand { font-size: 0.95rem; }
  .brand-logo { display: none; }
  .hud { gap: 10px; }
  .hud-item { min-width: 38px; }
  .hud-label { font-size: 0.55rem; }
  .hud-value { font-size: 0.85rem; }
  .controls { flex-wrap: nowrap; gap: 4px; }
  .ctl-btn { padding: 7px 9px; font-size: 0.9rem; line-height: 1; }
  .btn-label { display: none; }
  .toggle-btn { padding: 6px 8px; font-size: 0.72rem; }
  /* the image buttons always show their full baked-in label, so — unlike the
     icon-only text buttons above — they need to wrap rather than be forced
     into one row on narrow phones (klondike alone has 7 in this row) */
  .controls:has(.img-btn) { flex-wrap: wrap; row-gap: 6px; }
  .img-btn > img { height: 24px; }
}

/* ---------- pause (js/pause.js) ---------- */

/* The Time readout doubles as the pause button, so it has to look pressable. */
.hud-pause {
  cursor: pointer;
  border-radius: 8px;
  padding: 2px 8px;
  margin: -2px -2px;
  transition: background 0.15s, color 0.15s;
}
.hud-pause:hover, .hud-pause:focus-visible { background: rgba(255, 255, 255, 0.12); }
.hud-pause:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.hud-pause .hud-label::after {
  content: ' ❚❚';
  font-size: 0.72em;
  letter-spacing: -1px;
  color: var(--gold);
  opacity: 0.85;
}

/* Blank the board while paused. Opacity rather than a blur filter: the cards
   sit in a 3D transform context where iOS handles filters poorly, and blurring
   that many composited layers is expensive on a phone. */
.play-area.paused #board,
.play-area.paused .auto-btn { opacity: 0; pointer-events: none; }
.play-area #board { transition: opacity 0.25s ease; }

.pause-card { padding: 30px 44px 26px; }
.pause-mark {
  width: 62px;
  height: 62px;
  margin: 0 auto 14px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gold);
  background: rgba(212, 175, 55, 0.12);
  border: 1px solid rgba(212, 175, 55, 0.4);
}
.pause-mark svg { width: 26px; height: 26px; }
.pause-card .win-title { margin-bottom: 18px; }
.pause-stats { margin-bottom: 22px; }
.pause-resume { width: 100%; }
.pause-hint { font-size: 0.8rem; opacity: 0.6; margin-top: 12px; }

@media (max-width: 600px) {
  .pause-card { padding: 26px 24px 22px; }
  .pause-hint { display: none; }
}

/* ---------- promo ask (js/promo.js) ---------- */

.promo-card { padding: 30px 34px; max-width: 460px; position: relative; }

.promo-x {
  position: absolute;
  top: 10px; right: 14px;
  background: none;
  border: 0;
  color: var(--ink);
  opacity: 0.5;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
}
.promo-x:hover { opacity: 1; }

.promo-card .win-title { font-size: 1.5rem; margin-bottom: 12px; }

.promo-msg {
  font-size: 0.95rem;
  opacity: 0.82;
  line-height: 1.55;
  margin-bottom: 22px;
}

/* The share row is the actual ask, so it leads. Its icons are cloned from the
   footer and pick up the .share-btn styles further down this file. */
.promo-share {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 11px;
  padding: 4px 0 18px;
  margin-bottom: 4px;
  border-bottom: 1px solid rgba(212, 175, 55, 0.18);
}
.promo-share .share-btn {
  width: 44px;
  height: 44px;
}
.promo-native { min-width: 150px; }

.promo-rows { list-style: none; margin: 0 0 18px; padding: 0; text-align: left; }
.promo-rows li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 2px;
  border-top: 1px solid rgba(212, 175, 55, 0.18);
}
.promo-rows li:last-child { border-bottom: 1px solid rgba(212, 175, 55, 0.18); }
/* an author `display` beats the UA stylesheet's [hidden] rule, so restate it */
.promo-rows li[hidden] { display: none; }
.promo-ico { font-size: 1.15rem; flex: none; width: 22px; text-align: center; }
.promo-label { flex: 1; font-size: 0.95rem; }
.promo-rows .ctl-btn { flex: none; }

.promo-note { font-size: 0.84rem; opacity: 0.7; margin-bottom: 16px; min-height: 1.2em; }
.promo-later { width: 100%; }

.promo-step .win-actions { margin-top: 4px; }
.promo-step a.ctl-btn { text-decoration: none; display: inline-flex; align-items: center; }

@media (max-width: 480px) {
  .promo-card { padding: 26px 20px; }
  .promo-rows li { gap: 8px; padding: 11px 0; }
  .promo-label { font-size: 0.88rem; }
}

@media (prefers-reduced-motion: reduce) {
  .promo-overlay, .promo-overlay .win-card { transition: none; }
}

/* ============================================================
   The four-seat table (js/trick.js) for Hearts and Spades.
   Shares the felt, the cards, the header and the overlays with
   the patience games; everything below is what a table with
   three opponents needs and a tableau does not.
   ============================================================ */

/* cards you may not legally play right now */
.card.dim { cursor: default; }
.card.dim .card-face { filter: brightness(0.62) saturate(0.7); }

/* cards you have chosen to pass */
.card.sel { z-index: 900; }
.card.sel .card-face {
  outline: 3px solid var(--gold);
  outline-offset: -1px;
  box-shadow: 0 6px 20px rgba(212, 175, 55, 0.55);
  border-radius: 8%/6%;
}

/* ---------- seat plates ---------- */

.seat-plate {
  position: absolute;
  display: flex;
  align-items: baseline;
  gap: 7px;
  height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.32);
  border: 1px solid rgba(255, 255, 255, 0.14);
  white-space: nowrap;
  z-index: 950;
  pointer-events: none;
  transition: border-color 0.2s, background 0.2s;
}
.seat-name { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.2px; }
.seat-info { font-size: 0.72rem; opacity: 0.72; font-variant-numeric: tabular-nums; }

.seat-plate.partner .seat-name { color: var(--gold); }
.seat-plate.turn {
  background: rgba(212, 175, 55, 0.2);
  border-color: rgba(212, 175, 55, 0.75);
}

/* The plate's transform is set inline by the layout code, so the flash
   animates colour and glow instead of touching transform. */
@keyframes seat-flash {
  0%, 100% { background: rgba(0, 0, 0, 0.32); box-shadow: none; }
  35% { background: rgba(212, 175, 55, 0.55); box-shadow: 0 0 18px rgba(212, 175, 55, 0.6); }
}
.seat-plate.flash { animation: seat-flash 0.55s ease; }

/* ---------- status line ---------- */

.table-status {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  max-width: 62%;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 14px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.3);
  font-size: 0.8rem;
  opacity: 0.9;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  z-index: 950;
  pointer-events: none;
}
.table-status:empty { display: none; }

/* ---------- prompt panel (passing, bidding, the round score) ---------- */

.table-panel {
  position: absolute;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1200;
  width: min(410px, 92%);
  padding: 20px 22px;
  text-align: center;
  border-radius: 16px;
  background: linear-gradient(160deg, #14322a, #0a1f18);
  border: 1px solid rgba(212, 175, 55, 0.5);
  box-shadow: 0 20px 48px rgba(0, 0, 0, 0.5);
}
.table-panel[hidden] { display: none; }
.panel-title { font-size: 1.12rem; font-weight: 800; color: var(--gold); margin-bottom: 10px; }
.panel-msg { font-size: 0.88rem; opacity: 0.82; line-height: 1.5; margin-bottom: 14px; }
.table-panel .ctl-btn.big { font-size: 0.98rem; padding: 10px 22px; }

.bid-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin-bottom: 12px;
}
.bid-btn {
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.08);
  color: var(--ink);
  padding: 9px 0;
  border-radius: 7px;
  font-size: 0.92rem;
  font-weight: 700;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.bid-btn:hover { background: var(--gold); border-color: var(--gold); color: #2a2005; }
.bid-nil { width: 100%; }

/* ---------- round scoreboard ---------- */

.score-table {
  width: 100%;
  border-collapse: collapse;
  margin: 4px 0 16px;
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
}
.score-table th, .score-table td { padding: 6px 4px; text-align: right; }
.score-table thead th {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--gold);
  opacity: 0.85;
  border-bottom: 1px solid rgba(212, 175, 55, 0.3);
}
.score-table tbody th { text-align: left; font-weight: 400; opacity: 0.7; }
.score-table tr.total th, .score-table tr.total td {
  font-weight: 800;
  border-top: 1px solid rgba(212, 175, 55, 0.3);
}

/* ---------- end-of-game overlay extras ---------- */

.win-card .over-msg {
  max-width: 380px;
  margin: -6px auto 16px;
  font-size: 0.94rem;
  opacity: 0.85;
  line-height: 1.5;
}
.win-card .score-table { max-width: 340px; margin-left: auto; margin-right: auto; }

@media (max-width: 600px) {
  .seat-plate { height: 22px; padding: 0 8px; gap: 5px; }
  .seat-name { font-size: 0.7rem; }
  .seat-info { font-size: 0.64rem; }
  .table-status { height: 22px; font-size: 0.72rem; max-width: 56%; padding: 0 10px; }
  .table-panel { padding: 16px 14px; }
  .panel-title { font-size: 1rem; }
  .bid-grid { grid-template-columns: repeat(7, 1fr); gap: 4px; }
  .bid-btn { padding: 8px 0; font-size: 0.82rem; }
}

/* Three buttons instead of five: do not spread them across a phone header. */
@media (max-width: 760px) {
  .controls.compact { width: auto; margin-left: auto; justify-content: flex-end; }
}

/* ---------- "play it now" call to action inside the content block ----------
   Sits directly above the how-to-play list, which is the part of the page an
   answer engine is most likely to quote. Scrolls back up to the board. */

.game-content .play-now {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin: 4px 0 34px;
  padding: 18px 20px;
  border: 1px solid rgba(212, 175, 55, 0.45);
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.24);
}
.game-content .play-now-text { flex: 1 1 240px; }
.game-content .play-now-text strong {
  display: block;
  font-size: 1.06rem;
  color: var(--gold);
  margin-bottom: 5px;
}
.game-content .play-now-text span {
  display: block;
  font-size: 0.92rem;
  line-height: 1.55;
  opacity: 0.86;
}
.game-content .btn-play-now {
  flex: 0 0 auto;
  background: var(--gold);
  color: #2a2005;
  font-weight: 700;
  font-size: 1rem;
  padding: 12px 26px;
  border-radius: 999px;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.32);
  transition: background 0.15s, transform 0.1s;
}
.game-content .btn-play-now:hover { background: #e6c34c; color: #2a2005; text-decoration: none; }
.game-content .btn-play-now:active { transform: scale(0.97); }

@media (max-width: 520px) {
  .game-content .play-now { padding: 16px; gap: 14px; }
  .game-content .btn-play-now { width: 100%; text-align: center; }
}

/* ---------- footer share row ---------- */
/* Plain links to each network's share endpoint, no widget scripts. Felt
   colours are hard-coded rather than read from --gold: the blog defines its
   own lighter --gold for article text, but this row always sits on dark felt. */
.footer-share {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin: 26px auto 4px;
}
.share-label {
  font-size: 0.72rem;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  opacity: 0.65;
}
.share-links {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}
.share-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  color: #f5f0e6;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(212, 175, 55, 0.28);
  text-decoration: none;
  transition: color 0.18s, background 0.18s, border-color 0.18s, transform 0.18s;
}
.share-btn:hover, .share-btn:focus-visible {
  color: #0e5c3f;
  background: #d4af37;
  border-color: #d4af37;
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .share-btn { transition: none; }
  .share-btn:hover, .share-btn:focus-visible { transform: none; }
}

/* ---------- footer trust badges (Product Hunt, SaaSHub) ---------- */
.footer-badges {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  margin: 18px auto 4px;
}
.footer-badges img {
  display: block;
  height: 54px;
  width: auto;
  border-radius: 4px;
}

/* ============================================================
   The cat on the ledge (js/cat.js)

   It sits in the foot strip under the board, which is the only band of the
   play area that no game lays cards into, so it can never cover a card or
   swallow a tap meant for one. The strip is padded out below to make room,
   which costs the board a little height; that is deliberate, and cheaper
   than any placement that overlaps the felt.

   Everything here animates transform or opacity and nothing else. This
   element is on screen and moving for the whole session, and iOS Safari
   silently drops filter animations on a composited layer (see the hint
   glow above), so those two properties are the whole vocabulary.
   ============================================================ */

/* The ledge: reserved on .play-area itself rather than on the rules link,
   because daily.js moves that link into a centred .play-foot row and padding
   it would knock the row's alignment askew. .play-area is a border-box flex
   column of exactly one viewport, so this quietly takes the height off #board
   and leaves a clean strip the cat can sit in. */
.play-area { position: relative; padding-bottom: 40px; }

.game-cat {
  position: absolute;
  left: 14px;
  bottom: 4px;
  width: 62px;
  height: 62px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  z-index: 4;
  -webkit-tap-highlight-color: transparent;
  animation: cat-breathe 4.2s ease-in-out infinite;
}
.game-cat:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; border-radius: 10px; }
.game-cat:hover .cat-head { transform: translateY(-2px) scale(1.03); }
.game-cat:active .cat-body { transform: scaleY(0.94) translateY(2px); }

/* daily.js drops its entry button into a centred row down here, which on a
   phone lands exactly where the cat sits. Inset the row past the cat instead
   of making it taller: this shifts nothing vertically, so the board keeps the
   height it was laid out with and no relayout is needed when the class lands. */
.play-area.has-cat .play-foot { padding-left: 78px; }
/* The one-shot reactions animate this inner element rather than .game-cat,
   which keeps cat-breathe running underneath them. Two animations on one
   element do not compose (the last one named simply wins the property), so
   a finished one-shot on .game-cat used to leave the cat frozen mid-idle
   for as long as the mood outlasted it. */
.cat-svg {
  width: 100%; height: 100%;
  overflow: visible;
  display: block;
  transform-origin: 50% 100%;
}

/* a ginger cat reads against dark felt where a black one would disappear */
.cat-fur { fill: #e0a95f; }
.cat-cream { fill: #f7ecd8; }
.cat-pink { fill: #d98c8c; }
.cat-nose { fill: #c9737a; }
.cat-eye { fill: #f7ecd8; }
.cat-pupil { fill: #2b2a2e; }
.cat-mouth, .cat-whisker { fill: none; stroke: #8a5a22; stroke-width: 1.4; stroke-linecap: round; }
.cat-whisker { opacity: 0.5; }
.cat-lids { stroke: #8a5a22; stroke-width: 1.8; stroke-linecap: round; opacity: 0; }

.cat-tail path {
  fill: none;
  stroke: #e0a95f;
  stroke-width: 8.5;
  stroke-linecap: round;
}
.cat-tail { transform-box: fill-box; transform-origin: 5% 95%; animation: cat-tail 3.6s ease-in-out infinite; }
.cat-body { transform-box: fill-box; transform-origin: 50% 100%; transition: transform 0.12s ease-out; }
.cat-head { transform-box: fill-box; transform-origin: 50% 90%; }
.cat-eyes { transform-box: fill-box; transform-origin: 50% 50%; animation: cat-blink 6.5s ease-in-out infinite; }
.cat-pupils {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  transform: translate(var(--cat-look-x, 0px), var(--cat-look-y, 0px));
  transition: transform 0.12s ease-out;
}
.cat-ear { transform-box: fill-box; transform-origin: 50% 100%; }

@keyframes cat-breathe { 0%, 100% { transform: scaleY(1); } 50% { transform: scaleY(0.978); } }
@keyframes cat-tail { 0%, 100% { transform: rotate(0deg); } 50% { transform: rotate(-13deg); } }
@keyframes cat-blink { 0%, 92%, 100% { transform: scaleY(1); } 96% { transform: scaleY(0.1); } }

/* ---- perked up: someone just moved a card ---- */
.game-cat.is-alert .cat-tail { animation-duration: 0.9s; }
.game-cat.is-alert .cat-ear-l { transform: rotate(-9deg); }
.game-cat.is-alert .cat-ear-r { transform: rotate(9deg); }
.game-cat.is-alert .cat-head { transform: translateY(-1.5px); }

/* ---- a hint is flashing: lean over and look at it ---- */
.game-cat.is-hint .cat-tail { animation-duration: 0.45s; }
.game-cat.is-hint .cat-head { animation: cat-look 1.8s ease-in-out; }
@keyframes cat-look {
  0% { transform: rotate(0deg); }
  30%, 70% { transform: rotate(11deg) translateY(-2px); }
  100% { transform: rotate(0deg); }
}

/* ---- won, or just been petted ---- */
.game-cat.is-happy .cat-svg { animation: cat-hop 0.5s ease-in-out 3; }
.game-cat.is-happy .cat-tail { animation-duration: 0.4s; }
.game-cat.is-happy .cat-eyes { opacity: 0; }
.game-cat.is-happy .cat-lids { opacity: 1; }
@keyframes cat-hop {
  0%, 100% { transform: translateY(0) scaleY(1); }
  30% { transform: translateY(-9px) scaleY(1.04); }
  60% { transform: translateY(0) scaleY(0.94); }
}

/* ---- a fresh deal: startled ears and a quick hop ---- */
.game-cat.is-surprised .cat-svg { animation: cat-startle 0.42s ease-out 2; }
.game-cat.is-surprised .cat-tail { animation-duration: 0.25s; }
.game-cat.is-surprised .cat-ear-l { transform: rotate(-13deg); }
.game-cat.is-surprised .cat-ear-r { transform: rotate(13deg); }
@keyframes cat-startle {
  0%, 100% { transform: translateY(0) scale(1); }
  38% { transform: translateY(-7px) scale(1.06, 0.95); }
  68% { transform: translateY(0) scale(0.96, 1.04); }
}

/* ---- three quick pets: an extra-long playful wiggle ---- */
.game-cat.is-playful .cat-svg { animation: cat-play 0.68s ease-in-out 3; }
.game-cat.is-playful .cat-tail { animation-duration: 0.2s; }
.game-cat.is-playful .cat-eyes { opacity: 0; }
.game-cat.is-playful .cat-lids { opacity: 1; }
@keyframes cat-play {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  25% { transform: translateY(-6px) rotate(-8deg); }
  50% { transform: translateY(0) scaleY(0.94); }
  75% { transform: translateY(-6px) rotate(8deg); }
}

/* ---- asleep ---- */
.game-cat.is-sleep { animation: cat-breathe 5.6s ease-in-out infinite; }
.game-cat.is-sleep .cat-eyes { opacity: 0; animation: none; }
.game-cat.is-sleep .cat-lids { opacity: 1; }
.game-cat.is-sleep .cat-head { transform: translateY(3px) rotate(-6deg); }
.game-cat.is-sleep .cat-tail { animation-duration: 7s; }
.game-cat.is-sleep .cat-zzz { animation: cat-zzz 3.4s ease-out infinite; }

.cat-zzz, .cat-pop {
  position: absolute;
  top: -2px;
  right: -4px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink);
  opacity: 0;
  pointer-events: none;
}
.cat-pop { color: #ff8fa3; font-size: 1rem; }
.cat-pop.is-gold { color: var(--gold); font-size: 1.15rem; }
@keyframes cat-zzz {
  0% { opacity: 0; transform: translate(0, 0) scale(0.7); }
  25% { opacity: 0.75; }
  100% { opacity: 0; transform: translate(9px, -20px) scale(1.15); }
}
.game-cat.pop .cat-pop { animation: cat-pop 1s ease-out; }
@keyframes cat-pop {
  0% { opacity: 0; transform: translateY(0) scale(0.5); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-26px) scale(1.1); }
}

@media (max-width: 600px) {
  .play-area { padding-bottom: 32px; }
  .game-cat { width: 48px; height: 48px; left: 8px; bottom: 3px; }
  .play-area.has-cat .play-foot { padding-left: 0; gap: 8px; }
  .bookmark-entry { width: 96px; height: 34px; border-radius: 17px; }
  .play-foot .scroll-hint { min-height: 30px; padding: 0 10px; font-size: 0.63rem; }
}

/* it is decoration, so it holds still for anyone who asked motion to stop */
@media (prefers-reduced-motion: reduce) {
  .game-cat, .game-cat .cat-svg, .game-cat .cat-tail, .game-cat .cat-eyes,
  .game-cat .cat-head, .game-cat .cat-zzz, .game-cat .cat-pop {
    animation: none !important;
  }
  .game-cat .cat-pupils, .game-cat .cat-body,
  .game-cat .cat-head, .game-cat .cat-ear {
    transform: none !important;
    transition: none !important;
  }
}
