/* Isles of Calamity — shared web theme.
   Medieval RPG with an early-2000s soul, executed with modern CSS: design
   tokens, fluid type, faux-bevel controls (no UA outset/inset), GPU-friendly
   grounds, :focus-visible, and reduced-motion support. Dark timber ground,
   parchment panels, gilded gold controls, chiseled serif small-caps.
   Self-contained: no webfonts, no CDN — textures are tiny inline SVG. Every
   page under Web/sites/ links this one file. */

:root {
  /* ── grounds ─────────────────────────────────────────────────── */
  --wood:            #241708;
  --wood-light:      #3a2712;
  --stone:           #2a2724;
  --stone-dark:      #14120f;
  --stone-light:     #4a4640;
  --parchment:       #ecdcb2;
  --parchment-dark:  #ddc890;
  --parchment-inset: #f5ecce;
  /* ── ink on parchment ────────────────────────────────────────── */
  --ink:             #2e2212;
  --ink-dim:         #5f4d2c;   /* darkened from #6d5a38 → clears 4.5:1 on parchment */
  /* ── metals + accents ────────────────────────────────────────── */
  --gold:            #c9a227;
  --gold-bright:     #ecd06f;
  --gold-dark:       #8a6d1d;
  --blood:           #6e1f14;
  --link:            #7a2d12;
  --good:            #3e5f22;
  --bad:             #8b2020;
  --warn:            #8a5a10;
  /* ── borders ─────────────────────────────────────────────────── */
  --edge:            #8a744e;
  --edge-dark:       #55432a;

  /* ── spacing scale (4-based) ─────────────────────────────────── */
  --space-1: 4px; --space-2: 8px; --space-3: 12px;
  --space-4: 16px; --space-5: 24px; --space-6: 32px;

  /* ── radius / border / rings / shadows ───────────────────────── */
  --radius:    3px;
  --radius-sm: 2px;
  --ring: 0 0 0 3px rgba(201, 162, 39, 0.32);
  --shadow-sm:    0 1px 2px rgba(0, 0, 0, 0.30);
  --shadow-md:    0 3px 8px rgba(0, 0, 0, 0.38);
  --shadow-panel: 0 5px 18px rgba(0, 0, 0, 0.45);
  /* gilded-plaque bevel, layered so it reads 3D without UA outset borders */
  --bevel-btn: inset 0 1px 0 rgba(255, 250, 224, 0.80), inset 0 -2px 3px rgba(120, 80, 12, 0.32);
  --bevel-slot: inset 0 1px 2px rgba(80, 60, 25, 0.22);   /* carved input well */

  /* ── fluid type scale (rem base → honours user font-size) ────── */
  --fs-body:  clamp(0.95rem, 0.90rem + 0.20vw, 1.02rem);
  --fs-h1:    clamp(1.65rem, 1.36rem + 1.35vw, 2.05rem);
  --fs-h2:    clamp(1.22rem, 1.09rem + 0.62vw, 1.45rem);
  --fs-h3:    clamp(1.04rem, 0.98rem + 0.34vw, 1.20rem);
  --fs-hero:  clamp(2.10rem, 1.40rem + 3.30vw, 3.00rem);
  --fs-btn:   clamp(0.90rem, 0.87rem + 0.15vw, 1.00rem);
  --fs-small: 0.82rem;

  /* ── shared timber texture (header + footer + dropdowns) ─ real
     dark-stained oak (generated art, seamless mirror-tiled), grain kept
     smooth and low-contrast on purpose: small gold serif text sits directly
     on it. Consumers pair it with a gradient scrim, so each sets
     background-size for BOTH layers (gradient auto, timber 300px). ─ */
  --tex-timber: url("/shared/img/timber-tile.webp");

  /* ── legacy aliases (a few older per-page styles reference these) ─ */
  --bg: var(--wood);
  --bg-raised: var(--parchment);
  --bg-inset: var(--parchment-inset);
  --frame: var(--edge);
  --frame-light: var(--edge-dark);
  --text: var(--ink);
  --text-dim: var(--ink-dim);
  --accent: var(--blood);
  --accent-dim: var(--gold-dark);
  --font-ui: Georgia, "Palatino Linotype", "Book Antiqua", "Times New Roman", serif;
}

*, *::before, *::after { box-sizing: border-box; }

/* Visually hidden but available to screen readers (skip-content, status text). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Skip-to-content link (WCAG 2.4.1): off-screen until keyboard-focused, then
   slides into the top-left. First focusable element on every page (JS-mounted). */
.skip-link {
  position: fixed; left: 10px; top: -60px; z-index: 2000;
  background: var(--parchment); color: var(--ink);
  padding: 9px 16px; border: 1px solid var(--gold-dark); border-radius: var(--radius-sm);
  font-variant: small-caps; letter-spacing: 0.03em; text-decoration: none;
  box-shadow: var(--shadow-md); transition: top 0.16s ease;
}
.skip-link:focus { top: 10px; outline: 2px solid var(--gold-bright); outline-offset: 2px; }

html { font-size: 100%; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* Sticky footer: the page is a column; <main> flexes to fill, so the footer
     never floats mid-screen with a void beneath it on short pages (login). */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  line-height: 1.58;
  /* Aged tome-leather ground: a real weathered book-binding texture (generated
     art, seamless mirror-tiled), darkened for a heavier medieval "calamity"
     mood — replaces the old synthetic SVG turbulence. The framing torch-glow +
     deep vignette live on the fixed ::before overlay below, so every viewport
     stays centred on the parchment WITHOUT background-attachment:fixed's cost. */
  background-color: #17100a;
  background-image: url("/shared/img/leather-tile.webp");
  background-size: 420px 420px;
  background-repeat: repeat;
}

/* Framing light: a warm top torch-glow, a deep even vignette, and a soft
   top/bottom edge darkening — all viewport-anchored (position:fixed, not
   background-attachment) so a fixed compositor layer frames the content on
   every screen and never repaints while scrolling. z-index:-1 keeps it above
   the leather grain but behind all page content; pointer-events:none so it's
   inert. This is what makes the ground read "contained" like an RS interface. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 50% -8%, rgba(120, 74, 48, 0.16) 0%, rgba(120, 74, 48, 0.05) 26%, rgba(0, 0, 0, 0) 48%),
    radial-gradient(115% 130% at 50% 42%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0.30) 74%, rgba(0, 0, 0, 0.55) 100%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.22) 0%, rgba(0, 0, 0, 0) 16%, rgba(0, 0, 0, 0) 84%, rgba(0, 0, 0, 0.30) 100%);
}

/* ── mossy cobblestone side rails: fixed masonry columns framing the shell
   on wide viewports. They live on the ROOT's pseudo-elements so the body's
   vignette (body::before, painted later in tree order at the same -1 level)
   shades them for depth. The sticky header/footer are opaque and paint over
   them, so the rails read as columns between the two timber beams. The tile
   is drawn at 260px but the rail is at most 76px wide — only the tile's clean
   outer band shows, keeping the mirror seam out of view. Width is fluid:
   (free gutter) − 30px of breathing leather, clamped 44–76px, so rails never
   crowd the 1120px content column at the 1320px gate. ── */
@media (min-width: 1320px) {
  html::before, html::after {
    content: "";
    position: fixed; top: 0; bottom: 0;
    width: clamp(44px, calc((100vw - 1120px) / 2 - 30px), 76px);
    z-index: -1; pointer-events: none;
    background:
      linear-gradient(90deg, rgba(0, 0, 0, 0.34) 0%, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, 0) 62%, rgba(0, 0, 0, 0.44) 100%),
      linear-gradient(rgba(23, 15, 8, 0.42), rgba(23, 15, 8, 0.42)),  /* warm stain: pulls the grey stone toward the shell's palette */
      url("/shared/img/cobble-tile.webp") repeat left top / 260px auto;
  }
  html::before {
    left: 0;
    border-right: 1px solid rgba(16, 10, 4, 0.85);
    box-shadow: 1px 0 0 rgba(201, 162, 39, 0.14), 6px 0 18px rgba(0, 0, 0, 0.4);
  }
  html::after {
    right: 0;
    background-position: right top;  /* one value cycles to every layer */
    border-left: 1px solid rgba(16, 10, 4, 0.85);
    box-shadow: -1px 0 0 rgba(201, 162, 39, 0.14), -6px 0 18px rgba(0, 0, 0, 0.4);
  }
}

/* THE page column. Header, util strip, content and footer all share this one
   width so every edge lines up — per-page overrides are design drift. */
.wrap { max-width: var(--w-page, 1120px); margin-inline: auto; padding: 0 clamp(12px, 4vw, 18px); }

/* ── carved-timber TOP BAR with dropdown menus (declutters via grouping) ── */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background-color: #34210d;
  background-image:
    linear-gradient(180deg, rgba(96, 64, 30, 0.28), rgba(22, 13, 5, 0.5)),
    var(--tex-timber);
  background-size: auto, 300px 300px;
  border-bottom: 2px solid var(--gold-dark);
  box-shadow:
    inset 0 1px 0 rgba(236, 208, 111, 0.14),   /* top gleam */
    inset 0 -3px 0 rgba(236, 208, 111, 0.16),  /* single gilt inset above the border */
    0 4px 14px rgba(0, 0, 0, 0.5);             /* lift off the page */
}
.site-header .wrap {
  display: flex; align-items: stretch; gap: clamp(12px, 2vw, 22px);
  height: 64px; position: relative;   /* DEFINITE height: every cell resolves
                                         height:100% against it, so anchors,
                                         dropdown buttons and the search item
                                         all center on the same axis. Inherits
                                         the 1120px content column. */
}

/* ── Utility strip: the slim service row above the main bar. Population count
   + Status/Support/Report/Account — small, right-aligned, near-black, so the
   primary run below reads as THE navigation (two-row masthead anatomy). ── */
.nav-util {
  background: rgba(8, 5, 2, 0.55);
  border-bottom: 1px solid rgba(201, 162, 39, 0.22);
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.4);
}
.nav-util .wrap {
  display: flex; justify-content: flex-end; align-items: center; min-height: 27px;
  gap: 0; font-size: 0.72rem; font-variant: small-caps; letter-spacing: 0.08em;
}
.nav-util a, .nav-util .nav-online {
  color: #ab925f; text-decoration: none; line-height: 1; padding: 6px 10px;
  white-space: nowrap;
}
.nav-util a { transition: color 0.12s ease; }
.nav-util a + a { border-left: 1px solid rgba(201, 162, 39, 0.18); }
.nav-util a:hover, .nav-util a.on { color: var(--gold-bright); }
.nav-util a:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: -2px; }
.nav-util .nav-online { margin-right: auto; padding-left: 0; }
.nav-util .nav-online b { color: var(--gold); font-weight: 700; }

/* ── Masthead: the wordmark carries the visual weight (bigger, brighter, tracked) ── */
.brand {
  display: inline-flex; align-items: center; gap: 11px; align-self: center;
  color: var(--gold-bright); font-variant: small-caps; font-weight: 700;
  font-size: clamp(1.06rem, 0.95rem + 0.5vw, 1.28rem); letter-spacing: 0.11em;
  text-decoration: none; white-space: nowrap;
  padding: 6px 0; margin-right: 2px;
  text-shadow: 0 1px 0 #000, 0 0 16px rgba(236, 208, 111, 0.28);
}
.brand::before {
  content: ""; width: 27px; height: 33px; flex: 0 0 auto;
  background: url("/shared/img/emblem-crest.webp") center / contain no-repeat;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
}
/* Hairline gilded rule divides the masthead from the (quieter) nav run. */
.brand::after {
  content: ""; align-self: stretch; width: 1px; margin: 12px 0 12px 8px;
  background: linear-gradient(180deg, transparent, rgba(201, 162, 39, 0.55) 22%,
    rgba(201, 162, 39, 0.55) 78%, transparent);
}
.brand:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; border-radius: var(--radius-sm); }

/* ── Nav run: flat, quiet, one consistent treatment for EVERY top item ── */
.site-nav { display: flex; align-items: stretch; gap: 0; margin-left: auto; height: 100%; }
.site-nav > * { height: 100%; }
.nav-search-label {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); border: 0;
}
/* Bevelled column separators between cells (dark cut + gilt edge), the quiet
   structure that makes the run read as designed rather than floated. The CTA
   opts out — it's a button, not a cell. */
.site-nav > * + *:not(.nav-cta) {
  border-left: 1px solid rgba(0, 0, 0, 0.4);
  box-shadow: inset 1px 0 0 rgba(236, 208, 111, 0.09);
}
/* App subdomains author bare anchors in .site-nav — give them the identical
   cell treatment so every header on the platform matches. */
.site-nav > a:not(.nav-item):not(.nav-cta) {
  display: inline-flex; align-items: center;
  color: #cdb277; text-decoration: none; font-variant: small-caps;
  letter-spacing: 0.07em; font-size: 0.97rem; line-height: 1; white-space: nowrap;
  padding: 0 clamp(10px, 1.4vw, 16px); transition: color 0.14s ease;
}
.site-nav > a:not(.nav-item):not(.nav-cta):hover { color: var(--gold-bright); }

/* Rest state: no box, no border, no fill — just quiet gilt text.
   Each item reserves room below the baseline for its underline marker. */
.nav-item {
  position: relative;
  display: inline-flex; align-items: center; gap: 5px;
  color: #cdb277; text-decoration: none; font-variant: small-caps;
  letter-spacing: 0.07em; font-size: 0.94rem; line-height: 1; white-space: nowrap;
  padding: 0 clamp(9px, 1.2vw, 15px); margin: 0; border: 0; background: none; cursor: pointer; font-family: inherit;
  border-radius: 0;
  /* Dropdown triggers are <button>s — shed the global gilt-button chrome so
     every nav item (anchor or button) reads identically flat at rest. */
  box-shadow: none; appearance: none; -webkit-appearance: none;
  transition: color 0.14s ease;
}
/* The underline marker: a thin gold rule that animates in on hover and sits
   persistently under the active page (this is the shared, non-colour-only cue). */
.nav-item:hover, .nav-dd:hover .nav-dd-btn { background: rgba(236, 208, 111, 0.05); }
.nav-item::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--gold); border-radius: 1px;
  transform: scaleX(0); transform-origin: center; opacity: 0;
  transition: transform 0.22s cubic-bezier(.2, .7, .3, 1), opacity 0.22s ease, background-color 0.14s ease;
}
.nav-item:hover, .nav-dd:hover .nav-dd-btn, .nav-dd.open .nav-dd-btn { color: var(--gold-bright); }
.nav-item:hover::after, .nav-dd:hover .nav-dd-btn::after, .nav-dd.open .nav-dd-btn::after {
  transform: scaleX(1); opacity: 1;
}
/* Active page: persistent, brighter marker + brighter label (marker = the a11y cue). */
.nav-item.active, .nav-dd .nav-dd-btn.active { color: var(--gold-bright); }
.nav-item.active::after, .nav-dd .nav-dd-btn.active::after {
  transform: scaleX(1); opacity: 1;
  height: 3px; background: var(--gold-bright);
  box-shadow: 0 0 8px rgba(236, 208, 111, 0.4);
}
.nav-item:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; border-radius: var(--radius-sm); }
/* Desktop: the brand IS Home — the explicit Home cell only exists in the
   drawer, and Search is icon-only. Both keep the row from overflowing. Placed
   AFTER .nav-item so the hide wins the equal-specificity display contest. */
.nav-item.nav-home { display: none; }

.caret { font-size: 0.62em; opacity: 0.72; margin-left: 1px; transition: transform 0.18s ease; }
.nav-dd:hover .caret, .nav-dd.open .caret { transform: translateY(1px); opacity: 0.95; }

/* Search: same item, same underline system; the SVG glyph inherits currentColor
   so it transitions dim→gold identically to every sibling. No emoji. */
.nav-search { gap: 6px; }
.nav-search .nav-search-ico { width: 17px; height: 17px; flex: 0 0 auto; display: block; }

/* Underline/caret are the only animated cues here; honour reduced-motion even
   though the file's global guard also neutralises transitions (WCAG 2.3.3). */
@media (prefers-reduced-motion: reduce) {
  .nav-item::after { transition: none; }
  .caret { transition: none; }
}

/* ── Dropdown: the one framed surface (it floats above the timber) ── */
.nav-dd { position: relative; display: flex; align-items: stretch; }
.nav-dd .nav-dd-btn { height: 100%; }

/* ── The one loud element: the gold CTA (everything else stays quiet) ── */
.site-nav > .nav-cta { height: auto; }
.nav-cta {
  align-self: center; display: inline-flex; align-items: center;
  margin-left: clamp(8px, 1.2vw, 16px); padding: 9px 18px 10px;
  font-variant: small-caps; font-weight: 700; letter-spacing: 0.08em;
  font-size: 0.95rem; line-height: 1; white-space: nowrap; text-decoration: none;
  color: #2b1c07;
  background: linear-gradient(180deg, #f0d270, #c9a227 55%, #a98417);
  border: 1px solid #8a6d1d; border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 rgba(255, 246, 205, 0.75), 0 2px 6px rgba(0, 0, 0, 0.45);
  text-shadow: 0 1px 0 rgba(255, 246, 205, 0.4);
  transition: filter 0.14s ease, transform 0.14s ease;
}
.nav-cta:hover { filter: brightness(1.08); }
.nav-cta:active { transform: translateY(1px); }
.nav-cta:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
.nav-dd-menu {
  position: absolute; top: calc(100% + 8px); left: 0;
  min-width: 208px; z-index: 120;
  display: none; flex-direction: column; padding: 6px;
  background-color: #2c1c0b;
  background-image:
    linear-gradient(180deg, rgba(96, 64, 30, 0.3), rgba(18, 11, 4, 0.72)),
    var(--tex-timber);
  background-size: auto, 300px 300px;
  border: 1px solid var(--gold-dark); border-radius: var(--radius);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.58), inset 0 1px 0 rgba(236, 208, 111, 0.12);
}
/* A small gilt notch tying the menu back to its trigger (left-anchored to match
   the left:0 panel, so the rightmost trigger's menu never clips off-screen). */
.nav-dd-menu::before {
  content: ""; position: absolute; top: -5px; left: 18px; width: 9px; height: 9px;
  transform: rotate(45deg);
  background: #33220f; border-left: 1px solid var(--gold-dark); border-top: 1px solid var(--gold-dark);
}
/* Invisible hover bridge across the 8px visual gap between the trigger and the
   menu — without it, a diagonal pointer path (trigger → first item) briefly
   leaves .nav-dd and the menu snaps shut (the "Play menu closes" bug). */
.nav-dd-menu::after {
  content: ""; position: absolute; top: -9px; left: 0; right: 0; height: 9px;
}
.nav-dd:hover .nav-dd-menu, .nav-dd:focus-within .nav-dd-menu, .nav-dd.open .nav-dd-menu { display: flex; }
.nav-ddi {
  position: relative;
  display: block; color: #cdb277; text-decoration: none;
  font-variant: small-caps; letter-spacing: 0.05em; font-size: 0.95rem; white-space: nowrap;
  padding: 8px 12px 8px 15px; border-radius: var(--radius-sm); border: 0;
  transition: color 0.12s ease, background 0.12s ease;
}
/* Hairline divider between rows (refined menu, not a stack of chips). */
.nav-ddi + .nav-ddi { border-top: 1px solid rgba(138, 109, 29, 0.22); box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.35); }
/* Menu-item hover: left gilt marker + faint tint — echoes the underline language. */
.nav-ddi::before {
  content: ""; position: absolute; left: 5px; top: 7px; bottom: 7px; width: 2px;
  background: var(--gold); border-radius: 1px; opacity: 0; transition: opacity 0.12s ease;
}
.nav-ddi:hover, .nav-ddi.active {
  color: var(--gold-bright);
  background: linear-gradient(90deg, rgba(201, 162, 39, 0.16), rgba(201, 162, 39, 0.04));
}
.nav-ddi:hover::before, .nav-ddi.active::before { opacity: 1; }
.nav-ddi.active::before { background: var(--gold-bright); }
.nav-ddi:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: -2px; border-radius: var(--radius-sm); }

/* hamburger toggle — hidden on desktop, shown on mobile (JS-injected) */
.nav-toggle {
  display: none; position: absolute; top: 10px; right: 4px; z-index: 122;
  width: 44px; height: 40px; align-items: center; justify-content: center;
  font-size: 1.4rem; color: var(--gold-bright); cursor: pointer; line-height: 1;
  background: linear-gradient(180deg, #43290f, #2a1a0a); border: 1px solid var(--gold-dark);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
}
.nav-toggle:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
@media (max-width: 980px) {
  .site-header .wrap { flex-wrap: wrap; min-height: 52px; }
  .nav-toggle { display: flex; }
  .brand::after { display: none; }   /* no vertical rule when the nav is a drawer */
  /* Collapse the whole bar into a vertical panel; sections expand in place. */
  .site-nav {
    display: none; flex-direction: column; align-items: stretch;
    width: 100%; margin: 0 0 10px; gap: 1px;
  }
  body.nav-open .site-nav { display: flex; }
  .site-header .wrap { height: auto; }
  .site-nav { height: auto; }
  .site-nav > * { height: auto; }
  .nav-item.nav-home { display: inline-flex; }
  .nav-search-label { position: static; width: auto; height: auto; margin: 0; clip: auto; overflow: visible; }
  .site-nav > * + *:not(.nav-cta) { border-left: none; box-shadow: none; }
  .nav-item { justify-content: flex-start; padding: 11px 12px; background: none; }
  .nav-item:hover, .nav-dd:hover .nav-dd-btn { background: none; }
  .nav-cta { align-self: stretch; justify-content: center; margin: 10px 12px 4px; }
  .nav-util .wrap { flex-wrap: wrap; justify-content: flex-end; }
  .site-nav > a:not(.nav-item):not(.nav-cta) { padding: 11px 12px; }
  /* Underline marker becomes a left rail in the drawer (a full-row bar would
     read as a divider). */
  .nav-item::after {
    left: 0; right: auto; top: 6px; bottom: 6px; width: 3px; height: auto;
    transform: scaleY(0); transform-origin: center;
  }
  .nav-item:hover::after, .nav-item.active::after,
  .nav-dd:hover .nav-dd-btn::after, .nav-dd.open .nav-dd-btn::after,
  .nav-dd .nav-dd-btn.active::after { transform: scaleY(1); box-shadow: none; }
  .nav-dd { position: static; display: block; }
  /* The dropdown trigger becomes an inert section label; its items list below it.
     Override the desktop `.nav-dd .nav-dd-btn { height:100% }` (≈line 326): with
     the parent now a block of indefinite height, 100% stretched the label to
     ~200px and overlapped the menu items. */
  .nav-dd .nav-dd-btn { height: auto; }
  .nav-dd-btn {
    pointer-events: none; color: var(--gold); font-weight: 700; font-size: 0.72rem;
    letter-spacing: 0.14em; padding: 12px 12px 3px; border: none; background: none;
  }
  .nav-dd-btn:hover, .nav-dd-btn.active { background: none; border: none; color: var(--gold); }
  .nav-dd-btn::after { display: none; }   /* section labels get no marker */
  .nav-dd-btn .caret { display: none; }
  .nav-dd-menu {
    position: static; transform: none; display: flex; padding: 0 0 6px 10px;
    border: none; box-shadow: none; background: none; min-width: 0;
    border-left: 1px solid rgba(138, 109, 29, 0.28); margin: 0 0 4px 6px;
  }
  .nav-dd-menu::before { display: none; }
  .nav-ddi { padding: 8px 12px; }
  .nav-ddi + .nav-ddi { border-top: 1px solid rgba(138, 109, 29, 0.14); box-shadow: none; }
}

/* ── parchment panels ─────────────────────────────────────────────── */
.frame {
  color: var(--ink);
  background-color: var(--parchment);
  /* Real aged-vellum texture (generated art, seamless) under the top-light
     sheen + corner shade, so panels read as mottled parchment, not flat cream. */
  background-image:
    radial-gradient(120% 80% at 15% -10%, rgba(255, 250, 228, 0.55), transparent 60%),
    radial-gradient(120% 90% at 90% 110%, rgba(140, 110, 60, 0.16), transparent 55%),
    url("/shared/img/parchment-tile.webp");
  background-size: auto, auto, 300px 300px;
  background-repeat: no-repeat, no-repeat, repeat;
  border: 1px solid var(--edge-dark);
  border-radius: var(--radius);
  box-shadow:
    inset 0 0 0 1px rgba(255, 252, 236, 0.45),   /* top-lit inner hairline */
    inset 0 0 22px rgba(120, 90, 40, 0.12),       /* warm inner shade */
    var(--shadow-panel);                          /* lift off the stone */
  padding: clamp(16px, 3.2vw, 24px) clamp(16px, 3.4vw, 26px);
  margin: var(--space-5) 0;
}
.frame > h2:first-child, .frame > h3:first-child, .frame > h1:first-child { margin-top: 2px; }

h1, h2, h3 {
  font-family: var(--font-ui);
  font-variant: small-caps;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.2;
  color: var(--blood);
  text-shadow: 0 1px 0 rgba(255, 248, 220, 0.55);
}
h1 { font-size: var(--fs-h1); margin: 0 0 var(--space-3); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }
/* Heraldic section rule: a small gold lozenge at the head of a fading gold rule
   — a subtle medieval-manuscript flourish under every section heading. */
h2::after {
  content: "";
  display: block;
  height: 9px;
  margin-top: 5px;
  background:
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='9'%20height='9'%3E%3Cpath%20d='M4.5%200.6%20L8.4%204.5%20L4.5%208.4%20L0.6%204.5%20Z'%20fill='%238a6d1d'%20stroke='%236b5015'%20stroke-width='0.6'/%3E%3C/svg%3E") left center / 9px 9px no-repeat,
    linear-gradient(90deg, var(--gold-dark) 0%, rgba(138, 109, 29, 0.25) 45%, transparent 75%) left 15px center / calc(100% - 15px) 2px no-repeat;
}
a { color: var(--link); text-underline-offset: 0.14em; }
a:hover { color: var(--blood); }
a:focus-visible { outline: 2px solid var(--gold-dark); outline-offset: 2px; border-radius: var(--radius-sm); }
small, .dim { color: var(--ink-dim); }
.dim { font-size: 0.95em; }

/* ── forms: carved wells + gilded plaque buttons ──────────────────── */
label {
  display: block; margin: var(--space-3) 0 var(--space-1);
  color: var(--ink-dim);
  font-variant: small-caps;
  letter-spacing: 0.04em;
  font-size: 0.9rem;
}
input, select, textarea {
  width: 100%;
  background: var(--parchment-inset);
  border: 1px solid #ad9760;
  border-radius: var(--radius-sm);
  color: var(--ink);
  padding: 0.5em 0.7em;
  font-size: var(--fs-body);
  font-family: var(--font-ui);
  box-shadow: var(--bevel-slot);
  transition: border-color 0.12s, box-shadow 0.12s, background 0.12s;
}
/* Placeholders default to the input's ink at low opacity (~3.3:1 — fails AA);
   pin them to --ink-dim at full opacity for 6.9:1 (opacity:1 needed for FF). */
input::placeholder, textarea::placeholder { color: var(--ink-dim); opacity: 1; }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  /* A real 2px gold-dark outline (≥3:1 on parchment — WCAG 2.4.11); the soft
     glow ring alone was ~1.2:1 and effectively invisible. */
  outline: 2px solid var(--gold-dark);
  outline-offset: 1px;
  border-color: var(--gold-dark);
  background: #f9f2dc;
  box-shadow: var(--bevel-slot), var(--ring);
}
/* Fallback for engines without :focus-visible (keeps a visible ring). */
input:focus, select:focus, textarea:focus { border-color: var(--gold-dark); }

button, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5em;
  background: linear-gradient(180deg, #f4d585 0%, #d9ad38 52%, #b0871f 100%);
  border: 1px solid #8a6d1d;
  border-radius: var(--radius);
  color: #3a2708;
  font-family: var(--font-ui);
  font-variant: small-caps;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 0.55em 1.2em;
  margin: var(--space-3) var(--space-2) 0 0;
  font-size: var(--fs-btn);
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
  text-shadow: 0 1px 0 rgba(255, 246, 214, 0.65);
  box-shadow: var(--bevel-btn), var(--shadow-sm);
  transition: filter 0.12s, transform 0.06s, box-shadow 0.12s;
}
button:hover, .btn:hover { filter: brightness(1.05); }
button:active, .btn:active {
  transform: translateY(1px);
  box-shadow: inset 0 1px 3px rgba(90, 60, 10, 0.45), 0 1px 2px rgba(0, 0, 0, 0.32);
}
button:focus-visible, .btn:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
button:disabled, .btn:disabled { opacity: 0.5; cursor: default; filter: grayscale(0.2); box-shadow: var(--shadow-sm); }

/* Quiet (secondary) plaque: aged parchment instead of gold. */
.btn-quiet {
  background: linear-gradient(180deg, #efe3bd, #d6c491);
  border-color: #b6a271;
  color: #5a4a2b;
  text-shadow: 0 1px 0 rgba(255, 253, 242, 0.6);
  box-shadow: inset 0 1px 0 rgba(255, 253, 242, 0.75), inset 0 -2px 3px rgba(120, 95, 45, 0.22), var(--shadow-sm);
}

/* Toggle / tab plaque: the inactive state used by tab bars across the site.
   Shared here so pages stop hand-rolling a `.off` style each (one source). */
button.off, .btn.off, .btn-toggle {
  background: linear-gradient(180deg, #6f5a38, #4d3d24);
  border-color: #40331e;
  color: #decca2;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
  box-shadow: inset 0 1px 0 rgba(255, 240, 200, 0.10), var(--shadow-sm);
}
button.off:hover, .btn.off:hover, .btn-toggle:hover { filter: brightness(1.1); }
.btn-toggle[aria-selected="true"], .btn-toggle.active {
  background: linear-gradient(180deg, #f4d585 0%, #d9ad38 52%, #b0871f 100%);
  border-color: #8a6d1d; color: #3a2708;
  text-shadow: 0 1px 0 rgba(255, 246, 214, 0.65);
  box-shadow: var(--bevel-btn), var(--shadow-sm);
}

/* ── cinematic key-art hero banner ────────────────────────────────────
   Painted vista behind an overlaid title/CTAs, gold-framed with a base
   scrim for legibility. Each page sets its own background-image inline. */
.hero-banner {
  position: relative; margin-top: var(--space-5); min-height: clamp(292px, 42vw, 366px);
  display: flex; align-items: flex-end;
  background-color: #14120f;
  background-size: cover; background-position: center 42%; background-repeat: no-repeat;
  /* A real gilded picture frame: solid gold border, then a dark seam, then a
     soft gilt hairline. The old treatment was a 55%-alpha inset ring that let
     the art bleed through and read as a glow, not a frame — and its 92%-black
     120px scrim swallowed most of the painting. Keep the scrim just strong
     enough for the CTA text sitting on the art. */
  border: 2px solid var(--gold-dark); border-radius: var(--radius);
  box-shadow:
    inset 0 0 0 1px rgba(12, 8, 3, 0.9),
    inset 0 0 0 2px rgba(236, 208, 111, 0.38),
    inset 0 -96px 84px -30px rgba(9, 7, 4, 0.8),
    var(--shadow-panel);
  overflow: hidden;
}
.hero-inner { padding: clamp(18px, 3vw, 26px); width: 100%; }
.hero-title { font-size: var(--fs-hero); margin: 0 0 8px; color: #f7ecc6; line-height: 1.05;
  text-shadow: 0 2px 0 #000, 0 4px 18px rgba(0, 0, 0, 0.85); }
.hero-sub { max-width: 560px; color: #ece0bd; font-size: clamp(1rem, 0.9rem + 0.5vw, 1.12rem); margin: 0 0 16px;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.95); }
.hero-cta { display: flex; gap: 10px; flex-wrap: wrap; }
.hero-cta .btn { font-size: 1.02rem; margin-top: 0; }
/* Still used by /play/'s hero (its live count isn't a duplicate there — the
   landing page's copy was removed in favour of the nav-util strip). */
.hero-count { margin: 12px 0 0; }
.hero-count small { color: #dcc790; text-shadow: 0 1px 5px #000; }

/* ── tables: carved-stone header band, ruled parchment rows ───────── */
table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
th, td { text-align: left; padding: 7px 11px; border: 1px solid #b09863; }
th {
  background: linear-gradient(180deg, #423e37, #23201b);
  color: var(--gold-bright);
  border-color: #16130f;
  font-variant: small-caps;
  font-weight: 700;
  letter-spacing: 0.08em;
  font-size: 0.82rem;
  text-shadow: 0 1px 0 #000;
  box-shadow: inset 0 1px 0 rgba(255, 240, 200, 0.10);
}
tr:nth-child(even) td { background: rgba(120, 90, 40, 0.09); }
tbody tr:hover td { background: rgba(201, 162, 39, 0.12); }
/* Wrap wide tables so they scroll inside themselves on narrow screens instead
   of forcing the page to scroll. Keeps real <table> semantics intact. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }

/* ── status bits ──────────────────────────────────────────────────── */
.pill {
  display: inline-block; padding: 0 8px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--parchment-inset);
  font-size: 0.75rem;
  font-variant: small-caps;
  letter-spacing: 0.05em;
  color: var(--ink-dim);
}
.pill.up { color: var(--good); border-color: var(--good); }
.pill.down { color: var(--bad); border-color: var(--bad); }
/* Darker than --gold-dark for AA on the parchment-inset pill (was 4.15:1). */
.pill.members { color: #6f5713; border-color: var(--gold-dark); }
.pill.deg { color: var(--warn); border-color: var(--warn); }

/* ── four-tier currency (copper / silver / gold / platinum) ──────────────
   A row of small coin badges: a metallic disc + the count. Rendered by
   IocCurrency.coins() so every value matches the in-game denomination math. */
.coins { display: inline-flex; gap: 5px; align-items: center; flex-wrap: wrap;
         font-variant-numeric: tabular-nums; }
.coin {
  display: inline-flex; align-items: center; position: relative;
  padding: 0 7px 0 21px; line-height: 1.65;
  font-size: 0.82rem; font-weight: 700; color: var(--ink);
  border: 1px solid var(--edge); border-radius: var(--radius-sm); background: var(--parchment-inset);
}
.coin::before {
  content: ""; position: absolute; left: 5px; top: 50%; transform: translateY(-50%);
  width: 12px; height: 12px; border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.4); box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.45);
}
.coin.copper::before   { background: radial-gradient(circle at 34% 30%, #e69a5c, #9c4e1b); }
.coin.silver::before   { background: radial-gradient(circle at 34% 30%, #f2f4f7, #979da8); }
.coin.gold::before     { background: radial-gradient(circle at 34% 30%, #ffe288, #c39d1e); }
.coin.platinum::before { background: radial-gradient(circle at 34% 30%, #ffffff, #b6cbdd); }

.msg { padding: 9px 12px; margin: var(--space-3) 0; font-size: 0.9rem; display: none;
       border: 1px solid; border-radius: var(--radius-sm); }
.msg.err { display: block; background: #e6c1ae; border-color: var(--bad); color: #5d1410; }
.msg.ok { display: block; background: #d3dcb0; border-color: var(--good); color: #2c4416; }

.codes { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; margin: var(--space-4) 0; }
.codes code {
  background: var(--parchment-inset);
  border: 1px dashed var(--edge);
  border-radius: var(--radius-sm);
  color: var(--ink);
  padding: 7px 10px; text-align: center;
  font-size: 0.95rem; letter-spacing: 0.08em;
  font-family: "Courier New", monospace;
  font-weight: 700;
}

.steps { display: none; }
.steps.active { display: block; }

/* ── newsletter signup widget (shared, injected by IocNewsletter) ──── */
.nl-form .nl-row { display: flex; gap: 8px; align-items: stretch; }
.nl-form .nl-row input { margin: 0; }
.nl-form .nl-row button { margin: 0; white-space: nowrap; }
.nl-consent {
  display: flex; gap: 8px; align-items: flex-start;
  margin: 8px 0 0; font-variant: normal; letter-spacing: normal;
  font-size: 0.82rem; color: var(--ink-dim);
}
.nl-consent input { width: auto; margin: 2px 0 0; flex: 0 0 auto; }
.nl-msg { margin-top: 8px; }

/* ── footer: timber beam (shared texture) ─────────────────────────── */
body > main { flex: 1 0 auto; width: 100%; padding-bottom: var(--space-6); }
.site-footer {
  margin-top: auto;   /* sticky-footer partner: pushes to the column's end
                         (the content gap comes from main's padding-bottom) */
  border-top: 3px solid var(--gold-dark);
  padding: var(--space-5) 0 30px;
  font-size: 0.82rem;
  color: #c3ac78;
  background-color: #221607;
  background-image:
    linear-gradient(180deg, rgba(64, 42, 20, 0.35), rgba(14, 9, 3, 0.72)),
    var(--tex-timber);
  background-size: auto, 300px 300px;
  box-shadow: inset 0 4px 0 rgba(201, 162, 39, 0.22);
  text-shadow: 0 1px 0 #000;
}
.site-footer a { color: #e0c98d; }
.site-footer a:hover { color: var(--gold-bright); }
.site-footer .wrap { display: flex; flex-direction: column; gap: 12px; }

/* Link columns: the structured directory above the legal strip. */
.footer-cols {
  /* Explicit tracks: auto-fit repeat() is INVALID next to an fr track (the
     whole template gets dropped and the columns stack). Brand + 5 columns. */
  display: grid; grid-template-columns: 1.6fr repeat(5, 1fr);
  gap: 18px clamp(14px, 3vw, 30px);
  padding-bottom: 16px; margin-bottom: 2px;
  border-bottom: 1px solid rgba(138, 109, 29, 0.22);
}
@media (max-width: 900px) {
  .footer-cols { grid-template-columns: repeat(3, 1fr); }
  .f-brand { grid-column: 1 / -1; }
}
.f-brand strong {
  display: block; color: var(--gold-bright); font-variant: small-caps;
  font-size: 1.05rem; letter-spacing: 0.1em; margin: 4px 0 6px;
}
.f-mark {
  display: block; width: 34px; height: 42px;
  background: url("/shared/img/emblem-crest.webp") center / contain no-repeat;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
}
.f-brand p { margin: 0; font-size: 0.78rem; color: #a68f5f; line-height: 1.55; max-width: 30ch; }
.f-col h4 {
  margin: 2px 0 7px; font-variant: small-caps; font-weight: 700;
  font-size: 0.74rem; letter-spacing: 0.13em; color: var(--gold);
}
.f-col a {
  display: block; padding: 2.5px 0; font-size: 0.8rem;
  color: #c3ac78; text-decoration: none;
}
.f-col a:hover { color: var(--gold-bright); text-decoration: underline; }
@media (max-width: 640px) {
  .footer-cols { grid-template-columns: repeat(2, 1fr); }
}
.footer-main { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; justify-content: space-between; }
.footer-links { display: inline-flex; flex-wrap: wrap; gap: 4px 8px; }

/* Age-rating strip (self-assessed; full breakdown on /ratings/). */
.footer-ratings { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  padding-bottom: 9px; border-bottom: 1px solid rgba(138, 109, 29, 0.22); }
.rating-badges { display: inline-flex; gap: 6px; text-decoration: none; }
.rating-badge { display: inline-flex; align-items: center; gap: 5px; font-variant: small-caps;
  font-size: 0.72rem; letter-spacing: 0.04em; padding: 2px 8px; border: 1px solid var(--gold-dark);
  border-radius: 3px; color: #e8d49a; background: rgba(0, 0, 0, 0.28); white-space: nowrap; }
.rating-badge b { font-weight: 700; color: var(--gold-bright); }
.rating-badges:hover .rating-badge { border-color: var(--gold-bright); }
.rating-note { font-size: 0.76rem; color: #a68f5f; }

/* ── promo band: three art tiles under the hero (home page) ────────── */
.promo-band { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin: var(--space-5) 0; }
.promo-tile {
  position: relative; display: flex; align-items: flex-end;
  min-height: 118px; padding: 12px 14px; text-decoration: none;
  border: 1px solid var(--gold-dark); border-radius: var(--radius);
  background-size: cover; background-position: center;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.55), var(--shadow-panel);
  overflow: hidden; isolation: isolate;
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}
.promo-tile::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(10, 6, 2, 0.05) 30%, rgba(10, 6, 2, 0.78) 82%);
  transition: background 0.16s ease;
}
.promo-tile:hover { transform: translateY(-2px); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.55), 0 10px 24px rgba(0, 0, 0, 0.55); }
.promo-tile:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
.promo-tile b {
  color: #f4e7bd; font-variant: small-caps; font-weight: 700;
  letter-spacing: 0.08em; font-size: 1.02rem; line-height: 1.15;
  text-shadow: 0 1px 2px #000, 0 0 14px rgba(0, 0, 0, 0.7);
}
.promo-tile small { display: block; color: #cdb277; font-size: 0.74rem; letter-spacing: 0.02em; margin-top: 2px; text-shadow: 0 1px 2px #000; }
@media (max-width: 640px) { .promo-band { grid-template-columns: 1fr; } .promo-tile { min-height: 92px; } }

/* ── responsive: fluid tokens carry most of it; a couple of tightenings ─ */
@media (max-width: 600px) {
  h2::after { margin-top: 3px; }
  .site-header .wrap { padding-top: 8px; padding-bottom: 8px; }
  .nl-form .nl-row { flex-wrap: wrap; }
  button, .btn { padding: 0.55em 1em; }
}

/* ── respect reduced-motion (WCAG 2.3.3) ──────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
