/* The Adventurers Guild — theadventurersguild.co
   Palette and type derived from the crest. See docs/brand.md. */

/* Display face: Cinzel (SIL Open Font License) — a Trajan-style Roman capital that
   matches the banner lettering on the crest. NOT YET INSTALLED: the site currently
   falls back to the serif stack in --display below, which is a close enough match.
   To activate, drop cinzel-600.woff2 and cinzel-700.woff2 into assets/fonts/ and
   uncomment this block. Self-hosted deliberately — no third-party font CDN request.

@font-face {
  font-family: 'Cinzel';
  src: url('../fonts/cinzel-600.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Cinzel';
  src: url('../fonts/cinzel-700.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}
*/

:root {
  --void: #06070a;
  --ink: #0d1526;
  --navy: #152440;
  --navy-lift: #1e3357;
  --line: #2a3e63;
  --gold: #c8a34e;
  --gold-bright: #f2dc9b;
  --gold-deep: #8a6a28;
  --cream: #f2ede1;
  --muted: #a2aec4;

  --display: 'Cinzel', 'Trajan Pro', 'Optima', Georgia, 'Times New Roman', serif;
  --body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  --wrap: 1140px;
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --radius: 10px;
  --gold-rule: linear-gradient(90deg, transparent, var(--gold-deep) 15%, var(--gold) 50%, var(--gold-deep) 85%, transparent);
}

*,
*::before,
*::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--void);
  color: var(--cream);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

/* Faint radial vignette echoing the crest's lit-on-black composition */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(ellipse 80% 55% at 50% 0%, rgba(200, 163, 78, 0.07), transparent 70%);
}

body > * { position: relative; z-index: 1; }

img { max-width: 100%; height: auto; display: block; }

a { color: var(--gold-bright); text-decoration-color: rgba(200, 163, 78, 0.4); text-underline-offset: 3px; }
a:hover { color: var(--gold); }

:focus-visible {
  outline: 2px solid var(--gold-bright);
  outline-offset: 3px;
  border-radius: 4px;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: 0.02em;
  margin: 0 0 0.5em;
  color: var(--cream);
}

h1 { font-size: clamp(2.1rem, 5.5vw, 3.6rem); letter-spacing: 0.04em; }
h2 { font-size: clamp(1.5rem, 3.2vw, 2.2rem); }
h3 { font-size: 1.15rem; letter-spacing: 0.03em; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--gold);
  color: var(--void);
  padding: 0.6rem 1rem;
  font-weight: 600;
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------- Eyebrow / rules ---------- */

.eyebrow {
  font-family: var(--display);
  font-size: 0.78rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 0.9rem;
}

.rule {
  height: 1px;
  border: 0;
  background: var(--gold-rule);
  margin: 0;
  opacity: 0.55;
}

/* ---------- Header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(6, 7, 10, 0.88);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(42, 62, 99, 0.7);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 68px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  color: var(--cream);
}

.brand__crest {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex: none;
}

.brand__name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.98rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  line-height: 1.15;
}

.brand__name span {
  display: block;
  font-family: var(--body);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  color: var(--gold);
  font-weight: 500;
}

.nav {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
}

.nav a {
  display: inline-block;
  padding: 0.45rem 0.75rem;
  font-size: 0.86rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--muted);
  text-decoration: none;
  border-radius: 6px;
}

.nav a:hover { color: var(--cream); background: rgba(30, 51, 87, 0.55); }
.nav a[aria-current='page'] { color: var(--gold-bright); }

.nav__cta {
  margin-left: 0.35rem;
  border: 1px solid var(--gold-deep);
  color: var(--gold-bright) !important;
}
.nav__cta:hover { background: rgba(200, 163, 78, 0.12) !important; border-color: var(--gold); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.8rem 1.5rem;
  font-family: var(--body);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 6px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.btn:hover { transform: translateY(-1px); }

.btn--gold {
  background: linear-gradient(180deg, var(--gold-bright), var(--gold) 45%, var(--gold-deep));
  color: #1a1204;
  box-shadow: 0 2px 14px rgba(200, 163, 78, 0.22);
}
.btn--gold:hover { color: #1a1204; box-shadow: 0 6px 22px rgba(200, 163, 78, 0.34); }

.btn--ghost {
  border-color: var(--line);
  color: var(--cream);
  background: rgba(21, 36, 64, 0.5);
}
.btn--ghost:hover { border-color: var(--gold-deep); color: var(--gold-bright); }

/* ---------- Hero ---------- */

.hero {
  padding: clamp(3rem, 8vw, 6.5rem) 0 clamp(2.5rem, 6vw, 4.5rem);
  text-align: center;
}

.hero__crest {
  width: min(340px, 72vw);
  margin: 0 auto clamp(1.2rem, 3vw, 2rem);
  filter: drop-shadow(0 10px 40px rgba(200, 163, 78, 0.18));
}

.hero__tagline {
  font-family: var(--display);
  font-size: clamp(0.8rem, 2vw, 0.95rem);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 1.6rem;
}

.hero__lede {
  max-width: 46rem;
  margin: 0 auto 2rem;
  font-size: clamp(1.03rem, 2vw, 1.2rem);
  color: var(--muted);
}

.hero__lede strong { color: var(--cream); font-weight: 600; }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  justify-content: center;
}

/* ---------- Countdown ---------- */

.countdown-panel {
  max-width: 40rem;
  margin: 0 auto clamp(1.8rem, 4vw, 2.6rem);
  padding: 1.6rem 1.4rem 1.5rem;
  border: 1px solid var(--gold-deep);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(200, 163, 78, 0.1), rgba(21, 36, 64, 0.55));
  text-align: center;
}

.countdown-panel__label {
  font-family: var(--display);
  font-size: 0.75rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 1rem;
}

.countdown-panel__units {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.6rem;
  margin-bottom: 0.9rem;
}

.cd-unit {
  background: rgba(6, 7, 10, 0.55);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.7rem 0.3rem 0.55rem;
}

.cd-unit__value {
  display: block;
  font-family: var(--display);
  font-size: clamp(1.6rem, 5.5vw, 2.5rem);
  font-weight: 700;
  line-height: 1;
  color: var(--gold-bright);
  font-variant-numeric: tabular-nums;
}

.cd-unit__label {
  display: block;
  font-size: 0.63rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 0.4rem;
}

.countdown-panel__when {
  font-size: 0.9rem;
  color: var(--cream);
  margin: 0;
}

.countdown-panel__when strong { color: var(--gold-bright); }

.countdown-panel--open .countdown-panel__units { display: none; }

.countdown-bar {
  background: linear-gradient(90deg, rgba(200, 163, 78, 0.13), rgba(200, 163, 78, 0.05));
  border-bottom: 1px solid rgba(138, 106, 40, 0.7);
  font-size: 0.84rem;
  text-align: center;
  padding: 0.6rem var(--gutter);
}

.countdown-bar__label {
  font-family: var(--display);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
  font-size: 0.72rem;
  margin-right: 0.6rem;
}

.countdown-bar strong { color: var(--gold-bright); font-variant-numeric: tabular-nums; }

/* ---------- Sections ---------- */

.section { padding: clamp(3rem, 7vw, 5.5rem) 0; }
.section--ink { background: var(--ink); border-block: 1px solid rgba(42, 62, 99, 0.5); }

.section__head { max-width: 44rem; margin-bottom: clamp(2rem, 4vw, 3rem); }
.section__head--center { margin-inline: auto; text-align: center; }
.section__head p { color: var(--muted); margin-bottom: 0; }

/* ---------- Value proposition grid ---------- */

.pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
  gap: 1.1rem;
}

.pillar {
  position: relative;
  background: linear-gradient(180deg, var(--navy), rgba(13, 21, 38, 0.9));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.7rem 1.5rem;
  overflow: hidden;
}

.pillar::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: var(--gold-rule);
  opacity: 0.7;
}

.pillar__num {
  font-family: var(--display);
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  color: var(--gold);
  display: block;
  margin-bottom: 0.7rem;
}

.pillar h3 { margin-bottom: 0.55rem; }
.pillar p { color: var(--muted); font-size: 0.95rem; margin-bottom: 0; }

/* ---------- Stat strip ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.stat { background: var(--ink); padding: 1.6rem 1.3rem; text-align: center; }

.stat__value {
  font-family: var(--display);
  font-size: clamp(1.8rem, 4vw, 2.5rem);
  font-weight: 700;
  color: var(--gold-bright);
  line-height: 1;
  display: block;
  margin-bottom: 0.45rem;
}

.stat__label {
  font-size: 0.82rem;
  color: var(--muted);
  letter-spacing: 0.04em;
  margin: 0;
}

/* ---------- Release schedule (auto-updating) ---------- */

.releases { display: grid; gap: 0.9rem; }

.release {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 1.2rem;
  align-items: start;
  background: var(--navy);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.4rem;
}

.release--next { border-left-color: var(--gold); background: linear-gradient(100deg, rgba(200, 163, 78, 0.09), var(--navy) 45%); }
.release--past { opacity: 0.42; }

.release__date {
  font-family: var(--display);
  text-align: center;
  min-width: 4.2rem;
  line-height: 1.1;
}

.release__month {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}

.release__day { display: block; font-size: 1.75rem; font-weight: 700; }
.release__year { display: block; font-size: 0.7rem; color: var(--muted); letter-spacing: 0.1em; }

.release__body h3 { margin-bottom: 0.25rem; font-family: var(--body); font-weight: 600; font-size: 1.05rem; letter-spacing: 0; }
.release__sub { font-size: 0.82rem; color: var(--gold); margin: 0 0 0.5rem; letter-spacing: 0.04em; }
.release__notes { font-size: 0.9rem; color: var(--muted); margin: 0; }

.release__meta {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 0.55rem 0 0;
  padding-top: 0.55rem;
  border-top: 1px dashed rgba(42, 62, 99, 0.9);
}

.release__aside { text-align: right; display: grid; gap: 0.45rem; justify-items: end; }

.countdown {
  font-family: var(--display);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-bright);
  white-space: nowrap;
}

.tag {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.22rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--muted);
  white-space: nowrap;
}

.tag--mtg { border-color: #4a5da8; color: #9fb0ee; }
.tag--onepiece { border-color: #a8564a; color: #eda093; }
.tag--pokemon { border-color: var(--gold-deep); color: var(--gold); }
.tag--live { border-color: var(--gold); color: var(--void); background: var(--gold); }

/* ---------- Event calendar ---------- */

.events { display: grid; gap: 0.9rem; }

.event {
  display: grid;
  grid-template-columns: 5.5rem 1fr auto;
  gap: 1.2rem;
  align-items: center;
  background: var(--navy);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.1rem 1.35rem;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.event:hover { border-color: var(--gold-deep); background: var(--navy-lift); }
.event--today { border-color: var(--gold); box-shadow: inset 3px 0 0 var(--gold); }

.event__when { font-family: var(--display); line-height: 1.2; }
.event__weekday { display: block; font-size: 0.95rem; font-weight: 700; letter-spacing: 0.06em; }
.event__date { display: block; font-size: 0.75rem; color: var(--gold); letter-spacing: 0.08em; }
.event__time { display: block; font-family: var(--body); font-size: 0.78rem; color: var(--muted); margin-top: 0.2rem; }

.event__body h3 { margin-bottom: 0.2rem; font-family: var(--body); font-weight: 600; font-size: 1.02rem; letter-spacing: 0; }
.event__format { font-size: 0.8rem; color: var(--gold); margin: 0 0 0.35rem; }
.event__blurb { font-size: 0.9rem; color: var(--muted); margin: 0; }

.event__entry {
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--gold-bright);
  white-space: nowrap;
}

/* ---------- Buylist rates ---------- */

.rates {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 1.1rem;
}

.rate {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.8rem 1.5rem;
  text-align: center;
  background: var(--navy);
}

.rate__pct {
  font-family: var(--display);
  font-size: clamp(2.6rem, 7vw, 3.6rem);
  font-weight: 700;
  color: var(--gold-bright);
  line-height: 1;
  display: block;
}

.rate__pct sup { font-size: 0.4em; top: -0.9em; }
.rate h3 { margin: 0.7rem 0 0.4rem; }
.rate p { font-size: 0.9rem; color: var(--muted); margin: 0; }

.notice {
  border: 1px solid var(--gold-deep);
  background: rgba(200, 163, 78, 0.07);
  border-radius: var(--radius);
  padding: 1.2rem 1.4rem;
  font-size: 0.93rem;
  color: var(--cream);
}

.notice strong { color: var(--gold-bright); }

/* ---------- Steps ---------- */

.steps { list-style: none; counter-reset: step; padding: 0; margin: 0; display: grid; gap: 1rem; }

.steps li {
  counter-increment: step;
  position: relative;
  padding-left: 3.2rem;
  color: var(--muted);
  font-size: 0.96rem;
}

.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: -0.15rem;
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-weight: 700;
  color: var(--gold);
  border: 1px solid var(--gold-deep);
  border-radius: 50%;
}

.steps strong { color: var(--cream); display: block; font-weight: 600; }

/* ---------- Visit / info ---------- */

.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 1.5rem;
}

.hours-table { width: 100%; border-collapse: collapse; font-size: 0.94rem; }
.hours-table th, .hours-table td { text-align: left; padding: 0.55rem 0; border-bottom: 1px solid rgba(42, 62, 99, 0.6); }
.hours-table th { font-weight: 500; color: var(--muted); }
.hours-table td { text-align: right; color: var(--cream); font-variant-numeric: tabular-nums; }
.hours-table tr[data-today] th { color: var(--gold-bright); font-weight: 600; }
.hours-table tr[data-today] td { color: var(--gold-bright); }

address { font-style: normal; color: var(--muted); }
address strong { color: var(--cream); display: block; font-size: 1.05rem; margin-bottom: 0.3rem; }

/* ---------- CTA band ---------- */

.cta-band {
  text-align: center;
  padding: clamp(3rem, 7vw, 5rem) 0;
  background: linear-gradient(180deg, var(--ink), var(--void));
  border-top: 1px solid var(--line);
}

/* ---------- Footer ---------- */

.site-footer {
  border-top: 1px solid rgba(42, 62, 99, 0.6);
  padding: 2.5rem 0 3rem;
  font-size: 0.86rem;
  color: var(--muted);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  gap: 1.8rem;
  margin-bottom: 2rem;
}

.site-footer h4 {
  font-size: 0.74rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 0.7rem;
}

.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.site-footer a { text-decoration: none; color: var(--muted); }
.site-footer a:hover { color: var(--gold-bright); }

.site-footer__base {
  padding-top: 1.5rem;
  border-top: 1px solid rgba(42, 62, 99, 0.5);
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  justify-content: space-between;
  font-size: 0.8rem;
}

/* ---------- Utility ---------- */

.muted { color: var(--muted); }
.center { text-align: center; }
.stack > * + * { margin-top: 1.1rem; }
.mt-lg { margin-top: clamp(2rem, 4vw, 3rem); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Responsive ---------- */

@media (max-width: 720px) {
  .site-header__inner { flex-wrap: wrap; padding-block: 0.7rem; }
  .nav { width: 100%; justify-content: flex-start; gap: 0.15rem; }
  .nav a { padding: 0.4rem 0.55rem; font-size: 0.8rem; }
  .release { grid-template-columns: auto 1fr; }
  .release__aside { grid-column: 1 / -1; justify-items: start; text-align: left; flex-direction: row; display: flex; gap: 0.6rem; align-items: center; }
  .event { grid-template-columns: 4.6rem 1fr; }
  .event__entry { grid-column: 1 / -1; text-align: left; font-size: 1rem; }
}

/* ---------- Game filter pills ---------- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin-bottom: 1.4rem;
}

.filter {
  font-family: var(--body);
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.filter:hover { color: var(--cream); border-color: var(--gold-deep); }

.filter.is-active {
  color: var(--void);
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  border-color: var(--gold);
  font-weight: 600;
}

/* ---------- Game tags ---------- */

.tag--mtg        { border-color: #4a5da8; color: #9fb0ee; }
.tag--onepiece   { border-color: #a8564a; color: #eda093; }
.tag--pokemon    { border-color: #a8944a; color: #ecdc93; }
.tag--yugioh     { border-color: #c2478f; color: #f0a6d0; }
.tag--lorcana    { border-color: #6a4aa8; color: #c0a8ee; }
.tag--riftbound  { border-color: #2f7f80; color: #86d8d9; }
.tag--dragonball { border-color: #a87a4a; color: #edc493; }
.tag--gundam     { border-color: #4a7aa8; color: #93c4ed; }

.tag--new  { border-color: #3f8a5c; color: #8fe0ae; }
.tag--soon { border-color: var(--gold-deep); color: var(--gold-bright); }

/* ---------- Event extras ---------- */

.event__facts { font-size: 0.82rem; color: var(--gold); margin: 0 0 0.35rem; }

.event__aside { display: grid; gap: 0.45rem; justify-items: end; }

.event__link {
  font-family: var(--body);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.3rem 0.6rem;
  cursor: pointer;
  white-space: nowrap;
}

.event__link { text-decoration: none; text-align: center; }
.event__link:hover { color: var(--gold-bright); border-color: var(--gold-deep); }

/* ---------- Buylist: what we're chasing ---------- */

.wants {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 1rem;
}

.want {
  background: var(--navy);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line);
  border-radius: var(--radius);
  padding: 1.3rem 1.4rem;
}

.want--high { border-left-color: var(--gold); }

.want__head { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.7rem; }

.want h3 { font-family: var(--body); font-weight: 600; font-size: 1.02rem; letter-spacing: 0; margin-bottom: 0.35rem; }
.want p { font-size: 0.9rem; color: var(--muted); margin: 0; }

/* ---------- Condition guide ---------- */

.conditions { display: grid; gap: 0.7rem; }

.condition {
  display: grid;
  grid-template-columns: 3.6rem 1fr auto;
  gap: 1.1rem;
  align-items: center;
  background: var(--navy);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem 1.3rem;
}

.condition__grade {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  color: var(--gold-bright);
  text-align: center;
}

.condition__body h3 { font-family: var(--body); font-weight: 600; font-size: 0.98rem; letter-spacing: 0; margin-bottom: 0.2rem; }
.condition__body p { font-size: 0.88rem; color: var(--muted); margin: 0; }

.condition__effect {
  font-size: 0.82rem;
  color: var(--gold);
  text-align: right;
  max-width: 12rem;
}

/* ---------- Rank ladder ---------- */

.ranks { display: grid; gap: 0.9rem; counter-reset: rank; }

.rank {
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  gap: 1.3rem;
  align-items: start;
  background: linear-gradient(100deg, rgba(200, 163, 78, 0.05), var(--navy) 40%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.4rem 1.5rem;
}

.rank--capstone { border-color: var(--gold-deep); background: linear-gradient(100deg, rgba(200, 163, 78, 0.14), var(--navy) 55%); }

.rank__sigil {
  width: 4.5rem;
  height: 4.5rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--gold-deep);
  border-radius: 50%;
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--gold-bright);
  background: rgba(6, 7, 10, 0.5);
}

.rank__name { font-family: var(--display); font-size: 1.2rem; letter-spacing: 0.06em; margin-bottom: 0.15rem; }
.rank__req { font-size: 0.8rem; color: var(--gold); letter-spacing: 0.06em; text-transform: uppercase; margin: 0 0 0.6rem; }
.rank ul { margin: 0; padding-left: 1.1rem; color: var(--muted); font-size: 0.92rem; }
.rank li { margin-bottom: 0.3rem; }

/* ---------- Forms ---------- */

.form { display: grid; gap: 1rem; max-width: 42rem; }

.form__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 1rem; }

.field { display: grid; gap: 0.35rem; }

.field > label {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--gold);
}

.field input,
.field select,
.field textarea {
  font-family: var(--body);
  font-size: 0.95rem;
  color: var(--cream);
  background: rgba(6, 7, 10, 0.55);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.7rem 0.85rem;
  width: 100%;
}

.field textarea { resize: vertical; min-height: 8rem; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(200, 163, 78, 0.16);
}

.field select option { background: var(--ink); color: var(--cream); }

.field__hint { font-size: 0.8rem; color: var(--muted); }

/* Honeypot — hidden from humans, catches bots. */
.field--trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-status {
  border-radius: 6px;
  padding: 0.8rem 1rem;
  font-size: 0.92rem;
  border: 1px solid var(--line);
}

.form-status.is-ok { border-color: #3f8a5c; color: #8fe0ae; background: rgba(63, 138, 92, 0.1); }
.form-status.is-error { border-color: #a8564a; color: #eda093; background: rgba(168, 86, 74, 0.1); }

details summary { cursor: pointer; }

@media (max-width: 720px) {
  .condition { grid-template-columns: 3rem 1fr; }
  .condition__effect { grid-column: 1 / -1; text-align: left; max-width: none; }
  .rank { grid-template-columns: 1fr; }
  .event__aside { justify-items: start; }
}

/* ---------- Game grid ---------- */

.game-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
  gap: 0.7rem;
}

.game-grid li {
  position: relative;
  background: var(--navy);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.95rem 1.1rem 0.95rem 2.4rem;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--cream);
}

.game-grid li::before {
  content: '';
  position: absolute;
  left: 1.1rem;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--gold);
}

/* Footer lists reuse the same hook but stay plain text. */
.site-footer .game-grid {
  display: grid;
  gap: 0.4rem;
  grid-template-columns: 1fr;
}

.site-footer .game-grid li {
  background: none;
  border: 0;
  padding: 0;
  font-size: 0.86rem;
  font-weight: 400;
  color: var(--muted);
}

.site-footer .game-grid li::before { display: none; }

/* ---------- Rank ladder: F → SSS ---------- */

.rank__sigil {
  font-size: 1.6rem;
  letter-spacing: 0.04em;
}

/* SS and SSS need to shrink to stay inside the disc. */
.rank--long .rank__sigil { font-size: 1.15rem; letter-spacing: 0.02em; }

/* A and above read as prestige tiers. */
.rank--prestige {
  border-color: var(--gold-deep);
  background: linear-gradient(100deg, rgba(200, 163, 78, 0.13), var(--navy) 55%);
}

.rank--prestige .rank__sigil {
  border-color: var(--gold);
  background: linear-gradient(180deg, rgba(242, 220, 155, 0.16), rgba(6, 7, 10, 0.6));
  box-shadow: 0 0 18px rgba(200, 163, 78, 0.2);
}

.rank__letter {
  display: inline-block;
  font-family: var(--body);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--gold);
  border: 1px solid var(--gold-deep);
  border-radius: 4px;
  padding: 0.1rem 0.4rem;
  vertical-align: middle;
  margin-left: 0.4rem;
}

.rank__bonus {
  margin: 0 0 0.7rem;
  padding: 0.7rem 0.9rem;
  border-left: 2px solid var(--gold);
  background: rgba(200, 163, 78, 0.07);
  border-radius: 0 6px 6px 0;
  font-size: 0.92rem;
  color: var(--cream);
}

.rank__bonus span {
  display: block;
  font-family: var(--display);
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 0.25rem;
}

/* ---------- Brand wall ---------- */

.game-wall {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  gap: 0.9rem;
}

.game-tile {
  position: relative;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0.25rem;
  min-height: 118px;
  padding: 1.4rem 1.1rem;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background:
    radial-gradient(ellipse 120% 90% at 50% 0%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 70%),
    var(--navy);
  overflow: hidden;
  transition: border-color 0.18s ease, transform 0.18s ease;
}

.game-tile:hover {
  border-color: color-mix(in srgb, var(--accent) 60%, var(--line));
  transform: translateY(-2px);
}

.game-tile__bar {
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
}

.game-tile__short {
  font-family: var(--display);
  font-size: 1.28rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--cream);
  line-height: 1.1;
}

.game-tile__full {
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--accent) 75%, var(--cream));
}

.game-tile__logo {
  max-width: 100%;
  max-height: 72px;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* Fallback for browsers without color-mix(). */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .game-tile { background: var(--navy); }
  .game-tile__full { color: var(--gold); }
  .game-tile:hover { border-color: var(--gold-deep); }
}

/* ---------- Social links ---------- */

.socials {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  justify-content: center;
}

.social {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.7rem 1.2rem;
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--cream);
  text-decoration: none;
  background: var(--navy);
  border: 1px solid var(--line);
  border-radius: 999px;
  transition: border-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.social:hover {
  color: var(--gold-bright);
  border-color: var(--gold-deep);
  transform: translateY(-1px);
}

.social__icon {
  width: 20px;
  height: 20px;
  fill: currentColor;
  flex: none;
}

/* Footer variant: icon-led, no chrome. */
.social--compact {
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  font-weight: 400;
  font-size: 0.86rem;
  color: var(--muted);
  gap: 0.45rem;
}

.social--compact:hover { transform: none; border: 0; }
.social--compact .social__icon { width: 17px; height: 17px; }

.socials--footer { justify-content: flex-start; gap: 0.4rem; flex-direction: column; align-items: flex-start; }

/* ---------- Instagram feed ---------- */

.ig-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 190px), 1fr));
  gap: 0.7rem;
}

.ig-item { position: relative; }

.ig-link {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--navy);
  text-decoration: none;
}

.ig-link:hover { border-color: var(--gold-deep); }

.ig-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.35s ease, opacity 0.2s ease;
}

.ig-link:hover .ig-img { transform: scale(1.05); opacity: 0.55; }

.ig-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 1.9rem;
  color: rgba(242, 237, 225, 0.9);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.7);
  pointer-events: none;
}

.ig-caption {
  position: absolute;
  inset: auto 0 0;
  padding: 2.2rem 0.85rem 0.8rem;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--cream);
  background: linear-gradient(180deg, transparent, rgba(6, 7, 10, 0.92));
  opacity: 0;
  transition: opacity 0.25s ease;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ig-link:hover .ig-caption,
.ig-link:focus-visible .ig-caption { opacity: 1; }

/* Touch devices get no hover, so keep the caption visible but subtle. */
@media (hover: none) {
  .ig-caption { opacity: 1; -webkit-line-clamp: 2; font-size: 0.72rem; }
  .ig-link:hover .ig-img { transform: none; opacity: 1; }
}

.ig-meta {
  font-size: 0.8rem;
  color: var(--muted);
  letter-spacing: 0.04em;
}

/* ---------- Journal ---------- */

.wrap--article { max-width: 46rem; }

.crumbs {
  font-size: 0.8rem;
  color: var(--muted);
  letter-spacing: 0.04em;
  margin-bottom: 1.2rem;
}
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--gold-bright); }
.crumbs span[aria-hidden] { opacity: 0.5; margin: 0 0.35rem; }

.post-meta { font-size: 0.85rem; color: var(--muted); margin: 0 0 1rem; }

.tagrow { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.tagrow .tag { text-decoration: none; }
.tagrow .tag:hover { border-color: var(--gold); color: var(--gold-bright); }

.posts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: 1.1rem;
}

.post-card {
  background: var(--navy);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  transition: border-color 0.15s ease, transform 0.15s ease;
  overflow: hidden;
}
.post-card:hover { border-color: var(--gold-deep); transform: translateY(-2px); }

/* Thumbnail plate. Bleeds to the card edges, so it cancels the card padding
   rather than sitting inside it. Aspect ratio is fixed to the generated
   1200x630 so the grid does not reflow as images decode. */
.post-card__thumb {
  display: block;
  margin: -1.5rem -1.5rem 0;
  border-bottom: 1px solid var(--line);
  background: var(--ink);
  line-height: 0;
}
.post-card__thumb img {
  width: 100%;
  height: auto;
  aspect-ratio: 1200 / 630;
  object-fit: cover;
  display: block;
}

/* Spacing inside the card is deliberately uneven, not a single flex gap. A
   uniform gap put the date as far from the headline as the headline was from
   the body copy, which reads as a flat undifferentiated stack. The date is a
   kicker for the title, so it sits close to it; the full-bleed image needs a
   proper margin under it or the date looks stuck to the artwork; and the tags
   are pinned to the bottom so a two-line tag row does not float in the middle
   of the leftover space in a stretched grid cell. */
.post-card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding-top: 1.2rem;
}
.post-card__body .post-card__date { margin-bottom: 0.3rem; }
.post-card .post-card__body > h3 { margin-bottom: 0.55rem; }
.post-card__body > p:not(.post-card__date) { flex: 0 1 auto; margin-bottom: 1.1rem; }
.post-card__body .tagrow { margin-top: auto; }

/* Article lead plate */
.post-hero {
  margin: 1.6rem 0 2.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--ink);
  line-height: 0;
}
.post-hero img { width: 100%; height: auto; display: block; }
.post-card__date { font-size: 0.76rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gold); margin: 0; }
.post-card h3 { font-family: var(--body); font-size: 1.08rem; font-weight: 600; letter-spacing: 0; margin: 0; line-height: 1.35; }
.post-card h3 a { color: var(--cream); text-decoration: none; }
.post-card h3 a:hover { color: var(--gold-bright); }
.post-card p { font-size: 0.92rem; color: var(--muted); margin: 0; flex: 1; }

/* Article body */
.prose { font-size: 1.06rem; line-height: 1.75; }
.prose > p { margin: 0 0 1.3em; }
.prose .lede { font-size: 1.16rem; color: var(--cream); border-left: 2px solid var(--gold); padding-left: 1.1rem; }
.prose h2 {
  font-size: clamp(1.35rem, 3vw, 1.7rem);
  margin: 2.4rem 0 0.9rem;
  padding-top: 1.6rem;
  border-top: 1px solid rgba(42, 62, 99, 0.7);
}
.prose h3 { font-family: var(--body); font-weight: 600; font-size: 1.1rem; letter-spacing: 0; margin: 1.8rem 0 0.6rem; color: var(--gold-bright); }
.prose ul, .prose ol { margin: 0 0 1.3em; padding-left: 1.3rem; color: var(--muted); }
.prose li { margin-bottom: 0.5rem; }
.prose ol.steps { padding-left: 0; }
.prose strong { color: var(--cream); }
.prose em { color: var(--cream); font-style: italic; }
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.88em;
  background: rgba(6, 7, 10, 0.6);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.1em 0.4em;
  color: var(--gold-bright);
}

.btn--lg { padding: 1rem 2.2rem; font-size: 0.95rem; }

/* ============================================================
   PARALLAX & SCROLL REVEALS
   Depth is generated — gradients, dot fields and rings — because the
   site has no photography. Everything animates transform/opacity only.
   ============================================================ */

/* ---------- Scroll reveals ---------- */

.js .reveal {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ---------- Parallax stage ---------- */

.px-stage {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

/* Overscan. With centred travel a layer moves +/- (sectionH + viewportH) * rate / 2,
   which for a full-height section is roughly +/- viewportH * rate. So the overscan
   fraction must be at least the fastest rate on the section. Max rate in use is
   0.32, so 40% leaves headroom. Raise this before raising any data-px value —
   gradients hide an exposed edge, a photograph will not. */
.px-layers {
  position: absolute;
  inset: -40% 0 -40%;
  z-index: 0;
  pointer-events: none;
}

.px-layer {
  position: absolute;
  inset: 0;
  will-change: transform;
}

/* Far field: a sparse drift of gold motes. Two offset dot grids so the
   spacing never reads as a regular lattice. */
.px-layer--motes {
  background-image:
    radial-gradient(1.5px 1.5px at 12% 18%, rgba(242, 220, 155, 0.55), transparent 60%),
    radial-gradient(1px 1px at 32% 62%, rgba(200, 163, 78, 0.45), transparent 60%),
    radial-gradient(1.5px 1.5px at 58% 28%, rgba(242, 220, 155, 0.4), transparent 60%),
    radial-gradient(1px 1px at 74% 74%, rgba(200, 163, 78, 0.5), transparent 60%),
    radial-gradient(1.5px 1.5px at 88% 40%, rgba(242, 220, 155, 0.35), transparent 60%),
    radial-gradient(1px 1px at 22% 84%, rgba(200, 163, 78, 0.4), transparent 60%),
    radial-gradient(1px 1px at 46% 8%, rgba(242, 220, 155, 0.3), transparent 60%),
    radial-gradient(1.5px 1.5px at 66% 92%, rgba(200, 163, 78, 0.3), transparent 60%);
  background-size: 100% 100%;
  opacity: 0.85;
}

/* Mid field: the warm wash that sits behind the crest. */
.px-layer--glow {
  background:
    radial-gradient(ellipse 60% 46% at 50% 24%, rgba(200, 163, 78, 0.16), transparent 72%),
    radial-gradient(ellipse 90% 60% at 50% 92%, rgba(21, 36, 64, 0.85), transparent 78%);
}

/* Near field: faint heraldic rings, like a seal pressed into the dark. */
.px-layer--rings {
  background:
    repeating-radial-gradient(circle at 50% 30%,
      transparent 0 118px,
      rgba(200, 163, 78, 0.07) 118px 119px,
      transparent 119px 240px);
  opacity: 0.9;
}

/* A hairline horizon that catches the eye as the hero scrolls away. */
.px-layer--horizon {
  background: linear-gradient(180deg, transparent 62%, rgba(200, 163, 78, 0.13) 63%, transparent 64%);
}

.px-content { position: relative; z-index: 1; }

/* ---------- Hero on the stage ---------- */

.hero--parallax { padding-block: clamp(4rem, 11vw, 8.5rem) clamp(3rem, 8vw, 6rem); }

.hero--parallax .hero__crest {
  will-change: transform;
  filter: drop-shadow(0 18px 60px rgba(200, 163, 78, 0.28));
}

/* ---------- Full-bleed parallax band ---------- */

.px-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(4rem, 10vw, 7rem);
  border-block: 1px solid rgba(42, 62, 99, 0.6);
  background: var(--ink);
}

.px-band__bg {
  position: absolute;
  inset: -25% 0;
  z-index: 0;
  pointer-events: none;
  will-change: transform;
  background:
    radial-gradient(ellipse 70% 50% at 20% 30%, rgba(200, 163, 78, 0.13), transparent 70%),
    radial-gradient(ellipse 60% 50% at 82% 72%, rgba(30, 51, 87, 0.9), transparent 72%);
}

/* A slow drift of oversized crest marks, cropped by the band. */
.px-band__marks {
  position: absolute;
  inset: -30% -10%;
  z-index: 0;
  pointer-events: none;
  opacity: 0.055;
  will-change: transform;
  background-image: url('../brand/logo.svg');
  background-repeat: repeat-x;
  background-size: 280px auto;
  background-position: center;
}

.px-band > .wrap { position: relative; z-index: 1; }

/* ---------- Depth on cards ---------- */

.pillar, .post-card, .game-tile, .rank, .want {
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
              border-color 0.25s ease, box-shadow 0.25s ease;
}

@media (hover: hover) {
  .pillar:hover, .want:hover {
    transform: translateY(-4px);
    border-color: var(--gold-deep);
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45);
  }
  .game-tile:hover { box-shadow: 0 14px 34px rgba(0, 0, 0, 0.4); }
}

@media (prefers-reduced-motion: reduce) {
  .px-layer, .px-band__bg, .px-band__marks { transform: none !important; }
  .pillar:hover, .want:hover, .game-tile:hover { transform: none; }
}

/* ============================================================
   SCROLL STACK — panels cover and uncover as you scroll
   Named scroll-stack, not stack: .stack is already a spacing utility
   (.stack > * + *) used on address blocks, and one class cannot mean
   two things.
   Each panel pins at the top while the next slides over it. Scroll back
   up and they uncover in reverse. Pure CSS sticky does the covering;
   parallax.js adds the dim-and-recede on the panel being covered.
   ============================================================ */

.scroll-stack {
  position: relative;
  /* NOTE: no overflow here. Any overflow value other than visible on an
     ancestor silently kills position:sticky on the panels. */
}

.scroll-stack__panel {
  position: sticky;
  top: 0;
  min-height: 100svh;
  display: grid;
  align-content: center;
  overflow: hidden;          /* safe: clips this panel's own layers, not sticky */
  background: var(--void);   /* must be opaque or you see the panel beneath */
  border-top: 1px solid rgba(42, 62, 99, 0.55);
}

.scroll-stack__panel:first-child { border-top: 0; }
.scroll-stack__panel--ink { background: var(--ink); }

/* The incoming panel gets a lit top edge, so the overlap reads as a real
   sheet sliding over rather than a section change. */
.scroll-stack__panel::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: var(--gold-rule);
  opacity: 0.5;
  z-index: 3;
}
.scroll-stack__panel:first-child::before { display: none; }

.scroll-stack__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  will-change: transform;
}

/* Painted over the panel as the next one covers it. Cheaper than filter,
   and it composites on the GPU. */
.scroll-stack__veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: var(--void);
  opacity: 0;
}

/* Short viewports: pinning a full panel leaves no room to read it, so let
   these flow normally instead. */
@media (max-height: 620px) {
  /* relative rather than static - see the note on --flow above. */
  .scroll-stack__panel { position: relative; min-height: 0; padding-block: 3rem; }
  .scroll-stack__veil { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-stack__inner { transform: none !important; }
  .scroll-stack__veil { opacity: 0 !important; }
}

/* A panel whose content is taller than the viewport opts out of pinning —
   set by parallax.js at measure time. Pinning it would clip the bottom with
   no way to scroll to it. */
.scroll-stack__panel--flow {
  /* relative, NOT static, for the same reason --compact is: .px-layers is
     absolutely positioned with percentage insets, so a static panel hands it the
     whole .scroll-stack as its containing block. The layers then size against a
     box several times too tall. Gradients hide that; the SVG cape scene does not. */
  position: relative;
  min-height: 0;
  overflow: visible;
  padding-block: clamp(3rem, 7vw, 5rem);
}
.scroll-stack__panel--flow .scroll-stack__veil { display: none; }

/* ---------- Compact stack panel ----------
   A panel whose content is short has no business being a full viewport tall —
   it reads as an empty band. This hugs the content instead.

   It is deliberately NOT sticky. A short sticky panel can only cover the top
   slice of a taller pinned panel beneath it, which leaves the rest showing.
   Left in normal flow it scrolls up over the pinned panel as one opaque sheet,
   and because the next panel is its immediate sibling there is no gap where the
   panel underneath could reappear. */

.scroll-stack__panel--compact {
  position: relative;   /* NOT static: .px-layers is absolute and would escape */
  min-height: 0;
  overflow: visible;
  padding-block: clamp(2.25rem, 4.5vw, 3.25rem);
}

.scroll-stack__panel--compact .scroll-stack__veil { display: none; }

.scroll-stack__panel--compact .section__head {
  margin-bottom: clamp(1.25rem, 2.5vw, 1.75rem);
}

/* Slimmer stat tiles: the row is very wide, so tall tiles exaggerate the gap. */
.scroll-stack__panel--compact .stat { padding: 1.15rem 1.2rem; }
.scroll-stack__panel--compact .stat__value { font-size: clamp(1.65rem, 3.4vw, 2.15rem); margin-bottom: 0.3rem; }
.scroll-stack__panel--compact .stat__label { font-size: 0.79rem; line-height: 1.45; }

/* ---------- Map pin in the nav ----------
   Replaces the Visit tab. Jumps to the address in the footer rather than
   loading a page, so it works identically from anywhere on the site. */

.nav__map {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-left: 0.2rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--muted);
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.nav__map:hover,
.nav__map:focus-visible {
  color: var(--gold-bright);
  border-color: var(--gold-deep);
  background: rgba(200, 163, 78, 0.1);
}

.nav__map svg { width: 19px; height: 19px; fill: currentColor; display: block; }

/* The header is sticky, so an anchor jump must leave room for it. */
#find-us { scroll-margin-top: 96px; }

/* Brief highlight so it is obvious where the jump landed. */
#find-us:target strong { color: var(--gold-bright); }
#find-us:target { animation: findus 1.6s ease-out 1; }

@keyframes findus {
  0%, 40% { background: rgba(200, 163, 78, 0.14); }
  100%    { background: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  #find-us:target { animation: none; }
}

/* ---------- Photographic plates ----------
   A layer only becomes a photo when data/parallax.json names a file for it;
   otherwise its generated gradient stands. */

.px-layer--photo {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* Composed still, used where parallax is disabled. */
.px-has-still {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* Keep text legible over a photograph without touching the no-photo case. */
.px-layer--photo::after,
.px-has-still::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(6, 7, 10, 0.62), rgba(6, 7, 10, 0.78));
  pointer-events: none;
}

/* ---------- Drop-in panels with kicked-up dust ---------- */
/* Used on the "Two kinds of people" panels on the Guild Posts page. The card falls
   in, lands hard, squashes, settles; dust plumes out from the base on impact.
   .pillar has overflow:hidden, so the dust cannot live inside the card — hence the
   .drop wrapper, which is the grid item and is not clipped. */

.drop {
  position: relative;
  display: flex;

  /* Effect colour. --tint is the core, --tint2 the cooler outer haze. Both are
     bare "r, g, b" triples so they can go through rgba(). Override --tint on a
     .pillars container to colour-match a section: the game hub pages set it from
     the accent in games.json, so Magic dust is Magic blue. Variants below set
     their own defaults; an override still wins because it is set on an ancestor. */
  --tint: 212, 178, 104;
  --tint2: 178, 190, 212;
}
.drop__card {
  flex: 1;
  position: relative;
  z-index: 1;          /* the card sits over the dust, so it reads as kicked up
                          from underneath rather than sprayed across the front */
}

/* The wrapper takes .reveal only as a visibility gate. Cancel the slide-up it
   would normally do — the drop animation below does the moving. */
.js .drop.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}
.js .drop.reveal .drop__card { opacity: 0; }
.js .drop.reveal.is-visible .drop__card {
  animation: guild-drop 0.72s both;
  animation-delay: var(--drop-delay, 0s);
}

/* Cards land one after another rather than together. The step is per container so
   a two-up can take its time and an eight-up cascades quickly; CSS cannot do
   arithmetic on the nth-child index, hence the explicit ladder. */
.pillars { --drop-step: 0.09s; }
.pillars .drop:nth-child(1) { --drop-delay: 0s; }
.pillars .drop:nth-child(2) { --drop-delay: calc(var(--drop-step) * 1); }
.pillars .drop:nth-child(3) { --drop-delay: calc(var(--drop-step) * 2); }
.pillars .drop:nth-child(4) { --drop-delay: calc(var(--drop-step) * 3); }
.pillars .drop:nth-child(5) { --drop-delay: calc(var(--drop-step) * 4); }
.pillars .drop:nth-child(6) { --drop-delay: calc(var(--drop-step) * 5); }
.pillars .drop:nth-child(7) { --drop-delay: calc(var(--drop-step) * 6); }
.pillars .drop:nth-child(8) { --drop-delay: calc(var(--drop-step) * 7); }
.pillars--pair { --drop-step: 0.18s; }

@keyframes guild-drop {
  0% {
    opacity: 0;
    transform: translate3d(0, -110px, 0) scale(1.015) rotate(-0.5deg);
    animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.4);  /* gravity */
  }
  52% {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1) rotate(0deg);
    animation-timing-function: cubic-bezier(0.3, 0, 0.4, 1);
  }
  64% { transform: translate3d(0, 0, 0) scale(1.025, 0.94); }     /* impact squash */
  78% { transform: translate3d(0, -7px, 0) scale(0.994, 1.018); } /* small rebound */
  90% { transform: translate3d(0, 0, 0) scale(1.004, 0.992); }
  100% { opacity: 1; transform: none; }
}

/* ---- the dust ---- */

.drop__dust {
  position: absolute;
  left: -8%;
  right: -8%;
  bottom: -2px;
  height: 0;
  pointer-events: none;
}

/* Ground smear: a flat wash that spreads sideways along the base on impact. */
.drop__dust::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 74%;
  height: 30px;
  margin-left: -37%;
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 50%,
              rgba(var(--tint), 0.26), rgba(var(--tint2), 0.12) 55%, transparent 75%);
  opacity: 0;
  transform: scaleX(0.2);
}

.drop__dust i {
  position: absolute;
  left: var(--sx, 50%);
  bottom: -30px;       /* straddles the base line, so half the plume is below it */
  width: 96px;
  height: 96px;
  margin-left: -48px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 62%,
              rgba(var(--tint), 0.46), rgba(var(--tint2), 0.22) 44%, transparent 70%);
  opacity: 0;
  transform: scale(0.2);
}

/* Puffs: outward and up, at different rates, so it reads as a cloud rather than a
   ring. --x / --y are where the puff ends up, --s how far it swells. */
/* Puffs start spread along the base line, not stacked in the middle, then drift
   outward and up. The outer two travel furthest so the cloud escapes past the
   card's bottom corners where it can actually be seen. */
.drop__dust i:nth-child(1) { --sx: 12%; --x: -104px; --y: -30px; --s: 2.0; --pd: 0.00s; }
.drop__dust i:nth-child(2) { --sx: 31%; --x:  -46px; --y: -56px; --s: 1.6; --pd: 0.05s; }
.drop__dust i:nth-child(3) { --sx: 50%; --x:    0px; --y: -34px; --s: 2.3; --pd: 0.02s; }
.drop__dust i:nth-child(4) { --sx: 69%; --x:   48px; --y: -54px; --s: 1.6; --pd: 0.06s; }
.drop__dust i:nth-child(5) { --sx: 88%; --x: 108px; --y: -28px; --s: 2.0; --pd: 0.01s; }

/* Dust fires at the landing frame — 52% of a 0.72s drop is ~0.375s. */
.js .drop.reveal.is-visible .drop__dust::before {
  animation: guild-dust-smear 0.62s cubic-bezier(0.15, 0.7, 0.3, 1) both;
  animation-delay: calc(var(--drop-delay, 0s) + 0.36s);
}
.js .drop.reveal.is-visible .drop__dust i {
  animation: guild-dust 1.05s cubic-bezier(0.12, 0.75, 0.28, 1) both;
  animation-delay: calc(var(--drop-delay, 0s) + 0.37s + var(--pd, 0s));
}

@keyframes guild-dust {
  0%   { opacity: 0;    transform: translate3d(0, 0, 0) scale(0.2); }
  14%  { opacity: 0.95; }
  100% { opacity: 0;    transform: translate3d(var(--x), var(--y), 0) scale(var(--s)); }
}

@keyframes guild-dust-smear {
  0%   { opacity: 0;   transform: scaleX(0.2); }
  18%  { opacity: 0.9; }
  100% { opacity: 0;   transform: scaleX(1.5); }
}

/* Motion this large is exactly what the reduced-motion preference is for. */
@media (prefers-reduced-motion: reduce) {
  .js .drop.reveal .drop__card,
  .js .drop.reveal.is-visible .drop__card { opacity: 1; animation: none; }
  .drop__dust { display: none; }
}

/* ---------- Drop variants ---------- */
/* Swap a single class on the .drop wrapper. The markup never changes: the same
   five <i> puffs and the same ::before ground element are recoloured, resized and
   re-pathed per variant. Selectors carry .js .reveal.is-visible so they beat the
   base rules, which sit at the same specificity. */

/* ===== Electric ===== */
/* Snaps in fast, cracks, then jitters as the charge dissipates. Sparks, not dust:
   small, bright, fast, and gone. */
.drop--electric { --tint: 170, 225, 255; --tint2: 90, 180, 255; }
.js .drop--electric.reveal.is-visible .drop__card {
  animation-name: guild-drop-electric;
  animation-duration: 0.54s;
}
@keyframes guild-drop-electric {
  0% {
    opacity: 0;
    transform: translate3d(0, -90px, 0) scale(1.01);
    animation-timing-function: cubic-bezier(0.7, 0, 0.9, 0.3);
  }
  46% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    box-shadow: 0 0 0 0 rgba(150, 220, 255, 0);
  }
  50% { box-shadow: 0 0 34px 6px rgba(150, 220, 255, 0.55); transform: translate3d(-3px, 0, 0); }
  56% { box-shadow: 0 0 20px 2px rgba(150, 220, 255, 0.30); transform: translate3d(3px, -1px, 0); }
  62% { transform: translate3d(-2px, 1px, 0); }
  70% { transform: translate3d(2px, 0, 0); box-shadow: 0 0 12px 1px rgba(150, 220, 255, 0.18); }
  80% { transform: translate3d(-1px, 0, 0); }
  100% { opacity: 1; transform: none; box-shadow: 0 0 0 0 rgba(150, 220, 255, 0); }
}
.js .drop--electric.reveal.is-visible .drop__dust i {
  width: 22px;
  height: 22px;
  margin-left: -11px;
  background: radial-gradient(circle, #ffffff, rgba(var(--tint), 0.85) 32%,
              rgba(var(--tint2), 0.35) 58%, transparent 74%);
  animation-name: guild-spark;
  animation-duration: 0.44s;
  animation-timing-function: cubic-bezier(0.1, 0.85, 0.3, 1);
  animation-delay: calc(var(--drop-delay, 0s) + 0.26s + var(--pd, 0s));
}
@keyframes guild-spark {
  0%   { opacity: 0; transform: translate3d(0, 0, 0) scale(0.4); }
  10%  { opacity: 1; }
  100% { opacity: 0; transform: translate3d(calc(var(--x) * 2.1), calc(var(--y) * 0.55), 0) scale(0.25); }
}
/* The ground element becomes the arc flash along the base. */
.js .drop--electric.reveal.is-visible .drop__dust::before {
  height: 4px;
  bottom: 2px;
  background: linear-gradient(90deg, transparent, rgba(190, 235, 255, 0.9) 40%,
              rgba(255, 255, 255, 0.95) 50%, rgba(190, 235, 255, 0.9) 60%, transparent);
  animation-name: guild-arc;
  animation-duration: 0.34s;
  animation-delay: calc(var(--drop-delay, 0s) + 0.25s);
}
@keyframes guild-arc {
  0%   { opacity: 0; transform: scaleX(0.1); }
  22%  { opacity: 1; transform: scaleX(1.05); }
  100% { opacity: 0; transform: scaleX(1.2); }
}

/* ===== Fire ===== */
.js .drop--fire.reveal.is-visible .drop__dust,
.js .drop--water.reveal.is-visible .drop__dust { z-index: 2; }

/* Lands, then embers billow straight up and flicker out. Everything rises. */
.drop--fire { --tint: 255, 196, 92; --tint2: 232, 106, 32; }
.js .drop--fire.reveal.is-visible .drop__card {
  animation-name: guild-drop-fire;
  animation-duration: 0.78s;
}
@keyframes guild-drop-fire {
  0% {
    opacity: 0;
    transform: translate3d(0, -110px, 0) scale(1.015);
    animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.4);
  }
  52% { opacity: 1; transform: translate3d(0, 0, 0); box-shadow: 0 0 0 0 rgba(255, 140, 40, 0); }
  60% { transform: translate3d(0, 0, 0) scale(1.02, 0.95);
        box-shadow: 0 14px 40px -6px rgba(255, 130, 30, 0.5); }
  76% { transform: translate3d(0, -5px, 0) scale(0.996, 1.012);
        box-shadow: 0 10px 30px -8px rgba(255, 130, 30, 0.28); }
  100% { opacity: 1; transform: none; box-shadow: 0 0 0 0 rgba(255, 140, 40, 0); }
}
.js .drop--fire.reveal.is-visible .drop__dust i {
  width: 78px;
  height: 78px;
  margin-left: -39px;
  background: radial-gradient(circle at 50% 70%, rgba(var(--tint), 0.6),
              rgba(var(--tint2), 0.34) 40%, transparent 70%);
  animation-name: guild-ember;
  animation-duration: 1.25s;
  animation-timing-function: cubic-bezier(0.2, 0.6, 0.35, 1);
  animation-delay: calc(var(--drop-delay, 0s) + 0.38s + var(--pd, 0s));
}
@keyframes guild-ember {
  0%   { opacity: 0;    transform: translate3d(0, 10px, 0) scale(0.3); }
  12%  { opacity: 0.95; }
  55%  { opacity: 0.7;  transform: translate3d(calc(var(--x) * 0.3), -78px, 0) scale(1.25); }
  100% { opacity: 0;    transform: translate3d(calc(var(--x) * 0.45), -170px, 0) scale(0.5); }
}
.js .drop--fire.reveal.is-visible .drop__dust::before {
  background: radial-gradient(ellipse at 50% 50%, rgba(255, 150, 50, 0.5),
              rgba(200, 60, 20, 0.2) 55%, transparent 75%);
  animation-duration: 1s;
}

/* ===== Earthquake ===== */
/* Heaviest of the four. Lands, the card shudders sideways in a decaying shake,
   and the dust stays low and spreads wide instead of rising. */
.drop--quake { --tint: 196, 178, 148; --tint2: 150, 140, 128; }
.js .drop--quake.reveal.is-visible .drop__card {
  animation-name: guild-drop-quake;
  animation-duration: 1.05s;
}
@keyframes guild-drop-quake {
  0% {
    opacity: 0;
    transform: translate3d(0, -130px, 0) scale(1.02);
    animation-timing-function: cubic-bezier(0.6, 0, 0.9, 0.35);
  }
  38% { opacity: 1; transform: translate3d(0, 0, 0); }
  44% { transform: translate3d(0, 0, 0) scale(1.035, 0.9); }
  50% { transform: translate3d(-9px, 0, 0) scale(0.99, 1.02); }
  56% { transform: translate3d(8px, 0, 0) scale(1.01, 0.99); }
  62% { transform: translate3d(-6px, 1px, 0); }
  68% { transform: translate3d(5px, 0, 0); }
  74% { transform: translate3d(-4px, 0, 0); }
  80% { transform: translate3d(3px, 0, 0); }
  86% { transform: translate3d(-2px, 0, 0); }
  92% { transform: translate3d(1px, 0, 0); }
  100% { opacity: 1; transform: none; }
}
.js .drop--quake.reveal.is-visible .drop__dust i {
  width: 120px;
  height: 120px;
  margin-left: -60px;
  background: radial-gradient(circle at 50% 62%, rgba(var(--tint), 0.4),
              rgba(var(--tint2), 0.2) 46%, transparent 72%);
  animation-name: guild-rubble;
  animation-duration: 1.5s;
  animation-timing-function: cubic-bezier(0.1, 0.6, 0.25, 1);
  animation-delay: calc(var(--drop-delay, 0s) + 0.28s + var(--pd, 0s));
}
@keyframes guild-rubble {
  0%   { opacity: 0;   transform: translate3d(0, 0, 0) scale(0.2); }
  10%  { opacity: 0.9; }
  100% { opacity: 0;   transform: translate3d(calc(var(--x) * 1.9), -14px, 0) scale(calc(var(--s) * 1.3)); }
}
.js .drop--quake.reveal.is-visible .drop__dust::before {
  width: 96%;
  margin-left: -48%;
  height: 38px;
  background: radial-gradient(ellipse at 50% 50%, rgba(196, 178, 148, 0.34),
              rgba(150, 140, 128, 0.16) 55%, transparent 78%);
  animation-duration: 1.1s;
  animation-delay: calc(var(--drop-delay, 0s) + 0.27s);
}

/* ===== Waterflow ===== */
/* The odd one out: no impact at all. It pours down, settles with a liquid wobble,
   and a ripple ring spreads from the base. */
.drop--water { --tint: 180, 232, 240; --tint2: 90, 170, 200; }
.js .drop--water.reveal.is-visible .drop__card {
  animation-name: guild-drop-water;
  animation-duration: 1.15s;
  animation-timing-function: cubic-bezier(0.33, 0.02, 0.2, 1);
}
@keyframes guild-drop-water {
  0%   { opacity: 0; transform: translate3d(0, -70px, 0) scale(0.97, 1.06); }
  30%  { opacity: 1; }
  55%  { transform: translate3d(0, 0, 0) scale(1.03, 0.96); }
  70%  { transform: translate3d(0, 0, 0) scale(0.985, 1.022); }
  84%  { transform: translate3d(0, 0, 0) scale(1.008, 0.992); }
  93%  { transform: translate3d(0, 0, 0) scale(0.997, 1.004); }
  100% { opacity: 1; transform: none; }
}
.js .drop--water.reveal.is-visible .drop__dust i {
  width: 60px;
  height: 60px;
  margin-left: -30px;
  background: radial-gradient(circle at 50% 55%, rgba(var(--tint), 0.5),
              rgba(var(--tint2), 0.26) 44%, transparent 70%);
  animation-name: guild-droplet;
  animation-duration: 1.1s;
  animation-timing-function: cubic-bezier(0.25, 0.7, 0.4, 1);
  animation-delay: calc(var(--drop-delay, 0s) + 0.55s + var(--pd, 0s));
}
/* Droplets arc: up and out, then fall back past the base line. */
@keyframes guild-droplet {
  0%   { opacity: 0;    transform: translate3d(0, 6px, 0) scale(0.25); }
  14%  { opacity: 0.9; }
  45%  { opacity: 0.75; transform: translate3d(calc(var(--x) * 0.55), -42px, 0) scale(0.8); }
  100% { opacity: 0;    transform: translate3d(calc(var(--x) * 0.9), 26px, 0) scale(0.5); }
}
/* The ground element becomes an expanding ripple ring. */
.js .drop--water.reveal.is-visible .drop__dust::before {
  width: 30%;
  margin-left: -15%;
  height: 22px;
  bottom: -6px;
  background: none;
  border: 2px solid rgba(150, 220, 235, 0.55);
  border-radius: 50%;
  animation-name: guild-ripple;
  animation-duration: 1.3s;
  animation-timing-function: cubic-bezier(0.15, 0.75, 0.3, 1);
  animation-delay: calc(var(--drop-delay, 0s) + 0.52s);
}
@keyframes guild-ripple {
  0%   { opacity: 0;    transform: scale(0.2); }
  15%  { opacity: 0.85; }
  100% { opacity: 0;    transform: scale(3.4); }
}

/* ---------- Far-cape scene ---------- */
/* Seven SVG layers drawn by tools/parallax_art.py, stacked back to front inside a
   .px-layers box and moved at different rates. They go FIRST in the box so every
   existing gold layer paints over them - this is scenery on the far horizon, not
   a foreground element.

   Sizing: .px-layers is 180% of the section (inset -40% top and bottom) so layers
   have room to travel. 100/1.8 = 55.5556%, and a 50% vertical position centres
   that in the overscan - so each plate covers exactly the visible section and has
   40% of headroom above and below to move into. The SVGs carry
   preserveAspectRatio="xMidYMax slice", so they crop like object-fit: cover
   anchored to their own baseline and never distort. */
.px-layer--cape {
  background-repeat: no-repeat;
  background-position: center 50%;
  background-size: 100% 55.5556%;
}

/* Rates are all slower than the hero's existing 0.06-0.26 furniture, which is what
   puts the scene behind it: the further away a thing is, the less it moves. */
.px-cape-sky        { background-image: url('../parallax/01-sky.svg');        opacity: 0.95; }
.px-cape-backlight  { background-image: url('../parallax/02-backlight.svg');  opacity: 0.85; }
.px-cape-clouds     { background-image: url('../parallax/03-clouds.svg');     opacity: 0.6; }
.px-cape-cards-far  { background-image: url('../parallax/04-cards-far.svg');  opacity: 0.55; }
.px-cape-far        { background-image: url('../parallax/05-range-far.svg');  opacity: 0.75; }
.px-cape-mid        { background-image: url('../parallax/06-range-mid.svg');  opacity: 0.8; }
.px-cape-townglow   { background-image: url('../parallax/07-townglow.svg');   opacity: 0.7; }
.px-cape-skyline    { background-image: url('../parallax/08-skyline.svg');    opacity: 0.85; }
.px-cape-cards-near { background-image: url('../parallax/09-cards-near.svg'); opacity: 0.55; }
.px-cape-trees      { background-image: url('../parallax/10-treeline.svg');   opacity: 0.9; }
.px-cape-shade      { background-image: url('../parallax/11-shade.svg');      opacity: 1; }

/* Reprise. Further down the page the same country is seen from further out: sky,
   light, ridges and a few high cards - no town, no trees, no near cards - at half
   strength. It should register as the same place rather than the same picture. */
.cta-band--cape {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.cta-band--cape > .wrap { position: relative; z-index: 1; }
.cta-band--cape .px-layer--cape { opacity: 0.5; }
.cta-band--cape .px-cape-backlight { opacity: 0.6; }
.cta-band--cape .px-cape-cards-far { opacity: 0.4; }
.cta-band--cape .px-cape-shade { opacity: 0.9; }

/* On a phone the scene is mostly hidden behind the content anyway, and the extra
   compositing is not worth the battery. Keep the sky, the backlight and the shade,
   which are the three that carry the mood, and thin the detail layers. */
@media (max-width: 640px) {
  .px-cape-clouds, .px-cape-far, .px-cape-mid, .px-cape-townglow,
  .px-cape-skyline, .px-cape-cards-far, .px-cape-cards-near { opacity: 0.35; }
}

/* ---------- Hero fit on laptop-height screens ---------- */
/* The hero's spacing was tuned on a tall display, where it looked generous. On a
   typical laptop (~800px of viewport) the same spacing pushed the lede and both
   buttons below the fold - the crest alone was 340px before a word of copy. The
   first screen has to carry what the shop is and what to do next, so on short
   viewports everything above the lede gets tightened until it fits.
   Nothing here changes the design on a tall display. */
@media (max-height: 900px) {
  .hero--parallax { padding-block: clamp(1.25rem, 3vh, 2.4rem) clamp(1rem, 2.4vh, 2rem); }
  .scroll-stack__panel--flow { padding-block: clamp(1.5rem, 4vh, 3rem); }

  .hero__crest { width: min(210px, 42vw, 25vh); margin-bottom: 0.8rem; }
  .hero__tagline { margin-bottom: 0.9rem; }
  .hero h1 { font-size: clamp(1.85rem, 4.2vw, 2.75rem); margin-bottom: 0.38em; }

  .countdown-panel { padding: 0.95rem 1.15rem 0.9rem; margin-bottom: 1.05rem; }
  .countdown-panel .countdown__label { margin-bottom: 0.5rem; }

  .hero__lede { margin-bottom: 0.95rem; font-size: clamp(0.97rem, 1.6vw, 1.06rem); }
}

/* 768 is still the commonest laptop height there is, and at ~900 settings the
   buttons finished six pixels under the fold - close enough to look like a bug. */
@media (max-height: 800px) {
  .hero--parallax { padding-block: clamp(1rem, 2.4vh, 1.8rem) clamp(0.9rem, 2vh, 1.6rem); }
  .hero__crest { width: min(190px, 34vw, 23vh); margin-bottom: 0.7rem; }
  .hero h1 { font-size: clamp(1.75rem, 3.9vw, 2.5rem); margin-bottom: 0.32em; }
  .countdown-panel { padding: 0.9rem 1.1rem 0.85rem; margin-bottom: 1rem; }
  .hero__lede { margin-bottom: 1rem; }
}

/* Shorter again - netbooks, split screens, landscape phones. Drop the crest to a
   token size rather than losing the words. */
@media (max-height: 700px) {
  .hero__crest { width: min(160px, 30vw, 22vh); margin-bottom: 0.7rem; }
  .hero h1 { font-size: clamp(1.7rem, 3.6vw, 2.3rem); }
  .hero__tagline { margin-bottom: 0.7rem; }
  .countdown-panel { margin-bottom: 1rem; }
}

/* Narrow screens: the headline wraps to three lines and the lede to four, which
   put the buttons ~50px under the fold on a standard phone. Same treatment as the
   short-viewport blocks above, applied on width instead of height. */
@media (max-width: 560px) {
  .hero__crest { width: min(132px, 34vw); margin-bottom: 0.6rem; }
  .hero__tagline { margin-bottom: 0.6rem; }
  .hero h1 { margin-bottom: 0.3em; }
  .countdown-panel { padding: 0.85rem 1rem 0.8rem; margin-bottom: 0.85rem; }
  .hero__lede { margin-bottom: 0.85rem; }
}

/* Pre-open notice under the footer address. Hidden until site.js fills it from
   store.json, so it never flashes an empty box and it disappears sitewide the
   moment preOpen.active goes false. */
.preopen {
  margin: 0.9rem 0 0;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--gold-deep);
  border-radius: 8px;
  background: rgba(200, 163, 78, 0.07);
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.6;
}
.preopen strong {
  display: block;
  color: var(--gold-bright);
  font-family: var(--display);
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: 0.3rem;
}

/* ---------------------------------------------------------------------------
   Consent blocks - alerts.html
   ---------------------------------------------------------------------------
   These are compliance surfaces, not decoration. Two rules matter more than how
   they look:

   1. The checkbox and its full disclosure must be visible together, unchecked,
      before the visitor submits. Never pre-check one, never collapse the
      disclosure behind a "read more", and never shrink it below the size of the
      surrounding body text - a carrier reviewer reads this page as a screenshot
      and "clear and conspicuous" is the test it has to pass.
   2. The label wraps the whole block so the entire disclosure is a click target.
--------------------------------------------------------------------------- */
.consent-set { display: grid; gap: 0.9rem; margin: 0 0 1.4rem; }

.consent {
  display: grid;
  grid-template-columns: 1.15rem 1fr;
  gap: 0.9rem;
  align-items: start;
  padding: 1rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(10, 17, 32, 0.55);
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease;
}
.consent:hover { border-color: var(--gold-deep); background: rgba(13, 21, 38, 0.75); }
.consent:focus-within { border-color: var(--gold); outline: 2px solid var(--gold-deep); outline-offset: 2px; }

.consent input[type="checkbox"] {
  width: 1.15rem;
  height: 1.15rem;
  margin: 0.15rem 0 0;
  accent-color: var(--gold);
  cursor: pointer;
  flex: none;
}

.consent__text { margin: 0; font-size: 0.97rem; line-height: 1.6; color: var(--muted); }
.consent__text strong { display: block; margin-bottom: 0.3rem; color: var(--cream); font-size: 1.02rem; }
.consent__text a { color: var(--gold-bright); }

/* The carrier-required boilerplate. Muted, but never smaller than 0.86rem -
   below that it stops reading as conspicuous. */
.consent__fine { display: block; margin-top: 0.45rem; font-size: 0.86rem; line-height: 1.55; color: var(--muted); opacity: 0.85; }

.consent--required { border-color: var(--gold-deep); }

/* Standalone legal note under a form. */
.form-legal { margin: 1.1rem 0 0; font-size: 0.86rem; line-height: 1.6; color: var(--muted); opacity: 0.85; }
.form-legal a { color: var(--gold-bright); }

/* ---------------------------------------------------------------------------
   Legal pages - privacy.html, terms.html, sms-terms.html
--------------------------------------------------------------------------- */
.legal { max-width: 46rem; margin: 0 auto; }
.legal__meta {
  margin: 0 0 2rem;
  padding: 0.9rem 1.1rem;
  border-left: 2px solid var(--gold-deep);
  background: rgba(10, 17, 32, 0.5);
  font-size: 0.92rem;
  color: var(--muted);
}
.legal__meta strong { color: var(--cream); }
.legal .prose h2 { scroll-margin-top: 5rem; }

/* A short jump list at the top of a long policy. */
.legal-toc { margin: 0 0 2.4rem; padding: 1.1rem 1.3rem; border: 1px solid var(--line); border-radius: 10px; }
.legal-toc h2 { margin: 0 0 0.7rem !important; font-size: 0.78rem !important; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted) !important; border: 0 !important; padding: 0 !important; }
.legal-toc ol { margin: 0; padding-left: 1.2rem; columns: 2; column-gap: 2rem; }
.legal-toc li { margin-bottom: 0.4rem; break-inside: avoid; }
.legal-toc a { color: var(--gold-bright); text-decoration: none; }
.legal-toc a:hover { text-decoration: underline; }
@media (max-width: 560px) { .legal-toc ol { columns: 1; } }

/* The footer legal row. Deliberately quiet - these pages are reachable from the
   bottom of every page and nowhere else. */
.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
  margin-top: 1.1rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  font-size: 0.86rem;
}
.site-footer__legal a { color: var(--muted); text-decoration: none; }
.site-footer__legal a:hover { color: var(--gold-bright); text-decoration: underline; }

/* alerts.html runs wider than a policy page - it carries a form. */
.legal--wide { max-width: 56rem; }

/* An example of a real message, quoted on alerts.html. Showing people the actual
   thing they are agreeing to receive is worth more than describing it, and a
   carrier reviewer looking for sample messages finds them here too. */
.sample {
  margin: 0.9rem 0 1.4rem;
  padding: 0.9rem 1.1rem;
  border-left: 2px solid var(--gold-deep);
  border-radius: 0 8px 8px 0;
  background: rgba(10, 17, 32, 0.6);
  color: var(--cream);
  font-size: 0.95rem;
  line-height: 1.6;
}

/* ---------------------------------------------------------------------------
   QR opt-in block - visit.html, beside the contact form
   ---------------------------------------------------------------------------
   The QR sits on an explicit LIGHT plate. Every scanner expects dark modules on
   a light ground; inverting that polarity fails on a fair number of older Android
   cameras, and this site's own background is near-black - a transparent QR would
   be dark-on-dark and simply would not scan.

   The visible link next to it is not a nicety. A QR is unusable to a screen-reader
   user, to anyone on the desktop the code is displayed on, and to a phone with a
   dead camera. The code is a shortcut to the link, never a replacement for it.
--------------------------------------------------------------------------- */
.qr-optin {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.4rem;
  align-items: center;
  margin: 2.2rem 0 0;
  padding: 1.3rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(10, 17, 32, 0.55);
}
.qr-optin__code {
  width: 132px;
  height: 132px;
  padding: 0.5rem;
  border-radius: 8px;
  background: var(--cream);          /* the light ground the scanner needs */
}
.qr-optin__code img { display: block; width: 100%; height: 100%; }
.qr-optin h3 {
  margin: 0 0 0.4rem;
  font-family: var(--body);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--gold-bright);
}
.qr-optin p { margin: 0 0 0.6rem; font-size: 0.94rem; line-height: 1.6; color: var(--muted); }
.qr-optin p:last-child { margin-bottom: 0; }
.qr-optin a { color: var(--gold-bright); }
.qr-optin__fine { font-size: 0.84rem; opacity: 0.85; }

@media (max-width: 560px) {
  .qr-optin { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .qr-optin__code { width: 156px; height: 156px; }
}

/* ---------------------------------------------------------------------------
   Phone link in the nav, beside "Contact us"
   ---------------------------------------------------------------------------
   Hidden until site.js fills it from store.json, so a visitor never sees an empty
   pill and a crawler never indexes a blank link. The number itself is the label -
   people scan for digits, not for the word "phone".
--------------------------------------------------------------------------- */
/* SPECIFICITY NOTE, and it is the whole reason this block looks over-qualified:
   `.nav a` (~line 204) is (0,1,1) and sets display and padding for every anchor in
   the nav. A bare `.nav__phone` is (0,1,0) and loses to it silently - the rule sits
   in the stylesheet, the media query matches, and nothing happens. Everything below
   is written as `.nav a.nav__phone` (0,2,1) to clear it.

   WHY THE NAV SHOWS AN ICON AND NOT THE NUMBER:
   `.site-header__inner` is a `.wrap`, capped at max-width 1140px. The nav's share of
   that is ~741px at ANY viewport width - a wider screen does not give it more room.
   Measured, the six links, map pin and CTA need ~712px of that budget. The number as
   a pill is 152px, so digits in the nav need ~834px and simply never fit, on any
   monitor. A viewport media query cannot help with a container that does not grow.

   So the nav carries a one-tap call icon, the aria-label carries the number for
   screen readers, and the digits themselves live in the footer of every page and on
   the contact page - where there is room to read them. */
.nav a.nav__phone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  margin-left: 0.2rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--muted);
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.nav a.nav__phone:hover,
.nav a.nav__phone:focus-visible { color: var(--gold-bright); border-color: var(--gold); }
.nav a.nav__phone span { display: none; }
.nav__phone-icon { width: 19px; height: 19px; fill: currentColor; display: block; }

/* The map pin gives way to the phone. There is room in the nav's ~741px budget for
   one icon button, not two: with both, the row needs ~719px against a budget that
   drops to 711px because the extra width makes the brand wrap to two lines, which
   shrinks the nav further. A feedback loop, and eight pixels is not worth fighting.

   The pin scrolled to #find-us - the footer address block, which is on every page
   and now carries the phone number beside it. So nothing is lost: the pin's
   destination is still one scroll away, and the slot is spent on the action a
   customer standing in a car park actually wants. */
.nav a.nav__map { display: none; }

/* Footer address block. */
.site-footer address [data-phone] a { color: var(--muted); text-decoration: none; }
.site-footer address [data-phone] a:hover { color: var(--gold-bright); text-decoration: underline; }

/* Entry fee and prize list on an event card. The fee sits in the aside next to the
   calendar button because price is the second thing anyone looks for after the time,
   and it should not be buried in the blurb. */
.event__fee {
  display: inline-block;
  margin-bottom: 0.5rem;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--gold-deep);
  border-radius: 999px;
  color: var(--gold);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.event__prizes {
  margin: 0.55rem 0 0;
  padding-left: 1.05rem;
  color: var(--muted);
  font-size: 0.88rem;
  line-height: 1.55;
}
.event__prizes li { margin-bottom: 0.18rem; }

/* Sort bar sits above the events list, beside the game filter. Quieter than the
   filter pills - sorting is a refinement, filtering is the decision. */
.filters--sort { margin-top: 0.4rem; }
.filters__label {
  align-self: center;
  margin-right: 0.15rem;
  color: var(--muted);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ---------------------------------------------------------------------------
   BANDAI TCG+ app prompt — phone only
   ---------------------------------------------------------------------------
   Hidden on desktop by design, not by oversight. Registering for an Official Store
   Tournament happens inside Bandai's app, so on a phone this is the most useful
   control on the page; on a laptop it is a link to software that machine cannot run.

   Note `display: none !important` — the block ships with the `hidden` attribute and
   JS clears it, so without the bang the JS would reveal it on desktop too.
--------------------------------------------------------------------------- */
.app-cta {
  margin: 1.4rem 0 0;
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(10, 17, 32, 0.55);
}
.app-cta h3 {
  margin: 0 0 0.35rem;
  font-family: var(--body);
  font-weight: 600;
  font-size: 1.02rem;
  color: var(--gold-bright);
}
.app-cta p { margin: 0 0 0.9rem; font-size: 0.93rem; line-height: 1.6; color: var(--muted); }
.app-cta__links { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.app-cta__btn { flex: 1 1 auto; text-align: center; }

@media (min-width: 861px) {
  .app-cta { display: none !important; }
}

/* Off-site event: a booth at someone else's show. The badge and venue line exist for
   one reason — so nobody reads "Sat Oct 24" and drives to the shop. */
.event__offsite {
  display: inline-block;
  margin-left: 0.3rem;
  padding: 0.1rem 0.5rem;
  border: 1px solid #3d6b7d;
  border-radius: 999px;
  color: #86c5da;
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  vertical-align: middle;
}
.event__venue { margin: 0.35rem 0 0.1rem; font-size: 0.9rem; line-height: 1.5; color: var(--cream); }
.event__venue strong { color: var(--gold-bright); }
.event__venue-note { display: block; margin-top: 0.15rem; font-size: 0.84rem; color: var(--muted); }
