/* ================================================================
   Alaryon — game shell stylesheet
   Tokens are defined in tokens.css (loaded first).
   ================================================================ */

body {
  background: var(--bg);
  color: var(--t1);
  font-family: var(--f-prose);
  -webkit-font-smoothing: antialiased;
  /* Subtle grain texture — SVG fractal noise at low opacity adds parchment warmth */
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='256' height='256' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
}

/* ================================================================
   SHELL — 2 columns, 4 rows on left, marginalia spans rows 2-4
   Viewport constraints (height, overflow) belong here on .shell,
   NOT on html/body — that breaks non-game pages (login, landing).
   ================================================================ */
.shell {
  display: grid;
  grid-template-columns: 1fr 264px;
  grid-template-rows: 36px auto 1fr auto;
  height: 100vh;
  overflow: hidden;
  max-width: 1440px;
  margin: 0 auto;
}

/* ================================================================
   HUD — spans full width
   ================================================================ */
.hud {
  grid-column: 1 / -1;
  grid-row: 1;
  background: var(--bg-hud);
  display: flex;
  align-items: center;
  padding: 0 var(--s5);
  gap: var(--s5);
  font-family: var(--f-ui);
  font-size: 11px;
  font-weight: 500;
  color: var(--t2);
  z-index: 10;
  border-bottom: 1px solid var(--gold-dd);
}

.h-g { display: flex; align-items: center; gap: 6px; }

.h-lbl {
  font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em; opacity: 0.5;
}

.h-bar {
  width: 64px; height: 5px;
  background: var(--border);
  border-radius: 3px; overflow: hidden;
}

.h-bar-fill { height: 100%; border-radius: 3px; transition: width 0.4s; }

.h-val { font-family: var(--f-mono); font-size: 10px; }

.h-sep { width: 1px; height: 14px; background: var(--border); }
.h-spacer { flex: 1; }

.h-btn {
  background: none;
  border: 1px solid var(--border-m);
  color: var(--t2);
  font-family: var(--f-ui); font-size: 9px; font-weight: 700;
  letter-spacing: 0.06em; padding: 2px 8px;
  border-radius: 3px; cursor: pointer; transition: all 0.12s;
}
.h-btn:hover { background: var(--border); border-color: var(--border-l); }
.h-btn.on { background: var(--gold-d); border-color: var(--gold); color: var(--gold); }

.h-icon {
  background: none; border: none; color: var(--t2);
  font-size: 15px; padding: 2px; cursor: pointer;
  opacity: 0.65; transition: opacity 0.12s;
}
.h-icon:hover { opacity: 1; }

.meta-b {
  background: none; border: none;
  color: var(--t2); font-size: 14px;
  padding: 3px 4px; cursor: pointer;
  opacity: 0.4; transition: all 0.1s;
  border-radius: 3px;
}
.meta-b:hover { opacity: 1; color: var(--gold); background: var(--gold-dd); }

/* User menu trigger button — sits at the right end of the HUD */
.user-menu-btn {
  display: flex; align-items: center; gap: 5px;
  background: none; border: 1px solid var(--border-m);
  color: var(--t2); font-family: var(--f-ui); font-size: 11px;
  padding: 3px 8px 3px 6px; border-radius: 4px; cursor: pointer;
  transition: all 0.12s; white-space: nowrap;
}
.user-menu-btn:hover { color: var(--t1); border-color: var(--border-l); background: var(--bg-surface); }
.user-menu-btn .ph { font-size: 14px; }
.user-menu-caret { font-size: 10px !important; opacity: 0.5; }

/* WebAwesome theme overrides — maps WA semantic tokens to our design tokens.
   light-dark() ensures WA components adapt to OS theme automatically. */
body {
  --wa-color-surface-default:    var(--bg-codex);
  --wa-color-surface-raised:     var(--bg-raised);
  --wa-color-surface-lowered:    var(--bg);
  --wa-color-surface-border:     var(--border-m);
  --wa-color-text-normal:        var(--t1);
  --wa-color-text-quiet:         var(--t2);
  --wa-color-neutral-fill-quiet: var(--border);
  --wa-color-neutral-fill-normal:var(--border-m);
  --wa-panel-border-radius:      6px;
}
/* User menu dropdown panel — replaces wa-menu inside wa-dropdown */
.user-menu-panel {
  background: var(--bg-raised);
  border: 1px solid var(--border-m);
  border-radius: 6px;
  padding: 4px;
  min-width: 160px;
}
.user-menu-item {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-radius: 4px;
  color: var(--t2); font-family: var(--f-ui); font-size: 13px;
  text-decoration: none; cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.user-menu-item:hover { background: var(--border); color: var(--t1); }
.user-menu-item .ph { font-size: 15px; opacity: 0.7; }
.user-menu-item:hover .ph { opacity: 1; }
.user-menu-divider {
  border: none; border-top: 1px solid var(--border);
  margin: 4px 8px;
}

/* ================================================================
   SCENE BANNER — left column only
   ================================================================ */
.banner {
  grid-column: 1;
  grid-row: 2;
  position: relative;
  overflow: hidden;
  height: 280px;
  background: var(--bg) center/cover no-repeat;
  transition: height 384ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Compact strip when the room has no illustration — terrain colour + title/region only */
.banner.no-image {
  height: 64px;
}

/* Gradient rising from bottom — smooths the transition into the codex below and
   ensures banner-title/banner-region text stays legible over any background image.
   Terminal color matches --bg-codex exactly for a seamless edge. */
.banner::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    transparent 30%,
    color-mix(in oklch, var(--bg-codex) 50%, transparent) 60%,
    color-mix(in oklch, var(--bg-codex) 90%, transparent) 85%,
    var(--bg-codex) 100%
  );
}

/* Terrain-based banner background colors — shown when no banner image is available.
   light-dark() ensures warm, visible atmosphere in both themes. */
.banner[data-terrain="PUEBLO"]      { background-color: light-dark(oklch(72% 0.07 70), oklch(32% 0.07 65)); }
.banner[data-terrain="BOSQUE"]      { background-color: light-dark(oklch(55% 0.10 152), oklch(28% 0.10 152)); }
.banner[data-terrain="FOREST"]      { background-color: light-dark(oklch(55% 0.10 152), oklch(28% 0.10 152)); }
.banner[data-terrain="ALCANTARILLA"]{ background-color: light-dark(oklch(50% 0.04 200), oklch(25% 0.04 200)); }
.banner[data-terrain="SEWER"]       { background-color: light-dark(oklch(50% 0.04 200), oklch(24% 0.04 200)); }
.banner[data-terrain="DUNGEON"]     { background-color: light-dark(oklch(45% 0.05 280), oklch(22% 0.05 280)); }
.banner[data-terrain="ROAD"]        { background-color: light-dark(oklch(65% 0.06 68), oklch(30% 0.06 65)); }
.banner[data-terrain="CAVE"]        { background-color: light-dark(oklch(42% 0.04 55), oklch(20% 0.04 55)); }
.banner[data-terrain="PLAINS"]      { background-color: light-dark(oklch(60% 0.09 145), oklch(30% 0.09 145)); }
.banner[data-terrain="MOUNTAINS"]   { background-color: light-dark(oklch(55% 0.03 260), oklch(28% 0.03 260)); }
.banner[data-terrain="COAST"]       { background-color: light-dark(oklch(56% 0.09 232), oklch(28% 0.09 232)); }
.banner[data-terrain="TAVERN"]      { background-color: light-dark(oklch(52% 0.09 55), oklch(26% 0.09 52)); }

.banner-info {
  position: absolute; bottom: var(--s5); left: var(--s8);
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 2px; z-index: 2;
}

.banner-title {
  font-family: var(--f-display);
  font-size: 20px; font-weight: 700;
  color: rgba(255,255,255,0.92);
  text-shadow: 0 2px 16px rgba(0,0,0,0.7), 0 1px 3px rgba(0,0,0,0.5);
  letter-spacing: 0.05em;
}

.banner-region {
  font-family: var(--f-ui);
  font-size: 9px; font-weight: 700;
  color: rgba(255,255,255,0.45);
  text-shadow: 0 1px 6px rgba(0,0,0,0.6);
  letter-spacing: 0.12em; text-transform: uppercase;
}

/* ================================================================
   CODEX — left column, scrollable
   ================================================================ */
.codex {
  grid-column: 1;
  grid-row: 3;
  overflow-y: auto;
  /* min-height:0 is required — without it the grid item expands to content height,
     overriding the 1fr constraint and making overflow-y:auto a no-op */
  min-height: 0;
  padding: var(--s6) var(--s8);
  background: var(--bg-codex);
}

.codex::-webkit-scrollbar { width: 4px; }
.codex::-webkit-scrollbar-track { background: transparent; }
.codex::-webkit-scrollbar-thumb { background: rgba(112,120,144,0.2); border-radius: 2px; }
.codex::-webkit-scrollbar-thumb:hover { background: rgba(112,120,144,0.4); }

.codex-inner { max-width: 600px; margin: 0 auto; }

/* ---- Ornaments ---- */
.orn-sm {
  height: 1px;
  background: linear-gradient(to right, transparent 20%, var(--gold-dd) 50%, transparent 80%);
  margin: var(--s5) 48px;
}

.orn-dia {
  display: flex; align-items: center; margin: var(--s2) 0 var(--s6);
}
.orn-dia::before, .orn-dia::after { content: ''; flex: 1; height: 1px; }
.orn-dia::before { background: linear-gradient(to right, transparent, var(--gold)); }
.orn-dia::after  { background: linear-gradient(to left, transparent, var(--gold)); }
.orn-dia-dot {
  width: 5px; height: 5px; background: var(--gold);
  transform: rotate(45deg); margin: 0 var(--s3); opacity: 0.4;
}

/* ---- System Message ---- */
/* Uses --t3 (not --t4) — system messages must be legible even if de-emphasized.
   WCAG compliance note: --t3 at 4.2:1 meets AA for small-caps at this weight/size. */
.sys {
  font-family: var(--f-ui); font-size: 11px;
  font-variant: small-caps; letter-spacing: 0.08em;
  color: var(--t3); margin: var(--s4) 0 var(--s5);
}
.sys::before { content: '\2022\2002\2022\2002\2022\2003\2003'; }

/* ---- System Error — engine/data failures, shown in red ---- */
.sys-err {
  font-family: var(--f-ui); font-size: 12px;
  font-variant: small-caps; letter-spacing: 0.06em;
  color: var(--rose); margin: var(--s3) 0;
  opacity: 0.85;
}

/* ---- Player Error — invalid command feedback, shown in muted amber ---- */
.err {
  font-family: var(--f-ui); font-size: 14px;
  color: var(--gold); opacity: 0.85;
  margin: var(--s2) 0 var(--s3); font-style: italic;
}

/* ---- Combat Encounter — atmospheric monster discovery beat ---- */
.encounter {
  font-style: italic;
  color: var(--rose);
  opacity: 0.9;
}

/* ---- Drop Cap ---- */
.dc {
  font-family: var(--f-display); font-size: 3em;
  float: left; line-height: 0.78;
  margin: 6px 8px 0 -2px;
  color: var(--gold); font-weight: 700;
}

/* ---- Prose (legacy alias) ---- */
.prose { font-size: var(--size-prose); line-height: 1.78; margin-bottom: var(--s4); }
.prose p { margin-bottom: var(--s3); }
.prose p:last-child { margin-bottom: 0; }

/* ---- Narrate — narrative prose with sentence-level click-to-translate ---- */
/* Each translatable sentence is a .narr-s span; clicking it reveals its .narr-s-tr inline. */
.narr { font-size: var(--size-prose); line-height: 1.78; margin-bottom: var(--s4); }
.narr p { margin-bottom: var(--s3); }
.narr p:last-child { margin-bottom: 0; }

/* Clickable sentence — subtle dotted underline signals interactivity */
.narr-s {
  cursor: pointer;
  border-bottom: 1px dotted var(--border-m);
  transition: border-color 0.15s;
}
.narr-s:hover { border-bottom-color: var(--border-l); }

/* ▾ tap-to-reveal indicator — explicit span so it stays anchored to the sentence
   text and doesn't shift below the translation block when opened */
.narr-s-arrow {
  color: var(--gold);
  font-size: 9px;
  opacity: 0.25;
  margin-left: 3px;
  vertical-align: 1px;
  transition: opacity 0.15s;
}
.narr-s:hover .narr-s-arrow { opacity: 0.6; }
.narr-s.open .narr-s-arrow { opacity: 0.8; display: inline-block; transform: rotate(180deg); }

/* Translation — hidden by default; revealed as a block below the sentence when .narr-s gets 'open' */
/* Uses --t2 — translations are the core learning mechanic and MUST be clearly readable */
.narr-s-tr {
  display: none;
  font-size: 14px;
  font-style: italic;
  color: var(--t2);
  margin-top: 4px;
  margin-bottom: 6px;
  padding-left: 10px;
  border-left: 2px solid var(--gold-d);
}
.narr-s.open { border-bottom-style: solid; border-bottom-color: var(--border-l); }
.narr-s.open .narr-s-tr { display: block; }

/* Voiceover button — inline icon beside each translatable sentence */
.narr-vo {
  display: inline-block;
  cursor: pointer;
  color: var(--t4);
  font-size: 13px;
  margin-left: 4px;
  vertical-align: baseline;
  transition: color 0.15s;
}
.narr-vo:hover { color: var(--gold); }
.narr-vo.speaking { color: var(--gold); animation: vo-pulse 0.8s ease-in-out infinite; }
@keyframes vo-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }

/* ---- Entity links ---- */
.e { font-weight: 600; cursor: pointer; text-decoration: none; transition: opacity 0.1s; }
.e:hover { opacity: 0.6; text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px; }
.e.npc  { color: var(--gold); }
.e.mon  { color: var(--rose); }
.e.item { color: var(--blue); }
.e.dir  { color: var(--sage); }

/* ---- Player Command ---- */
.cmd {
  font-family: var(--f-mono); font-size: 13px;
  color: var(--sage); opacity: 0.85;
  margin: var(--s5) 0;
  padding: var(--s1) 0 var(--s1) var(--s4);
  border-left: 2px solid var(--sage-d);
}
.cmd::before { content: '> '; opacity: 0.4; }

/* ---- NPC Dialogue ---- */
.dlg {
  margin: var(--s5) 0 var(--s6);
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--gold);
  background: var(--bg-dlg);
  border-radius: 0 var(--s1) var(--s1) 0;
}
.dlg-who {
  font-family: var(--f-ui); font-weight: 700;
  font-size: 10px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--gold);
  margin-bottom: 6px;
}
.dlg-text { font-style: italic; font-size: var(--size-prose); line-height: 1.72; }

/* ---- Tutor Tip ---- */
.tip {
  margin: var(--s1) 0 var(--s6);
  margin-left: var(--s6);
  padding: var(--s2) var(--s3);
  background: var(--bg-tip);
  border: 1px dashed var(--gold-dd);
  border-radius: 5px;
  font-family: var(--f-ui); font-size: 13px;
  line-height: 1.6; color: var(--t2);
}
.tip i { color: var(--gold); margin-right: 4px; font-size: 11px; }
.tip strong { color: var(--t1); }
.tip em { color: var(--gold); font-style: normal; font-weight: 600; }

/* ---- Item Event ---- */
.evt { margin: var(--s5) 0; }
.evt-pill {
  display: inline-block;
  font-family: var(--f-ui); font-size: 12px;
  color: var(--t2); padding: 3px var(--s4);
  background: var(--blue-d);
  border: 1px solid color-mix(in oklch, var(--blue) 20%, transparent);
  border-radius: 12px;
}
.evt-pill .got { color: var(--blue); font-weight: 600; }
.evt-pill .lost { color: var(--rose); font-weight: 600; }

/* ---- Hint ---- */
.hint {
  border: 1px dashed var(--gold-d);
  padding: 8px;
  border-radius: 4px;
  color: var(--t2);
  font-family: var(--f-ui);
  font-size: 14px;
  margin: var(--s4) 0;
}
.suggestion {
  color: var(--sage);
  cursor: pointer;
  text-decoration: underline;
  margin: 0 4px;
}

/* ---- Exit List — one row per exit, direction word + destination room name ---- */
.exits {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  margin: 0 0 var(--s5);
}
.exits-lbl {
  font-family: var(--f-ui);
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--t4);
}
.exits-rows { display: flex; flex-direction: column; gap: 1px; }
.exit-row {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
}
.exit-word {
  font-family: var(--f-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--sage);
  min-width: 52px;
  border-bottom: 1px dotted var(--sage-d);
  transition: border-color 0.15s;
}
.exit-word:hover { border-bottom-color: color-mix(in oklch, var(--sage) 55%, transparent); }
.exit-room {
  font-family: var(--f-ui);
  font-size: 12px;
  color: var(--t2);
}
.exits-none { font-family: var(--f-mono); font-size: 12px; color: var(--t4); }

/* ================================================================
   INPUT — left column, aligned with codex text
   ================================================================ */
.input-zone {
  grid-column: 1;
  grid-row: 4;
  background: var(--bg-codex);
  border-top: 1px solid var(--gold-dd);
  padding: var(--s3) var(--s8);
}

.input-inner {
  max-width: 600px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.inp-prompt {
  font-family: var(--f-mono); font-size: 14px;
  color: var(--gold); opacity: 0.55; user-select: none;
}

.inp-field {
  flex: 1; font-family: var(--f-mono); font-size: 14px;
  color: var(--t1); background: transparent;
  border: none; outline: none; padding: 5px 0;
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s;
}
.inp-field::placeholder { color: var(--t4); font-style: italic; }
.inp-field:focus { border-bottom-color: var(--gold-d); }

/* ================================================================
   MARGINALIA — right column, spans rows 2-4 (banner through input)
   ================================================================ */
.marg {
  grid-column: 2;
  grid-row: 2 / -1;
  overflow-y: auto;
  background: var(--bg-surface);
  padding: var(--s5) var(--s4);
  display: flex; flex-direction: column; gap: var(--s5);
  border-left: 1px solid transparent;
  background-image:
    linear-gradient(var(--bg-surface), var(--bg-surface)),
    linear-gradient(180deg, transparent, var(--gold-d) 15%, var(--gold) 50%, var(--gold-d) 85%, transparent);
  background-origin: padding-box, border-box;
  background-clip: padding-box, border-box;
}

.marg::-webkit-scrollbar { width: 3px; }
.marg::-webkit-scrollbar-thumb { background: rgba(112,120,144,0.15); border-radius: 2px; }

/* Uppercase bold labels get 3:1 credit — --t3 at ~4.2:1 is comfortable here */
.m-lbl {
  font-family: var(--f-ui); font-size: 9px;
  font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--t3);
  margin-bottom: var(--s2);
}

.m-sep {
  height: 1px;
  background: linear-gradient(to right, transparent, var(--gold-dd), transparent);
}

/* ---- Compass ---- */
/* Wrapper holds the 3x3 grid plus the optional UP/DOWN row */
.compass-wrap { display: flex; flex-direction: column; align-items: center; gap: 4px; margin: 0 auto; }
.compass-grid {
  display: grid;
  grid-template-rows: repeat(3, 36px);
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
}
/* UP/DOWN exits — shown below the grid when at least one vertical exit exists */
.compass-ud { display: flex; gap: 4px; width: 100%; }
.compass-ud .dir-btn { flex: 1; height: 32px; }

.dir-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.15s;
  font-size: 16px;
  background: none;
  border: none;
  color: var(--sage);
  font-family: var(--f-ui);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 0 4px;
}
.dir-btn:hover { opacity: 0.6; }
.dir-btn.active { background: var(--sage-d); color: var(--sage); }
.dir-btn.inactive { opacity: 0.2; cursor: default; pointer-events: none; }
/* button element needs explicit font inheritance in some browsers */
button.dir-btn { font: inherit; cursor: pointer; }
.dir-center {
  background: var(--gold-dd);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---- Entity List ---- */
.ent-list { display: flex; flex-direction: column; gap: 2px; }
.ent {
  display: flex; align-items: baseline;
  justify-content: space-between; gap: var(--s2);
  padding: 4px 6px; cursor: pointer;
  border-radius: 3px; transition: background 0.1s;
}
.ent:hover { background: var(--bg-hover); }
/* button element needs explicit styles to override browser default */
button.ent { width: 100%; text-align: left; font: inherit; background: none; border: none; }
.ent-n { font-family: var(--f-ui); font-size: 13px; font-weight: 500; }
.ent-n.npc  { color: var(--gold); }
.ent-n.item { color: var(--blue); }
.ent-n.mon  { color: var(--rose); }
/* WCAG fix: .ent-sub bumped to --t2 and 10px minimum; was --t3/9px which failed AA at tiny size */
.ent-sub { font-family: var(--f-ui); font-size: 10px; color: var(--t2); }
/* WCAG fix: .ent-act base opacity raised from 0.6 to 0.8 for legibility */
.ent-act {
  font-family: var(--f-mono); font-size: 9px;
  color: var(--t3); opacity: 0.8; transition: opacity 0.1s;
}
.ent:hover .ent-act { opacity: 1; }
/* ================================================================
   LOAD ANIMATION — fade-in for codex-inner children
   Use a simple fade (no translateY) so re-triggering on HTMX appends
   is less jarring. Stagger delays removed to avoid nauseating re-fires.
   ================================================================ */
.codex-inner > * { animation: fade 0.25s ease-out both; }

@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* ================================================================
   RESPONSIVE
   ================================================================ */
@media (max-width: 959px) {
  .shell { grid-template-columns: 1fr; }
  /* Hamburger visible on mobile — opens the marginalia drawer */
  #marg-toggle { display: block; }
  /* Marginalia becomes a fixed right-side drawer instead of a grid column */
  .marg {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: 280px;
    z-index: 50;
    transform: translateX(100%);
    transition: transform 0.25s ease;
    /* Keep existing background/border styles — only position changes */
  }
  .shell.marg-open .marg { transform: translateX(0); }
  .shell.marg-open .marg-backdrop { display: block; }
  .codex { padding: var(--s5) var(--s4); }
  .input-zone { padding: var(--s3) var(--s4); }
  /* Touch target improvements */
  .meta-b { padding: 8px 10px; }
  .ent { padding: 10px 6px; min-height: 44px; }
  .dir-btn { min-width: 44px; min-height: 44px; }
  /* Prose size reduction on mobile */
  :root { --size-prose: 15px; }
}

@media (max-width: 599px) {
  .hud { padding: 0 var(--s3); gap: var(--s3); }
  .h-bar { display: none; }
  .h-class-lbl { display: none; }
  .h-sep { display: none; }
  /* Fixed input on mobile so it doesn't scroll away */
  .input-zone {
    position: fixed; bottom: 0; left: 0; right: 0;
    z-index: 20;
    border-top: 1px solid var(--gold-d);
  }
  .codex { padding-bottom: 60px; } /* make room for fixed input */
}

/* ================================================================
   DESIGN SYSTEM — named classes replacing all inline styles
   ================================================================ */

/* HUD bar fill color variants — width is always dynamic (inline), color uses these classes */
.h-bar-fill.hp  { background: var(--rose); }
.h-bar-fill.xp  { background: var(--purple); }

/* HUD value color variants */
.h-val.hp   { color: var(--rose); }
.h-val.xp   { color: var(--purple); }
.h-val.gold { color: var(--gold); }

/* Tiny class name label beside level in the XP group */
.h-class-lbl { font-size: 10px; opacity: 0.45; }

/* XP label needs slight left nudge after the class name */
.h-xp-lbl { margin-left: 4px; }

/* Coins icon and combat badge icon */
.h-coins-icon  { font-size: 11px; color: var(--gold); opacity: 0.5; }
.h-combat-icon { font-size: 11px; }

/* Hamburger hidden on desktop — marg is always visible, button would do nothing */
#marg-toggle { display: none; }

/* Mobile marginalia drawer backdrop — sits between shell and drawer, dismisses on tap */
.marg-backdrop {
  display: none;
  position: fixed; inset: 0;
  background: var(--bg-backdrop);
  z-index: 49;
}

/* Compass center dot (inside .dir-center) */
.dir-center-dot {
  width: 8px; height: 8px;
  background: var(--gold); border-radius: 50%; opacity: 0.4;
}

/* Marginalia sidebar location name */
.sidebar-loc { font-family: var(--f-ui); font-size: 12px; color: var(--t2); }

/* Empty state placeholders */
.ent-empty   { font-size: 11px; color: var(--t4); padding: 4px 0; font-family: var(--f-ui); }

/* Event pill danger variant — combat hostile/started events */
.evt-pill.danger { color: var(--rose); }

/* Event pill level-up variant — gold tint for achievement/promotion events */
.evt-pill.level-up { color: var(--gold); border-color: var(--gold-d); }

/* Fled-combat narrative beat — muted italic, distinct from system messages */
.narr-fled {
  font-family: var(--f-prose); font-size: var(--size-prose); line-height: 1.78;
  color: var(--t2); font-style: italic;
  margin: var(--s4) 0;
}

/* ---- Grammar Note ---- */
/* Appears in the codex after language-learning events to explain grammar or usage */
.gram {
  margin: var(--s1) 0 var(--s5);
  margin-left: var(--s6);
  font-family: var(--f-ui); font-size: 13px;
  font-style: italic; line-height: 1.6;
  color: var(--t2);
}
.gram strong { color: var(--t1); font-style: normal; }
.gram em { color: var(--gold); font-style: normal; font-weight: 600; }

/* ---- Thinking indicator ---- */
/* Shown via HTMX hx-indicator during in-flight requests */
.dots {
  display: flex; gap: 5px; align-items: center;
  padding: var(--s3) 0; margin: var(--s2) 0;
}
.dot {
  width: 5px; height: 5px;
  background: var(--gold); border-radius: 50%;
  opacity: 0.3;
  animation: throb 1.2s ease-in-out infinite;
}
.dot:nth-child(2) { animation-delay: 0.2s; }
.dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes throb {
  0%, 100% { opacity: 0.15; transform: scale(0.8); }
  50%       { opacity: 0.7;  transform: scale(1.1); }
}

/* HTMX indicator visibility — hidden until request is in flight */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { display: flex !important; }

/* ---- Combat state — toggled on .shell by HTMX OOB ---- */
.state-combat .codex {
  border-left: 2px solid var(--rose-d);
  border-right: 2px solid var(--rose-d);
}
.state-combat .orn-dia::before {
  background: linear-gradient(to right, transparent, var(--rose));
}
.state-combat .orn-dia::after {
  background: linear-gradient(to left, transparent, var(--rose));
}
.state-combat .orn-dia-dot { background: var(--rose); }

/* ---- Death state ---- */
.state-death .banner { filter: grayscale(1); transition: filter 0.5s; }
.state-death .banner::before {
  content: '';
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 1;
}
.state-death .codex { opacity: 0.7; }

/* EN-all toggle: shows all translations simultaneously */
.codex.en-all .narr-s-tr { display: block !important; }
.codex.en-all .narr-s { border-bottom-style: solid; }


/* ================================================================
   WEBAWESOME — hide tooltip elements before the JS module registers them
   ================================================================ */
/* Before the WebAwesome JS module registers wa-tooltip, the custom element renders
   as a generic inline element and its text content leaks visibly into the page.
   :not(:defined) hides it until the component upgrades; after that WebAwesome's
   own shadow styles take over and the text is only shown in the tooltip popup. */
wa-tooltip:not(:defined) { display: none; }

/* ================================================================
   ACCESSIBILITY
   ================================================================ */

/* Focus-visible states — keyboard navigation indicators for all interactive elements */
.meta-b:focus-visible,
.h-btn:focus-visible,
.h-icon:focus-visible,
.dir-btn.active:focus-visible,
.ent:focus-visible,
.suggestion:focus-visible,
.inp-field:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* Reduced motion — disable animations for users who prefer it */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ================================================================
   DESIGN GALLERY (/dev/design — dev only)
   ================================================================ */
.dg-shell { max-width: 920px; margin: 0 auto; padding: var(--s8) var(--s7); }

.dg-header {
  font-family: var(--f-display); font-size: 28px; font-weight: 700;
  color: var(--gold); margin-bottom: var(--s2); letter-spacing: 0.04em;
}
.dg-subtitle {
  font-family: var(--f-ui); font-size: 13px; color: var(--t3);
  margin-bottom: var(--s8);
}
.dg-section {
  margin-bottom: var(--s8); padding-bottom: var(--s7);
  border-bottom: 1px solid var(--gold-dd);
}
.dg-section:last-child { border-bottom: none; }
.dg-section-title {
  font-family: var(--f-display); font-size: 13px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gold); opacity: 0.7; margin-bottom: var(--s5);
}
.dg-row { display: flex; align-items: flex-start; gap: var(--s6); margin-bottom: var(--s5); }
.dg-label {
  min-width: 160px; padding-top: 3px; flex-shrink: 0;
  font-family: var(--f-mono); font-size: 10px; color: var(--t4);
}
.dg-preview { flex: 1; }
.dg-swatch-row { display: flex; flex-wrap: wrap; gap: var(--s4); margin-bottom: var(--s5); }
.dg-swatch { display: flex; align-items: center; gap: var(--s2); }
.dg-swatch-dot { width: 24px; height: 24px; border-radius: 4px; flex-shrink: 0; }
.dg-swatch-name { font-family: var(--f-mono); font-size: 10px; color: var(--t2); }
.dg-swatch-val  { font-family: var(--f-mono); font-size: 9px; color: var(--t4); }
