/* events.css — shared multi-event chrome for the dey.ci guide site.
   Loaded on every page (home, bear-hunt, vikings-vengeance, swordland-showdown,
   vip-calculator) after styles.css. Adds: the event switcher, the page deck, the page themes, and the components shared between events (the
   wave/phase ruled rows, the practical checklist). Page-specific components
   live next to their page: home.css (event cards, hover preview), vikings.css
   (troop composition), swordland.css (buildings, scoreboards, matrix, games),
   vip.css (the calculator's ruled rows and the reference ladder).
   Same tokens and the same one-signal-per-page contract as the base theme:
   each page owns one signal hue (home amber · bearhunt moss · vikings ember
   orange · swordland duel crimson + enemy steel-blue), everything else —
   parchment ink, oxblood rubrication, manuscript voice — stays shared. */

/* ─── Swipe setup ──────────────────────────────────────── */
html, body { overscroll-behavior-x: none; }


/* ─── Event switcher — the topbar tabs ────────────────── */
/* Sits between brand and lang-picker; hidden below 1240px, where the bar can
   no longer hold the masthead and seven labels with the strip on the centre
   line — there the ledger drawer carries the same links. The label size is
   capped below the type scale's --step--1 (1.2rem): a strip of seven uppercase
   labels at the full label size is ~864px, which pushes the bar's centre off
   any laptop it is asked to fit. At 0.85rem with the tracking pulled in it is
   550-664px depending on the language, which the centre line can hold. */
.ev-switch {
  display: flex; align-items: center;
  gap: 0.26rem;
  min-width: 0;
}
.ev-switch a {
  font-family: var(--body);
  font-size: min(var(--step--1), 0.85rem);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-muted);
  padding: 0.22rem 0.42rem;
  border: 1px solid transparent;
  border-radius: 2px;
  white-space: nowrap;
  transition: color 0.3s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.ev-switch a:hover { color: var(--ink-dim); }
.ev-switch a.active {
  color: var(--amber);
  border-color: var(--signal-line);
}

/* ─── Footer switch — the same three links, always there ─ */
.ev-foot {
  display: flex; justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-s) var(--space-m);
  margin-top: var(--space-m);
}
.ev-foot a {
  font-family: var(--body);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-muted);
}
.ev-foot a:hover { color: var(--amber); }

@media (max-width: 1799px) {
  .ev-switch { display: none; }
}

/* ─── The ledger — the ❧ directory drawer (mobile) ───── */
/* Below 700px the tab strip is hidden, so the topbar carries a small
   fleuron trigger that opens the grouped page list as a floating leaf
   under the bar — the same float recipe as the language menu. The active
   row wears the page's one signal with a ❧ prefix; every other row
   recedes to ink-muted. Companion of the ≥700px .ev-switch strip. */
.ledger-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  font-size: var(--step-0);
  line-height: 1;
  color: var(--amber-dim);
  background: transparent;
  border: 1px solid var(--signal-line);
  border-radius: 2px;
  cursor: pointer;
  transition: color 0.3s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.ledger-btn:hover, .ledger-btn:focus-visible, .ledger-btn.open {
  color: var(--amber);
  border-color: var(--amber);
}
/* The drawer replaces the strip wherever the strip can't fit (see .ev-switch),
   not just on phones — a squeezed strip is worse than an honest drawer. */
@media (min-width: 1800px) {
  .ledger-btn { display: none; }
}
.ledger {
  position: absolute;
  top: var(--topbar-h);
  inset-inline-end: var(--space-s);
  z-index: 60;
  width: min(92vw, 24rem);
  max-height: 62vh;
  overflow-y: auto;
  padding: var(--space-s) var(--space-m) var(--space-m);
  background: var(--void-2);
  border: 1px solid var(--signal-line);
  border-radius: 3px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55);
  animation: ledger-in 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes ledger-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ledger-group {
  margin: 0.7rem 0 0.2rem;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.ledger-group:first-child { margin-top: 0; }
.ledger a {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.45rem 0.2rem;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-muted);
  border-bottom: 1px solid rgba(157, 149, 127, 0.12);
}
.ledger a:hover { color: var(--amber); }
.ledger a.active { color: var(--amber); }
.ledger a.active::before { content: "\2767 "; }

@property --deck-accent { syntax: '<color>'; inherits: true; initial-value: #F5C851; }

.page-deck {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  height: 100dvh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  color: var(--ink);
  background: #090d14;
  isolation: isolate;
  -webkit-tap-highlight-color: transparent;
  overflow: auto;
  overscroll-behavior: contain;
}
.page-deck[data-selected="home"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #F5C851; --deck-ground: #25231b; }
.page-deck[data-selected="bearhunt"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #AEC878; --deck-ground: #1d2320; }
.page-deck[data-selected="vikings"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #E08A3C; --deck-ground: #231c19; }
.page-deck[data-selected="swordland"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #E05555; --deck-ground: #23161c; }
.page-deck[data-selected="vip"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #C5A3EE; --deck-ground: #201f2e; }
.page-deck[data-selected="sim"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #88A8F0; --deck-ground: #18202e; }
.page-deck[data-selected="kvksg"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #5FC8A6; --deck-ground: #132326; }
.page-deck[data-selected="gear"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #72CBDD; --deck-ground: #16242c; }
.page-deck[data-selected="heroes"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #E68AB4; --deck-ground: #241c27; }
.page-deck[data-selected="masters"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #A29BF4; --deck-ground: #1d1c30; }
.page-deck[data-selected="governor"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #86D48A; --deck-ground: #19241b; }
.page-deck[data-selected="pets"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #F0907A; --deck-ground: #271b1b; }
.page-deck[data-selected="castle"] :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) { --deck-accent: #DFAA77; --deck-ground: #27201b; }
/* The selected page's colours land only on the parts that use them, not on
   the strip, so a change restyles a handful of elements rather than every
   cover in the ring. */
.page-deck :is(.deck-ground, .deck-atmosphere, .deck-header, .deck-groups, .deck-footer, #deck-hint) {
  --amber: var(--deck-accent);
  --amber-dim: color-mix(in srgb, var(--deck-accent) 76%, #090d14);
  --signal-line: color-mix(in srgb, var(--deck-accent) 35%, transparent);
}
/* The ground takes the selected page's colour (its signal, 12% into the
   night) and moves to the next one as a plain background-color transition.
   That interpolates in every browser and never dims on the way: stacking a
   wash per page and cross-fading their opacity did, pulsing the whole
   screen darker at the midpoint of every change.
   The fade runs on its own empty, full-screen layer. A plain colour layer
   is the cheapest thing to redraw; fading the dialog's own background
   repainted the header, buttons and glow every frame, and Android Chrome
   sometimes showed a frame with the dialog missing. The accent the header
   and buttons use switches once rather than fading, so the deck restyles
   once per change instead of every frame.
   Selection follows the card in the centre while the strip moves, so
   the ground drifts with the finger and nothing changes when it stops. */
.deck-ground {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-color: var(--deck-ground, #090d14);
  transition: background-color 0.6s ease;
  will-change: opacity;
}
.deck-atmosphere { background: radial-gradient(ellipse 80% 60% at 50% 46%, rgba(241, 227, 194, 0.035), transparent 72%); }
.page-deck .ascii-ambient > span { opacity: 0.18; }
.page-deck::backdrop { background: rgba(5, 8, 13, 0.8); }
html.deck-open { overflow-y: hidden; scrollbar-gutter: stable; }
/* The deck covers the whole screen, so the page under it is hidden while
   it is open. Android Chrome sometimes draws a frame without the dialog's
   layers when the selection changes; with the page still painted, that
   frame showed the page through the deck as a flash. Hidden, the page has
   no layers to show, frees the memory its own layers held, and the root
   under the dialog is the deck's own night colour. */
html.deck-open, html.deck-open body { background: #090d14; }
html.deck-open body > :not(.page-deck) { visibility: hidden; }
.deck-sheet {
  position: relative;
  z-index: 1;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1rem;
  padding-block: max(1rem, env(safe-area-inset-top)) max(1rem, env(safe-area-inset-bottom));
}
.deck-header, .deck-groups, .deck-footer, #deck-hint {
  width: min(90%, 38rem);
  margin-inline: auto;
}
.deck-header { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
/* The deck's name stays for screen readers (it labels the dialog) but is not shown;
   the header holds only the Town Centre button and close. */
.deck-header h2 { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* The Town Centre is not a page in the ring: it holds your inventory, so it is one fixed button beside close. */
.deck-town { display: inline-flex; align-items: center; gap: .4rem; min-height: 44px; padding: 0 .7rem; border: 1px solid var(--amber-dim); border-radius: 2px; background: var(--void-2); color: var(--amber); font-size: var(--step--1); font-weight: 700; letter-spacing: .05em; text-decoration: none; white-space: nowrap; }
.page-deck .deck-close { padding: 0 .7rem; font-size: var(--step--1); font-weight: 700; letter-spacing: .05em; }
.deck-town svg { width: 1rem; height: 1rem; fill: currentColor; }
.deck-town:hover, .deck-town:focus-visible, .deck-town[aria-current="page"] { color: var(--ink); border-color: var(--amber); }
.page-deck button {
  min-width: 44px;
  min-height: 44px;
  border: 1px solid var(--signal-line);
  border-radius: 2px;
  background: var(--void-2);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.page-deck button:hover, .page-deck button:focus-visible { color: var(--amber); border-color: var(--signal-line); }
.page-deck :focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }
.deck-groups { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.15rem 0.4rem; }
.deck-groups button {
  padding: 0.25rem 0.55rem;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.05em;
}
.deck-groups button[aria-pressed="true"] { color: var(--amber); border-color: var(--signal-line); }
/* The strip reaches under the position label and the hint, so a swipe
   where the thumb naturally rests, below the covers, still moves it.
   The footer sits on top of the strip and lets touches through to it;
   only its buttons take taps. */
.deck-stage {
  --strip-height: clamp(32rem, 70dvh, 39rem);
  display: grid;
  grid-template-columns: 100%;
  grid-template-rows: calc(var(--strip-height) - 0.75rem) auto auto;
  row-gap: 1rem;
  flex-shrink: 0;
}
.deck-stage > .deck-footer, .deck-stage > #deck-hint {
  grid-column: 1;
  position: relative;
  z-index: 1;
  pointer-events: none;
}
.deck-stage > .deck-footer { grid-row: 2; }
.deck-stage > #deck-hint { grid-row: 3; }
.deck-footer button { pointer-events: auto; }
.deck-viewport {
  --card-width: min(76vw, 23rem);
  position: relative;
  grid-row: 1 / -1;
  grid-column: 1;
  display: flex;
  align-items: flex-start;
  gap: clamp(1rem, 4vw, 1.5rem);
  min-height: 0;
  padding: 0.75rem calc((100% - var(--card-width)) / 2) 0;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Sideways only: a slightly diagonal swipe on the covers must not be
     taken by the sheet's vertical scroll and stall the strip. */
  touch-action: pan-x;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  direction: ltr;
  user-select: none;
  -webkit-user-select: none;
}
.deck-viewport::-webkit-scrollbar { display: none; }
.deck-card {
  position: relative;
  flex: 0 0 var(--card-width);
  width: var(--card-width);
  height: calc(var(--strip-height) - 1.5rem);
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 14rem;
  padding: clamp(1.25rem, 5vw, 2rem);
  background: var(--void-2);
  border: 1px solid var(--amber-dim);
  border-radius: 3px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
  color: var(--ink);
  text-decoration: none;
  scroll-snap-align: center;
  scroll-margin-inline: 1rem;
  -webkit-user-drag: none;
  isolation: isolate;
  --amber: var(--deck-accent);
  --amber-dim: color-mix(in srgb, var(--deck-accent) 76%, #090d14);
}
/* Each cover keeps its own page's colour, whichever card is selected, so
   covers never recolour as the selection moves. */
:is(.deck-card, .deck-pip)[data-page="home"] { --deck-accent: #F5C851; }
:is(.deck-card, .deck-pip)[data-page="bearhunt"] { --deck-accent: #AEC878; }
:is(.deck-card, .deck-pip)[data-page="vikings"] { --deck-accent: #E08A3C; }
:is(.deck-card, .deck-pip)[data-page="swordland"] { --deck-accent: #E05555; }
:is(.deck-card, .deck-pip)[data-page="vip"] { --deck-accent: #C5A3EE; }
:is(.deck-card, .deck-pip)[data-page="sim"] { --deck-accent: #88A8F0; }
:is(.deck-card, .deck-pip)[data-page="kvksg"] { --deck-accent: #5FC8A6; }
:is(.deck-card, .deck-pip)[data-page="gear"] { --deck-accent: #72CBDD; }
:is(.deck-card, .deck-pip)[data-page="heroes"] { --deck-accent: #E68AB4; }
:is(.deck-card, .deck-pip)[data-page="masters"] { --deck-accent: #A29BF4; }
:is(.deck-card, .deck-pip)[data-page="governor"] { --deck-accent: #86D48A; }
:is(.deck-card, .deck-pip)[data-page="pets"] { --deck-accent: #F0907A; }
:is(.deck-card, .deck-pip)[data-page="castle"] { --deck-accent: #DFAA77; }
.deck-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 50%, color-mix(in srgb, var(--amber) 7%, transparent), transparent 70%);
}
.deck-card-copy { display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: 0.75rem; min-height: 0; }
.deck-mark { color: var(--amber-dim); font-size: 2.2rem; line-height: 1; }
.deck-card-title {
  min-height: 0;
  overflow: hidden;
  align-self: start;
  max-height: 100%;
  font-family: var(--display-2);
  font-weight: 700;
  font-size: min(var(--step-2), 7vw);
  line-height: 1.2;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--amber);
  overflow-wrap: anywhere;
}
.deck-card-lede {
  align-self: end;
  max-height: 100%;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--ink-dim);
}
/* Title and lede are never scroll boxes of their own. As one (the lede
   also contained its overscroll) they caught a sideways swipe started on
   the text, the lower half of the cover where the thumb rests, and the
   strip never moved. The strip only pans sideways anyway, so they could
   not be scrolled by touch. */
.deck-card-action { display: block; margin-top: auto; color: var(--amber); font-size: var(--step--1); }
.deck-footer { direction: ltr; padding: 0; display: flex; align-items: center; justify-content: center; gap: 0.75rem; }
.deck-footer button { font-size: 2rem; line-height: 1; }
.deck-position { min-width: 0; text-align: center; color: var(--ink-dim); font-size: var(--step--1); }
/* The rail: a mark per page in ledger order, each in its own page's colour,
   with a little air between the groups. The selected page is a solid
   diamond, the page you came from a hollow one, the rest small dots; a mark
   changes glyph, never size or position. The whole rail is the target, so
   the marks can sit closer than a tap's width: a touch picks the nearest. */
.deck-locator { flex: 0 1 18rem; min-width: 0; display: grid; justify-items: center; gap: 0.2rem; }
.deck-rail {
  pointer-events: auto;
  touch-action: none;
  width: 100%;
  min-height: 44px;
  display: flex;
  align-items: center;
  font-family: var(--ascii-font);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.deck-rail:focus-visible { outline-offset: 0; }
.deck-pip { flex: 1 1 0; text-align: center; color: color-mix(in srgb, var(--deck-accent) 62%, #090d14); }
.deck-pip-break { margin-inline-start: 0.6rem; }
.deck-pip::before { content: "\2022"; }
.deck-pip.is-last::before { content: "\25C7"; }
.deck-pip.is-selected::before { content: "\25C6"; }
.deck-pip:is(.is-selected, .is-last) { color: var(--deck-accent); }
#deck-hint { margin-block: 0; text-align: center; color: var(--ink-dim); font-size: var(--step--1); }
html[dir="rtl"] .deck-card { direction: rtl; }
@media (prefers-reduced-motion: no-preference) {
  .page-deck[open] { animation: deck-reveal 0.16s ease-out; }
  @keyframes deck-reveal { from { opacity: 0; } }
}
@media (max-height: 540px) {
  .deck-sheet { gap: 0.4rem; }
  .deck-stage { --strip-height: 32rem; }
}
@media (prefers-reduced-motion: reduce) {
  .deck-ground { transition-duration: 0.3s; }
  .deck-viewport { scroll-behavior: auto; }
}


@view-transition { navigation: auto; }

html[data-entry="deck"]::view-transition { background: #090d14; }
html[data-entry="deck"]::view-transition-group(root) { animation-duration: 0.4s; }

@media (prefers-reduced-motion: no-preference) {
  .topbar { view-transition-name: topbar; }
  /* Both sides of every move composite normally. The UA gives the root's old
     and new images `plus-lighter`, which *adds* them together — so a fade
     brightens as it goes and a slide picks up a glow along its seam. Nothing
     here wants that: these are two opaque pages, and one should simply be
     replaced by the other. */
  ::view-transition-old(root) { mix-blend-mode: normal; }
  ::view-transition-new(root) { mix-blend-mode: normal; }
  /* The bar is the same bar on both sides and is not part of the move: no
     group animation and no cross-fade inside it, so the chrome never ghosts
     through itself. The new image sits over the old one unblended. */
  ::view-transition-group(topbar) { animation: none; }
  ::view-transition-old(topbar) { animation: none; }
  ::view-transition-new(topbar) { animation: none; mix-blend-mode: normal; }

  /* A page arriving from outside the ring: the old one is held and the new one
     fades in on top. Holding a layer is what keeps this smooth — see the fold
     note below. */
  ::view-transition-old(root) { animation: none; }
  ::view-transition-new(root) { animation: vt-dissolve-in 0.3s ease both; }

  html[data-nav="next"]::view-transition-old(root) { animation: vt-out-left 0.45s cubic-bezier(0.16, 1, 0.3, 1) both; }
  html[data-nav="next"]::view-transition-new(root) { animation: vt-in-right 0.45s cubic-bezier(0.16, 1, 0.3, 1) both; }
  html[data-nav="prev"]::view-transition-old(root) { animation: vt-out-right 0.45s cubic-bezier(0.16, 1, 0.3, 1) both; }
  html[data-nav="prev"]::view-transition-new(root) { animation: vt-in-left 0.45s cubic-bezier(0.16, 1, 0.3, 1) both; }

  html[data-entry="deck"]::view-transition-old(root),
  html[data-entry="fold"]::view-transition-old(root) { animation: none; }
  html[data-entry="deck"]::view-transition-new(root),
  html[data-entry="fold"]::view-transition-new(root) { animation: vt-dissolve-in 0.4s ease both; }

  @keyframes vt-dissolve-in { from { opacity: 0; } }
  @keyframes vt-out-left { to { transform: translateX(-100%); } }
  @keyframes vt-in-right { from { transform: translateX(100%); } }
  @keyframes vt-out-right { to { transform: translateX(100%); } }
  @keyframes vt-in-left { from { transform: translateX(-100%); } }
}

/* No motion: the swap is instant — neither the dissolve nor the slide. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* ─── Page themes — one signal hue per event ──────────── */
/* The same manuscript night, parchment ink and oxblood rubrication on
   every page; only the hue of the night, the signal, and the drifting
   motes change, so each guide reads as its own world. Derived tints
   (hairlines, glows, hover washes) are explicit rgba siblings of the
   page's signal — same alphas as the base amber theme — and every
   hardcoded amber in styles.css was tokenised, so a page theme is
   just these token overrides. Home is the canonical theme — the
   tokens in styles.css, no overrides.

   Each .deck-card carries its destination's data-page theme. */
.deck-card[data-page="home"] {
  --void: #0B0E16;        /* ground — the same night home lands on */
  --void-2: #121726;      /* one step up (fields)            */
  --amber: #F5C851;       /* the one signal — active         */
  --amber-dim: #D3A33E;   /* antique gold — secondary signal */
}

@property --void { syntax: '<color>'; inherits: true; initial-value: #0B0E16; }
@property --void-2 { syntax: '<color>'; inherits: true; initial-value: #121726; }
@property --amber { syntax: '<color>'; inherits: true; initial-value: #F5C851; }
@property --amber-dim { syntax: '<color>'; inherits: true; initial-value: #D3A33E; }
@property --ember { syntax: '<color>'; inherits: true; initial-value: rgba(216, 166, 64, 0.18); }
@property --ember-2 { syntax: '<color>'; inherits: true; initial-value: rgba(245, 200, 81, 0.11); }
@property --ember-3 { syntax: '<color>'; inherits: true; initial-value: rgba(241, 227, 194, 0.09); }
@property --chrome { syntax: '<color>'; inherits: true; initial-value: rgba(11, 14, 22, 0.9); }
@property --signal-line { syntax: '<color>'; inherits: true; initial-value: rgba(245, 200, 81, 0.35); }
@property --signal-tint { syntax: '<color>'; inherits: true; initial-value: rgba(245, 200, 81, 0.07); }
@property --signal-glow { syntax: '<color>'; inherits: true; initial-value: rgba(245, 200, 81, 0.22); }
@property --signal-halo { syntax: '<color>'; inherits: true; initial-value: rgba(245, 200, 81, 0.28); }
@property --enemy { syntax: '<color>'; inherits: true; initial-value: #4E74CB; }
@property --enemy-dim { syntax: '<color>'; inherits: true; initial-value: #3C5CA6; }

:root { --theme-shift: 0.7s; }

/* The transition lives on <html> because the theme blocks redeclare
   the tokens there; every descendant inherits the animated value, so
   the whole page moves as one. Keep the list in step with the tokens
   a theme block may override. */
html {
  transition:
    --void var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --void-2 var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --amber var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --amber-dim var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --ember var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --ember-2 var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --ember-3 var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --chrome var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --signal-line var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --signal-tint var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --signal-glow var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --signal-halo var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --enemy var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1),
    --enemy-dim var(--theme-shift) cubic-bezier(0.16, 1, 0.3, 1);
}

html[data-page="bearhunt"],
html[data-page="home"]:has(.event-card[data-hover-page="bearhunt"]:is(:hover, :focus-within)),
.deck-card[data-page="bearhunt"] {
  --void: #0B110C;        /* pine night — black-green        */
  --void-2: #121B13;      /* one step up (fields)            */
  --amber: #AEC878;       /* moss-verdigris — the hunt signal */
  --amber-dim: #879E52;   /* deep moss — secondary            */
  --ember: rgba(220, 208, 120, 0.18); /* golden fireflies    */
  --ember-2: rgba(214, 200, 110, 0.11);
  --ember-3: rgba(235, 228, 190, 0.09);
  --chrome: rgba(11, 17, 12, 0.9);
  --signal-line: rgba(174, 200, 120, 0.35);
  --signal-tint: rgba(174, 200, 120, 0.07);
  --signal-glow: rgba(174, 200, 120, 0.22);
  --signal-halo: rgba(174, 200, 120, 0.28);
}

html[data-page="vikings"],
html[data-page="home"]:has(.event-card[data-hover-page="vikings"]:is(:hover, :focus-within)),
.deck-card[data-page="vikings"] {
  --void: #150D08;        /* forge night — ember brown         */
  --void-2: #1E140D;      /* one step up (fields)             */
  --amber: #E08A3C;       /* ember orange — the forge signal  */
  --amber-dim: #B96A2E;   /* burnt ember — secondary           */
  --ember: rgba(224, 138, 60, 0.16); /* ember sparks           */
  --ember-2: rgba(214, 120, 44, 0.09);
  --ember-3: rgba(241, 227, 194, 0.06); /* pale ash            */
  --chrome: rgba(21, 13, 8, 0.9);
  --signal-line: rgba(224, 138, 60, 0.35);
  --signal-tint: rgba(224, 138, 60, 0.07);
  --signal-glow: rgba(224, 138, 60, 0.22);
  --signal-halo: rgba(224, 138, 60, 0.28);
}

/* Motes move their own way: embers drift (home, default), fireflies
   rise and sway (bearhunt), ember-ash falls (vikings). Three soft dot
   layers, no streak grid — nothing that reads as flicker. */
html[data-page="bearhunt"] .dust i:nth-child(1) { background-size: 120px 120px; animation: mote-drift 120s linear infinite; }
html[data-page="bearhunt"] .dust i:nth-child(2) { background-size: 190px 190px; animation: mote-drift 170s linear infinite reverse; }
html[data-page="bearhunt"] .dust i:nth-child(3) { background-size: 260px 260px; animation: mote-drift 220s linear infinite; }
@keyframes mote-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-3%, -6%, 0); }
}

html[data-page="vikings"] .dust i:nth-child(1) {
  background-image: radial-gradient(circle, var(--ember) 1px, transparent 1.9px);
  background-size: 130px 130px;
  animation: ash-fall 80s linear infinite;
}
html[data-page="vikings"] .dust i:nth-child(2) {
  background-image: radial-gradient(circle, var(--ember-2) 1.7px, transparent 2.6px);
  background-size: 220px 220px;
  animation: ash-fall 130s linear infinite reverse;
}
html[data-page="vikings"] .dust i:nth-child(3) {
  background-image: radial-gradient(circle, var(--ember-3) 1.6px, transparent 2.4px);
  background-size: 280px 280px;
  animation: ash-fall 180s linear infinite;
}
@keyframes ash-fall {
  from { transform: translate3d(0, -5%, 0); }
  to   { transform: translate3d(2%, 8%, 0); }
}

/* ─── Swordland — red vs blue, one duel ────────────────── */
/* The event is literally red vs blue, so the duel night keeps
   both sides in the dust: crimson motes drift one way, steel-blue
   motes the other, a far rose layer settles the middle. This is
   the one page that breaks the one-signal rule on purpose: the
   sections alternate accents down the page — odd sections carry
   duel crimson (your side), even sections (.section.blue) carry
   the enemy steel-blue, and the .tag-them accent stays blue. */
html[data-page="swordland"],
html[data-page="home"]:has(.event-card[data-hover-page="swordland"]:is(:hover, :focus-within)),
.deck-card[data-page="swordland"] {
  --void: #120A0D;        /* duel night — black-red            */
  --void-2: #1B1115;      /* one step up (fields)              */
  --amber: #E05555;       /* duel crimson — your side          */
  --amber-dim: #A8443F;   /* deep red — secondary               */
  --ember: rgba(224, 85, 85, 0.16);    /* crimson motes         */
  --ember-2: rgba(78, 116, 203, 0.22); /* enemy steel-blue      */
  --ember-3: rgba(224, 85, 85, 0.08);  /* far red motes         */
  --chrome: rgba(18, 10, 13, 0.9);
  --signal-line: rgba(224, 85, 85, 0.35);
  --signal-tint: rgba(224, 85, 85, 0.07);
  --signal-glow: rgba(224, 85, 85, 0.22);
  --signal-halo: rgba(224, 85, 85, 0.28);
  --enemy: #4E74CB;       /* the other side — sparingly        */
  --enemy-dim: #3C5CA6;   /* deep steel — secondary blue        */
}

/* Alternate section accents: every other section runs on the
   enemy blue instead of the duel crimson. Scoping the signal
   tokens flips every amber accent inside the section at once —
   carets, rubric labels, table accents, checklist numbers. */
html[data-page="swordland"] .section.blue {
  --amber: var(--enemy);
  --amber-dim: var(--enemy-dim);
}
html[data-page="swordland"] .section.blue h2 { color: var(--enemy-dim); }
html[data-page="swordland"] .section.blue.front h2 { color: var(--enemy); }

/* Two tides drifting toward each other: crimson one way, blue
   the other. Layer three just settles (base dust-drift). */
html[data-page="swordland"] .dust i:nth-child(1) { animation: duel-tide 150s linear infinite; }
html[data-page="swordland"] .dust i:nth-child(2) { background-size: 150px 150px; animation: duel-tide 190s linear infinite reverse; }
html[data-page="swordland"] .dust i:nth-child(3) { animation: dust-drift 80s linear infinite; }
@keyframes duel-tide {
  from { transform: translate3d(-3%, 0, 0); }
  to   { transform: translate3d(3%, -4%, 0); }
}

/* ─── VIP — the court's violet night ───────────────────── */
/* The calculator page is a tool, not an event, so its world is the
   court rather than a battlefield: a violet night, slow candlelight
   motes, and a pale amethyst signal — the one cool signal on the
   site, for the page that keeps the ledger. */
html[data-page="vip"],
html[data-page="home"]:has(.event-card[data-hover-page="vip"]:is(:hover, :focus-within)),
.deck-card[data-page="vip"] {
  --void: #120A1E;        /* court night — violet-black        */
  --void-2: #1C1330;      /* one step up (fields)              */
  --amber: #C5A3EE;       /* amethyst — the court signal       */
  --amber-dim: #9A75C9;   /* deep violet — secondary            */
  --ember: rgba(197, 163, 238, 0.16); /* candlelight motes      */
  --ember-2: rgba(166, 124, 219, 0.10);
  --ember-3: rgba(236, 226, 250, 0.08); /* pale parchment motes */
  --chrome: rgba(18, 10, 30, 0.9);
  --signal-line: rgba(197, 163, 238, 0.35);
  --signal-tint: rgba(197, 163, 238, 0.07);
  --signal-glow: rgba(197, 163, 238, 0.22);
  --signal-halo: rgba(197, 163, 238, 0.28);
}

/* Candlelight rises slow and straight — the court's quiet dust. */
html[data-page="vip"] .dust i:nth-child(1) { animation: candle-rise 90s linear infinite; }
html[data-page="vip"] .dust i:nth-child(2) { background-size: 200px 200px; animation: candle-rise 140s linear infinite reverse; }
html[data-page="vip"] .dust i:nth-child(3) { background-size: 300px 300px; animation: candle-rise 200s linear infinite; }
@keyframes candle-rise {
  from { transform: translate3d(0, 4%, 0); }
  to   { transform: translate3d(-2%, -6%, 0); }
}

/* ─── Battle Simulator — the war room's night ─────────── */
/* Another tool, not an event: the page where the maths of a fight gets
   worked out on a map table. A blue-black war-room night with a war-map
   blue signal, cold and exact, for the page that does the arithmetic. */
html[data-page="sim"],
html[data-page="home"]:has(.event-card[data-hover-page="sim"]:is(:hover, :focus-within)),
.deck-card[data-page="sim"] {
  --void: #090C18;        /* war-room night — blue-black        */
  --void-2: #10172A;      /* one step up (fields)              */
  --amber: #88A8F0;       /* war-map blue — the simulator signal */
  --amber-dim: #5D7CC2;   /* deep map blue — secondary          */
  --rubric: #E05555;      /* rubrication red — draft marks only (oxblood is too dark on this night) */
  --ember: rgba(136, 168, 240, 0.16); /* lamp motes on the map  */
  --ember-2: rgba(100, 132, 210, 0.10);
  --ember-3: rgba(241, 227, 194, 0.07); /* pale parchment motes */
  --chrome: rgba(9, 12, 24, 0.9);
  --signal-line: rgba(136, 168, 240, 0.35);
  --signal-tint: rgba(136, 168, 240, 0.07);
  --signal-glow: rgba(136, 168, 240, 0.22);
  --signal-halo: rgba(136, 168, 240, 0.28);
}

/* Embers drift slow and straight — the war room's quiet dust. */
html[data-page="sim"] .dust i:nth-child(1) { animation: candle-rise 90s linear infinite; }
html[data-page="sim"] .dust i:nth-child(2) { background-size: 200px 200px; animation: candle-rise 140s linear infinite reverse; }
html[data-page="sim"] .dust i:nth-child(3) { background-size: 300px 300px; animation: candle-rise 200s linear infinite; }

/* ─── KvK & Strongest Governor — one wheel, two crowns ─── */
/* The event cycle: one 28-day clock on a sea night, so its signal is
   tide jade. The Strongest Governor sections step up to crown gold, the
   way Swordland alternates to the enemy blue. The wheel's battle weekend
   borrows the shared --enemy red. */
html[data-page="kvksg"],
html[data-page="home"]:has(.event-card[data-hover-page="kvksg"]:is(:hover, :focus-within)),
.deck-card[data-page="kvksg"] {
  --void: #081315;        /* sea night — black-teal            */
  --void-2: #0F1F1E;      /* one step up (fields)              */
  --amber: #5FC8A6;       /* tide jade — the cycle signal      */
  --amber-dim: #3E9A7E;   /* deep jade — secondary             */
  --ember: rgba(95, 200, 166, 0.16); /* sea-spray motes         */
  --ember-2: rgba(70, 168, 140, 0.10);
  --ember-3: rgba(240, 222, 178, 0.07); /* pale gold light      */
  --chrome: rgba(8, 19, 21, 0.9);
  --signal-line: rgba(95, 200, 166, 0.35);
  --signal-tint: rgba(95, 200, 166, 0.07);
  --signal-glow: rgba(95, 200, 166, 0.22);
  --signal-halo: rgba(95, 200, 166, 0.28);
  --enemy: #E05555;       /* the enemy kingdom — battle red    */
  --enemy-dim: #B04040;
}

/* Strongest Governor sections wear crown gold against the page's tide
   jade, so the SG blocks read as the peak of the campaign. Scoping the signal tokens flips every amber accent in
   the section at once. */
html[data-page="kvksg"] .section.sg {
  --amber: #F0CE7A;
  --amber-dim: #C69A4E;
}
html[data-page="kvksg"] .section.sg h2 { color: var(--amber-dim); }
html[data-page="kvksg"] .section.sg.front h2 { color: var(--amber); }

/* The wheel's motes rise slowly — campaign banners going up. */
html[data-page="kvksg"] .dust i:nth-child(1) { animation: mote-rise 110s linear infinite; }
html[data-page="kvksg"] .dust i:nth-child(2) { background-size: 180px 180px; animation: mote-rise 160s linear infinite reverse; }
html[data-page="kvksg"] .dust i:nth-child(3) { background-size: 260px 260px; animation: mote-rise 210s linear infinite; }
@keyframes mote-rise {
  from { transform: translate3d(0, 6%, 0); }
  to   { transform: translate3d(2%, -6%, 0); }
}

/* ─── Shared ruled rows — wave/phase tables ───────────── */
/* The wave schedule (Vikings) and the phase/timeline tables
   (Swordland) are the same ruled rows; the three type labels are
   the only per-page difference. */
.wavetable { margin: var(--space-m) 0; border-top: 1px solid rgba(157, 149, 127, 0.25); }
.wt-row {
  display: grid;
  /* The type track sizes to its content: a fixed 6.8rem cut "GOVERNOR" (102px
     at the label step) and "MOBILIZE" to 83px, and with `overflow: visible`
     they painted over the note beside them. `auto` gives the widest label in
     the table the room it needs and the note takes what is left. */
  grid-template-columns: 5rem auto 1fr;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.5rem 0;
  border-bottom: 1px solid rgba(157, 149, 127, 0.14);
  font-size: var(--step--1);
}
.wt-waves { font-family: var(--body); font-weight: 700; letter-spacing: 0.04em; color: var(--ink); }
.wt-type { font-family: var(--body); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.wt-type.city { color: var(--ink-muted); }
.wt-type.online { color: var(--amber); }
.wt-type.hq { color: var(--ink); }
.wt-note { color: var(--ink-dim); }
@media (max-width: 640px) {
  .wt-row { grid-template-columns: 3.6rem auto 1fr; gap: 0.5rem; }
}

/* ─── The practical checklist (Swordland, Vikings) ─────── */
/* The practical close: a page's advice in the order it
   actually happens. Numbered ruled rows, no epigram. */
.checklist { list-style: none; margin: var(--space-m) 0; border-top: 1px solid rgba(157, 149, 127, 0.25); }
.checklist li {
  display: grid;
  grid-template-columns: 2.8rem 1fr;
  gap: 0.9rem;
  align-items: baseline;
  padding: 0.65rem 0;
  border-bottom: 1px solid rgba(157, 149, 127, 0.14);
}
.check-num { font-family: var(--display-2); font-weight: 700; font-size: var(--step-1); color: var(--amber); }
.checklist h3 { font-size: var(--step-0); letter-spacing: 0.04em; margin-bottom: 0.2rem; }
.checklist p { color: var(--ink-dim); font-size: var(--step--1); }


/* ─── Bear Hunt — collapsible major sections ────────────
   The guide is long on mobile. Major sections use native details so the page
   can collapse into a scannable contents view without hiding the core thesis
   or the final four rules. */
html[data-page="bearhunt"] .section-fold {
  margin-top: 0;
}

html[data-page="bearhunt"] .section-fold > summary {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  cursor: pointer;
  list-style: none;
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  text-transform: none;
  color: inherit;
  user-select: none;
}

html[data-page="bearhunt"] .section-fold > summary::-webkit-details-marker { display: none; }
html[data-page="bearhunt"] .section-fold > summary::before { content: none; }

html[data-page="bearhunt"] .section-fold > summary h2 {
  flex: 1 1 auto;
  margin-bottom: 0;
}

html[data-page="bearhunt"] .section-fold > summary h2::after {
  content: "⌄";
  display: inline-block;
  margin-inline-start: 0.45em;
  color: var(--amber);
  font-family: var(--body);
  font-size: 0.72em;
  font-weight: 700;
  transform: translateY(-0.06em) rotate(-90deg);
  transform-origin: center;
  transition: transform 0.2s ease, color 0.2s ease;
}

html[data-page="bearhunt"] .section-fold[open] > summary h2::after {
  transform: translateY(-0.06em) rotate(0deg);
}

html[data-page="bearhunt"] .section-fold > summary:hover h2::after {
  color: var(--ink);
}

html[data-page="bearhunt"] .section-fold:not([open]) > summary h2 {
  color: var(--ink-dim);
}

html[data-page="bearhunt"] .section-fold:not([open]) > summary h2::before {
  opacity: 0.72;
}

@media (max-width: 760px) {
  html[data-page="bearhunt"] .section {
    padding-block: clamp(1.1rem, 5vw, 1.8rem);
  }

  html[data-page="bearhunt"] .section-fold:not([open]) {
    margin-bottom: 0;
  }

  html[data-page="bearhunt"] .section-fold > summary {
    min-height: 2.75rem;
    align-items: center;
  }
}

/* ─── Hero gear — mithril on a steel night ─────────────── */
html[data-page="gear"], html[data-page="home"]:has(.event-card[data-hover-page="gear"]:is(:hover, :focus-within)), .deck-card[data-page="gear"] {
  --void: #08111A;        /* steel night — blue-black          */
  --void-2: #101C27;      /* one step up (fields)              */
  --amber: #72CBDD;       /* mithril — the smith's signal      */
  --amber-dim: #4C9DB0;   /* tempered mithril — secondary      */
  --ember: rgba(114, 203, 221, 0.15); /* quench sparks          */
  --ember-2: rgba(86, 170, 190, 0.10);
  --ember-3: rgba(236, 240, 242, 0.07);
  --chrome: rgba(8, 17, 26, .94);
  --signal-line: rgba(114, 203, 221, .35);
  --signal-tint: rgba(114, 203, 221, .07);
  --signal-glow: rgba(114, 203, 221, .22);
  --signal-halo: rgba(114, 203, 221, .28);
}


/* ─── Heroes — the hall of banners ─────────────────────── */
html[data-page="heroes"], html[data-page="home"]:has(.event-card[data-hover-page="heroes"]:is(:hover, :focus-within)), .deck-card[data-page="heroes"] {
  --void: #150A11;        /* hall night — wine-black           */
  --void-2: #20121B;      /* one step up (fields)              */
  --amber: #E68AB4;       /* banner rose — the roster signal   */
  --amber-dim: #B5628A;   /* deep rose — secondary             */
  --ember: rgba(230, 138, 180, 0.15); /* banner motes           */
  --ember-2: rgba(196, 110, 152, 0.10);
  --ember-3: rgba(241, 227, 194, 0.07);
  --chrome: rgba(21, 10, 17, .94);
  --signal-line: rgba(230, 138, 180, .35);
  --signal-tint: rgba(230, 138, 180, .07);
  --signal-glow: rgba(230, 138, 180, .22);
  --signal-halo: rgba(230, 138, 180, .30);
}


/* ─── Masters — the lapis academy ──────────────────────── */
html[data-page="masters"], html[data-page="home"]:has(.event-card[data-hover-page="masters"]:is(:hover, :focus-within)), .deck-card[data-page="masters"] {
  --void: #0E0D1A;        /* academy night — ink-black indigo  */
  --void-2: #171627;      /* one step up (fields)              */
  --amber: #A29BF4;       /* lapis — the scholar's signal      */
  --amber-dim: #7670C4;   /* pressed lapis — secondary         */
  --ember: rgba(162, 155, 244, 0.15); /* lamp-lit motes        */
  --ember-2: rgba(130, 124, 210, 0.10);
  --ember-3: rgba(241, 227, 194, 0.07);
  --chrome: rgba(14, 13, 26, .94);
  --signal-line: rgba(162, 155, 244, .35);
  --signal-tint: rgba(162, 155, 244, .07);
  --signal-glow: rgba(162, 155, 244, .22);
  --signal-halo: rgba(162, 155, 244, .28);
}

/* ─── Governor gear — the laurel wardrobe ──────────────── */
html[data-page="castle"], html[data-page="home"]:has(.event-card[data-hover-page="castle"]:is(:hover, :focus-within)), .deck-card[data-page="castle"] {
  --void: #0B0E16;
  --void-2: #121726;
  --amber: #DFAA77;
  --amber-dim: #B9895D;
  --chrome: rgba(11, 14, 22, .94);
  --signal-line: rgba(223, 170, 119, .35);
  --signal-tint: rgba(223, 170, 119, .07);
  --signal-glow: rgba(223, 170, 119, .22);
  --signal-halo: rgba(223, 170, 119, .28);
}

html[data-page="governor"], html[data-page="home"]:has(.event-card[data-hover-page="governor"]:is(:hover, :focus-within)), .deck-card[data-page="governor"] {
  --void: #0A130C;        /* garden night — laurel-black       */
  --void-2: #121D14;      /* one step up (fields)              */
  --amber: #86D48A;       /* laurel green — the governor signal */
  --amber-dim: #5FA466;   /* pressed laurel — secondary        */
  --ember: rgba(134, 212, 138, 0.15); /* laurel motes           */
  --ember-2: rgba(108, 180, 114, 0.10);
  --ember-3: rgba(241, 227, 194, 0.07);
  --chrome: rgba(10, 19, 12, .94);
  --signal-line: rgba(134, 212, 138, .35);
  --signal-tint: rgba(134, 212, 138, .07);
  --signal-glow: rgba(134, 212, 138, .22);
  --signal-halo: rgba(134, 212, 138, .28);
}

/* ─── Pets — the coral Beast Cage ─────────────────────── */
html[data-page="pets"], html[data-page="home"]:has(.event-card[data-hover-page="pets"]:is(:hover, :focus-within)), .deck-card[data-page="pets"] {
  --void: #140F10;        /* den night — warm earth-black       */
  --void-2: #1E1718;      /* one step up (fields)              */
  --amber: #F0907A;       /* fox coral — the beast signal       */
  --amber-dim: #BC6A58;   /* pressed coral — secondary          */
  --ember: rgba(240, 144, 122, 0.15); /* hearth-warm motes      */
  --ember-2: rgba(200, 120, 100, 0.10);
  --ember-3: rgba(241, 227, 194, 0.07);
  --chrome: rgba(20, 15, 16, .94);
  --signal-line: rgba(240, 144, 122, .35);
  --signal-tint: rgba(240, 144, 122, .07);
  --signal-glow: rgba(240, 144, 122, .22);
  --signal-halo: rgba(240, 144, 122, .28);
}

/* ─── Town Centre — the orchid storehouse ──────────────── */
html[data-page="town"], html[data-page="home"]:has(.event-card[data-hover-page="town"]:is(:hover, :focus-within)), .deck-town {
  --void: #130C14;        /* storehouse night — orchid-black   */
  --void-2: #1C141E;      /* one step up (fields)              */
  --amber: #DC8FDB;       /* town-crier orchid — the signal    */
  --amber-dim: #AC66AB;   /* pressed orchid — secondary        */
  --ember: rgba(220, 143, 219, 0.15); /* orchid motes          */
  --ember-2: rgba(180, 112, 180, 0.10);
  --ember-3: rgba(241, 227, 194, 0.07);
  --chrome: rgba(19, 12, 20, .94);
  --signal-line: rgba(220, 143, 219, .35);
  --signal-tint: rgba(220, 143, 219, .07);
  --signal-glow: rgba(220, 143, 219, .22);
  --signal-halo: rgba(220, 143, 219, .28);
}
