/* ============================================================================
   Lumoria — design tokens: THE DUSK ACCORD

   The shell is the owner's own page (oaths-of-lumoria.html): dusk violet
   ground, warm vellum ink, one antique gold identity, the seven god colours
   as accents. Structure lessons (centered rhythm, cards, one bar) come from
   studying the reference site; every value here is ours and the licence gate
   in check.py enforces that.

   ONE GOLD. --leaf-gold is the metal; --gold-lit its highlight; --gold-shadow
   its depth. Derive every gold-ish alpha with color-mix from --leaf-gold —
   an audit found eight competing golds and the page read as three metals.
   ========================================================================= */

:root {
  color-scheme: dark;

  /* ---- ground: warm parchment cream, sampled off our own sunny paintings ---- */
  --dusk:        #171126;   /* the page */
  --dusk-raised: #1e1730;   /* a soft band */
  --plate:       #221a38;   /* a card */
  --plate-lit:   #2a2145;   /* a card, hovered */
  --gauze:       rgba(124, 96, 180, .10);   /* warm wash for band rhythm */
  --gauze-2:     rgba(124, 96, 180, .17);

  /* ---- ink: warm chocolate, never black ---- */
  --vellum:       #efe7d4;   /* main text + headings */
  --vellum-soft:  #b3a68d;   /* secondary */
  /* Was #8a7d68, which measured 4.10:1 on --plate: below the 4.5:1 AA floor, and it is
     worn by the SMALLEST strings on the site (.78rem italic weapon lines, .64rem "· KEPT"
     tags, .82rem hints). Small text needs more contrast, not less. #a2957f clears AA on
     all three grounds: 5.61:1 on --plate, 6.24:1 on --dusk, 5.85:1 on --dusk-raised. */
  --vellum-faint: #a2957f;   /* captions */

  /* ---- hairlines ---- */
  --rule:        #3a2f58;
  --rule-faint:  #2e2548;
  --rule-strong: color-mix(in srgb, var(--leaf-gold) 50%, transparent);
  --rule-bright: color-mix(in srgb, var(--leaf-gold) 78%, transparent);
  --rule-field:  #4d3f78;

  /* ---- identity: the wordmark's metals ---- */
  --leaf-gold:   #e7b33b;   /* CTA gold */
  --gold-lit:    #f6d878;
  --gold-soft:   #c39b45;
  --gold-shadow: #8f6c1e;
  --ivy:         #9dc46e;   /* eyebrows */
  --ivy-deep:    #b5d68a;
  --star:        #a7bdf2;   /* links — the bezel gem, darkened for cream */
  --star-shadow: #c9d7fa;
  --hearth:      #e6883c;

  /* ---- the seven orders (deep = text-safe on white, base = tint source) ---- */
  --wallsworn:  #83c8ec;  --wallsworn-shadow:  #2a5c78;
  --starspire:  #c384e2;  --starspire-shadow:  #5b3671;
  --wildhunt:   #79c169;  --wildhunt-shadow:   #2e5d29;
  --dawnflame:  #f0d068;  --dawnflame-shadow:  #8e6a1f;
  --moonveil:  #8fa7ef;  --moonveil-shadow:   #2d3f76;
  --emberforge: #e88b55;  --emberforge-shadow: #713315;
  --packsworn:  #e0a26a;  --packsworn-shadow:  #7c491d;
  --sundered:   #8a7d5e;  --sundered-shadow:   #3a2f1a;

  /* ---- roles ---- */
  --tank: #6fa7e4;  --mend: #63c48e;  --aid: #d9a94a;
  --edge: #e07a6c;  --mixed: #ab7fd4;

  /* ---- type: rounded warm display, quiet body ---- */
  --face-display: 'Palatino Linotype', Palatino, 'Book Antiqua', Georgia, serif;
  --face-text:    'Segoe UI', system-ui, -apple-system, sans-serif;

  --step-banner: clamp(2.3rem, 4vw, 3.6rem);
  --step-title:  clamp(2rem, 3.4vw, 2.9rem);
  --step-head:   clamp(1.75rem, 2.8vw, 2.3rem);
  --step-sub:    1.08rem;
  --step-text:   1rem;
  --step-small:  .9rem;
  --step-rank:   .72rem;
  --step-micro:  .66rem;   /* the one size for tiny uppercase meta labels */
  --step-card:   1.1rem;   /* the one size for card titles */

  --lead-tight: 1.15;
  --lead-text:  1.65;
  --track-rank: .18em;

  /* ---- shape: soft and friendly ---- */
  --arch-sm: 12px;
  --arch-md: 18px;
  --arch-lg: 26px;
  --seal: 999px;

  /* ---- depth: soft warm shadows, no harshness ---- */
  --cast:      0 10px 26px -12px rgba(5, 2, 14, .55);
  --cast-far:  0 20px 44px -16px rgba(5, 2, 14, .7);
  --glow-gold: 0 7px 20px -6px rgba(231, 179, 59, .5);

  /* ---- layout ---- */
  --column: 1140px;
  --column-text: 66ch;
  --bar-h: 70px;
  --course: clamp(2.6rem, 4.5vw, 4rem);

  /* ---- motion ---- */
  --swing: cubic-bezier(.18, .9, .24, 1.02);
  --tick: .15s;
  --beat: .28s;
  --pass: .55s;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
   Lumoria — THE DUSK ACCORD: layout and components

   Dusk violet shell on a centered card rhythm. Hard-won rules:
     · decoding="sync" ONLY on the eager/LCP image; lazy images decode async
       (sync decodes froze the renderer at scale; pixel-verified safe).
     · No `position: fixed; z-index: -1` layer, ever.
     · Never combine `auto-fit` with a bare `fr` track.
     · NO opacity animations on content. Two ghost-page incidents.
     · ONE GOLD: derive every gold alpha from --leaf-gold via color-mix.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(var(--bar-h) + 1rem); }

body {
  margin: 0;
  background: var(--dusk);
  color: var(--vellum);
  font: 400 var(--step-text)/var(--lead-text) var(--face-text);
  overflow-x: hidden;
  /* faint warm daylight vignettes; plain scrolling background on <body> */
  background-image:
    radial-gradient(ellipse 60% 40% at 15% -5%, rgba(124, 96, 180, .18), transparent 60%),
    radial-gradient(ellipse 50% 35% at 85% 0%, rgba(231, 179, 59, .10), transparent 60%);
  background-repeat: no-repeat;
}

img, video, svg { max-width: 100%; height: auto; display: block; }
a { color: var(--star); text-decoration: none; transition: color var(--tick); }
a:hover { color: var(--star-shadow); }
:focus-visible { outline: 2px solid var(--star); outline-offset: 3px; border-radius: 4px; }

.skip {
  position: absolute; left: 12px; top: -60px; z-index: 300;
  background: var(--plate); color: var(--vellum);
  border: 1px solid var(--rule-strong); border-radius: var(--arch-sm);
  padding: 10px 16px;
}
.skip:focus { top: 12px; }

[hidden] { display: none !important; }

/* ---------------------------------------------------------------- topbar ---
   One slim sticky bar: brand left, ways centre, CTA right.
   ------------------------------------------------------------------------- */
.topbar {
  position: sticky; top: 0; z-index: 90;
  min-height: var(--bar-h); padding: .5rem 0;
  /* opaque on purpose: a backdrop-filter on a sticky bar re-blurs every scroll
     frame and froze the renderer on a loaded machine */
  background: var(--bar-bg, #151022);
  box-shadow: 0 1px 0 var(--rule);
}
.topbar > .column {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem;
}
.topbar .btn { justify-self: end; }
.topbar__brand { flex: none; display: block; justify-self: start; }
.topbar__brand img {
  height: 54px; width: auto; margin: -6px 0;
  filter: drop-shadow(0 3px 6px rgba(5, 2, 14, .5));
  transition: filter .25s var(--swing), transform .25s var(--swing);
}
.topbar__brand:hover img {
  transform: scale(1.04);
  filter: drop-shadow(0 3px 6px rgba(5, 2, 14, .5)) drop-shadow(0 0 14px rgba(246, 216, 120, .65))
          brightness(1.08);
}
.ways {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: .1rem; margin: 0; justify-self: center; min-width: 0;
}
.ways a:not(.btn) {
  padding: .5rem .8rem; border-radius: var(--seal);
  color: var(--vellum-soft); font: 600 .88rem/1 var(--face-text);
  transition: color var(--tick), background var(--tick);
}
.ways a:not(.btn):hover { color: var(--vellum); background: color-mix(in srgb, var(--leaf-gold) 14%, transparent); }
.ways a:not(.btn)[aria-current] { color: var(--gold-lit); background: var(--plate); box-shadow: 0 1px 4px rgba(5, 2, 14, .5); }
.topbar .btn { flex: none; }
@media (max-width: 860px) {
  .topbar > .column { grid-template-columns: auto auto; grid-template-rows: auto auto; }
  .topbar__brand img { height: 44px; margin: -4px 0; }
  .ways { grid-column: 1 / -1; grid-row: 2; flex-wrap: wrap; }
  .ways a:not(.btn) { padding: .6rem .6rem; font-size: .82rem; min-height: 44px; display: inline-flex; align-items: center; }
  .shell, body { overflow-x: hidden; }
  .chips--stick, .sift { top: 0; }
}

.shell { min-width: 0; }

/* ---------------------------------------------------------------- layout --- */
.column { width: 100%; max-width: var(--column); margin: 0 auto; padding: 0 clamp(1rem, 3vw, 2rem); }
.course { padding: var(--course) 0; position: relative; }
.course--tight { padding: calc(var(--course) * .55) 0; }
.course--wash { background: var(--gauze); }

/* ---------------------------------------------------------------- type -----
   THE ONE SECTION SKELETON: centered eyebrow → heading → subhead. Every
   section on every page uses it; that is where "aligned" comes from. */
h1, h2, h3, h4 { font-family: var(--face-display); font-weight: 800; line-height: var(--lead-tight); margin: 0; color: var(--vellum); }
h1 { font-size: var(--step-title); }
h2 { font-size: var(--step-head); }
h3 { font-size: var(--step-card); }

.head { text-align: center; margin: 0 auto 1.8rem; max-width: 46rem; }
.head--stack { max-width: 52rem; }
.head .rank {
  justify-content: center; position: relative; padding: .32rem .95rem;
  background: color-mix(in srgb, var(--accent, var(--leaf-gold)) 14%, transparent);
  border-radius: 3px;
  clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 8px 100%, 0 50%);
}
.head h1, .head h2 {
  margin-top: .45rem; text-wrap: balance; letter-spacing: .08em; font-weight: 600;
  background: linear-gradient(180deg, var(--gold-lit) 0%, var(--leaf-gold) 58%, var(--gold-shadow) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, .5));
  padding-bottom: .08em;
}
/* The PAGE title, canon-scale. canon/oaths-of-lumoria.html:28-33 runs its banner at
   clamp(2.4em,7vw,4.4em) with .14em tracking and a 34px gold bloom, and that scale is most
   of why the canon page reads as a title page instead of a heading. Scoped to `.head h1` so
   only the one h1 per page grows: section h2s keep --step-banner and their tighter tracking. */
.head h1 {
  font-size: clamp(2.4rem, 7vw, 4.4rem); letter-spacing: .14em;
  filter: drop-shadow(0 0 34px rgba(212, 175, 55, .25)) drop-shadow(0 2px 5px rgba(0, 0, 0, .5));
}
.head__note { color: var(--vellum-soft); font-size: .98rem; margin: .65rem auto 0; max-width: 57ch; }

.rank {
  display: inline-flex; align-items: center; gap: .4rem;
  font: 700 var(--step-rank)/1.3 var(--face-display); letter-spacing: var(--track-rank);
  text-transform: uppercase; color: var(--accent, var(--gold-soft));
}

.gem { display: inline-block; color: var(--leaf-gold); }
.gem::before { content: "✦"; }

/* ---------------------------------------------------------------- buttons -- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font: 700 .92rem/1 var(--face-display); letter-spacing: .01em;
  padding: .85rem 1.6rem; border-radius: var(--seal);
  border: 1px solid transparent; cursor: pointer;
  transition: box-shadow var(--tick), background var(--tick), border-color var(--tick), color var(--tick), transform var(--tick);
}
.btn--primary {
  background: linear-gradient(180deg, var(--gold-lit), var(--leaf-gold) 74%);
  color: #3c2b0c;
  box-shadow: 0 3px 0 var(--gold-shadow), var(--glow-gold), inset 0 1px 0 rgba(255, 255, 255, .55);
}
.btn--primary:hover { transform: translateY(-1px); box-shadow: 0 4px 0 var(--gold-shadow), 0 10px 24px -6px color-mix(in srgb, var(--leaf-gold) 60%, transparent), inset 0 1px 0 rgba(255, 255, 255, .55); }
.btn--primary:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--gold-shadow), inset 0 1px 0 rgba(255, 255, 255, .4); }
.btn--ghost { background: rgba(34, 26, 56, .8); border-color: var(--rule-field); color: var(--vellum); box-shadow: 0 2px 0 rgba(23, 15, 44, .9), 0 4px 10px -6px rgba(5, 2, 14, .5); }
.btn--ghost:hover { border-color: var(--gold-soft); color: var(--vellum); transform: translateY(-1px); }
.btn--sm { padding: .55rem 1.05rem; font-size: .82rem; }
.btn:active { transform: translateY(1px); }

/* ---------------------------------------------------------------- porch ----
   Split hero: copy left on the cream, one framed painting right. No text on
   art, no giant band — the owner has vetoed both twice. */
.porch { position: relative; overflow: hidden; padding: clamp(2rem, 5vw, 3.6rem) 0 clamp(1.6rem, 4vw, 3rem); }
.porch__sky { position: absolute; inset: 0; z-index: 0; }
.porch__sky img { width: 100%; height: 100%; object-fit: cover; object-position: 72% 30%; opacity: .92; }
.porch__sky::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(94deg, rgba(23, 17, 38, .93) 0%, rgba(23, 17, 38, .82) 30%,
                    rgba(23, 17, 38, .45) 52%, rgba(23, 17, 38, .05) 74%, transparent 88%),
    linear-gradient(180deg, rgba(23, 17, 38, .45) 0%, transparent 18%),
    linear-gradient(180deg, transparent 70%, var(--dusk) 100%);
}
.porch > .column { position: relative; z-index: 1; }
.porch__grid { display: grid; grid-template-columns: minmax(0, 34rem); align-items: center; min-height: clamp(420px, 46vw, 560px); }
@media (max-width: 900px) { .porch__grid { grid-template-columns: minmax(0, 1fr); } }
.porch h1 {
  font-size: var(--step-banner); text-wrap: balance; letter-spacing: .04em; font-weight: 600;
  background: linear-gradient(180deg, var(--gold-lit) 0%, var(--leaf-gold) 58%, var(--gold-shadow) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 30px rgba(231, 179, 59, .28)) drop-shadow(0 2px 5px rgba(0, 0, 0, .5));
  padding-bottom: .08em;
}
.porch__lead { color: var(--gold-lit); font-size: 1.15rem; font-style: italic; margin: .8rem 0 0; }
.porch__sub { color: var(--vellum-soft); font-size: var(--step-sub); max-width: 46ch; margin: .9rem 0 0; }
.porch__cta { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 1.3rem; }
.porch__hint { color: var(--vellum-faint); font-size: .82rem; margin: .9rem 0 0; max-width: 46ch; }

/* the medallion strip — the eight gods as jewelry, from his page */
.pantheon { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 1.3rem; }
.pantheon img {
  width: 44px; height: 44px; border-radius: 50%; object-fit: cover;
  border: 2px solid var(--rule); cursor: pointer;
  transition: transform .16s, border-color .16s, box-shadow .16s;
}
.pantheon a:hover img { transform: scale(1.13); border-color: var(--leaf-gold); box-shadow: 0 0 20px rgba(231, 179, 59, .4); }


/* ---------------------------------------------------------------- tiles ---- */
.tiles { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: .8rem; }
@media (max-width: 1000px) { .tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 540px)  { .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.tile {
  background: var(--plate); border: 1px solid var(--rule); border-radius: var(--arch-md);
  box-shadow: 0 6px 18px rgba(5, 2, 14, .5); text-align: center; padding: 1.15rem .6rem 1.05rem;
}
.tile b { display: block; font-family: var(--face-display); font-weight: 600; font-size: 1.6rem; color: var(--gold-lit); }
.tile span { display: block; font: 700 var(--step-micro)/1.3 var(--face-text); letter-spacing: .12em; text-transform: uppercase; color: var(--vellum-soft); margin-top: .35rem; }

/* ---------------------------------------------------------------- cards ----
   THE CARD: white, rounded, soft shadow, art on top on a pastel tint, short
   body below. Doors, vistas, saga panels, beasts and posts all wear it. */
.plate {
  position: relative; overflow: hidden;
  background: var(--plate); border: 1px solid var(--rule);
  border-radius: var(--arch-md); box-shadow: var(--cast);
  transition: box-shadow var(--beat), transform var(--beat), border-color var(--beat);
}
a.plate:hover, .door:hover { box-shadow: var(--cast-far); }
a.plate:hover, .door:hover { transform: translateY(-3px); }
.plate--pad { padding: 1.25rem; }
.plate--pad h3 { color: var(--vellum); }
.plate--r2, .plate--r3 { border-color: var(--rule); }

.grid { display: grid; gap: clamp(.8rem, 1.6vw, 1.1rem); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1080px) { .grid--4 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 860px)  { .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); } }

/* a door: card with painting top, words below — never words ON the painting */
.gate { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(.8rem, 1.6vw, 1.1rem); }
@media (max-width: 1000px) { .gate { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .gate { grid-template-columns: minmax(0, 1fr); } }
.door {
  display: flex; flex-direction: column; overflow: hidden; color: inherit;
  background: var(--plate); border: 1px solid var(--rule);
  border-radius: var(--arch-md); box-shadow: var(--cast);
  transition: box-shadow var(--beat), transform var(--beat);
}
.door:hover { color: inherit; box-shadow: var(--cast-far); }
.door img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; transition: transform var(--pass) var(--swing); }
.door:hover img { transform: scale(1.045); }
.door__say { padding: .95rem 1.1rem 1.1rem; display: flex; flex-direction: column; gap: .3rem; flex: 1; }

.door__say p { color: var(--vellum-soft); font-size: .88rem; margin: 0; }
.door__say .rank { font-size: .62rem; }

/* a vista: the same card, big */
.vista { position: relative; display: flex; flex-direction: column; overflow: hidden; background: var(--plate); border: 1px solid var(--rule); border-radius: var(--arch-md); box-shadow: var(--cast); }
.vista img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.vista__say { padding: .95rem 1.1rem 1.05rem; display: flex; flex-direction: column; flex: 1; }

.vista__say p {
  color: var(--vellum-soft); margin: .3rem 0 0; font-size: .88rem; max-width: 58ch;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.vista.is-open .vista__say p { display: block; -webkit-line-clamp: none; }
.vista__more {
  align-self: flex-start; margin-top: .45rem; background: none; border: 0; padding: .3rem 0; min-height: 30px;
  cursor: pointer; font: 700 .66rem/1.4 var(--face-text); letter-spacing: .1em;
  text-transform: uppercase; color: var(--gold-soft);
}
.vista__more:hover { color: var(--accent, var(--gold-lit)); }
.vista__tag { position: absolute; top: .75rem; left: .8rem; z-index: 2; background: var(--plate); border-radius: var(--seal); padding: .3rem .7rem; font-size: .6rem; box-shadow: var(--cast); }

.strip { display: grid; gap: clamp(.8rem, 1.6vw, 1.1rem); grid-template-columns: repeat(4, minmax(0, 1fr)); }
.strip--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1200px) { .strip--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .strip--3 { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 1200px) { .strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .strip { grid-template-columns: minmax(0, 1fr); } }

/* the four story panels */
.saga { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(.7rem, 1.5vw, 1rem); }
@media (max-width: 900px) { .saga { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.saga figure { margin: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--plate); border: 1px solid var(--rule); border-radius: var(--arch-md); box-shadow: var(--cast); }
.saga img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; object-position: 50% 38%; }
.saga figcaption { padding: .8rem .95rem 1rem; font-size: .84rem; color: var(--vellum-soft); }
.saga figcaption b { display: block; font-family: var(--face-display); font-weight: 800; font-size: .98rem; color: var(--vellum); margin-bottom: .2rem; }

/* --------------------------------------------------------------- beasts ---- */
.beasts { display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 11.5rem)); justify-content: center; gap: .8rem; }
.beast { text-align: center; display: flex; flex-direction: column; overflow: hidden; }
.beast__art { background: var(--tint, var(--dusk-raised)); border-radius: calc(var(--arch-md) - 5px); margin: .55rem .55rem 0; padding: .8rem .4rem .5rem; }
.beast img { width: 100%; max-width: none; height: auto; aspect-ratio: 1; object-fit: contain; object-position: 50% 100%; margin: 0 auto; }
.beast b { display: block; font-family: var(--face-display); font-weight: 800; font-size: .82rem; color: var(--vellum); line-height: 1.25; padding: .55rem .5rem .7rem; margin-top: auto; }

/* ---------------------------------------------------------------- chips ---- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.chips--stick { position: sticky; top: var(--bar-h); z-index: 50; padding: .55rem .5rem; margin: 0 -0.5rem; background: linear-gradient(180deg, var(--dusk) 78%, transparent); }
.chips a, .chips button {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--vellum-soft); border: 1px solid var(--rule);
  padding: 7px 15px; border-radius: var(--seal); font: 600 .86rem/1 var(--face-text);
  background: var(--plate); cursor: pointer; box-shadow: 0 2px 6px rgba(5, 2, 14, .35);
  transition: border-color var(--tick), color var(--tick), background var(--tick), box-shadow var(--tick);
}
.chips a:hover, .chips button:hover { border-color: var(--gold-soft); color: var(--vellum); }
.chips .is-on, .chips a[aria-current] {
  border-color: var(--leaf-gold); color: var(--vellum);
  background: color-mix(in srgb, var(--leaf-gold) 12%, transparent); box-shadow: none;
}
/* 28px, not 21px. The emblems are detailed circular paintings and at 21px they read as
   coloured smudges: you cannot tell the Wallsworn shield from the Starspire book. Only the
   /classes/ god chips carry images (the /world/ region chips are text), so this is safe. */
.chips img { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; }

/* -------------------------------------------------------------- bestiary ----
   The grid is the same .beast card the world page already uses; these add the
   level badge, the element line, and the drop rows. */
.beasts--grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: .8rem; }
.beast--card { position: relative; text-align: center; }
.beast__lv {
  position: absolute; top: .5rem; left: .5rem; z-index: 2;
  font: 700 var(--step-micro)/1 var(--face-text); letter-spacing: .1em;
  text-transform: uppercase; color: var(--dusk);
  background: var(--accent, var(--leaf-gold)); border-radius: var(--seal);
  padding: .22rem .5rem;
}
.beast__el {
  display: block; margin-top: .2rem;
  font: 600 var(--step-micro)/1.4 var(--face-text); letter-spacing: .1em;
  text-transform: uppercase; color: var(--accent, var(--gold-soft));
}
/* items: the icon sits on a lit tile rather than bleeding into the card, and rarity is the
   one place a colour other than the page accent is allowed to speak. */
.item--card .beast__art { background: rgba(0, 0, 0, .28); border-radius: var(--arch-sm); padding: .5rem; }
.emblemslot--item { border-radius: var(--arch-md); }
.emblemslot--item img { border-radius: var(--arch-sm); object-fit: contain; padding: .4rem; }
.beast__el.r-legendary { color: var(--gold-lit); }
.beast__el.r-epic      { color: var(--mixed); }
.beast__el.r-rare      { color: var(--tank); }
.beast__el.r-uncommon  { color: var(--mend); }
.beast__el.r-common    { color: var(--vellum-faint); }

.beastentry { scroll-margin-top: calc(var(--bar-h) + 2rem); }
.beast__note { color: var(--vellum-soft); margin: .55rem 0 0; font-size: .93rem; max-width: 62ch; }
/* the anchored entry lights up so a jump from the grid is obvious */
:target > .beastentry { border-color: color-mix(in srgb, var(--accent, var(--leaf-gold)) 55%, var(--rule)); }

.drops { list-style: none; margin: .8rem 0 0; padding: 0; }
.drops li {
  display: flex; align-items: baseline; gap: .7rem;
  padding: .45rem 0; border-top: 1px dotted var(--rule);
  font-size: .9rem; color: var(--vellum-soft);
}
.drops li b { color: var(--vellum); font-weight: 600; flex: 1; }
.drop__pct { color: var(--mend); font-weight: 700; font-variant-numeric: tabular-nums; }
.drop__n { color: var(--vellum-faint); font-size: .82rem; min-width: 4ch; text-align: right; }

/* ----------------------------------------------------------- page backdrop ---
   The layer the whole site is translucent OVER. canon/oaths-of-lumoria.html:261 does this
   with `position:fixed; z-index:-1` — we must NOT copy that. Per HANDOFF.md §4, fixed +
   negative z-index is the exact pattern that suppressed the raster of every lazily-decoded
   image on this site. Same effect, safe construction: the layer sits at z-index 0 and the
   topbar / .shell / footer are lifted to 1, so nothing ever needs a negative index.
   The top 14% is masked out so the backdrop's warm sky edge cannot tint the topbar. */
/* NOT lazy, and the reason is measured: as `loading="lazy"` inside this position:fixed box
   the browser never counted it as entering the viewport, so it never fetched. At a real
   375px viewport it reported complete:false, naturalWidth:0, no currentSrc — the backdrop
   was simply absent. It is emitted eager but `decoding="async"`, deliberately NOT the
   fetchpriority=high + decoding=sync pair img() gives eager images: that pair is reserved
   for the LCP hero (HANDOFF §4), and a full-viewport image decoding synchronously is the
   shape of the bug that painted the hero black. 17 KB at 1920, so eager costs nothing. */
.pagebg { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.pagebg img {
  width: 100%; height: 100%; object-fit: cover; opacity: .22;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 14%);
          mask-image: linear-gradient(180deg, transparent 0, #000 14%);
}
.topbar, .shell, .footing, .skip { position: relative; z-index: 1; }

/* ------------------------------------------------------------- god panel --- */
.godpanel {
  position: relative; overflow: hidden;
  /* Translucent so the page backdrop reads through. Opaque --plate/--dusk-raised meant the
     panel sat ON the page instead of IN it. */
  background: linear-gradient(168deg, rgba(34, 26, 56, .86) 0%, rgba(30, 23, 48, .8) 70%);
  border: 1px solid var(--rule);
  border-radius: var(--arch-lg); box-shadow: var(--cast-far), 0 0 0 1px rgba(231, 179, 59, .07);
  scroll-margin-top: calc(var(--bar-h) + 4.4rem);
}
.godpanel + .godpanel { margin-top: 2rem; }
/* FOUR stops, not two. canon:51 ramps the band across --c1..--c4 so it shifts hue and
   BRIGHTENS to the right. Ours ran accent -> accent-dim, i.e. straight into the dark, so the
   band died halfway across and the panel lost its light source. */
.godpanel__band {
  height: 6px;
  background: linear-gradient(90deg,
    var(--accent-dim, var(--gold-shadow)) 0%,
    var(--accent, var(--leaf-gold)) 32%,
    color-mix(in srgb, var(--accent, var(--leaf-gold)) 55%, #fff8e2) 66%,
    var(--leaf-gold) 100%);
}
.godpanel__in { padding: clamp(1.2rem, 3vw, 1.9rem) clamp(1rem, 3vw, 2rem); position: relative; z-index: 1; }
/* The god's own plate art, ghosted into their own panel. canon:.cardbg — this is what gives
   each panel its own weather instead of seven identically-tinted rectangles. */
.godpanel .cardbg {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: .08; filter: blur(3px) saturate(.85); pointer-events: none; z-index: 0;
}

.godhead { display: grid; grid-template-columns: 96px minmax(0, 1fr) 360px; gap: 22px; align-items: center; }
@media (max-width: 980px) {
  .godhead { grid-template-columns: 76px minmax(0, 1fr); }
  .godhead .godkeyart { grid-column: 1 / -1; }
}
/* The medallion GLOWS. canon/oaths-of-lumoria.html:55 lights it with a 38px accent halo over
   a radial fill; ours had a flat ring on a flat fill and read as a sticker. */
.emblemslot {
  width: 96px; height: 96px; border: 2px solid var(--accent, var(--rule)); border-radius: 50%;
  overflow: hidden; align-self: start;
  background: radial-gradient(circle, var(--accent-glow, transparent), rgba(0, 0, 0, .45) 78%);
  box-shadow: 0 0 38px var(--accent-glow, transparent), var(--cast);
}
.emblemslot img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
@media (max-width: 980px) { .emblemslot { width: 76px; height: 76px; } }

/* The god's name is the brightest thing in the panel and it must RADIATE. canon:59 carries
   `text-shadow:0 0 26px var(--accentglow)`; we had none, which is most of why ours read flat. */
.godtitle h2 {
  font-size: 1.85rem; color: var(--accent, var(--gold-lit)); letter-spacing: .04em;
  text-transform: uppercase; font-weight: 600;
  text-shadow: 0 0 26px var(--accent-glow, transparent);
}
/* The order line is a TITLE, not a caption. canon:60 sets it in the serif at small-caps,
   1.04em, in full ink. Ours was .72rem uppercase sans in --vellum-faint, i.e. system chrome:
   "the Wildhunt" reads as a name, "THE WILDHUNT · THE HUNT LODGE" reads as a database key. */
.godtitle .order {
  font: 400 1.04rem/1.4 var(--face-display); font-variant: small-caps; letter-spacing: .16em;
  text-transform: none; color: var(--vellum); margin-top: 2px;
}
.godtitle .creed { font-style: italic; color: var(--vellum-soft); margin: 4px 0 0; }
.godtitle .lore { color: var(--vellum-soft); margin: 8px 0 0; max-width: 62ch; font-size: .93rem; }
.godkeyart { border-radius: var(--arch-md); overflow: hidden; border: 1px solid var(--rule); box-shadow: var(--cast); }
.godkeyart img { width: 100%; height: 100%; max-height: 240px; object-fit: cover; }

.factsrow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin-top: 16px; }
@media (max-width: 860px) { .factsrow { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.fact {
  border: 1px solid var(--rule); border-radius: var(--arch-sm); padding: 8px 14px;
  font-size: .82rem; color: var(--vellum-soft); background: rgba(0, 0, 0, .3);
  display: flex; flex-direction: column; justify-content: center;
}
.fact b { color: var(--vellum); font-weight: 600; font-size: .95rem; }
.fact .k { font: 700 var(--step-micro)/1.4 var(--face-text); letter-spacing: .12em; text-transform: uppercase; color: var(--accent, var(--vellum-faint)); }

/* collapsible rows */
details.more { margin-top: 14px; border: 1px solid var(--rule); border-radius: var(--arch-md); background: rgba(0, 0, 0, .18); }
details.more > summary {
  cursor: pointer; list-style: none; padding: 14px 18px;
  color: var(--accent, var(--gold-soft)); font: 800 .8rem/1.4 var(--face-display);
  letter-spacing: .12em; text-transform: uppercase;
  display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap;
}
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::before { content: "▸ "; }
details.more[open] > summary::before { content: "▾ "; }
details.more > summary .tprev { color: var(--vellum-faint); font: 400 italic .85rem/1.4 var(--face-text); letter-spacing: normal; text-transform: none; }
details.more .morein { padding: 4px 18px 20px; }
/* folds open by animating their own height (see THE MOTION LAYER at the foot
   of this file). Nothing here animates opacity on content, ever. */

.secnav { display: flex; justify-content: space-between; margin-top: 18px; gap: .6rem; flex-wrap: wrap; }

/* the system folds on /oath/: a door-card summary with the detail beneath */
details.sysfold { border: 1px solid var(--rule); border-radius: var(--arch-md); background: var(--plate); box-shadow: var(--cast); overflow: hidden; scroll-margin-top: calc(var(--bar-h) + 1rem); }
details.sysfold + details.sysfold { margin-top: .9rem; }
details.sysfold > summary { list-style: none; cursor: pointer; display: grid; grid-template-columns: 300px minmax(0, 1fr) auto; gap: 1.1rem; align-items: center; padding-right: 1.2rem; }
details.sysfold > summary::-webkit-details-marker { display: none; }
details.sysfold > summary img { width: 300px; height: 128px; object-fit: cover; }
details.sysfold > summary h3 { font-size: 1.25rem; }
details.sysfold > summary p { margin: .15rem 0 0; color: var(--vellum-soft); font-size: .86rem; }
details.sysfold > summary .fold-cue { font: 800 .72rem/1 var(--face-display); letter-spacing: .1em; text-transform: uppercase; color: var(--accent, var(--gold-soft)); white-space: nowrap; }
details.sysfold[open] > summary .fold-cue::after { content: " ▴"; }
details.sysfold:not([open]) > summary .fold-cue::after { content: " ▾"; }
details.sysfold > .morein { padding: .4rem 1.3rem 1.5rem; border-top: 1px solid var(--rule-faint); }
.foldnext { margin: 1.4rem 0 0; padding-top: .9rem; border-top: 1px dotted var(--rule);
  font-size: .88rem; color: var(--vellum-faint); }
@media (max-width: 700px) {
  details.sysfold > .morein, details.more .morein { padding-left: .6rem; padding-right: .6rem; }
  details.sysfold > summary { grid-template-columns: minmax(0, 1fr); padding: 0 0 .9rem; }
  details.sysfold > summary img { width: 100%; height: 140px; }
  details.sysfold > summary h3, details.sysfold > summary p, details.sysfold > summary .fold-cue { padding: 0 1rem; }
}

/* ------------------------------------------------------------------ tree --- */
/* the level rail — one marker per tier band, sitting on the connector line */
.tier { display: flex; justify-content: center; margin: 12px 0 2px; }
.tier span {
  display: inline-flex; align-items: baseline; gap: .5rem;
  font: 700 var(--step-micro)/1 var(--face-text); letter-spacing: .16em;
  text-transform: uppercase; color: var(--accent, var(--gold-soft));
  background: var(--dusk); border: 1px solid var(--rule);
  border-radius: var(--seal); padding: .34rem .8rem;
}
.tier em { font-style: normal; letter-spacing: .1em; color: var(--vellum-faint); }
.branch > .tier { margin-top: 2px; }

.tree { margin-top: 4px; }
.root { display: flex; justify-content: center; margin-top: 10px; }
.root > .oath { min-width: min(300px, 100%); max-width: 430px; }
.stem { width: 2px; height: 20px; margin: 0 auto; background: var(--rule); }
.branches { display: flex; gap: 18px; align-items: stretch; position: relative; padding-top: 18px; }
.branches::before { content: ""; position: absolute; top: 0; left: 25%; right: 25%; height: 2px; background: var(--rule); }
.branch {
  flex: 1; display: flex; flex-direction: column; position: relative;
  border: 1px solid var(--rule-faint); border-radius: var(--arch-md);
  padding: 14px 12px 12px; background: rgba(0, 0, 0, .16);
}
.branch::before { content: ""; position: absolute; top: -18px; left: 50%; width: 2px; height: 18px; background: var(--rule); }
.leaves { display: flex; gap: 10px; position: relative; padding-top: 16px; }
.leaves::before { content: ""; position: absolute; top: 0; left: 25%; right: 25%; height: 2px; background: var(--rule); }
.leaves > .oath { position: relative; flex: 1; }
.leaves > .oath::before { content: ""; position: absolute; top: -16px; left: 50%; width: 2px; height: 16px; background: var(--rule); }
.branch > .oath { margin-bottom: 10px; }
@media (max-width: 900px) {
  .branches { flex-direction: column; padding-top: 0; }
  .branches::before, .branch::before { display: none; }
}
@media (max-width: 560px) {
  .leaves { flex-direction: column; padding-top: 0; }
  .leaves::before, .leaves > .oath::before { display: none; }
  .branch { padding: 10px 0 8px; border: 0; background: none; }
}

/* TRANSLUCENT, not opaque. This is the single biggest reason our panels read flat next to
   canon/oaths-of-lumoria.html: every nested surface there is translucent black over the
   panel (canon:102 .node rgba(0,0,0,.34), :66 .fact .3, :98 .branch .16, :126 details.more
   .18), so the panel gradient, the accent halo and the page backdrop all show through. Ours
   painted opaque --plate / --dusk rectangles, which block the halo completely. */
.oath {
  position: relative; display: block; scroll-margin-top: calc(var(--bar-h) + 1rem);
  background: rgba(0, 0, 0, .34); border: 1px solid var(--rule);
  border-left: 4px solid var(--role-c, var(--leaf-gold));
  border-radius: var(--arch-sm); padding: 11px 13px; box-shadow: var(--cast);
}
.oath--root { border-left-color: var(--leaf-gold); background: linear-gradient(160deg, rgba(234, 179, 44, .10), var(--plate) 60%); }
.oath h3 { font-size: 1.1rem; display: inline; letter-spacing: .01em; }
.oath__line { display: inline-flex; align-items: center; margin-left: 7px; font: 800 .58rem/1 var(--face-text); letter-spacing: .07em; text-transform: uppercase; vertical-align: 2px; color: var(--dusk); background: var(--role-c, var(--gold-soft)); padding: .28rem .55rem; border-radius: var(--seal); }
.oath__line i { display: none; }
.oath__stat { font: 600 .68rem/1 var(--face-text); color: var(--gold-soft); margin-left: 6px; }
.oath__wpn { font-size: .78rem; color: var(--vellum-faint); display: block; margin-top: 3px; font-style: italic; }

.oath__row { display: flex; align-items: baseline; gap: 1rem; justify-content: space-between; flex-wrap: wrap; }
.oath__row details { flex: 1; min-width: 0; }
.oath__peek {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: 700 .68rem/1.4 var(--face-text); letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent, var(--gold-soft)); transition: color var(--tick);
  min-height: 30px;
}
.oath__peek:hover { color: var(--accent-dim, var(--gold-lit)); }

.oath details { margin-top: 7px; }
.oath summary { cursor: pointer; min-height: 30px; display: flex; align-items: center; font: 700 .68rem/1.4 var(--face-text); color: var(--accent, var(--ivy-deep)); letter-spacing: .1em; text-transform: uppercase; list-style: none; }
.oath summary::-webkit-details-marker { display: none; }
.oath summary::before { content: "▸ "; }
.oath details[open] summary::before { content: "▾ "; }
.oath__kit { list-style: none; margin: 6px 0 0; padding: 0; }
.oath__kit li { font-size: .84rem; color: var(--vellum-soft); padding: 4px 0; border-top: 1px dotted var(--rule); }
.oath__kit b { color: var(--vellum); font-weight: 600; }
/* The one-line stand-in for a node's inherited skills. Replaces the old per-row "· kept"
   tag, which required printing all of them: 64% of every tree was duplicated text. */
.oath__kit .kept-note {
  font-style: italic; color: var(--vellum-faint); border-top: none;
  padding-bottom: 6px; margin-bottom: 2px; border-bottom: 1px dotted var(--rule);
}
.oath__kit .ult { background: color-mix(in srgb, var(--leaf-gold) 10%, transparent); border-radius: 6px; padding-left: 6px; border-top: none; margin-top: 6px; }
.oath__kit .ult b { color: var(--gold-lit); }
.oath__kit .ult::before { content: "✦ "; color: var(--gold-lit); font-size: .85em; }

/* The role chips (TANK, DPS, SUPPORT…) are FILLED PILLS: the role colour is the
   background and the label is punched out of it in `--dusk`, set on .oath__line.
   There used to be a `.r-tank { color: var(--tank) }` rule per role here, left over
   from an earlier coloured-dot-plus-coloured-text treatment. Equal specificity to
   .oath__line and later in the file, so it won the cascade and repainted every label
   in the SAME colour as the pill behind it: 49 solid lozenges with invisible text.
   The `<i>` dot those rules also styled has been `display: none` since the pill
   landed. Do not reintroduce a bare `.r-*` colour rule; scope it to a descendant if
   a role colour is ever needed as ink again. */

/* SCOPED TO #accord. This hides the six unselected god panels in the /classes/ switcher.
   Unscoped it hid EVERY .godpanel on the site the moment JS loaded, because only the
   switcher ever adds .is-on (site.js queries inside #accord). That made the panel language
   unusable on any other page: the first one placed on /world/ would render, then vanish. */
.js #accord .godpanel:not(.is-on) { display: none; }
.allnames { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: .9rem; }
.allnames section { background: var(--plate); border: 1px solid var(--rule); border-radius: var(--arch-md); box-shadow: var(--cast); padding: .9rem 1rem 1rem; border-top: 3px solid var(--g, var(--leaf-gold)); }
.allnames h3 { color: var(--g, var(--gold-lit)); font-size: 1rem; margin-bottom: .35rem; }
.allnames a { display: block; padding: .32rem 0; color: var(--vellum-soft); font-size: .9rem; border-top: 1px dotted var(--rule-faint); }
.allnames a:hover { color: var(--gold-lit); }
.js .allnames { display: none; }
.js .is-all .allnames { display: grid; }
.js .is-all .godpanel { display: none; }
.js .godpanel { animation: tabfade .28s ease-out; }
/* movement only — NEVER animate opacity on content; ghosted-content bugs, twice */
@keyframes tabfade { from { transform: translateY(8px); } to { transform: none; } }

/* ---------------------------------------------------------------- sift ----- */
.sift {
  position: sticky; top: var(--bar-h); z-index: 40;
  display: flex; flex-wrap: wrap; gap: .45rem; align-items: center;
  padding: .7rem 0; margin-bottom: 1rem;
  background: var(--dusk); box-shadow: 0 1px 0 var(--rule);
}
.sift input {
  background: var(--plate); border: 1px solid var(--rule-field); color: var(--vellum);
  border-radius: var(--seal); padding: .5rem 1rem; font: inherit; font-size: .88rem; min-width: 15rem;
}
.sift input:focus { outline: none; border-color: var(--gold-soft); }
.sift input::placeholder { color: var(--vellum-faint); }
.sift__key {
  background: var(--plate); border: 1px solid var(--rule); color: var(--vellum-soft);
  border-radius: var(--seal); padding: .45rem .85rem; cursor: pointer;
  font: 700 .7rem/1 var(--face-text); letter-spacing: .08em; text-transform: uppercase;
  transition: border-color var(--tick), color var(--tick), background var(--tick);
}

/* ---------------------------------------------------------------- ledger --- */
.scroller { overflow-x: auto; overscroll-behavior-x: contain; }
.ledger { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .9rem; }
.ledger caption { text-align: left; color: var(--vellum-faint); font-size: .85rem; padding-bottom: .6rem; }
.ledger th {
  text-align: left; font: 700 var(--step-micro)/1.4 var(--face-text);
  letter-spacing: .12em; text-transform: uppercase; color: var(--accent, var(--vellum-faint));
  padding: .55rem .75rem; box-shadow: 0 1px 0 var(--rule-strong);
}
.ledger th[data-sort] { cursor: pointer; user-select: none; }
.ledger th[data-sort]:hover { color: var(--vellum); }
.ledger th[aria-sort]::after { content: " ▾"; opacity: .8; }
.ledger th[aria-sort="ascending"]::after { content: " ▴"; }
.ledger td { padding: .6rem .75rem; color: var(--vellum-soft); box-shadow: 0 1px 0 var(--rule-faint); vertical-align: top; }
.ledger tbody tr:hover td { background: color-mix(in srgb, var(--leaf-gold) 6%, transparent); color: var(--vellum); }
.ledger b { color: var(--vellum); font-weight: 600; }
.ledger .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ledger--sticky1 td:first-child, .ledger--sticky1 th:first-child {
  position: sticky; left: 0; background: var(--dusk); z-index: 2;
}
.ledger tr.kept td { color: var(--vellum-faint); }
.ledger tr.ult b { color: var(--gold-lit); }
.ledger td:last-child { max-width: 20rem; }

.matrix { border-collapse: collapse; font-size: .8rem; min-width: 44rem; }
.matrix th, .matrix td { border: 1px solid var(--rule); padding: .38rem .45rem; text-align: center; }
.matrix thead th, .matrix tbody th {
  font: 700 .64rem/1.3 var(--face-text); letter-spacing: .06em; text-transform: uppercase;
  color: var(--order, var(--vellum-soft)); background: var(--dusk);
}
.matrix tbody th { text-align: left; white-space: nowrap; position: sticky; left: 0; z-index: 2; }
.matrix td { color: var(--vellum-soft); }
.matrix td.self { background: repeating-linear-gradient(135deg, transparent 0 5px, rgba(5, 2, 14, .35) 5px 10px); }
.matrix td.locked { color: var(--gold-lit); background: color-mix(in srgb, var(--leaf-gold) 12%, transparent); font-weight: 700; }
.matrix tr.sealed th, .matrix tr.sealed td { color: var(--vellum-soft); background: rgba(58, 47, 26, .06); font-style: italic; }

.gate--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1000px) { .gate--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .gate--4 { grid-template-columns: minmax(0, 1fr); } }
.door--more { border-style: dashed; border-color: var(--rule-strong); align-items: center; justify-content: center; }
.door--more h3 { color: var(--gold-lit); }

/* --------------------------------------------------------------- lists ----- */
.lines { list-style: none; margin: 0; padding: 0; }
.lines li { position: relative; padding: .36rem 0 .36rem 1.35rem; color: var(--vellum-soft); }
.lines li::before { content: "✦"; position: absolute; left: 0; top: .36rem; font-size: .78em; color: var(--accent, var(--gold-soft)); }
.lines b { color: var(--vellum); font-weight: 600; }

.pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(1rem, 3vw, 2.2rem); align-items: start; }
.pair--stretch { align-items: stretch; }
.pair--stretch > .plate--pad { display: flex; flex-direction: column; }
.pair--stretch > .plate--pad .btn { margin-top: auto; }
@media (max-width: 900px) { .pair { grid-template-columns: minmax(0, 1fr); } }

/* --------------------------------------------------------------- coins ----- */
.coin { padding: 1.2rem; display: flex; flex-direction: column; }
.coin__face {
  width: 46px; height: 46px; border-radius: 50%; margin-bottom: .8rem;
  background: radial-gradient(circle at 34% 30%, var(--tint-lit, var(--gold-lit)), var(--tint, var(--leaf-gold)) 62%, var(--tint-dim, var(--gold-shadow)) 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4), var(--cast);
  display: grid; place-items: center;
}
.coin__face .gem { color: rgba(66, 47, 11, .6); }

.coin__rank { font: 700 .64rem/1.4 var(--face-text); letter-spacing: .14em; text-transform: uppercase; color: var(--vellum-faint); margin: .3rem 0 .6rem; }
.coin dl { margin: 0; font-size: .86rem; }
.coin dt { color: var(--vellum-faint); font-size: .64rem; letter-spacing: .12em; text-transform: uppercase; margin-top: .55rem; }
.coin dd { margin: .16rem 0 0; color: var(--vellum-soft); }

/* --------------------------------------------------------------- ladder ---- */
.ladder { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(.7rem, 1.5vw, 1rem); }
@media (max-width: 860px) { .ladder { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ladder figure { margin: 0; }
.ladder figcaption { padding: .7rem .9rem .95rem; }
.ladder figcaption b { display: block; font-family: var(--face-display); font-weight: 800; font-size: 1rem; }
.ladder figcaption span { display: block; font: 700 .62rem/1.4 var(--face-text); letter-spacing: .13em; text-transform: uppercase; color: var(--vellum-faint); margin-top: .25rem; }
.ladder img { width: 100%; aspect-ratio: 3 / 4; object-fit: contain; object-position: 50% 88%; background: var(--dusk-raised); }

/* --------------------------------------------------------------- posts ----- */
.post { display: block; padding: 1.05rem 1.2rem; color: inherit; }
.post:hover { color: inherit; }
.post time { font-size: .76rem; color: var(--vellum-faint); }
.post h3 { margin: .3rem 0 .35rem; }
.post p { color: var(--vellum-soft); font-size: .88rem; margin: 0; }
.post__more { display: inline-block; margin-top: .6rem; font: 700 .68rem/1.4 var(--face-text); letter-spacing: .12em; text-transform: uppercase; color: var(--star); }

/* --------------------------------------------------------- the wax seal ----
   The one deliberately DARK card on the light page — the night moment. */
.seal-panel {
  border: 1px solid rgba(231, 179, 59, .28); border-radius: var(--arch-md);
  background:
    radial-gradient(90% 140% at 8% 50%, rgba(231, 179, 59, .10), transparent 55%),
    linear-gradient(168deg, #251d42, #161027 75%);
  overflow: hidden; color: var(--vellum-soft); box-shadow: var(--cast-far);
}
.seal-panel > summary { list-style: none; cursor: pointer; padding: 1.05rem 1.25rem; display: flex; align-items: center; gap: 1rem; }
.seal-panel > summary::-webkit-details-marker { display: none; }
.wax {
  flex: none; width: 40px; height: 40px; border-radius: 50%; position: relative;
  background: radial-gradient(circle at 34% 30%, var(--gold-soft), #3a2f1a 74%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.14);
  transition: rotate var(--pass) var(--swing);
}
.wax::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: linear-gradient(158deg, transparent 46%, rgba(234, 179, 44, .75) 47%, rgba(234, 179, 44, .75) 49%, transparent 50%);
}
.seal-panel[open] .wax { rotate: -8deg; }
.seal-panel summary b { font-family: var(--face-display); font-weight: 600; font-size: 1.05rem; color: var(--gold-lit); }
.seal-panel summary span { display: block; font-size: .82rem; color: var(--vellum-faint); margin-top: .12rem; }
.seal-panel__body { padding: 0 1.25rem 1.2rem; max-width: 66ch; }
.seal-panel__body a { color: var(--gold-lit); }
.seal-panel__body img { border-radius: var(--arch-sm); margin-bottom: 1rem; }

/* the big closing CTA band */
.callband {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  overflow: hidden; border-radius: var(--arch-lg);
  box-shadow: var(--cast-far), 0 0 0 1px rgba(231, 179, 59, .35);
  background: linear-gradient(120deg, #2a2145, #1a142e);
}
@media (max-width: 800px) { .callband { grid-template-columns: minmax(0, 1fr); } }
.callband__say { padding: clamp(1.4rem, 4vw, 2.6rem); }
.callband__say .rank { color: var(--gold-soft); }
.callband__say h2 {
  margin-top: .4rem; letter-spacing: .06em;
  background: linear-gradient(180deg, var(--gold-lit) 0%, var(--leaf-gold) 58%, var(--gold-shadow) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.callband__say p { color: var(--vellum-soft); margin: .6rem 0 1.1rem; max-width: 44ch; }
.callband__art { position: relative; }
.callband__art::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, #221a38 0%, transparent 30%); }
.callband__art img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------- footing --- */
.footing { border-top: 1px solid var(--rule-faint); background: color-mix(in srgb, var(--dusk) 88%, black); padding: 2rem 0 1.2rem; }
.footing__end { display: flex; align-items: center; justify-content: space-between; gap: 1rem 2rem; flex-wrap: wrap; }
.footing__end p { color: var(--vellum-soft); font-size: .9rem; margin: 0; max-width: 46ch; }
.footing__acts { display: flex; gap: .6rem; flex-wrap: wrap; }
.footing__legal { margin-top: 1.1rem; padding-top: .8rem; color: var(--vellum-faint); font-size: .8rem; text-align: center; position: relative; }
.footing__legal::before { content: ""; position: absolute; top: 0; left: 20%; right: 20%; height: 1px; background: var(--rule); }

/* --------------------------------------------------------------- loupe ----- */
.loupe { position: fixed; inset: 0; z-index: 200; display: none; align-items: center; justify-content: center; padding: 2rem; background: color-mix(in srgb, var(--dusk) 90%, black); }
.loupe.is-open { display: flex; }
.loupe img { max-width: min(92vw, 880px); max-height: 84vh; border-radius: 14px; background: var(--plate); }
.loupe figcaption { position: absolute; bottom: 1.3rem; left: 0; right: 0; text-align: center; color: var(--gold-lit); font: 700 .72rem/1.4 var(--face-text); letter-spacing: .15em; text-transform: uppercase; }
.loupe__shut { position: absolute; top: 1rem; right: 1.2rem; }
.loupe__prev, .loupe__next { position: absolute; top: 50%; translate: 0 -50%; }
.loupe__prev { left: 1.1rem; }
.loupe__next { right: 1.1rem; }

/* --------------------------------------------------------------- misc ------ */
.tally { font: 600 .78rem/1 var(--face-text); padding: .38rem .7rem; border-radius: var(--seal); border: 1px solid var(--rule); color: var(--vellum-soft); background: var(--plate); transition: border-color var(--tick), color var(--tick); }
.tally:hover { border-color: var(--gold-soft); color: var(--vellum); }

.node {
  position: relative; display: block; padding: .55rem .8rem;
  background: var(--plate); border: 1px solid var(--rule);
  border-radius: var(--arch-sm); color: var(--vellum); box-shadow: var(--cast);
  font: 700 .84rem/1.3 var(--face-display); text-align: center;
  transition: border-color var(--tick), transform var(--tick);
}
.node small { display: block; font: 600 .62rem/1.3 var(--face-text); letter-spacing: .1em; text-transform: uppercase; color: var(--vellum-faint); margin-top: .2rem; }
.node:hover { border-color: var(--gold-soft); transform: translateY(-2px); }


.modpath { font: 500 .72rem/1.4 ui-monospace, 'Cascadia Mono', Consolas, monospace; color: var(--vellum-faint); word-break: break-word; }

.keyart { float: right; width: clamp(180px, 30vw, 360px); margin: 0 0 1.2rem 1.6rem; }
.keyart img { width: 100%; height: auto; border-radius: var(--arch-lg); border: 1px solid var(--rule); box-shadow: var(--cast); }
@media (max-width: 700px) { .keyart { float: none; margin: 0 0 1.2rem; width: min(60vw, 240px); } }

.faq { border: 1px solid var(--rule); border-radius: var(--arch-md); background: var(--plate); box-shadow: var(--cast); }
.faq + .faq { margin-top: .5rem; }
.faq > summary { cursor: pointer; list-style: none; padding: .9rem 1.15rem; font: 700 var(--step-card)/1.4 var(--face-display); color: var(--vellum); }
.faq > summary::-webkit-details-marker { display: none; }
.faq > summary::before { content: "▸ "; color: var(--gold-soft); }
.faq[open] > summary::before { content: "▾ "; }
.faq p { margin: 0; padding: 0 1.15rem 1.05rem; color: var(--vellum-soft); max-width: 70ch; }

.prose p { color: var(--vellum-soft); }
.prose b { color: var(--vellum); }

/* ------------------------------------------------------------- edit mode ---
   Localhost only (site.js gates it). The glow marks what the keeper may touch. */
.quill {
  position: fixed; left: 14px; bottom: 14px; z-index: 250;
  display: flex; gap: 8px; align-items: center;
  background: var(--plate); border: 1px solid var(--rule); border-radius: var(--seal);
  padding: 7px 9px; box-shadow: var(--cast-far);
}
.quill__note { font-size: .74rem; color: var(--vellum-faint); max-width: 30ch; }
.is-editing [data-edit], .is-editing .is-editable {
  outline: 1px dashed rgba(231, 179, 59, .55); outline-offset: 3px; border-radius: 3px;
  cursor: text;
}
.is-editing [data-edit]:focus, .is-editing .is-editable:focus {
  outline: 2px solid var(--leaf-gold); background: rgba(231, 179, 59, .07);
}

/* every clickable disclosure answers the pointer the same way */
details > summary { transition: background var(--tick), color var(--tick); border-radius: var(--arch-sm); }
details > summary:hover { background: color-mix(in srgb, var(--leaf-gold) 7%, transparent); }
.vista { transition: transform var(--beat), box-shadow var(--beat); }
.vista:hover { transform: translateY(-3px); box-shadow: var(--cast-far); }

/* ============================================================ THE MOTION LAYER ==
   How the site should feel: things move, lift and catch light. Nothing fades
   in. Two earlier reveal effects animated opacity on content and left whole
   sections ghosted in real screenshots — that class of effect is banned here,
   not merely tuned down. Everything below animates transform, height, shadow,
   border or colour, so a failed or unsupported animation can only ever leave
   content fully visible.

   Every block is inert under `prefers-reduced-motion: reduce` (bottom of file).
   ============================================================================ */

/* ---- folds open instead of snapping --------------------------------------
   `interpolate-size` lets height animate to `auto`; `::details-content` is the
   fold's own box. Where unsupported the fold just snaps open as before. */
@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }
  details::details-content {
    height: 0; overflow: clip;
    transition: height var(--beat) var(--swing), content-visibility var(--beat) allow-discrete;
  }
  details[open]::details-content { height: auto; }
}

/* the fold's arrow turns rather than swapping character */
details > summary { position: relative; }
.faq > summary::before,
details.more > summary::before,
.oath summary::before {
  display: inline-block;
  transition: rotate var(--beat) var(--swing);
}
.faq[open] > summary::before,
details.more[open] > summary::before,
.oath details[open] summary::before { rotate: 90deg; }
details.sysfold > summary .fold-cue { transition: color var(--tick), transform var(--beat) var(--swing); }
details.sysfold[open] > summary .fold-cue { transform: translateY(-1px); }

/* ---- moving between pages ------------------------------------------------
   A browser-managed cross-document transition: it snapshots the outgoing page,
   so our own content is never mid-opacity. Chrome-only today; elsewhere pages
   simply swap as they always did. The bar is named so it holds still while the
   body changes underneath it. */
@view-transition { navigation: auto; }
.topbar { view-transition-name: lumoria-bar; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation-duration: .22s; }
  ::view-transition-new(root) { animation-duration: .26s; }
}

/* ---- cards answer the pointer -------------------------------------------- */
.vista { overflow: hidden; }
.vista img { transition: transform var(--pass) var(--swing); }
.vista:hover img { transform: scale(1.045); }

.tile { transition: transform var(--beat) var(--swing), box-shadow var(--beat), border-color var(--beat); }
.tile:hover { transform: translateY(-2px); border-color: var(--rule-strong); box-shadow: var(--cast-far); }

.beast { transition: transform var(--beat) var(--swing), border-color var(--beat); }
.beast:hover { transform: translateY(-2px); border-color: var(--rule-strong); }
.beast img { transition: transform var(--beat) var(--swing); }
.beast:hover img { transform: scale(1.06) translateY(-2px); }

/* ---- the class cards answer the pointer -----------------------------------
   canon:103 lights a node's border to the god's accent on hover. Ours had no hover
   state at all, so 49 cards sat inert under the cursor. Border and lift only: no
   opacity, nothing scroll-driven, so a card can never strand mid-transition. */
.oath { transition: transform var(--beat) var(--swing), border-color var(--beat), box-shadow var(--beat), background var(--beat); }
.oath:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--role-c, var(--leaf-gold)) 55%, var(--rule));
  background: rgba(0, 0, 0, .26);
  box-shadow: var(--cast-far);
}
.fact { transition: border-color var(--beat), background var(--beat); }
.fact:hover { border-color: color-mix(in srgb, var(--accent, var(--leaf-gold)) 40%, var(--rule)); background: rgba(0, 0, 0, .22); }

details.more { transition: border-color var(--beat), background var(--beat); }
details.more:hover { border-color: color-mix(in srgb, var(--accent, var(--leaf-gold)) 34%, var(--rule)); }
details.more[open] { background: rgba(0, 0, 0, .26); }

/* ---- the medallion answers the pointer ------------------------------------
   The emblem is the one piece of per-god identity on the panel, so it gets the
   strongest pointer response on the page: it lifts, and its halo opens up. */
.emblemslot { transition: transform var(--beat) var(--swing), box-shadow var(--beat), border-color var(--beat); }
.emblemslot:hover {
  transform: scale(1.06);
  border-color: color-mix(in srgb, var(--accent, var(--leaf-gold)) 70%, #fff8e2);
  box-shadow: 0 0 64px var(--accent-glow, transparent), var(--cast-far);
}
.emblemslot img { transition: transform var(--beat) var(--swing); }
.emblemslot:hover img { transform: scale(1.04); }

.chips a, .chips button { transition: border-color var(--tick), color var(--tick), background var(--tick), transform var(--tick); }
.chips a:hover, .chips button:hover { transform: translateY(-1px); }
.chips .is-on, .chips a[aria-current] { transform: none; }

.tally, .node { transition: border-color var(--tick), color var(--tick), transform var(--tick), box-shadow var(--tick); }
.tally:hover { transform: translateY(-1px); }

.pantheon img { transition: transform var(--beat) var(--swing), border-color var(--beat), box-shadow var(--beat); }

/* the primary button catches light across its face */
.btn--primary { background-size: 100% 100%; transition: box-shadow var(--tick), transform var(--tick), filter var(--tick); }
.btn--primary:hover { filter: brightness(1.04); }

/* ---- the god panel arrives from the direction you clicked ---------------- */
.js .godpanel { animation: panel-in var(--beat) var(--swing) both; }
/* Rise and fade. The blanket "never animate opacity" ban was lifted 2026-07-25; the rule
   that replaced it is that the animation must END at opacity 1 and must not depend on a
   scroll observer to get there. This runs on click, uses fill-mode `both`, and the panel
   is display:none when not selected — so it can never strand at partial opacity. */
@keyframes panel-in {
  from { transform: translateY(10px) scale(.995); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* ---- the overlay grows into place --------------------------------------- */
.loupe.is-open img { animation: loupe-in .26s var(--swing) both; }
@keyframes loupe-in {
  from { transform: scale(.965) translateY(6px); }
  to { transform: none; }
}

/* ---- the bar earns its shadow once you have left the top ----------------- */
.topbar { transition: box-shadow var(--beat), background var(--beat); }
.topbar.is-scrolled { box-shadow: 0 2px 0 var(--rule), 0 10px 26px -18px rgba(5, 2, 14, .9); }

/* ---- anchored jumps land softly ----------------------------------------- */
:target { scroll-margin-top: calc(var(--bar-h) + 1.5rem); }

/* -------------------------------------------------------------- polish ----- */
::selection { background: var(--leaf-gold); color: #33240a; }
* { scrollbar-color: var(--gold-soft) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--dusk-raised); }
::-webkit-scrollbar-thumb { background: var(--gold-soft); border-radius: 99px; border: 3px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--gold-soft); background-clip: padding-box; }

@media print {
  .topbar, .sift, .loupe, .btn, .footing { display: none !important; }
  body { background: #fff; color: #111; background-image: none; }
}
@media (prefers-reduced-motion: reduce) {
  .wax { rotate: 0deg !important; }
  .door img, .vista img, .beast img, .pantheon img { transition: none; }
  .js .godpanel, .loupe.is-open img { animation: none; }
  details::details-content { transition: none; }
  .faq > summary::before, details.more > summary::before, .oath summary::before { transition: none; }
  .tile:hover, .beast:hover, .chips a:hover, .chips button:hover, .tally:hover { transform: none; }
  .emblemslot, .emblemslot img, .oath, .fact, details.more { transition: none; }
  .emblemslot:hover, .emblemslot:hover img, .oath:hover { transform: none; }
  @view-transition { navigation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE PANTHEON PANEL — the owner's own design language, ported from
   canon/oaths-of-lumoria.html. Owner ruling 2026-07-25: this is the whole
   site's language, not just this page. See docs/HANDOFF.md §3.
   ═══════════════════════════════════════════════════════════════════════ */

/* the accent halo — a 400px radial bleeding in from the top-right. this is what
   makes a panel read as luminous in its god's colour instead of flat. */
.godpanel { position: relative; isolation: isolate; }
.godpanel::before {
  content: ""; position: absolute; top: -140px; right: -140px;
  width: 400px; height: 400px; border-radius: 50%;
  background: radial-gradient(circle, var(--accent-glow, transparent), transparent 62%);
  opacity: .6; pointer-events: none; z-index: -1;
}

/* the epithet — "Aegemar, the Unbroken Wall" */
.godtitle h2 em {
  font-style: normal; color: var(--accent, var(--leaf-gold));
  text-shadow: 0 0 26px var(--accent-glow, transparent);
}
.godtitle .order { font-variant: small-caps; letter-spacing: .16em; }

/* the illuminated capital on the god's prose */
.godtitle .lore::first-letter {
  font-size: 3.1em; float: left; line-height: .8; margin: .12em .32em 0 0;
  color: var(--accent, var(--leaf-gold)); font-variant: small-caps;
  text-shadow: 0 0 22px var(--accent-glow, transparent);
}

/* the four meters. the fourth axis is bespoke per god — Resolve, Control,
   Precision, Radiance, Stealth, Craft, Pack — and comes from pantheon.json. */
.meter {
  display: flex; gap: clamp(.7rem, 2vw, 1.1rem); align-items: flex-start;
  border: 1px solid color-mix(in srgb, var(--accent, var(--leaf-gold)) 24%, var(--rule));
  border-radius: var(--arch-sm); padding: .6rem 1rem; background: rgba(0, 0, 0, .3);
}
.meter .m {
  font: 600 var(--step-micro)/1 var(--face-text); letter-spacing: .1em;
  text-transform: uppercase; text-align: center;
  color: color-mix(in srgb, var(--accent, var(--leaf-gold)) 70%, var(--vellum));
}
.meter .pips { display: flex; gap: 3px; justify-content: center; margin-top: .45rem; }
.meter .pip {
  width: 9px; height: 9px; border-radius: 50%;
  background: color-mix(in srgb, var(--accent, var(--leaf-gold)) 16%, rgba(255, 255, 255, .06));
}
.meter .pip.is-on {
  background: var(--accent, var(--leaf-gold));
  box-shadow: 0 0 10px var(--accent, var(--leaf-gold));
}
.factsrow { display: flex; flex-wrap: wrap; gap: .7rem; align-items: stretch; }
.factsrow .meter { margin-left: auto; }

@media (max-width: 720px) {
  .godpanel::before { display: none; }
  .factsrow .meter { margin-left: 0; width: 100%; justify-content: space-between; }
}

/* ---- the LEFT-ALIGNED section header -------------------------------------
   The default shape now. Eyebrow, heading, and a gold hairline running to the
   right margin. Replaces the centred-on-every-band skeleton, which the
   structural audit measured as the loudest PawBound tell (see §16 of
   docs/REFERENCE-TEARDOWN.md). Centred is kept for the hero-adjacent section
   and the closing band only. */
.head--rule { text-align: left; max-width: none; margin: 0 0 1.6rem; }
.head--rule .head__line { display: flex; align-items: baseline; gap: 1.1rem; flex-wrap: wrap; }
.head--rule .rank { flex: none; }
/* `flex: none` stops the heading shrinking, which is right on a wide row and wrong on a
   phone: at 375px "Others in the same country" ran 31px past the panel and .godpanel's
   overflow:hidden simply cut it off. Measured at a real 375 viewport across every page.
   It may shrink and wrap now, and long single words break rather than escape the box. */
.head--rule h1, .head--rule h2 {
  margin: 0; flex: 1 1 auto; min-width: 0; letter-spacing: .04em;
  overflow-wrap: break-word;
}
.head--rule .head__rule {
  flex: 1 1 8rem; height: 1px; min-width: 3rem;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent, var(--leaf-gold)) 70%, transparent),
    color-mix(in srgb, var(--accent, var(--leaf-gold)) 4%, transparent));
}
.head--rule .head__note { margin: .7rem 0 0; max-width: 62ch; }
@media (max-width: 620px) {
  .head--rule .head__rule { display: none; }
  /* the eyebrow and the heading each get their own line rather than competing for one */
  .head--rule .head__line { gap: .5rem; }
  .head--rule .rank { flex-basis: 100%; }
  .head--rule h1, .head--rule h2 { font-size: clamp(1.35rem, 6.4vw, 1.9rem); }
}
