/* ==========================================================================
   KINGDOMS — candlelit map-room aesthetic.
   Mobile-first; desktop layout from 920px up.
   Themes swap the custom properties under html[data-theme=...] only.
   ========================================================================== */

:root {
  --ink: #241d12;
  --ink-soft: #4a3f2c;
  --vellum: #e8d9b4;
  --vellum-hi: #f3e8c8;
  --vellum-lo: #d8c69b;
  --room: #15130d;
  --room-hi: #221d13;
  --room-a: #2a2417;   /* body gradient inner */
  --room-b: #0c0b07;   /* body gradient outer */
  --gold: #d8b84a;
  --gold-deep: #a8842a;
  --gold-glow: rgba(216, 184, 74, 0.35);
  --blood: #8e2f23;
  --pine: #3c5233;
  --arcane: #7b6fd0;             /* special-tile reach — NOT a player color */
  --arcane-glow: rgba(123, 111, 208, 0.45);

  --c-red: #a93226;
  --c-red-deep: #6e1f16;
  --c-blue: #2e5a8f;
  --c-blue-deep: #1d3a5e;
  --c-yellow: #d29d18;
  --c-yellow-deep: #8f6a0c;
  --c-green: #3e7c4f;
  --c-green-deep: #285233;

  --frame-a: #5a4326;  /* board frame wood */
  --frame-b: #43311a;
  --frame-c: #57401f;
  --board-a: #ead9ae;  /* board vellum */
  --board-b: #dcc795;
  --board-c: #c9b27c;

  --text-dim: #c9b98e;
  --text-faint: #9b8c66;

  --font-display: 'Cinzel', 'Times New Roman', serif;
  --font-fancy: 'Cinzel Decorative', 'Cinzel', serif;
  --font-body: 'Alegreya', Georgia, serif;

  --tray-h: 8rem;
  --shadow-deep: 0 18px 50px rgba(0, 0, 0, 0.55);

  /* motion tokens */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-in: cubic-bezier(0.4, 0, 0.7, 0.2);
  --ease-decel: cubic-bezier(0.05, 0.7, 0.1, 1);
  --dur-fast: 150ms;
  --dur-med: 320ms;
  --dur-slow: 600ms;

  --noise-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --- themes ------------------------------------------------------------- */

html[data-theme="midnight"] {
  --room: #0c0f17;
  --room-hi: #161b28;
  --room-a: #1b2233;
  --room-b: #06070c;
  --gold: #a8bcdf;
  --gold-deep: #6d82ab;
  --gold-glow: rgba(168, 188, 223, 0.3);
  --frame-a: #323a52;
  --frame-b: #222940;
  --frame-c: #2d354c;
  --board-a: #dcdcd2;
  --board-b: #c4c4b4;
  --board-c: #a6a692;
  --vellum: #d8dce6;
  --vellum-hi: #eceef5;
  --vellum-lo: #c0c6d4;
  --text-dim: #aab6cc;
  --text-faint: #76819a;
}

html[data-theme="scriptorium"] {
  --room: #3a3226;
  --room-hi: #4a4030;
  --room-a: #564a35;
  --room-b: #241f15;
  --gold: #e8c95e;
  --gold-glow: rgba(232, 201, 94, 0.4);
  --frame-a: #6e5430;
  --frame-b: #543f22;
  --frame-c: #6a5029;
  --board-a: #f4e6c0;
  --board-b: #e8d6a8;
  --board-c: #d4bf8d;
  --text-dim: #d8caa2;
  --text-faint: #b0a178;
}

/* --- Cosmolancer edition skin (orthogonal to the colour themes) --------- */
/* Recolours the world to deep space: a dark sensor-grid board and steel frame
   on which the glowing sci-fi tiles read like objects in the void. Kept to
   surface vars + a few hard-coded warm spots so the light-panel / dark-ink
   layout assumptions elsewhere still hold. */
html[data-edition="cosmolancer"] {
  --ink: #0c1424; --ink-soft: #33405c;
  --room: #04060e; --room-hi: #0b1120; --room-a: #0a1428; --room-b: #02030a;
  --gold: #46c6ff; --gold-deep: #1f86b8; --gold-glow: rgba(70, 198, 255, 0.32);
  --frame-a: #233252; --frame-b: #111c34; --frame-c: #2b3d62;
  --board-a: #0f1a34; --board-b: #0a1226; --board-c: #060c1c;
  --vellum: #dbe6f5; --vellum-hi: #eef4fc; --vellum-lo: #c3d0e4;
  --text-dim: #aebfe0; --text-faint: #6f80a0;
  --arcane: #b06bff; --arcane-glow: rgba(176, 107, 255, 0.5);
  --blood: #ff5a3c; --pine: #27e0c8;
}
/* cool the hard-coded-warm chrome (buttons, primary CTA, parchment panels) */
html[data-edition="cosmolancer"] .btn {
  background: linear-gradient(180deg, #16243f 0%, #0e1830 100%);
  border-color: #2a3d62;
}
html[data-edition="cosmolancer"] .btn:hover { box-shadow: 0 0 18px rgba(70, 198, 255, 0.18); }
html[data-edition="cosmolancer"] .btn-grand {
  color: #04222e;
  background: linear-gradient(180deg, #5ad6e2 0%, #29b3cb 55%, #1689a6 100%);
  border-color: #1f86b8;
  box-shadow: inset 0 1px 0 rgba(220, 255, 255, 0.35), 0 6px 18px rgba(0, 0, 0, 0.5);
}
html[data-edition="cosmolancer"] .btn-grand:hover {
  box-shadow: inset 0 1px 0 rgba(220, 255, 255, 0.4), 0 0 26px var(--gold-glow);
}
html[data-edition="cosmolancer"] .panel.parchment {
  border-color: #2a3d62;
  box-shadow: var(--shadow-deep), inset 0 0 60px rgba(40, 90, 150, 0.18);
}
html[data-edition="cosmolancer"] .panel.parchment::after { border-color: rgba(120, 160, 210, 0.3); }
html[data-edition="cosmolancer"] .board {
  background-image:
    radial-gradient(120% 100% at 35% 20%, var(--board-a) 0%, var(--board-b) 55%, var(--board-c) 100%);
  box-shadow: inset 0 0 40px rgba(0, 18, 40, 0.7), inset 0 0 95px rgba(40, 120, 200, 0.12);
}
html[data-edition="cosmolancer"] .cell {
  border: 1.5px solid rgba(80, 150, 220, 0.30);
  background: linear-gradient(180deg, rgba(22, 44, 86, 0.42), rgba(8, 16, 36, 0.62));
  box-shadow: inset 0 1px 6px rgba(0, 8, 26, 0.6), inset 0 -1px 0 rgba(120, 180, 255, 0.08);
}
html[data-edition="cosmolancer"] .cell.occupied {
  background: linear-gradient(145deg, rgba(24, 48, 92, 0.5), rgba(8, 16, 36, 0.55));
}
html[data-edition="cosmolancer"] .cell.occupied .cell-art svg {
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6));
}
html[data-edition="cosmolancer"] .line-badge {
  background: linear-gradient(180deg, #0e1a30, #081020);
  border-color: #1f3a5e;
}

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

html, body {
  margin: 0;
  height: 100%;
}

body {
  font-family: var(--font-body);
  color: var(--vellum);
  background:
    radial-gradient(120% 90% at 50% 0%, var(--room-a) 0%, var(--room) 58%, var(--room-b) 100%);
  background-attachment: fixed;
  overflow-x: hidden;
}

/* candle-grain over everything */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 4;
  opacity: 0.5;
  background-image: var(--noise-url);
}

/* floor vignette grounds the room */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  background: radial-gradient(130% 70% at 50% 115%, rgba(0, 0, 0, 0.5), transparent 60%);
}

#app { min-height: 100dvh; display: flex; flex-direction: column; }

/* --- boot splash (removed by app.js on first navigation) ----------------- */
.boot-splash {
  position: fixed; inset: 0; z-index: 60;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem;
  background: radial-gradient(120% 90% at 50% 0%, var(--room-a) 0%, var(--room) 58%, var(--room-b) 100%);
}
.boot-splash svg { width: clamp(90px, 24vw, 140px); height: auto; animation: bootPulse 2.2s ease-in-out infinite; }
.boot-splash .boot-sub {
  font-family: var(--font-display); letter-spacing: 0.4em; text-indent: 0.4em;
  font-size: 0.7rem; text-transform: uppercase; color: var(--text-faint);
}
@keyframes bootPulse { 50% { filter: drop-shadow(0 0 26px var(--gold-glow)); transform: scale(1.02); } }

.screen { flex: 1; display: flex; flex-direction: column; animation: screenIn 420ms ease backwards; }
/* The [hidden] attribute must win over .screen's display:flex, or every
   screen stays in flow stacked on top of the active one. */
.screen[hidden] { display: none !important; }
/* fill-mode is `backwards`, not `both`: a lingering `transform: none` end
   state resolves to the identity matrix, which would make .screen a
   containing block and break position:fixed on the tray, overlays and toast. */
@keyframes screenIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

button { font: inherit; cursor: pointer; }
input[type="text"] {
  font: inherit;
  background: var(--vellum-hi);
  color: var(--ink);
  border: 2px solid var(--ink-soft);
  border-radius: 6px;
  padding: 0.55rem 0.8rem;
  width: 100%;
}
input[type="text"]:focus { outline: 2px solid var(--gold); outline-offset: 1px; }

/* keyboard play is first-class: gold focus ring on every interactive piece */
:is(.btn, .cell, .tray-item, .line-badge, .seg-btn, .epoch-pip):focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--vellum);
  background: linear-gradient(180deg, #3a3122 0%, #2a2316 100%);
  border: 1px solid #54462c;
  border-radius: 10px;
  padding: 0.7rem 1.2rem;
  text-transform: uppercase;
  font-size: 0.85rem;
  transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
}
.btn:hover { border-color: var(--gold); box-shadow: 0 0 18px rgba(216, 184, 74, 0.15); }
.btn:active { transform: translateY(1px) scale(0.99); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }

.btn-grand {
  position: relative;
  overflow: hidden;
  font-size: 1rem;
  padding: 0.95rem 1.6rem;
  color: #f6ecce;
  background:
    linear-gradient(180deg, #4d3f24 0%, #382c15 55%, #2c2210 100%);
  border: 1px solid var(--gold-deep);
  box-shadow: inset 0 1px 0 rgba(255, 230, 160, 0.25), 0 6px 18px rgba(0, 0, 0, 0.5);
}
.btn-grand:hover { box-shadow: inset 0 1px 0 rgba(255, 230, 160, 0.3), 0 0 26px var(--gold-glow); }
/* light sweep across grand buttons on hover */
.btn-grand::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 42%, rgba(255, 240, 200, 0.2) 50%, transparent 58%);
  transform: translateX(-130%);
  pointer-events: none;
}
.btn-grand:hover::after { transition: transform 650ms ease; transform: translateX(130%); }
.btn-glyph { color: var(--gold); margin-right: 0.4rem; }

.btn-quiet {
  background: transparent;
  border-color: transparent;
  color: #b8a87d;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: rgba(216, 184, 74, 0.4);
}
.btn-quiet:hover { color: var(--gold); box-shadow: none; }

.btn-back { padding: 0.45rem 0.9rem; font-size: 0.8rem; }
.btn-icon { padding: 0.4rem 0.7rem; font-size: 1rem; border-radius: 8px; }
.btn-icon.active { color: var(--gold); border-color: var(--gold); box-shadow: inset 0 0 12px rgba(216, 184, 74, 0.18); }
.btn-wide { width: 100%; }
.btn-danger { border-color: var(--blood); color: #e8b0a6; }

/* busy state while connecting: conic spinner ring */
.btn.loading { pointer-events: none; position: relative; color: transparent; }
.btn.loading::after {
  content: '';
  position: absolute; left: 50%; top: 50%; width: 1.1em; height: 1.1em;
  margin: -0.55em 0 0 -0.55em;
  border-radius: 50%;
  border: 2px solid rgba(216, 184, 74, 0.25);
  border-top-color: var(--gold);
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   Menu screen
   ========================================================================== */

.screen-menu {
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem 1.4rem calc(2rem + env(safe-area-inset-bottom));
  position: relative;
  min-height: 100dvh;
  overflow: hidden;
}
.menu-vignette {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(85% 60% at 50% 38%, rgba(216, 184, 74, 0.07), transparent 70%);
  animation: candle 9s ease-in-out infinite alternate;
}
@keyframes candle {
  0% { opacity: 0.85; transform: scale(1); }
  35% { opacity: 1; }
  60% { opacity: 0.9; transform: scale(1.015); }
  100% { opacity: 0.95; transform: scale(0.99); }
}

/* castle-skyline horizon behind the masthead */
.menu-horizon {
  position: absolute; left: 0; right: 0; bottom: 0; height: 30vh;
  pointer-events: none;
  background-image:
    linear-gradient(180deg, transparent, rgba(216, 150, 40, 0.07) 65%, rgba(216, 150, 40, 0.02)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 260' preserveAspectRatio='xMidYMax slice'%3E%3Cpath d='M0 260 V180 Q150 150 300 168 L300 120 l12 -14 12 14 v46 Q420 160 540 150 l0 -30 h8 v-22 l14 -16 14 16 v22 h8 v34 Q700 150 860 165 l0 -36 l12 -13 12 13 v40 Q1050 175 1200 160 V260 Z' fill='%230a0905'/%3E%3C/svg%3E");
  background-size: cover;
  background-position: bottom center;
  background-repeat: no-repeat;
}

/* ember motes drifting up through the dark */
.menu-motes { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.menu-motes::before, .menu-motes::after {
  content: '';
  position: absolute; left: 0; top: 100%;
  width: 3px; height: 3px; border-radius: 50%;
  background: transparent;
  box-shadow:
    8vw -12vh 0 0 rgba(232, 190, 92, 0.32),
    22vw -34vh 1px 0 rgba(232, 190, 92, 0.2),
    35vw -8vh 0 1px rgba(232, 190, 92, 0.28),
    48vw -26vh 0 0 rgba(232, 190, 92, 0.22),
    61vw -15vh 1px 0 rgba(232, 190, 92, 0.3),
    74vw -40vh 0 0 rgba(232, 190, 92, 0.18),
    88vw -22vh 0 1px rgba(232, 190, 92, 0.26);
  animation: moteRise 52s linear infinite;
}
.menu-motes::after {
  box-shadow:
    14vw -28vh 0 0 rgba(232, 190, 92, 0.22),
    29vw -16vh 0 1px rgba(232, 190, 92, 0.3),
    44vw -38vh 1px 0 rgba(232, 190, 92, 0.18),
    57vw -6vh 0 0 rgba(232, 190, 92, 0.3),
    69vw -30vh 0 0 rgba(232, 190, 92, 0.2),
    83vw -12vh 0 1px rgba(232, 190, 92, 0.28),
    95vw -34vh 0 0 rgba(232, 190, 92, 0.16);
  animation-duration: 67s;
  animation-delay: -22s;
}
@keyframes moteRise { to { transform: translateY(-130vh); } }

.menu-masthead { position: relative; animation: mastIn 800ms cubic-bezier(0.22, 1, 0.36, 1) both; }
@keyframes mastIn { from { opacity: 0; transform: translateY(-18px); } to { opacity: 1; transform: none; } }

.menu-crest {
  width: clamp(96px, 26vw, 150px); margin: 0 auto 0.6rem;
  filter: drop-shadow(0 6px 18px rgba(216, 184, 74, 0.25));
  animation: crestBreath 5s ease-in-out infinite alternate;
}
@keyframes crestBreath {
  from { filter: drop-shadow(0 6px 18px rgba(216, 184, 74, 0.22)); }
  to { filter: drop-shadow(0 6px 26px rgba(216, 184, 74, 0.45)); }
}
.menu-crest svg { width: 100%; height: auto; }

.menu-title {
  font-family: var(--font-fancy);
  font-size: clamp(2.6rem, 11vw, 4.6rem);
  font-weight: 700;
  margin: 0;
  letter-spacing: 0.08em;
  /* gold-foil gradient clipped into the letterforms */
  background: linear-gradient(168deg, #f7e7a8 8%, var(--gold) 36%, #9a7420 52%, #e7cc72 70%, #fdf3c8 95%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 2px 0 #5e4612) drop-shadow(0 0 22px rgba(216, 184, 74, 0.3));
}
.menu-subtitle {
  font-family: var(--font-display);
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  font-size: clamp(0.62rem, 2.6vw, 0.85rem);
  text-transform: uppercase;
  color: #b8a87d;
  margin: 0.5rem 0 0;
}

/* start-page edition toggle — top-left, only present on the menu screen */
.menu-edition {
  position: absolute; z-index: 4;
  top: calc(1rem + env(safe-area-inset-top)); left: 1rem;
  border-color: rgba(216, 184, 74, 0.4);
  background: rgba(10, 8, 5, 0.55);
  backdrop-filter: blur(5px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  animation: screenIn 600ms ease both; animation-delay: 240ms;
}
.menu-edition .seg-btn {
  color: #b8a87d; padding: 0.4rem 0.85rem;
  font-size: clamp(0.72rem, 2.6vw, 0.86rem);
}
.menu-edition .seg-btn + .seg-btn { border-left-color: rgba(216, 184, 74, 0.4); }
.menu-edition .seg-btn:hover { color: var(--gold); }
.menu-edition .seg-btn.active { background: rgba(216, 184, 74, 0.18); color: var(--gold); }
html[data-edition="cosmolancer"] .menu-edition {
  border-color: rgba(70, 198, 255, 0.45);
}
html[data-edition="cosmolancer"] .menu-edition .seg-btn + .seg-btn { border-left-color: rgba(70, 198, 255, 0.4); }
html[data-edition="cosmolancer"] .menu-edition .seg-btn.active { background: rgba(70, 198, 255, 0.18); }

/* Cosmolancer swaps the castle skyline for a spaceport-and-fleet horizon and
   tints the drifting embers into cool starlight. */
html[data-edition="cosmolancer"] .menu-horizon {
  background-image:
    linear-gradient(180deg, transparent, rgba(70, 198, 255, 0.08) 65%, rgba(70, 198, 255, 0.02)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 260' preserveAspectRatio='xMidYMax slice'%3E%3Cg fill='%23070b16'%3E%3Cpath d='M0 260 V214 H1200 V260 Z'/%3E%3Cpath d='M70 214 V120 h8 V214 Z M58 140 h40 v7 h-40 Z M58 172 h40 v7 h-40 Z'/%3E%3Cpath d='M150 214 v-78 a20 20 0 0 1 40 0 v78 Z'/%3E%3Cpath d='M170 60 q14 30 18 76 h-36 q4 -46 18 -76 Z'/%3E%3Cpath d='M150 214 l-20 0 l20 -30 Z M190 214 l20 0 l-20 -30 Z'/%3E%3Cpath d='M250 214 a55 55 0 0 1 110 0 Z'/%3E%3Cpath d='M380 214 a35 35 0 0 1 70 0 Z'/%3E%3Cpath d='M520 214 V96 l10 -16 10 16 V214 Z'/%3E%3Cpath d='M610 214 v-64 a16 16 0 0 1 32 0 v64 Z'/%3E%3Cpath d='M626 96 q11 24 14 54 h-28 q3 -30 14 -54 Z'/%3E%3Cpath d='M610 214 l-15 0 l15 -24 Z M642 214 l15 0 l-15 -24 Z'/%3E%3Cpath d='M720 214 V150 h7 V214 Z'/%3E%3Ccircle cx='723' cy='140' r='18'/%3E%3Cpath d='M800 214 a70 40 0 0 1 140 0 Z'/%3E%3Cpath d='M1010 214 V120 h6 V214 Z M990 120 h46 v6 h-46 Z'/%3E%3Cpath d='M1090 214 V150 l8 -12 8 12 V214 Z'/%3E%3Cpath d='M1140 214 V170 l7 -10 7 10 V214 Z'/%3E%3C/g%3E%3Cg fill='%230a1222'%3E%3Cellipse cx='430' cy='70' rx='66' ry='15'/%3E%3Cpath d='M404 66 a28 16 0 0 1 52 0 Z'/%3E%3Cellipse cx='930' cy='52' rx='48' ry='11'/%3E%3Cpath d='M912 49 a20 12 0 0 1 36 0 Z'/%3E%3Ccircle cx='1120' cy='80' r='16'/%3E%3Cellipse cx='1120' cy='80' rx='34' ry='9' fill='none' stroke='%230a1222' stroke-width='5'/%3E%3C/g%3E%3C/svg%3E");
}
html[data-edition="cosmolancer"] .menu-motes::before {
  box-shadow:
    8vw -12vh 0 0 rgba(120, 210, 255, 0.34),
    22vw -34vh 1px 0 rgba(120, 210, 255, 0.22),
    35vw -8vh 0 1px rgba(150, 230, 255, 0.3),
    48vw -26vh 0 0 rgba(120, 210, 255, 0.24),
    61vw -15vh 1px 0 rgba(150, 230, 255, 0.32),
    74vw -40vh 0 0 rgba(120, 210, 255, 0.2),
    88vw -22vh 0 1px rgba(150, 230, 255, 0.28);
}
html[data-edition="cosmolancer"] .menu-motes::after {
  box-shadow:
    14vw -28vh 0 0 rgba(120, 210, 255, 0.24),
    29vw -16vh 0 1px rgba(150, 230, 255, 0.32),
    44vw -38vh 1px 0 rgba(120, 210, 255, 0.2),
    57vw -6vh 0 0 rgba(150, 230, 255, 0.32),
    69vw -30vh 0 0 rgba(120, 210, 255, 0.22),
    83vw -12vh 0 1px rgba(150, 230, 255, 0.3),
    95vw -34vh 0 0 rgba(120, 210, 255, 0.18);
}

.menu-actions {
  display: flex; flex-direction: column; gap: 0.85rem;
  width: min(20rem, 86vw);
  margin-top: 2.4rem;
  position: relative;
}
.menu-actions .btn { animation: screenIn 500ms ease both; }
.menu-actions .btn:nth-child(1) { animation-delay: 180ms; }
.menu-actions .btn:nth-child(2) { animation-delay: 280ms; }
.menu-actions .btn:nth-child(3) { animation-delay: 380ms; }
.menu-actions .btn:nth-child(4) { animation-delay: 480ms; }
.menu-actions .btn:nth-child(5) { animation-delay: 560ms; }
.menu-quiet-row { display: flex; justify-content: center; gap: 0.2rem; flex-wrap: wrap; }
.menu-quiet-row .btn { animation: screenIn 500ms ease 560ms both; }

.menu-footer { margin-top: 2.6rem; font-size: 0.78rem; color: var(--text-faint); font-style: italic; line-height: 1.5; position: relative; }

/* ==========================================================================
   Setup / online / lobby screens
   ========================================================================== */

.page-head {
  display: flex; align-items: center; gap: 0.9rem;
  padding: max(0.9rem, env(safe-area-inset-top)) 1rem 0.9rem;
}
.page-head h2 {
  font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--gold); margin: 0;
}

.panel.parchment {
  background:
    var(--noise-url),
    radial-gradient(140% 120% at 30% 0%, var(--vellum-hi) 0%, var(--vellum) 55%, var(--vellum-lo) 100%);
  background-blend-mode: multiply, normal;
  color: var(--ink);
  border-radius: 14px;
  border: 1px solid #9a8657;
  box-shadow: var(--shadow-deep), inset 0 0 60px rgba(160, 130, 70, 0.25);
  position: relative;
}
.panel.parchment::after {
  content: ''; position: absolute; inset: 6px; pointer-events: none;
  border: 1.5px solid rgba(74, 63, 44, 0.35); border-radius: 9px;
}

.setup-panel {
  margin: 0.4rem auto 2rem;
  width: min(34rem, calc(100vw - 1.6rem));
  padding: 1.3rem 1.2rem 1.5rem;
  display: flex; flex-direction: column; gap: 1.1rem;
}

.field-row { display: flex; flex-direction: column; gap: 0.45rem; }
.field-label {
  font-family: var(--font-display); font-size: 0.75rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-soft);
}

.seg { display: inline-flex; border: 2px solid var(--ink-soft); border-radius: 8px; overflow: hidden; width: max-content; }
.seg-btn {
  border: none; background: transparent; color: var(--ink-soft);
  font-family: var(--font-display); font-weight: 700;
  padding: 0.45rem 1.2rem; font-size: 1rem;
}
.seg-btn + .seg-btn { border-left: 2px solid var(--ink-soft); }
.seg-btn.active { background: var(--ink); color: var(--gold); }

.setup-seats { display: flex; flex-direction: column; gap: 0.6rem; }
.seat-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 0.6rem; align-items: center;
  background: rgba(255, 250, 235, 0.55);
  border: 1.5px solid rgba(74, 63, 44, 0.4);
  border-radius: 10px;
  padding: 0.5rem 0.6rem;
}
.seat-row.seat-new { animation: seatIn 360ms var(--ease-out) backwards; }
@keyframes seatIn { from { opacity: 0; transform: translateX(-10px); } }
.seat-row input[type="text"] { padding: 0.4rem 0.6rem; border-width: 1.5px; }
.seat-swatch {
  width: 2.1rem; height: 2.1rem; border-radius: 8px; flex: none;
  border: 2px solid rgba(0, 0, 0, 0.35);
  box-shadow: inset 0 -6px 12px rgba(0, 0, 0, 0.25);
}
.seat-swatch.red { background: var(--c-red); }
.seat-swatch.blue { background: var(--c-blue); }
.seat-swatch.yellow { background: var(--c-yellow); }
.seat-swatch.green { background: var(--c-green); }
/* heraldic shields replace flat swatches wherever players appear */
.seat-shield { width: 2.3rem; height: 2.3rem; flex: none; filter: drop-shadow(0 2px 3px rgba(0,0,0,0.35)); }
.seat-shield svg { width: 100%; height: 100%; display: block; }
.seat-kind { display: flex; gap: 0.4rem; align-items: center; }
.seat-kind select {
  font: inherit; font-size: 0.85rem; color: var(--ink);
  background: var(--vellum-hi); border: 1.5px solid var(--ink-soft); border-radius: 6px;
  padding: 0.3rem 0.4rem;
}
.seat-tag { font-size: 0.78rem; font-style: italic; color: var(--ink-soft); }
.seat-tag .host-mark { color: var(--gold-deep); font-style: normal; }

.variants summary {
  font-family: var(--font-display); font-size: 0.8rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-soft); cursor: pointer;
}
.variants-hint { text-transform: none; letter-spacing: 0; font-family: var(--font-body); font-style: italic; }
.variants .check { display: flex; gap: 0.55rem; align-items: flex-start; margin-top: 0.7rem; font-size: 0.92rem; line-height: 1.35; }
.variants input { margin-top: 0.2rem; accent-color: var(--gold-deep); }

.online-split { display: flex; flex-direction: column; gap: 0.8rem; }
.online-card {
  border: 1.5px solid rgba(74, 63, 44, 0.4); border-radius: 10px;
  background: rgba(255, 250, 235, 0.5);
  padding: 0.9rem; display: flex; flex-direction: column; gap: 0.6rem;
}
.online-card h3 { margin: 0; font-family: var(--font-display); font-size: 0.95rem; letter-spacing: 0.06em; }
.online-card p { margin: 0; font-size: 0.88rem; font-style: italic; color: var(--ink-soft); }
.online-or { text-align: center; font-style: italic; color: var(--ink-soft); }
.online-status { min-height: 1.2em; margin: 0; font-style: italic; color: var(--blood); text-align: center; }

.code-input {
  font-family: var(--font-display); font-size: 1.5rem !important; letter-spacing: 0.4em;
  text-transform: uppercase; text-align: center;
}

.lobby-code-wrap { text-align: center; display: flex; flex-direction: column; gap: 0.3rem; align-items: center; }
.lobby-code-label { font-size: 0.8rem; letter-spacing: 0.14em; text-transform: uppercase; font-family: var(--font-display); color: var(--ink-soft); }
.lobby-code {
  font-family: var(--font-display); font-weight: 900; font-size: 2.6rem; letter-spacing: 0.35em; text-indent: 0.35em;
  color: var(--ink);
  background: rgba(255, 250, 235, 0.6); border: 2px dashed var(--gold-deep); border-radius: 12px;
  padding: 0.2rem 1rem;
}
.lobby-code .code-rune { display: inline-block; animation: runeIn 420ms var(--ease-out) backwards; }
.lobby-code .code-rune:nth-child(2) { animation-delay: 90ms; }
.lobby-code .code-rune:nth-child(3) { animation-delay: 180ms; }
.lobby-code .code-rune:nth-child(4) { animation-delay: 270ms; }
@keyframes runeIn { from { opacity: 0; transform: translateY(8px) rotateX(70deg); } }
.lobby-host-tools { display: flex; flex-direction: column; gap: 0.9rem; }

/* ==========================================================================
   Game screen
   ========================================================================== */

.screen-game { min-height: 100dvh; }

.game-topbar {
  display: flex; align-items: center; gap: 0.7rem;
  padding: max(0.55rem, env(safe-area-inset-top)) 0.8rem 0.55rem;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.45), transparent);
}

.epoch-track { display: flex; gap: 0.35rem; }
.epoch-pip {
  font-family: var(--font-display); font-weight: 700; font-size: 0.78rem;
  width: 1.7rem; height: 1.7rem; display: grid; place-items: center;
  border-radius: 50%; border: 1.5px solid #54462c; color: #7d7050;
  transition: color var(--dur-med) ease, background var(--dur-med) ease, box-shadow var(--dur-med) ease;
}
.epoch-pip.done { color: var(--gold-deep); border-color: var(--gold-deep); }
.epoch-pip.current {
  color: var(--room); background: var(--gold); border-color: var(--gold);
  box-shadow: 0 0 14px var(--gold-glow);
}

.turn-banner {
  flex: 1; text-align: right;
  font-family: var(--font-display); font-size: 0.86rem; letter-spacing: 0.06em;
  color: var(--vellum); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.turn-banner .turn-dot { display: inline-block; width: 0.65em; height: 0.65em; border-radius: 50%; margin-right: 0.4em; vertical-align: baseline; }
.turn-banner .turn-shield { display: inline-block; width: 1em; height: 1em; margin-right: 0.35em; vertical-align: -0.15em; }
.turn-banner .turn-shield svg { width: 100%; height: 100%; display: block; }

/* animated 'thinking' dots */
.think-dot { display: inline-block; animation: thinkDot 1.2s ease-in-out infinite; }
.think-dot:nth-child(2) { animation-delay: 0.18s; }
.think-dot:nth-child(3) { animation-delay: 0.36s; }
@keyframes thinkDot { 0%, 60%, 100% { opacity: 0.25; } 30% { opacity: 1; } }

.game-main {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  padding: 0.2rem 0.55rem calc(var(--tray-h) + 0.8rem);
  gap: 0.6rem;
  width: 100%;
  position: relative;
}
/* warm candle-pool centered on the board */
.game-main::before {
  content: '';
  position: absolute; inset: -6rem 0 0;
  background: radial-gradient(60% 55% at 50% 42%, rgba(216, 170, 80, 0.1), transparent 70%);
  pointer-events: none;
}

/* --- players rail (horizontal strip on mobile) --- */
.players-rail {
  display: flex; gap: 0.45rem; width: 100%;
  overflow-x: auto; scrollbar-width: none; padding: 0.1rem 0.1rem;
}
.players-rail::-webkit-scrollbar { display: none; }

.player-chip {
  flex: 1 1 0; min-width: 7.2rem;
  display: flex; flex-direction: column; gap: 0.18rem;
  background: linear-gradient(180deg, #262013, #1c170d);
  border: 1px solid #3e3520; border-radius: 10px;
  padding: 0.4rem 0.55rem;
  position: relative;
  transition: border-color 200ms ease, box-shadow 200ms ease;
}
.player-chip.current {
  border-color: var(--gold);
  background: linear-gradient(180deg, #2e2614, #221c0e);
  box-shadow: 0 0 16px rgba(216, 184, 74, 0.22);
}
.player-chip.current::before {
  content: '♕';
  position: absolute; top: -0.65rem; right: 0.45rem;
  color: var(--gold); font-size: 0.85rem;
  text-shadow: 0 0 8px var(--gold-glow);
}
/* crown drops in only when the turn actually changes (turn-fresh is keyed) */
.player-chip.turn-fresh::before { animation: crownIn 450ms var(--ease-spring) both; }
@keyframes crownIn { from { transform: translateY(-10px) rotate(-12deg); opacity: 0; } to { transform: none; opacity: 1; } }
.player-chip.turn-fresh { animation: chipPulse 600ms ease; }
@keyframes chipPulse { 35% { box-shadow: 0 0 26px rgba(216, 184, 74, 0.45); } }
/* slow breathe while an AI considers its move */
.player-chip.thinking { animation: thinkBreathe 1.4s ease-in-out infinite; }
@keyframes thinkBreathe { 50% { border-color: var(--gold); box-shadow: 0 0 18px rgba(216, 184, 74, 0.3); } }

.player-chip .p-name {
  font-family: var(--font-display); font-size: 0.78rem; font-weight: 700;
  letter-spacing: 0.04em;
  display: flex; align-items: center; gap: 0.4rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.p-flag { width: 0.72rem; height: 0.72rem; border-radius: 3px; flex: none; border: 1px solid rgba(0,0,0,0.45); }
.p-flag.red { background: var(--c-red); } .p-flag.blue { background: var(--c-blue); }
.p-flag.yellow { background: var(--c-yellow); } .p-flag.green { background: var(--c-green); }
.p-shield { width: 1.15rem; height: 1.15rem; flex: none; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.4)); }
.p-shield svg { width: 100%; height: 100%; display: block; }
/* face-down tile badge: this player still holds their secret starting tile */
.player-chip .p-secret { width: 0.95rem; margin-left: auto; flex: none; opacity: 0.9; line-height: 0; }
.player-chip .p-secret svg { width: 100%; height: auto; display: block; }
.player-chip .p-gold {
  font-family: var(--font-display); font-weight: 700; font-size: 1.02rem; color: var(--gold);
  display: flex; align-items: center; gap: 0.3rem;
  position: relative;
}
.player-chip .p-gold .coin { width: 0.85rem; height: 0.85rem; }
.player-chip .p-gold.negative { color: #d4715f; }
/* castles in hand: one staggered stack per rank */
.player-chip .p-castles { display: flex; gap: 0.45rem; align-items: flex-end; min-height: 1.1rem; padding-top: 0.15rem; }
.p-castles .castle-col { display: flex; flex-direction: column; align-items: center; }
.p-castles .c-mini { width: 1.15rem; line-height: 0; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35)); }
.p-castles .c-mini + .c-mini { margin-top: -0.78rem; }
.p-castles .c-mini:nth-child(even) { transform: translateX(3px); }
.p-castles .c-mini svg { width: 100%; height: auto; display: block; }
.p-castles .castles-empty { font-size: 0.72rem; font-style: italic; color: #8d805e; }
.player-chip .p-extra { font-size: 0.72rem; color: #8d805e; font-style: italic; }
.player-chip.disconnected { opacity: 0.55; }
.gold-bump { animation: goldBump 700ms ease; }
@keyframes goldBump { 30% { transform: scale(1.18); color: #ffe9a0; } }

/* floating +N/−N chip when gold changes */
.gold-delta {
  position: absolute; right: 0; top: -0.15rem;
  font-family: var(--font-display); font-weight: 700; font-size: 0.85rem;
  pointer-events: none;
  animation: deltaRise 1100ms var(--ease-out) forwards;
}
.gold-delta.pos { color: #8fd07a; }
.gold-delta.neg { color: #e08a7a; }
@keyframes deltaRise {
  from { opacity: 0; transform: translateY(4px); }
  25% { opacity: 1; }
  to { opacity: 0; transform: translateY(-16px); }
}

/* coins in flight between scored lines and player chips */
.coin-fly {
  position: fixed; left: 0; top: 0; z-index: 36;
  width: 18px; height: 18px; pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5));
}
.coin-fly svg { width: 100%; height: 100%; display: block; }

/* a piece flying from the tray to its cell */
.fly-piece {
  position: fixed; left: 0; top: 0; z-index: 35;
  pointer-events: none;
  filter: drop-shadow(0 10px 16px rgba(0, 0, 0, 0.5));
}
.fly-piece svg { width: 100%; height: 100%; display: block; }

/* --- board --- */
.board-wrap { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0.45rem; }

.board-frame {
  width: min(100%, 78dvh, 60rem);
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='120'%3E%3Cfilter id='w'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012 0.14' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 0.13 0 0 0 0 0.08 0 0 0 0 0.03 0 0 0 0.14 0'/%3E%3C/filter%3E%3Crect width='420' height='120' filter='url(%23w)'/%3E%3C/svg%3E"),
    linear-gradient(160deg, var(--frame-a) 0%, var(--frame-b) 45%, var(--frame-c) 100%);
  background-size: 420px 120px, auto;
  border-radius: 12px;
  padding: clamp(5px, 1.6vw, 12px);
  box-shadow:
    var(--shadow-deep),
    0 30px 40px -18px rgba(0, 0, 0, 0.7),
    inset 0 2px 2px rgba(255, 220, 150, 0.18),
    inset 0 -3px 8px rgba(0, 0, 0, 0.5);
  border: 1px solid #2c2010;
  position: relative;
}
/* gold corner brackets */
.board-frame::before, .board-frame::after {
  content: '';
  position: absolute; width: 22px; height: 22px;
  border: 2px solid var(--gold-deep);
  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8));
  pointer-events: none;
  opacity: 0.85;
}
.board-frame::before { left: 4px; top: 4px; border-right: none; border-bottom: none; border-top-left-radius: 9px; }
.board-frame::after { right: 4px; bottom: 4px; border-left: none; border-top: none; border-bottom-right-radius: 9px; }

.board-frame { --board-pad: clamp(4px, 1.2vw, 9px); --board-gap: clamp(2px, 0.7vw, 5px); }

/* When line scores are shown, a gutter of badges is added to the right (rows)
   and bottom (columns). Otherwise the board fills the frame as before. */
.board-grid { display: contents; }
.board-grid.show-scores {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: 1fr auto;
  gap: clamp(3px, 0.8vw, 6px);
}
.gutter, .gutter-corner { display: none; }
.board-grid.show-scores .gutter,
.board-grid.show-scores .gutter-corner { display: grid; }

.board {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--board-gap);
  background-color: var(--board-b);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 500'%3E%3Cg fill='none' stroke='%238a7142' stroke-opacity='0.1' stroke-width='3'%3E%3Ccircle cx='505' cy='415' r='52'/%3E%3Ccircle cx='505' cy='415' r='38'/%3E%3Cpath d='M505 355 v120 M445 415 h120 M468 378 l74 74 M468 452 l74 -74'/%3E%3Cpath d='M505 391 l8 16 16 8 -16 8 -8 16 -8 -16 -16 -8 16 -8 z' stroke-width='4'/%3E%3Cpath d='M60 90 q40 -32 80 0 M80 110 q30 -22 60 0 M380 70 q35 -26 70 0 M400 88 q25 -16 50 0'/%3E%3Cpath d='M70 420 q50 -20 90 5 M90 442 q35 -14 60 4'/%3E%3C/g%3E%3C/svg%3E"),
    radial-gradient(120% 100% at 35% 20%, var(--board-a) 0%, var(--board-b) 60%, var(--board-c) 100%);
  background-size: cover, auto;
  border-radius: 7px;
  padding: var(--board-pad);
  box-shadow:
    inset 0 0 34px rgba(120, 90, 40, 0.5),
    inset 0 0 80px rgba(90, 60, 20, 0.28);
}

/* Gutters reuse the board's padding + gap so each badge lines up with its
   row / column. */
.gutter-rows {
  grid-column: 2; grid-row: 1;
  grid-template-rows: repeat(5, 1fr);
  gap: var(--board-gap);
  padding: var(--board-pad) 0;
}
.gutter-cols {
  grid-column: 1; grid-row: 2;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--board-gap);
  padding: 0 var(--board-pad);
}
.gutter-corner { grid-column: 2; grid-row: 2; }

.line-badge {
  align-self: center; justify-self: center;
  min-width: clamp(1.5rem, 4.6vw, 2.1rem);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(0.62rem, 2vw, 0.82rem);
  line-height: 1;
  color: var(--vellum);
  background: linear-gradient(180deg, #2c2415, #1d180d);
  border: 1px solid #54462c; border-radius: 7px;
  padding: 0.2rem 0.25rem;
  cursor: pointer;
  transition: border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease;
}
.gutter-cols .line-badge { flex-direction: row; gap: 0.18rem; min-width: 0; width: 100%; }
.line-badge:hover { border-color: var(--gold); box-shadow: 0 0 10px var(--gold-glow); }
.line-badge .seg-val { padding: 0 0.1rem; }
.line-badge .seg-val.pos { color: #8fd07a; }
.line-badge .seg-val.neg { color: #e08a7a; }
.line-badge .seg-val.zero { color: #8d805e; }
.line-badge .seg-sep { color: #6f6347; font-weight: 400; }
.line-badge.line-hot { border-color: var(--gold); box-shadow: 0 0 0 1.5px var(--gold), 0 0 12px var(--gold-glow); }
.line-badge.badge-flash { animation: badgeFlash 600ms ease; }
@keyframes badgeFlash { 35% { border-color: var(--gold); box-shadow: 0 0 14px var(--gold-glow); transform: scale(1.08); } }

.cell {
  aspect-ratio: 1;
  border-radius: 6px;
  border: 1.5px solid rgba(110, 88, 48, 0.55);
  /* empty cells read as recessed slots carved into the map */
  background: linear-gradient(180deg, rgba(190, 160, 105, 0.3), rgba(255, 248, 226, 0.35));
  box-shadow:
    inset 0 2px 5px rgba(96, 70, 28, 0.38),
    inset 0 -1px 0 rgba(255, 250, 230, 0.55);
  position: relative;
  padding: 0;
  transition: box-shadow 150ms ease, transform 150ms ease, border-color 150ms ease;
}
.cell:not(.occupied) { cursor: default; }
/* placed pieces sit proud of the recess and cast a shadow on the vellum */
.cell.occupied {
  background: linear-gradient(145deg, rgba(255, 248, 226, 0.5), rgba(190, 160, 105, 0.25));
  box-shadow: none;
}
.cell .cell-art { position: absolute; inset: 0; width: 100%; height: 100%; }
.cell .cell-art svg { width: 100%; height: 100%; display: block; }
.cell.occupied .cell-art svg { filter: drop-shadow(0 2px 2px rgba(40, 25, 5, 0.4)); }

.cell.placeable {
  cursor: pointer;
  border-color: var(--gold-deep);
  box-shadow: inset 0 0 0 1.5px rgba(216, 184, 74, 0.5), 0 0 10px rgba(216, 184, 74, 0.18);
  /* a brief wake, then settle — the drag ghost is the loud thing, not 30 strobes */
  animation: placeablePulse 1.4s ease-in-out 2;
}
@keyframes placeablePulse {
  50% { box-shadow: inset 0 0 0 1.5px rgba(216, 184, 74, 0.85), 0 0 16px rgba(216, 184, 74, 0.4); }
}
.cell.preview { transform: scale(1.04); z-index: 2; }
.cell.preview .cell-art { opacity: 0.82; }
.cell.preview::after {
  content: 'TAP TO PLACE';
  position: absolute; left: 50%; bottom: -1.3rem; transform: translateX(-50%);
  font-family: var(--font-display); font-size: 0.58rem; font-weight: 700; letter-spacing: 0.08em;
  background: var(--gold); color: var(--room);
  border-radius: 4px; padding: 0.14rem 0.4rem;
  white-space: nowrap; z-index: 5;
  box-shadow: 0 4px 12px rgba(0,0,0,0.6);
}
.cell.preview.confirm::after { content: 'TAP AGAIN TO PLACE'; }
body.dragging-piece .cell.preview::after { display: none; } /* ghost is the cue while dragging */
.cell.just-placed .cell-art { animation: dropIn 380ms cubic-bezier(0.2, 1.4, 0.4, 1); }
@keyframes dropIn { from { transform: scale(1.6); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* placement settles: tiles lay flat, castles land with weight */
.cell.placed-tile .cell-art { animation: tileLay 220ms var(--ease-spring); }
@keyframes tileLay { from { transform: scale(1.18) rotate(-3deg); opacity: 0; } to { transform: none; opacity: 1; } }
.cell.placed-castle .cell-art { animation: castleThunk 380ms var(--ease-spring); transform-origin: 50% 90%; }
@keyframes castleThunk {
  0% { transform: translateY(-42%) scale(1.04); opacity: 0; }
  55% { transform: translateY(0) scaleX(1.1) scaleY(0.88); opacity: 1; }
  80% { transform: scaleX(0.97) scaleY(1.04); }
  100% { transform: none; }
}
/* dust ring puffing out under a landed castle */
.cell.placed-castle::after {
  content: '';
  position: absolute; left: 12%; right: 12%; bottom: 8%; height: 18%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(120, 95, 50, 0.4), transparent 70%);
  animation: dustPuff 500ms var(--ease-out) both;
  pointer-events: none;
}
@keyframes dustPuff {
  from { opacity: 0; transform: scale(0.4); }
  35% { opacity: 1; }
  to { opacity: 0; transform: scale(1.5); }
}

/* invalid move: a firm refusal */
.cell.shake, .tray-item.shake { animation: nudge 240ms ease; }
@keyframes nudge {
  20%, 60% { transform: translateX(-4px); }
  40%, 80% { transform: translateX(4px); }
}

/* the opponent's last move stays marked until you respond */
.cell.last-move {
  box-shadow: 0 0 0 2px var(--vellum), 0 0 14px rgba(232, 217, 180, 0.4);
}
.cell.last-move::before {
  content: '';
  position: absolute; top: 3px; right: 3px; width: 10px; height: 10px;
  border-radius: 50%; z-index: 3;
  background: var(--last-move-color, var(--gold));
  border: 1.5px solid rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

.cell.score-dim .cell-art { opacity: 0.22; transition: opacity 300ms ease; }
.cell.score-hot {
  z-index: 2;
  box-shadow: 0 0 0 2px var(--gold), 0 0 22px var(--gold-glow);
  animation: scoreSweep 500ms var(--ease-out) var(--sweep-delay, 0ms) backwards;
}
@keyframes scoreSweep {
  from { box-shadow: 0 0 0 0 transparent; transform: scale(1); }
  45% { box-shadow: 0 0 0 3px var(--gold), 0 0 28px var(--gold-glow); transform: scale(1.07); }
  to { box-shadow: 0 0 0 2px var(--gold), 0 0 22px var(--gold-glow); transform: scale(1); }
}

/* Cells a hovered/placing special tile influences — arcane violet, distinct
   from every player color (blue collided with the blue seat). */
.cell.affect {
  z-index: 1;
  box-shadow: 0 0 0 2px var(--arcane);
  animation: affectPulse 1.3s ease-in-out infinite;
}
.cell.affect::after {
  content: '';
  position: absolute; inset: 0; border-radius: 6px; pointer-events: none;
  background: radial-gradient(circle at 50% 50%, rgba(123, 111, 208, 0.28), transparent 72%);
}
@keyframes affectPulse {
  50% { box-shadow: 0 0 0 2px var(--arcane), 0 0 14px var(--arcane-glow); }
}
.cell.affect.placeable { box-shadow: 0 0 0 2px var(--arcane), inset 0 0 0 1.5px rgba(216,184,74,0.6); }

.action-hint {
  min-height: 1.4rem; text-align: center;
  font-style: italic; font-size: 0.95rem; color: #cdbd92;
  text-shadow: 0 2px 6px rgba(0,0,0,0.7);
  padding: 0 1rem;
}

/* --- right rail (hidden on mobile: Chronicle has a drawer, the draw panel
   is desktop-only) --- */
.right-rail { display: none; }
.log-rail { display: none; }
.draw-rail { display: none; }
.draw-note { font-size: 0.72rem; font-style: italic; color: #8d805e; margin: -0.25rem 0 0.5rem; }
.draw-list { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.45rem 0.4rem; }
.draw-entry { position: relative; line-height: 0; }
.draw-entry .de-art svg { width: 100%; height: auto; display: block; }
.draw-entry .de-count {
  position: absolute; top: -0.32rem; right: -0.28rem;
  background: var(--gold); color: var(--room);
  font-family: var(--font-display); font-weight: 900; font-size: 0.58rem;
  min-width: 0.95rem; height: 0.95rem; border-radius: 50%;
  display: grid; place-items: center; padding: 0 0.15rem;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
}
.draw-entry.depleted { opacity: 0.22; filter: grayscale(0.85); }
.rail-title {
  font-family: var(--font-display); font-size: 0.78rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: #8d805e; margin: 0 0 0.5rem;
}
.log { font-size: 0.84rem; line-height: 1.5; overflow-y: auto; color: #c9bb95; }
.log p { margin: 0 0 0.35rem; border-left: 2px solid #3e3520; padding-left: 0.5rem; }
.log p b { color: var(--vellum); }
.log p.score-entry { color: var(--gold); }
/* the same log renders inside light parchment sheets (mobile Chronicle
   drawer) where gold-on-vellum is unreadable */
.sheet .log p { color: var(--ink-soft); }
.sheet .log p b { color: var(--ink); }
.sheet .log p.score-entry { color: #7a5c12; }

/* --- tray --- */
.tray {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 6;
  min-height: var(--tray-h);
  background: linear-gradient(180deg, #2c2415 0%, #1d180d 100%);
  border-top: 1px solid #54462c;
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.55);
  padding: 0.6rem 0.5rem calc(0.55rem + env(safe-area-inset-bottom));
  display: flex; align-items: stretch; justify-content: safe center; gap: 0.4rem;
  overflow-x: auto; scrollbar-width: none;
}
.tray::-webkit-scrollbar { display: none; }
/* edge fades signal there's more to scroll */
.tray.tray-scrolls {
  mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
}
.tray-group { display: flex; align-items: stretch; gap: 0.4rem; }
.tray-sep { width: 1px; background: #4a3e24; margin: 0.2rem 0.15rem; }

.tray-item {
  position: relative; flex: none;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 0.15rem;
  background: linear-gradient(180deg, #3a3122, #281f10);
  border: 1.5px solid #54462c; border-radius: 10px;
  width: clamp(3.3rem, 13vw, 4.8rem);
  padding: 0.3rem 0.2rem 0.25rem;
  color: var(--vellum);
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.tray-item:not(:disabled):not(.disabled):hover { border-color: var(--gold); }
.tray-item.armed {
  border-color: var(--gold);
  box-shadow: 0 0 0 1.5px var(--gold), 0 0 18px var(--gold-glow);
  transform: translateY(-3px);
}
/* "disabled" is a class, not the attribute, so the item can still shake and
   explain itself when tapped. */
.tray-item:disabled, .tray-item.disabled { opacity: 0.38; cursor: not-allowed; }
.tray-item .t-art { width: 70%; max-height: 3rem; }
.tray-item .t-art svg { width: 100%; height: auto; display: block; }

/* 3D draw flip: face-down back rotates away to reveal the drawn tile */
.tray-item .t-art.flip-wrap { perspective: 480px; }
.tray-item .t-art .flip { position: relative; transform-style: preserve-3d; }
.tray-item .t-art .flip-front, .tray-item .t-art .flip-back { backface-visibility: hidden; }
.tray-item .t-art .flip-front { position: absolute; inset: 0; transform: rotateY(180deg); }
.tray-item .t-art.flipping .flip { animation: tileFlip 380ms var(--ease-decel) both; }
@keyframes tileFlip {
  from { transform: rotateY(0); }
  50% { transform: rotateY(90deg) scale(1.2); }
  to { transform: rotateY(180deg); }
}
/* reveal glow tinted by the drawn tile's frame color */
.tray-item.reveal-glow { animation: revealGlow 900ms ease both; }
@keyframes revealGlow {
  35% { box-shadow: 0 0 0 2px var(--reveal-color, var(--gold)), 0 0 26px var(--reveal-color, var(--gold)); }
}

.tray-item .t-label {
  font-family: var(--font-display); font-size: 0.62rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: #b8a87d;
  white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.tray-item .t-count {
  position: absolute; top: -0.45rem; right: -0.35rem;
  background: var(--gold); color: var(--room);
  font-family: var(--font-display); font-weight: 900; font-size: 0.68rem;
  min-width: 1.15rem; height: 1.15rem; border-radius: 50%;
  display: grid; place-items: center; padding: 0 0.2rem;
  box-shadow: 0 2px 6px rgba(0,0,0,0.5);
}
.tray-item .t-count.zero { background: #5a4f35; color: #221d13; }
/* keyboard hint: only where a physical keyboard is likely (fine pointer) */
.tray-item .t-key { display: none; }
@media (min-width: 920px) and (pointer: fine) {
  /* Sits INSIDE the top-left corner. Jutting out (negative offsets) made the
     legend overlap the count badge on the next tile's top-right corner. */
  .tray-item .t-key {
    position: absolute; top: 0.18rem; left: 0.18rem;
    display: grid; place-items: center;
    min-width: 1.05rem; height: 1.05rem; padding: 0 0.15rem;
    background: linear-gradient(180deg, #3a3122, #241c0e);
    border: 1px solid #54462c; border-radius: 4px;
    font-family: var(--font-display); font-size: 0.6rem; font-weight: 700;
    font-style: normal; color: #b8a87d;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.45);
  }
}
.tray-note {
  align-self: center; text-align: center; font-style: italic;
  color: #b8a87d; font-size: 0.85rem; padding: 0 0.8rem; max-width: 16rem;
}

/* ==========================================================================
   Overlays
   ========================================================================== */

.overlay {
  position: fixed; inset: 0; z-index: 20;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10, 8, 4, 0.72);
  backdrop-filter: blur(3px);
  animation: fadeIn 240ms ease both;
  padding: 1rem;
}
@keyframes fadeIn { from { opacity: 0; } }
.overlay.overlay-out { animation: fadeOut 150ms ease-in both; }
@keyframes fadeOut { to { opacity: 0; } }
.overlay.overlay-clear { background: rgba(10, 8, 4, 0.25); backdrop-filter: none; align-items: flex-end; pointer-events: none; }
.overlay.overlay-clear .sheet { pointer-events: auto; }

.sheet {
  background:
    var(--noise-url),
    radial-gradient(140% 120% at 30% 0%, var(--vellum-hi) 0%, var(--vellum) 55%, var(--vellum-lo) 100%);
  background-blend-mode: multiply, normal;
  color: var(--ink);
  border-radius: 14px;
  border: 1px solid #9a8657;
  box-shadow: var(--shadow-deep), inset 0 0 18px rgba(140, 105, 50, 0.22);
  width: min(26rem, calc(100vw - 2rem));
  max-height: min(86dvh, 44rem);
  overflow-y: auto;
  padding: 1.2rem 1.2rem 1.3rem;
  animation: sheetIn 260ms var(--ease-decel) both;
  position: relative;
}
@keyframes sheetIn { from { opacity: 0; transform: translateY(26px) scale(0.97); } }
.overlay-out .sheet { animation: sheetOut 150ms ease-in both; }
@keyframes sheetOut { to { opacity: 0; transform: translateY(12px) scale(0.98); } }
.sheet h3 {
  font-family: var(--font-display); font-size: 1.05rem; letter-spacing: 0.1em;
  text-transform: uppercase; text-align: center; margin: 0 0 0.8rem;
}
.sheet h3::after {
  content: ''; display: block; width: 4rem; height: 2px; margin: 0.45rem auto 0;
  background: linear-gradient(90deg, transparent, var(--gold-deep), transparent);
}
.sheet .sheet-actions { display: flex; gap: 0.6rem; margin-top: 1rem; }
.sheet .sheet-actions .btn { flex: 1; background: var(--ink); }
/* quiet buttons keep their transparent look — the ink fill above would put
   ink-soft text on an ink background (Skip / Return to Game vanished) */
.sheet .sheet-actions .btn-quiet { background: transparent; }
.sheet .btn-quiet { color: var(--ink-soft); }

/* settings sheet bits */
.sheet .seg { width: 100%; display: flex; }
.sheet .seg-btn { flex: 1; padding: 0.45rem 0.4rem; font-size: 0.82rem; white-space: nowrap; }
.sheet input[type="range"] { accent-color: var(--gold-deep); }
.sheet .check { display: flex; gap: 0.55rem; align-items: flex-start; font-size: 0.92rem; line-height: 1.35; margin-top: 0.6rem; }
.sheet .check input { margin-top: 0.2rem; accent-color: var(--gold-deep); }

/* drawn tile reveal */
.draw-reveal { text-align: center; }
.draw-reveal .big-tile {
  width: min(11rem, 50vw); margin: 0.4rem auto 0.6rem;
  filter: drop-shadow(0 10px 24px rgba(0,0,0,0.35));
  position: relative;
}
.draw-reveal .big-tile::before {
  content: '';
  position: absolute; inset: -22%;
  background: radial-gradient(circle, rgba(216, 184, 74, 0.3), transparent 65%);
  z-index: -1;
  animation: burstIn 600ms ease both;
}
@keyframes burstIn { from { opacity: 0; transform: scale(0.6); } }
.draw-reveal .big-tile svg { width: 100%; height: auto; }
.draw-reveal .tile-name { font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; }
.draw-reveal .tile-desc { font-style: italic; color: var(--ink-soft); margin: 0.2rem 0 0; }

/* peek (starting tile) */
.peek-hint { text-align: center; font-style: italic; color: var(--ink-soft); margin: 0.4rem 0 0; }

/* hand-off */
.handoff { text-align: center; padding: 1.6rem 1rem; }
.handoff .h-flag { width: 3.2rem; height: 3.2rem; border-radius: 12px; margin: 0 auto 0.8rem; border: 2px solid rgba(0,0,0,0.4); }
.handoff .h-shield { width: 4rem; height: 4rem; margin: 0 auto 0.8rem; filter: drop-shadow(0 3px 6px rgba(0,0,0,0.35)); }
.handoff .h-shield svg { width: 100%; height: 100%; display: block; }

/* scoring walkthrough — one fixed-size box holds every line card and the final
   epoch totals, so it never jumps as the content changes between steps. */
.score-sheet {
  width: min(30rem, calc(100vw - 1.6rem));
  height: min(31rem, calc(100dvh - 2rem));
  display: flex; flex-direction: column; overflow: hidden;
}
.score-sheet .score-head { flex: none; }
.score-sheet .score-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.score-sheet .sheet-actions { flex: none; margin-top: 0.9rem; }
.score-sheet .score-detail { margin-top: 0; }
.score-totals-title { margin-bottom: 0; }
.score-line-title { text-align: center; font-family: var(--font-display); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.08em; }
.score-tally {
  display: flex; justify-content: center; gap: 0.8rem; flex-wrap: wrap;
  margin: 0.5rem 0 0.2rem; padding: 0.4rem 0.5rem;
  border: 1.5px solid rgba(74, 63, 44, 0.3); border-radius: 8px;
  background: rgba(255, 250, 235, 0.45);
  font-size: 0.85rem;
}
.score-tally .tally-entry { display: inline-flex; align-items: center; gap: 0.3rem; font-family: var(--font-display); font-weight: 700; }
.score-tally .p-flag { width: 0.7rem; height: 0.7rem; }
.score-detail { margin: 0.6rem 0; display: flex; flex-direction: column; gap: 0.45rem; }
.score-seg {
  border: 1.5px solid rgba(74, 63, 44, 0.4); border-radius: 8px;
  background: rgba(255, 250, 235, 0.55); padding: 0.5rem 0.7rem; font-size: 0.9rem;
}
.score-seg .seg-base { font-weight: 700; }
.score-seg .seg-note { font-style: italic; color: var(--ink-soft); font-size: 0.82rem; }
.score-rows { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.3rem; }
.score-row { display: flex; justify-content: space-between; gap: 0.5rem; font-size: 0.9rem; }
.score-row .amt { font-family: var(--font-display); font-weight: 700; }
.amt.pos { color: var(--pine); } .amt.neg { color: var(--blood); } .amt.zero { color: var(--ink-soft); }

.score-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; margin-top: 0.4rem; }
.score-table th, .score-table td { padding: 0.3rem 0.45rem; text-align: right; border-bottom: 1px solid rgba(74,63,44,0.25); }
.score-table th:first-child, .score-table td:first-child { text-align: left; }
.score-table th { font-family: var(--font-display); font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); }
.score-table .total-row td { font-weight: 700; border-top: 2px solid var(--ink-soft); border-bottom: none; }

/* epoch banner */
.epoch-banner {
  position: fixed; inset: 0; z-index: 30; pointer-events: none;
  display: flex; align-items: center; justify-content: center; flex-direction: column;
  animation: bannerLife 2100ms ease both;
}
.epoch-banner::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(80% 60% at 50% 50%, rgba(10, 8, 4, 0.78), rgba(10, 8, 4, 0.45));
}
.epoch-banner .eb-rule {
  width: min(70vw, 26rem); height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
  animation: ruleWipe 500ms var(--ease-out) both;
}
@keyframes ruleWipe { from { transform: scaleX(0); } }
.epoch-banner .eb-text {
  font-family: var(--font-fancy); font-size: clamp(1.8rem, 8vw, 3.2rem);
  background: linear-gradient(168deg, #f7e7a8 8%, var(--gold) 36%, #9a7420 52%, #e7cc72 70%, #fdf3c8 95%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 3px 0 #4a3810) drop-shadow(0 0 28px rgba(216, 184, 74, 0.45));
  padding: 0.6rem 1.2rem; letter-spacing: 0.1em; text-align: center;
}
.epoch-banner .eb-sub { font-family: var(--font-display); color: var(--vellum); letter-spacing: 0.3em; text-transform: uppercase; font-size: 0.75rem; }
@keyframes bannerLife {
  0% { opacity: 0; transform: scale(0.94); }
  12%, 80% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.03); }
}

/* a cleared piece leaving the board between epochs */
.epoch-clear-piece {
  position: fixed; z-index: 28; pointer-events: none;
}
.epoch-clear-piece svg { width: 100%; height: 100%; display: block; }

/* game over */
.gameover-sheet { text-align: center; }
.gameover-sheet .crown { font-size: 2.6rem; line-height: 1; }
.gameover-sheet .crown-art { width: 4.4rem; height: 4.4rem; margin: 0 auto; animation: crownLand 600ms var(--ease-spring) both; }
.gameover-sheet .crown-art svg { width: 100%; height: 100%; display: block; filter: drop-shadow(0 4px 10px rgba(216,184,74,0.35)); }
@keyframes crownLand { from { transform: translateY(-26px) scale(1.15); opacity: 0; } 60% { transform: translateY(2px) scale(0.97); opacity: 1; } to { transform: none; } }
.gameover-sheet .streak-tease { font-style: italic; color: var(--ink-soft); margin: 0.3rem 0 0; }
.standings { display: flex; flex-direction: column; gap: 0.4rem; margin: 0.9rem 0 0.3rem; }
.standing {
  display: flex; align-items: center; gap: 0.6rem;
  border: 1.5px solid rgba(74, 63, 44, 0.4); border-radius: 10px;
  padding: 0.5rem 0.7rem; background: rgba(255, 250, 235, 0.5);
  position: relative; overflow: hidden;
  animation: screenIn 400ms var(--ease-out) backwards;
  animation-delay: calc(var(--i, 0) * 120ms);
}
.standing.winner { border-color: var(--gold-deep); background: rgba(216, 184, 74, 0.22); box-shadow: 0 0 16px rgba(216,184,74,0.25); }
.standing.winner::after {
  content: '';
  position: absolute; inset: 0; border-radius: 10px;
  background: linear-gradient(110deg, transparent 30%, rgba(255, 236, 170, 0.5) 50%, transparent 70%);
  background-size: 250% 100%;
  animation: shimmer 2.4s ease-in-out 600ms 3;
  pointer-events: none;
}
@keyframes shimmer { from { background-position: 120% 0; } to { background-position: -60% 0; } }
.standing .s-place { font-family: var(--font-display); font-weight: 900; width: 1.4rem; }
.standing .s-shield { width: 1.5rem; height: 1.5rem; flex: none; }
.standing .s-shield svg { width: 100%; height: 100%; display: block; }
.standing .s-name { flex: 1; text-align: left; font-weight: 700; }
.standing .s-gold {
  font-family: var(--font-display); font-weight: 700;
  display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap;
}
.standing .s-gold svg { width: 1rem; height: 1rem; flex: none; }

/* ============ HALL OF RECORDS: rating + achievements ============ */
.records-sheet { width: min(30rem, calc(100vw - 1.6rem)); }
.records-extra { margin-top: 0.5rem; }

.rating-card {
  border: 1.5px solid rgba(74, 63, 44, 0.4); border-radius: 10px;
  background: rgba(255, 250, 235, 0.5);
  padding: 0.7rem 0.8rem; margin-bottom: 0.7rem;
}
.rating-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.rating-now { display: flex; flex-direction: column; line-height: 1; }
.rating-label {
  font-family: var(--font-display); font-size: 0.66rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-soft);
}
.rating-value {
  font-family: var(--font-display); font-weight: 900; font-size: 2.1rem; color: var(--gold-deep);
  text-shadow: 0 1px 0 rgba(255,255,255,0.4);
}
.rating-meta { text-align: right; font-size: 0.82rem; color: var(--ink-soft); display: grid; gap: 0.1rem; }
.rating-meta b { color: var(--ink); font-family: var(--font-display); }
.rating-hint { text-align: center; font-style: italic; color: var(--ink-soft); font-size: 0.85rem; margin: 0.6rem 0 0.2rem; }

.elo-graph-wrap { margin-top: 0.6rem; }
.elo-graph { width: 100%; height: 96px; display: block; }
.elo-axis {
  display: flex; justify-content: space-between; font-size: 0.66rem;
  color: var(--ink-soft); margin-top: 0.1rem; font-family: var(--font-display); letter-spacing: 0.04em;
}
.elo-axis span:nth-child(2) { color: var(--gold-deep); font-weight: 700; }

.records-ach-link {
  width: 100%; display: flex; align-items: center; gap: 0.5rem;
  border: 1.5px solid rgba(74, 63, 44, 0.4); border-radius: 10px;
  background: rgba(255, 250, 235, 0.5); color: var(--ink);
  padding: 0.55rem 0.8rem; margin-bottom: 0.7rem; cursor: pointer;
  font-family: var(--font-display); font-size: 0.92rem; letter-spacing: 0.03em;
  transition: border-color 120ms, box-shadow 120ms;
}
.records-ach-link:hover { border-color: var(--gold); box-shadow: 0 0 16px var(--gold-glow); }
.records-ach-count { margin-left: auto; color: var(--gold-deep); font-weight: 700; }
.records-ach-go { color: var(--ink-soft); font-size: 1.2rem; line-height: 1; }

/* achievements sheet */
.ach-sheet { width: min(34rem, calc(100vw - 1.4rem)); }
.ach-summary {
  display: flex; align-items: center; gap: 0.7rem; margin-bottom: 0.9rem;
}
.ach-summary-stat { display: flex; flex-direction: column; line-height: 1.05; text-align: center; flex: none; }
.ach-summary-stat b { font-family: var(--font-display); font-size: 1.1rem; color: var(--gold-deep); }
.ach-summary-stat span { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-soft); }
.ach-meter {
  flex: 1; height: 9px; border-radius: 99px; overflow: hidden;
  background: rgba(74, 63, 44, 0.22); box-shadow: inset 0 1px 2px rgba(0,0,0,0.18);
}
.ach-meter-fill {
  height: 100%; border-radius: 99px;
  background: linear-gradient(90deg, var(--gold-deep), var(--gold));
  box-shadow: 0 0 10px var(--gold-glow);
}

.ach-section { margin-bottom: 1rem; }
.ach-section-head {
  display: flex; align-items: baseline; gap: 0.5rem; margin: 0 0 0.5rem;
  border-bottom: 1px solid rgba(74, 63, 44, 0.25); padding-bottom: 0.25rem;
}
.ach-section-head h4 {
  font-family: var(--font-display); font-size: 0.78rem; letter-spacing: 0.1em;
  text-transform: uppercase; margin: 0; color: var(--ink);
}
.ach-section-count { margin-left: auto; font-size: 0.74rem; color: var(--ink-soft); font-family: var(--font-display); }

.ach-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
@media (max-width: 30rem) { .ach-grid { grid-template-columns: 1fr; } }

.ach-card {
  display: flex; gap: 0.55rem; align-items: flex-start;
  border: 1.5px solid rgba(74, 63, 44, 0.3); border-radius: 9px;
  background: rgba(255, 250, 235, 0.55); padding: 0.5rem 0.55rem;
  position: relative; overflow: hidden;
}
.ach-card.unlocked {
  border-color: var(--tier-color);
  box-shadow: inset 0 0 14px var(--tier-glow), 0 0 0 1px var(--tier-color);
}
.ach-card.unlocked::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(120% 80% at 80% -10%, var(--tier-glow), transparent 60%);
  pointer-events: none;
}
.ach-card.locked { opacity: 0.62; }
.ach-card.locked .ach-medal-svg { filter: grayscale(0.85) brightness(0.92); }

.ach-medal { width: 2.4rem; height: 2.4rem; flex: none; }
.ach-medal-svg { width: 100%; height: 100%; display: block; }
.ach-card.unlocked .ach-medal-svg { filter: drop-shadow(0 1px 3px var(--tier-glow)); }

.ach-body { flex: 1; min-width: 0; }
.ach-name-row { display: flex; align-items: baseline; gap: 0.35rem; }
.ach-name { font-family: var(--font-display); font-weight: 700; font-size: 0.85rem; line-height: 1.1; }
.ach-tier {
  margin-left: auto; font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--tier-color); font-weight: 700; flex: none;
}
.ach-desc { font-size: 0.76rem; color: var(--ink-soft); margin: 0.15rem 0 0.35rem; line-height: 1.25; }
.ach-when { font-size: 0.68rem; color: var(--gold-deep); font-style: italic; }
.ach-when.locked { color: var(--ink-soft); }

.ach-progress { display: flex; align-items: center; gap: 0.4rem; }
.ach-bar {
  flex: 1; height: 6px; border-radius: 99px; overflow: hidden;
  background: rgba(74, 63, 44, 0.2);
}
.ach-bar-fill { height: 100%; border-radius: 99px; background: var(--tier-color); opacity: 0.85; }
.ach-bar-text { font-size: 0.64rem; color: var(--ink-soft); font-family: var(--font-display); white-space: nowrap; }

/* coins raining behind the game-over sheet */
.coin-rain {
  position: fixed; inset: 0; z-index: 19; pointer-events: none; overflow: hidden;
}
.coin-rain .rain-coin {
  position: absolute; top: -6%;
  width: 22px; height: 22px;
  animation: coinFall 1600ms var(--ease-in) both;
  filter: drop-shadow(0 3px 5px rgba(0,0,0,0.5));
}
.coin-rain .rain-coin svg { width: 100%; height: 100%; display: block; }
@keyframes coinFall {
  from { transform: translateY(0) rotate(0); opacity: 0; }
  12% { opacity: 1; }
  to { transform: translateY(115vh) rotate(320deg); opacity: 0.9; }
}

/* rules sheet */
.rules-sheet { width: min(34rem, calc(100vw - 1.6rem)); font-size: 0.93rem; line-height: 1.55; }
.rules-sheet h4 { font-family: var(--font-display); letter-spacing: 0.06em; margin: 1rem 0 0.3rem; }
.rules-sheet p, .rules-sheet ul { margin: 0.3rem 0; }
.rules-sheet li { margin-bottom: 0.25rem; }
.rules-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(4.2rem, 1fr)); gap: 0.5rem; margin-top: 0.5rem; }
.rules-tile { text-align: center; font-size: 0.68rem; }
.rules-tile svg { width: 100%; height: auto; border-radius: 6px; }

/* interactive special-tile demos in How to Play */
.mini-demo { display: flex; gap: 0.7rem; align-items: center; margin: 0.6rem 0; }
.mini-demo .mini-tile { width: 3.4rem; flex: none; }
.mini-demo .mini-tile svg { width: 100%; height: auto; border-radius: 5px; }
.mini-board {
  display: grid; grid-template-columns: repeat(4, 1.6rem); gap: 2px;
  background: var(--board-b); padding: 3px; border-radius: 5px; border: 1px solid #9a8657;
}
.mini-cell {
  aspect-ratio: 1; border-radius: 3px;
  background: rgba(255, 248, 226, 0.5);
  border: 1px solid rgba(110, 88, 48, 0.45);
}
.mini-cell.mini-hot {
  background: rgba(123, 111, 208, 0.4);
  border-color: var(--arcane);
}
.mini-cell.mini-self { background: var(--gold); border-color: var(--gold-deep); }
.mini-cell.mini-split { background: rgba(36, 29, 18, 0.5); }

/* toast */
.toast {
  position: fixed; top: max(0.8rem, env(safe-area-inset-top)); left: 50%; transform: translateX(-50%);
  z-index: 50;
  background: var(--vellum); color: var(--ink);
  font-family: var(--font-display); font-weight: 700; font-size: 0.82rem; letter-spacing: 0.04em;
  border-radius: 999px; padding: 0.5rem 1.1rem;
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.6);
  animation: toastIn 240ms ease both;
  max-width: calc(100vw - 2rem); text-align: center;
}
@keyframes toastIn { from { opacity: 0; transform: translate(-50%, -8px); } }
.toast.toast-out { animation: toastOut 200ms ease-in both; }
@keyframes toastOut { to { opacity: 0; transform: translate(-50%, -10px); } }

/* mobile log drawer */
.log-drawer-btn { position: fixed; right: 0.7rem; bottom: calc(var(--tray-h) + 0.7rem); z-index: 5; }

/* undo (vs computer only) floats opposite the log drawer */
.undo-btn { position: fixed; left: 0.7rem; bottom: calc(var(--tray-h) + 0.7rem); z-index: 5; }

/* draggable tray pieces + floating drag ghost */
.tray-item.draggable { cursor: grab; touch-action: none; }
.tray-item.draggable:active { cursor: grabbing; }
body.dragging-piece { cursor: grabbing; user-select: none; }
body.dragging-piece .cell { cursor: grabbing; }
.drag-ghost {
  position: fixed; left: 0; top: 0; z-index: 40;
  width: clamp(48px, 13vw, 76px); height: clamp(48px, 13vw, 76px);
  pointer-events: none;
  filter: drop-shadow(0 10px 16px rgba(0, 0, 0, 0.6));
  transform: translate(-100px, -100px);
  /* The appear "pop" is driven by a composited WAAPI scale in startDrag so it
     grows in place under the pointer — a CSS keyframe here would reset the
     translate and make the piece fly in from the corner. */
}
.drag-ghost svg { width: 100%; height: 100%; display: block; }
/* drag-to-draw: the carried piece flips from tile back to face in hand */
.drag-ghost.flipping { perspective: 480px; }
.drag-ghost .flip { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; }
.drag-ghost .flip-front, .drag-ghost .flip-back { backface-visibility: hidden; width: 100%; height: 100%; }
.drag-ghost .flip-front { position: absolute; inset: 0; transform: rotateY(180deg); }
.drag-ghost.flipping .flip { animation: tileFlip 380ms var(--ease-decel) both; }

/* placement impact ledger: shield + gold delta per player, under the
   previewed cell */
.place-delta {
  position: fixed; left: 0; top: 0; z-index: 41; pointer-events: none;
  display: flex; gap: 0.6rem; align-items: center;
  background: linear-gradient(180deg, var(--vellum-hi), var(--vellum-lo));
  border: 1px solid var(--gold-deep); border-radius: 999px;
  padding: 0.24rem 0.65rem;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.55);
  animation: fadeIn 120ms ease both;
  white-space: nowrap;
}
/* display:flex above beats the UA [hidden] rule — restate it, or the ledger
   never actually leaves the screen */
.place-delta[hidden] { display: none; }
.place-delta.pd-out { animation: pdOut 200ms ease both; }
@keyframes pdOut { to { opacity: 0; transform: translateY(5px); } }
.place-delta .pd-entry { display: inline-flex; align-items: center; gap: 0.22rem; }
.place-delta .pd-shield { width: 1.1rem; height: 1.1rem; }
.place-delta .pd-shield svg { width: 100%; height: 100%; display: block; }
.place-delta .pd-val { font-family: var(--font-display); font-weight: 900; font-size: 0.88rem; }
.place-delta .pd-val.pos { color: var(--pine); }
.place-delta .pd-val.neg { color: var(--blood); }
.place-delta .pd-val.zero { color: var(--ink-soft); }

/* tile tooltip */
.tile-tip {
  position: fixed; z-index: 45; pointer-events: none;
  max-width: 14rem;
  background: linear-gradient(180deg, var(--vellum-hi), var(--vellum-lo));
  color: var(--ink);
  border: 1px solid var(--gold-deep); border-radius: 9px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.55);
  padding: 0.5rem 0.65rem;
  animation: fadeIn 120ms ease both;
}
.tile-tip .tip-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.tile-tip .tip-name { font-family: var(--font-display); font-weight: 700; font-size: 0.9rem; letter-spacing: 0.03em; }
.tile-tip .tip-val { font-family: var(--font-display); font-weight: 900; font-size: 1rem; }
.tile-tip .tip-val.pos { color: var(--pine); }
.tile-tip .tip-val.neg { color: var(--blood); }
.tile-tip .tip-effect { font-size: 0.82rem; font-style: italic; color: var(--ink-soft); margin-top: 0.2rem; line-height: 1.35; }

/* ==========================================================================
   Mobile & tablet overhaul (portrait-first; everything below 920px).
   Goal: the board owns the screen, vertically centered in the space between a
   compact players strip and the tray — no dead gap dumped above the tray —
   and a drag that never fights the page (no rubber-band, no scroll-hijack).
   Desktop (>= 920px) is deliberately untouched.
   ========================================================================== */
@media (max-width: 919px) {
  :root { --tray-h: 8.4rem; }

  /* Kill page rubber-banding / pull-to-refresh so a drag stays a drag. The
     whole game fits one screen, so there is nothing to scroll away. */
  html, body { overscroll-behavior: none; }
  .screen-game { overflow: hidden; touch-action: manipulation; }

  .game-topbar { gap: 0.4rem; padding-left: 0.6rem; padding-right: 0.6rem; }
  .game-topbar .btn-icon { padding: 0.38rem 0.6rem; }

  /* The board area grows into the space between the strip and the tray, and
     the board sits centered in it. */
  .game-main {
    justify-content: flex-start;
    padding: 0.3rem 0.4rem calc(var(--tray-h) + 0.5rem);
    gap: 0.5rem;
  }
  .players-rail {
    flex: none; order: 0; gap: 0.4rem; padding: 0.05rem 0;
    scroll-snap-type: x proximity;
  }
  /* Let flex size the chips so 3-4 fit the strip without a scroll; a low floor
     just keeps a lone chip from collapsing. Each chip snaps if it must scroll. */
  .player-chip { scroll-snap-align: start; }
  .board-wrap { flex: 1 1 auto; min-height: 0; justify-content: center; gap: 0.55rem; }
  /* The frame is 6 wide : 5 tall, so width = available-height x 1.2. Whichever
     of full-width or that height-budget is smaller wins, and the board centers
     in whatever's left over. The height budget over-reserves the chrome on
     purpose, so the board never overflows the clipped screen. */
  .board-frame { width: min(100%, calc((100dvh - var(--tray-h) - 11rem) * 1.2), 60rem); }

  /* Compact, tidy chips — three or four still fit the strip cleanly. */
  .player-chip { min-width: 6.2rem; padding: 0.36rem 0.55rem; gap: 0.1rem; }
  .player-chip .p-name { font-size: 0.74rem; }
  .player-chip .p-gold { font-size: 0.95rem; }
  .player-chip .p-castles { min-height: 0.95rem; gap: 0.35rem; padding-top: 0.1rem; }
  .p-castles .c-mini { width: 1.05rem; }

  /* Tray: two centered rows that never scroll — towers (castles) on top, tiles
     (draw / secret / any draft) below. Items are kept SQUARE with the art
     centered and a small caption, instead of the tall flex-end columns. */
  .tray {
    flex-direction: column; align-items: center; justify-content: center;
    gap: 0.3rem; overflow: visible;
    padding: 0.45rem 0.5rem calc(0.4rem + env(safe-area-inset-bottom));
  }
  .tray.tray-scrolls { -webkit-mask-image: none; mask-image: none; }
  .tray-group { flex-wrap: wrap; justify-content: center; gap: 0.35rem; }
  .tray-sep { width: 55%; max-width: 15rem; height: 1px; margin: 0.05rem 0; }
  .tray-item {
    aspect-ratio: 1; width: clamp(2.9rem, 13.5vw, 3.8rem);
    justify-content: center; gap: 0.08rem; padding: 0.22rem;
  }
  .tray-item .t-art { width: 60%; max-height: 56%; }
  .tray-item .t-label { font-size: 0.5rem; }
  .tray-item.draggable:active { transform: scale(0.93); transition-duration: 60ms; }
  .tray-item.armed:active { transform: translateY(-3px) scale(0.95); }

  .action-hint { min-height: 1.2rem; font-size: 0.9rem; }
}

/* --- Landscape phones: height is the scarce axis. Players strip becomes a
   LEFT column and the tray a RIGHT column, so the board can expand to fill
   (almost) the whole height between them. --------------------------------- */
@media (max-width: 919px) and (orientation: landscape) and (max-height: 560px) {
  :root { --tray-w: 5rem; }

  .game-main {
    flex-direction: row; align-items: stretch; justify-content: center;
    gap: 0.5rem;
    padding: 0.3rem calc(var(--tray-w) + 0.5rem) 0.3rem 0.4rem;
  }
  .players-rail {
    flex-direction: column; width: 7rem; flex: none; order: 0;
    overflow-y: auto; overflow-x: visible; gap: 0.35rem; scroll-snap-type: none;
  }
  .player-chip { min-width: 0; }
  .board-wrap { flex: 1 1 auto; order: 1; justify-content: center; min-height: 0; }
  /* The tray no longer sits beneath the board, so the play area takes the
     full height (minus the top bar + the score-gutter row's extra height). */
  .board-frame { width: min(100%, calc((100dvh - 4.8rem) * 1.2), 60rem); }
  .action-hint { display: none; } /* the turn banner already says whose move */

  /* Tray: a fixed column down the right edge, below the top bar. */
  .tray {
    flex-direction: column; align-items: center; justify-content: center;
    top: max(2.9rem, calc(env(safe-area-inset-top) + 2.7rem)); right: 0; bottom: 0; left: auto;
    width: var(--tray-w); min-height: 0; gap: 0.3rem;
    padding: 0.4rem 0.3rem calc(0.4rem + env(safe-area-inset-bottom));
    border-top: none; border-left: 1px solid #54462c;
    box-shadow: -8px 0 22px rgba(0, 0, 0, 0.45);
    overflow-y: auto; overflow-x: hidden;
  }
  .tray.tray-scrolls { -webkit-mask-image: none; mask-image: none; }
  .tray-group { flex-direction: column; align-items: center; gap: 0.3rem; }
  .tray-sep { width: 60%; height: 1px; margin: 0.15rem 0; }
  .tray-item {
    aspect-ratio: 1; width: clamp(2.8rem, 9.5vh, 3.7rem);
    justify-content: center; gap: 0.06rem; padding: 0.2rem;
  }
  .tray-item .t-art { width: 58%; max-height: 54%; }
  .tray-item .t-label { font-size: 0.46rem; }
}

/* ==========================================================================
   Desktop layout
   ========================================================================== */

@media (min-width: 920px) {
  :root { --tray-h: 8rem; }

  /* balanced 1fr | board | 1fr grid: the board stays centered on the screen
     whatever size it is set to and whether the Chronicle is shown */
  .game-main {
    display: grid;
    grid-template-columns: minmax(min-content, 1fr) auto minmax(min-content, 1fr);
    align-items: start;
    gap: 1.4rem;
    padding-top: 0.8rem;
  }
  .players-rail {
    flex-direction: column; width: 16rem; flex: none; overflow: visible;
    order: 0; gap: 0.7rem;
    justify-self: end;
  }
  /* the chips own a whole column — let their contents fill it */
  .player-chip { min-width: 0; padding: 0.85rem 1rem; gap: 0.45rem; }
  .player-chip .p-name { font-size: 1.08rem; }
  .player-chip .p-secret { width: 1.25rem; }
  .player-chip .p-gold { font-size: 1.7rem; }
  .player-chip .p-gold .coin { width: 1.25rem; height: 1.25rem; }
  .player-chip .p-castles { gap: 0.7rem; min-height: 1.7rem; }
  .p-castles .c-mini { width: 1.9rem; }
  .p-castles .c-mini + .c-mini { margin-top: -1.25rem; }
  .p-castles .castles-empty { font-size: 0.85rem; }
  .player-chip .p-extra { font-size: 0.85rem; }
  .p-shield { width: 1.7rem; height: 1.7rem; }

  .board-wrap { order: 1; flex: 0 1 auto; width: auto; }
  /* board size: Settings -> "Board size (desktop)" tunes these knobs */
  .board-frame {
    width: min(var(--bf-vh, 74dvh), var(--bf-cap, 46rem), calc(100vw - var(--bf-rails, 36rem)));
    min-width: 30rem;
  }
  html[data-boardsize="small"] .board-frame { --bf-vh: 56dvh; --bf-cap: 36rem; min-width: 24rem; }
  html[data-boardsize="large"] .board-frame { --bf-vh: 90dvh; --bf-cap: 58rem; }

  /* "Your move" leaves the top bar and sits front and center above the tray */
  .turn-banner {
    position: fixed; left: 50%; bottom: calc(var(--tray-h) + 0.7rem);
    transform: translateX(-50%);
    z-index: 7; text-align: center;
    max-width: min(42rem, 92vw);
    background: linear-gradient(180deg, #2c2415, #1d180d);
    border: 1px solid #54462c; border-radius: 999px;
    padding: 0.42rem 1.3rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  }

  .right-rail {
    display: flex; flex-direction: column; gap: 1.1rem;
    order: 2; justify-self: start;
    max-height: calc(100dvh - var(--tray-h) - 7rem);
    min-height: 0;
  }
  .draw-rail {
    display: block; width: 15rem; flex: none;
    background: linear-gradient(180deg, rgba(216, 184, 74, 0.04), transparent);
    border-top: 1px solid #3e3520;
    padding: 0.6rem 0.6rem 0.7rem;
    border-radius: 4px;
  }
  .log-rail {
    display: flex; flex-direction: column;
    width: 15rem; flex: 0 1 auto; min-height: 4rem;
    background: linear-gradient(180deg, rgba(216, 184, 74, 0.04), transparent);
    border-top: 1px solid #3e3520;
    padding: 0.6rem 0.6rem 0;
    border-radius: 4px;
  }
  .log { flex: 1; min-height: 0; }
  .log-drawer-btn { display: none !important; }

  .tray-item { width: 5.2rem; }
  .tray-item .t-label { font-size: 0.64rem; }
  .tray-item .t-art { max-height: 3.4rem; }
  .cell.preview::after { font-size: 0.62rem; }
  .action-hint { font-size: 1rem; }
  .turn-banner { font-size: 1rem; }

  /* The scoring popup ran tall enough to crowd the board on desktop. Cap it
     shorter and let the line/totals body scroll internally when a step
     overflows (the fixed height still stops it jumping between steps). */
  .score-sheet { height: min(24rem, calc(100dvh - 7rem)); }
}

/* ==========================================================================
   Chronicle visibility (Settings -> "Show the Chronicle")
   ========================================================================== */
html[data-chronicle="0"] .log-rail { display: none !important; }
html[data-chronicle="0"] .log-drawer-btn { display: none !important; }

/* ==========================================================================
   Draw panel visibility (Settings -> "Show tiles left in the draw")
   ========================================================================== */
html[data-drawpanel="0"] .draw-rail { display: none !important; }

/* ==========================================================================
   Reduced motion — honored from the OS *or* forced from Settings
   ========================================================================== */

/* iteration-count 1 stops `infinite` animations from strobing through a 1ms
   cycle every frame; content-bearing one-shots whose visibility lives in the
   animation (banner, gold deltas) fall back to their static base styles. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
  }
  .epoch-banner, .gold-delta { animation: none !important; }
  .gold-delta { opacity: 1; }
}
html[data-motion="reduced"] *,
html[data-motion="reduced"] *::before,
html[data-motion="reduced"] *::after {
  animation-duration: 0.001s !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001s !important;
}
html[data-motion="reduced"] .epoch-banner,
html[data-motion="reduced"] .gold-delta { animation: none !important; }
html[data-motion="reduced"] .gold-delta { opacity: 1; }

/* ==========================================================================
   Faster animations (Settings -> "Faster animations")
   Shortens only the transient animations that gate perceived speed; ambient
   loops (candle, motes, thinking dots) keep their natural rhythm.
   ========================================================================== */
html[data-speed="fast"] .cell.placed-tile .cell-art { animation-duration: 130ms; }
html[data-speed="fast"] .cell.placed-castle .cell-art { animation-duration: 230ms; }
html[data-speed="fast"] .cell.just-placed .cell-art { animation-duration: 220ms; }
html[data-speed="fast"] .tray-item .t-art.flipping .flip { animation-duration: 230ms; }
html[data-speed="fast"] .overlay { animation-duration: 150ms; }
html[data-speed="fast"] .sheet { animation-duration: 170ms; }
html[data-speed="fast"] .screen { animation-duration: 240ms; }
html[data-speed="fast"] .epoch-banner { animation-duration: 1350ms; }
html[data-speed="fast"] .cell .score-hot { animation-duration: 300ms; }
