/* ---------- Tokens ---------- */
:root {
  --color-flame: #ff7a3d;
  --color-flame-soft: #ffa45c;
  --color-flame-glow: rgba(255, 138, 70, 0.45);
  --color-amber: #ffb56b;
  --color-cream: #f4e6d2;
  --color-cream-dim: rgba(244, 230, 210, 0.65);
  --color-cream-faint: rgba(244, 230, 210, 0.4);
  --color-shadow: rgba(8, 4, 2, 0.78);
  --color-shadow-deep: rgba(0, 0, 0, 0.88);
  --color-edge: rgba(255, 165, 90, 0.35);
  --color-edge-dim: rgba(255, 165, 90, 0.15);

  --font-display: 'Cinzel', 'Cormorant Garamond', serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
}

/* ---------- Reset ---------- */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
  font-family: var(--font-body);
  color: var(--color-cream);
  /* Match the body's dark warm color so any inter-page flash
     blends in instead of showing default white/black. */
  background-color: #1a0d08;
}

/* Always reserve space for the scrollbar so the viewport width is identical
   on every page, whether it overflows or not. Without this, switching from a
   short page (no scrollbar) to a tall page (scrollbar appears) shrinks the
   viewport by ~17px and the cover-sized background visibly resizes. */
html {
  scrollbar-gutter: stable;
}

/* Hide page chrome until auth.js confirms the session and stamps the
   top-bar with the user's name + totals. The rule lives here in CSS
   (not JS-injected) so it applies on the very first paint, before
   auth.js has had a chance to run. auth.js removes the attribute as
   soon as values are stamped (instantly from localStorage cache, or
   after /me.php returns on first visit). */
body[data-auth-pending] .top-bar,
body[data-auth-pending] .hub,
body[data-auth-pending] .map-layout,
body[data-auth-pending] .footnote {
  visibility: hidden;
}

button {
  font-family: inherit;
  color: inherit;
}

/* ---------- Page ---------- */
body.hearth {
  /* The page background lives on a separate fixed-position div (.page-bg)
     instead of body. iOS Safari is unreliable with body backgrounds +
     background-attachment: fixed (it ignores fixed and re-sizes the bg
     when the URL bar shows/hides). A dedicated fixed div bypasses that. */
  background-color: #1a0d08;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow-x: hidden;
}

/* Page background layer — pinned to the viewport, scaled with cover.
   Each page sets its own image via inline style on this div.
   z-index: 0 (not -1) so it stays *above* the body's own background-color
   even when the body grows taller than the viewport on long pages. */
.page-bg {
  position: fixed;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: #1a0d08;
  z-index: 0;
  pointer-events: none;
}

/* Vignette pinned to the viewport and sitting between the transition overlay
   (z 50) and the top bar (z 60) so it stays visible during page swaps. */
.vignette {
  position: fixed;
  inset: 0;
  background:
    radial-gradient(ellipse at 50% 35%, transparent 0%, transparent 30%, rgba(0,0,0,0.55) 100%),
    linear-gradient(to bottom, rgba(0,0,0,0.30) 0%, transparent 18%, transparent 55%, rgba(0,0,0,0.65) 100%);
  pointer-events: none;
  z-index: 55;
}

/* ---------- Top bar (persistent shell — sits above the page transition overlay) ---------- */
.top-bar {
  position: relative;
  z-index: 60;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24px 32px;
  gap: 16px;
}

/* (Player nameplate has been removed. The nav-buttons pill stands alone
   on the left of the top bar.) */

.stats {
  display: flex;
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 12px;
  padding: 6px 3px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Multi-pill grouping: holds the .nav-buttons pills (Navigation,
   Habits, Lists) with a small gap between. margin-right: auto pushes
   the nav to the left and lets the remaining top-bar children
   (.stats then the .settings-pill) cluster together on the right.
   flex-wrap: wrap lets the pills stack on narrow screens. */
.nav-groups {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-right: auto;
}

/* Settings gear — its own single-button pill, sitting on the far
   right past the .stats readout. Reuses .nav-buttons styling. */
.settings-pill {
  flex: 0 0 auto;
}

/* Top-bar navigation pill — page-circle buttons in their own
   rounded pill. Each .nav-groups child is one of these pills. */
.nav-buttons {
  display: flex;
  gap: 4px;
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 999px;
  padding: 5px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.nav-button {
  display: inline-flex;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  align-items: center;
  justify-content: center;
  color: var(--color-cream-dim);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, transform 0.15s ease;
}

.nav-button svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nav-button:hover {
  background: rgba(255, 138, 70, 0.18);
  color: var(--color-cream);
}

.nav-button.is-current {
  background: linear-gradient(135deg, var(--color-flame), #c84718);
  color: var(--color-cream);
  box-shadow: 0 0 10px var(--color-flame-glow), inset 0 1px 0 rgba(255,255,255,0.18);
}

.nav-button.is-current:hover {
  background: linear-gradient(135deg, var(--color-flame), #c84718);
  transform: none;
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 3px 14px;
  border-right: 1px solid var(--color-edge-dim);
  min-width: 56px;
}

.stat:last-child {
  border-right: none;
}

.stat-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--color-cream-dim);
  margin-bottom: 2px;
}

.stat-value {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  color: var(--color-amber);
  line-height: 1;
}

/* ---------- Hub ---------- */
.hub {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 16px 32px 32px;
  gap: 56px;
}

.title-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.title {
  font-family: var(--font-display);
  font-size: clamp(36px, 6vw, 64px);
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--color-cream);
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  /* Layered halo so the title reads cleanly against any background image.
     Multiple stacked shadows create a denser, more solid dark surround than
     a single soft shadow. */
  text-shadow:
    0 0 28px rgba(0, 0, 0, 0.95),
    0 0 14px rgba(0, 0, 0, 0.85),
    0 2px 8px rgba(0, 0, 0, 0.7);
}

.title::before,
.title::after {
  /* Stars rendered as a real Unicode glyph so we can use text-shadow for
     the halo. (Filter drop-shadow on a CSS shape would be suppressed
     during the entrance transform animation — same Chromium bug as
     backdrop-filter — and the stars would pop in after the slide.) */
  content: '\2726'; /* ✦ BLACK FOUR-POINTED STAR */
  color: var(--color-flame);
  font-size: 0.55em;
  line-height: 1;
  text-shadow:
    0 0 8px var(--color-flame-glow),
    0 0 12px rgba(0, 0, 0, 0.85),
    0 0 5px rgba(0, 0, 0, 0.7);
  flex-shrink: 0;
}

/* Pill-shaped dark backdrop so subtitles stay readable over busy bgs.
   No backdrop-filter — see the note above about Chromium's transform
   suppression of filters. The ~55%-opaque black does the job. */
.subtitle {
  display: inline-block;
  margin-top: 16px;
  padding: 7px 20px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
  background: rgba(0, 0, 0, 0.72);
  border-radius: 999px;
}

/* ---------- Loadout ---------- */
.loadout {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  justify-content: center;
}

.slot {
  position: relative;
  width: 168px;
  min-height: 224px;
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 12px;
  padding: 22px 16px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 12px;
  cursor: pointer;
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
  overflow: hidden;
}

.slot:focus {
  outline: none;
  border-color: var(--color-flame);
  box-shadow: 0 0 32px var(--color-flame-glow);
}

.slot:hover {
  transform: translateY(-4px);
  border-color: var(--color-flame);
  box-shadow: 0 0 32px var(--color-flame-glow);
}

.slot-glow {
  position: absolute;
  inset: -1px;
  border-radius: 12px;
  pointer-events: none;
  box-shadow: 0 0 0 1px var(--color-flame), 0 0 22px var(--color-flame-glow);
  opacity: 0;
  animation: pulse 2.6s ease-in-out infinite;
}

.slot--active .slot-glow {
  opacity: 1;
}

@keyframes pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.85; }
}

.slot-icon {
  width: 48px;
  height: 48px;
  color: var(--color-flame);
  /* No filter: drop-shadow — Chromium suppresses filter during ancestor
     transforms, so the glow would snap on after the entrance animation.
     The flame stroke against the dark slot bg stays plenty visible. */
  margin-top: 4px;
}

.slot-icon svg {
  width: 100%;
  height: 100%;
}

.slot-label {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-cream);
}

.slot-state {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 5px 14px;
  border: 1px solid var(--color-edge);
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.slot-state--empty {
  color: var(--color-amber);
}

.slot-state--locked {
  color: var(--color-cream-faint);
  border-color: var(--color-edge-dim);
}

.lock {
  width: 12px;
  height: 12px;
}

.slot-hint {
  font-size: 12px;
  color: var(--color-cream-dim);
  margin-top: auto;
  line-height: 1.45;
  letter-spacing: 0.02em;
}

/* Locked variant */
.slot--locked {
  cursor: not-allowed;
  opacity: 0.55;
}

.slot--locked:hover {
  transform: none;
  border-color: var(--color-edge);
  box-shadow: none;
}

.slot--locked .slot-icon {
  color: var(--color-cream-faint);
  filter: none;
}

/* ---------- Run button ---------- */
.run-button {
  background: linear-gradient(135deg, var(--color-flame), #c84718);
  border: none;
  padding: 18px 56px;
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  /* Anchor element styled as a button — kill the default underline +
     blue link color so it looks like a CTA, not text. */
  text-decoration: none;
  color: var(--color-cream);
  box-shadow: 0 0 36px var(--color-flame-glow), inset 0 1px 0 rgba(255,255,255,0.22);
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease, opacity 0.2s ease;
}

.run-button:hover:not([aria-disabled="true"]) {
  transform: translateY(-2px);
  box-shadow: 0 0 52px var(--color-flame-glow), inset 0 1px 0 rgba(255,255,255,0.22);
}

.run-button[aria-disabled="true"] {
  background: linear-gradient(135deg, #5a3220, #3a1f12);
  cursor: not-allowed;
  box-shadow: none;
  opacity: 0.7;
}

/* ---------- Hearth quick-quest editor ----------
   A subtle single-line text field + two compact outcome buttons,
   sitting between the loadout slots and the big Run button on
   home.html. Shares state with quest.html via the 'quest' state key —
   both pages stay synced through the server. */

/* Wraps .hearth-quest + .run-button into a tight group with a small
   internal gap, so the Run button sits close under the Cleared/Fell
   pills (the .hub's outer 56px gap separates this group from the
   loadout above, which is the spacing we want there). */
.hearth-final {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.hearth-quest {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 380px;
  margin: 0 auto;
}

.hearth-quest-label {
  display: inline-block;
  padding: 4px 14px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.75);
  border: 1px solid var(--color-edge-dim);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--color-cream);
  cursor: pointer; /* clicking the label focuses the input */
}

/* The status row (Cleared / Fell) gets a bit more breathing room
   from the input than the label does. */
.hearth-quest-input + .hearth-quest-status {
  margin-top: 4px;
}

.hearth-quest-input {
  width: 100%;
  background: rgba(8, 4, 2, 0.78);
  border: 1px solid var(--color-edge-dim);
  border-radius: 8px;
  padding: 9px 14px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--color-cream);
  letter-spacing: 0.01em;
  text-align: center;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.hearth-quest-input::placeholder {
  color: var(--color-cream-faint);
  font-style: italic;
}

.hearth-quest-input:focus {
  outline: none;
  border-color: var(--color-flame);
  box-shadow: 0 0 12px var(--color-flame-glow);
}

.hearth-quest-status {
  display: flex;
  gap: 8px;
}

.hearth-quest-btn {
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 6px 16px;
  border-radius: 999px;
  border: 1px solid var(--color-edge);
  background: rgba(28, 16, 8, 0.85);
  color: var(--color-cream-dim);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease,
              border-color 0.15s ease, opacity 0.15s ease;
}

.hearth-quest-btn:hover:not(:disabled) {
  background: rgba(46, 26, 14, 0.92);
  color: var(--color-cream);
  border-color: var(--color-flame);
}

.hearth-quest-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Active state: the outcome that's been set. Survives the disabled
   styling above by overriding opacity and using the flame gradient. */
.hearth-quest-btn.is-active {
  background: linear-gradient(135deg, var(--color-flame), #c84718);
  border-color: var(--color-flame);
  color: var(--color-cream);
  opacity: 1;
  box-shadow: 0 0 14px rgba(255, 122, 61, 0.30);
}

.run-button-text {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-cream);
}

.run-button-hint {
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
}

/* ---------- Footer ---------- */
.footnote {
  position: relative;
  z-index: 2;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-cream-faint);
  padding: 14px 16px 22px;
}

/* ---------- Slot as link (used for Map) ---------- */
a.slot {
  text-decoration: none;
  color: inherit;
}

/* ---------- Map page ---------- */
.map-layout {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px 32px 32px;
  gap: 32px;
}

.map-panel {
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 28px;
  width: min(840px, calc(100% - 32px));
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.free-time-readout {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 4px 8px 12px;
  border-bottom: 1px solid var(--color-edge-dim);
}

.readout-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.readout-label {
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
}

.readout-value {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 700;
  color: var(--color-amber);
  line-height: 1;
}

.readout-value--dim {
  color: var(--color-cream-faint);
}

/* horizontal "platformer" timeline */
.tile-row-wrap {
  overflow-x: auto;
  overflow-y: visible;
  padding: 0 4px 6px;
  margin: 0 -8px;
}

.tile-row-wrap::-webkit-scrollbar {
  height: 6px;
}

.tile-row-wrap::-webkit-scrollbar-track {
  background: transparent;
}

.tile-row-wrap::-webkit-scrollbar-thumb {
  background: rgba(255, 165, 90, 0.3);
  border-radius: 3px;
}

.tile-row {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 130px;
  padding: 0 8px;
  width: max-content;
  margin: 0 auto;
}

/* the ground line under the tiles */
.tile-row::before {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(to right,
    transparent,
    var(--color-flame) 8%,
    var(--color-flame) 92%,
    transparent);
  box-shadow: 0 0 16px var(--color-flame-glow);
  pointer-events: none;
  z-index: 0;
}

.hour-tile {
  position: relative;
  width: 50px;
  height: 50px;
  background: linear-gradient(to bottom,
    rgba(255, 165, 90, 0.28),
    rgba(255, 122, 61, 0.12)
  );
  border: 1px solid var(--color-flame);
  border-bottom-width: 2px;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  color: var(--color-amber);
  font-family: var(--font-display);
  padding: 0;
  z-index: 1;
  transition:
    height 0.28s cubic-bezier(0.34, 1.2, 0.64, 1),
    background 0.25s ease,
    box-shadow 0.25s ease,
    transform 0.15s ease,
    border-color 0.25s ease,
    color 0.25s ease;
  box-shadow:
    0 0 12px rgba(255, 122, 61, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.hour-tile:hover {
  transform: translateY(-2px);
  box-shadow:
    0 0 20px rgba(255, 122, 61, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

.hour-tile:focus {
  outline: none;
  box-shadow:
    0 0 0 2px var(--color-flame),
    0 0 20px rgba(255, 122, 61, 0.45);
}

.hour-tile--blocked {
  height: 100px;
  background: linear-gradient(to bottom,
    rgba(70, 44, 32, 0.92),
    rgba(28, 16, 10, 0.98)
  );
  border-color: rgba(120, 82, 60, 0.55);
  color: var(--color-cream-faint);
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.55),
    inset 0 2px 0 rgba(255, 255, 255, 0.06),
    inset 0 -2px 0 rgba(0, 0, 0, 0.4);
}

.hour-tile--blocked:hover {
  transform: translateY(-2px);
  box-shadow:
    0 6px 16px rgba(0, 0, 0, 0.65),
    inset 0 2px 0 rgba(255, 255, 255, 0.08),
    inset 0 -2px 0 rgba(0, 0, 0, 0.4);
}

.tile-num {
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
}

.tile-period {
  font-size: 8px;
  letter-spacing: 0.2em;
  font-weight: 500;
  opacity: 0.75;
  font-family: var(--font-body);
  text-transform: uppercase;
}

.tile-hint {
  font-size: 11px;
  color: var(--color-cream-dim);
  text-align: center;
  letter-spacing: 0.05em;
  margin: -8px 0 0;
  font-weight: 400;
  font-style: italic;
}

.map-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

.btn {
  font-family: var(--font-display);
  padding: 14px 28px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-edge);
  background: transparent;
  color: var(--color-cream);
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.btn--primary {
  background: linear-gradient(135deg, var(--color-flame), #c84718);
  border-color: var(--color-flame);
  box-shadow: 0 0 18px var(--color-flame-glow);
}

.btn--primary:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 0 28px var(--color-flame-glow);
}

.btn--primary:disabled {
  background: linear-gradient(135deg, #5a3220, #3a1f12);
  border-color: var(--color-edge-dim);
  cursor: not-allowed;
  opacity: 0.6;
  box-shadow: none;
}

.btn--ghost {
  background: var(--color-shadow);
}

.btn--ghost:hover {
  border-color: var(--color-flame);
  color: var(--color-amber);
}

/* ---------- Quest page ---------- */
.quest-panel {
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 32px;
  width: min(560px, calc(100% - 32px));
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.quest-input {
  width: 100%;
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 8px;
  padding: 16px 18px;
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--color-cream);
  resize: vertical;
  min-height: 80px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  letter-spacing: 0.01em;
}

.quest-input::placeholder {
  color: var(--color-cream-faint);
  font-style: italic;
}

.quest-input:focus {
  outline: none;
  border-color: var(--color-flame);
  box-shadow: 0 0 16px var(--color-flame-glow);
}

.quest-status {
  display: flex;
  justify-content: center;
}

.status-pill {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 7px 18px;
  border-radius: 999px;
  border: 1px solid var(--color-edge-dim);
  color: var(--color-cream-dim);
  font-weight: 500;
}

.status-pill--cleared {
  color: var(--color-amber);
  border-color: var(--color-flame);
  background: rgba(255, 138, 70, 0.14);
  box-shadow: 0 0 14px var(--color-flame-glow);
}

.status-pill--fell {
  color: var(--color-cream-faint);
  border-color: rgba(120, 80, 60, 0.5);
  background: rgba(40, 22, 15, 0.7);
}

.quest-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
}

.quest-actions .btn {
  flex: 1;
  max-width: 200px;
  justify-content: center;
}

.btn:disabled {
  cursor: not-allowed;
  opacity: 0.45;
  pointer-events: none;
}

.quest-undo-row {
  display: flex;
  justify-content: center;
  min-height: 16px;
}

.btn-undo {
  background: none;
  border: none;
  color: var(--color-cream-dim);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: underline;
  font-family: var(--font-body);
  padding: 0;
  font-weight: 500;
}

.btn-undo:hover {
  color: var(--color-amber);
}

.quest-hint {
  font-size: 12px;
  color: var(--color-cream-dim);
  text-align: center;
  font-style: italic;
  letter-spacing: 0.03em;
  line-height: 1.5;
  margin: 0;
}

/* ---------- Dailies / category pages (mirrored elsewhere) ---------- */
.dailies-panel {
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 28px;
  width: min(840px, calc(100% - 32px));
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.today-readout {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 0 18px;
  border-bottom: 1px solid var(--color-edge-dim);
}

.today-readout .readout-label {
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
}

.today-readout .readout-value {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 700;
  color: var(--color-amber);
  line-height: 1;
}

/* Per-currency icon, used in each category page's "today's X" readout.
   Each page references its own PNG (ember / mettle / essence) inside a
   <span class="currency-icon"><img …></span> wrapper. No filter or
   box-shadow on this — it lives inside an animating panel and filters
   get suppressed during transforms. */
.currency-icon {
  display: inline-flex;
  width: 31px;
  height: 31px;
  vertical-align: middle;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  /* Lift slightly to optically align with the numeral's cap-height center.
     -2px is the sweet spot for the current 38px Cinzel readout. */
  transform: translateY(-2px);
}

/* Per-currency size adjustments. Mettle uses the default (30px). */
.currency-icon--ember {
  width: 26px;
  height: 26px;
}

.currency-icon--essence {
  width: 27px;
  height: 27px;
}

.currency-icon img,
.currency-icon svg {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}

.readout-hint {
  font-size: 11px;
  color: var(--color-cream-faint);
  font-style: italic;
  margin: 6px 0 0;
  letter-spacing: 0.04em;
}

.readout-hint--bonus {
  color: var(--color-amber);
  font-style: normal;
  font-weight: 500;
  letter-spacing: 0.08em;
}

/* Add form */
.add-form {
  display: flex;
  gap: 10px;
  align-items: stretch;
  flex-wrap: wrap;
}

.text-input {
  flex: 1 1 180px;
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 8px;
  padding: 11px 14px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--color-cream);
  letter-spacing: 0.01em;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.text-input::placeholder {
  color: var(--color-cream-faint);
}

.text-input:focus {
  outline: none;
  border-color: var(--color-flame);
  box-shadow: 0 0 12px var(--color-flame-glow);
}

.add-btn {
  padding: 11px 22px;
  font-size: 11px;
  white-space: nowrap;
  flex-shrink: 0;
}

/* Category grid */
.category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
}

.category-box {
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.category-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.category-title {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-amber);
  margin: 0;
  word-break: break-word;
  flex: 1;
}

.category-count {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--color-cream-faint);
  font-weight: 500;
  flex-shrink: 0;
}

.item-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Item pill — both a button and a checkbox */
.item-pill {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  background: rgba(40, 22, 15, 0.7);
  border: 1px solid var(--color-edge-dim);
  border-radius: 8px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--color-cream-dim);
  text-align: left;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
  position: relative;
  /* Prevent iOS long-press from selecting text or showing the
     callout menu — long-press is reserved for the delete gesture. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.item-pill:hover {
  border-color: var(--color-edge);
  color: var(--color-cream);
}

.item-pill.is-checked {
  background: linear-gradient(135deg, rgba(255, 138, 70, 0.20), rgba(255, 122, 61, 0.08));
  border-color: var(--color-flame);
  color: var(--color-cream);
  box-shadow: 0 0 14px rgba(255, 122, 61, 0.22);
}

.item-check {
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--color-edge);
  border-radius: 50%;
  flex-shrink: 0;
  transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

.item-pill.is-checked .item-check {
  background: radial-gradient(circle at 32% 30%,
    #ffd9a8 0%,
    var(--color-flame-soft) 40%,
    var(--color-flame) 75%);
  border-color: var(--color-flame);
  box-shadow: 0 0 8px var(--color-flame-glow);
}

.item-name {
  flex: 1;
  min-width: 0;
  line-height: 1.3;
  overflow-wrap: break-word;
}

.item-bonus {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--color-amber);
  opacity: 0;
  transition: opacity 0.2s ease;
  flex-shrink: 0;
}

.item-pill.is-checked .item-bonus {
  opacity: 1;
}

/* Freshness multiplier dots — show on items that haven't been done in
   a while (Boon and Charm only). 1 dot = 2-3 days, 2 = 4-6, 3 = 7+. */
.item-multiplier {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex-shrink: 0;
  margin-right: 2px;
}

.item-mult-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%,
    var(--color-flame-soft), var(--color-flame));
  box-shadow: 0 0 5px var(--color-flame-glow);
}
/* 4-dot maximum-freshness items get a slightly redder shade so the
   "deeply neglected" tier reads visually distinct from the orange-flame
   1/2/3-dot tiers. */
.item-multiplier--max .item-mult-dot {
  background: radial-gradient(circle at 30% 30%, #ff9a72, #d94f3a);
  box-shadow: 0 0 6px rgba(217, 79, 58, 0.65);
}

/* Strip the browser-default up/down spinner on number inputs.
   We never need to "nudge" values up or down by 1 — typing is faster
   and the arrows just visually clutter the field. Keyboard arrow
   keys still nudge if you actually want that. */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type=number] {
  -moz-appearance: textfield;
  appearance: textfield;
}

/* ============================================================
   The Pantry — calorie log + weight chart.
   Two-box panel inside .map-layout. Each box (.scales-box) follows
   the same dark-card pattern as .pack-box on the inventory page.
   ============================================================ */
/* Scales page outer panel — same dark-with-inner-cards pattern as
   .dailies-panel so the page reads as one cohesive surface against
   the bright scales background image. */
.scales-panel {
  width: min(840px, calc(100% - 32px));
  margin: 24px auto 0;
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.scales-box {
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  padding: 16px 18px;
}
.scales-box-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.scales-box-title {
  margin: 0;
  font-family: 'Cinzel', serif;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-cream);
}
.scales-total {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--font-display);
}
.scales-total-value {
  font-size: 22px;
  font-weight: 700;
  color: var(--color-amber);
}
.scales-total-target {
  font-size: 13px;
  color: var(--color-cream-dim);
  letter-spacing: 0.04em;
}
.scales-total.is-over-target .scales-total-value {
  color: #ff7a5a;
}

.scales-add-form {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}
.scales-food-name-input { flex: 1 1 auto; min-width: 0; }
.scales-food-cal-input,
.scales-weight-input    { flex: 0 0 88px; }
.scales-target-input    { flex: 0 0 100px; }
@media (max-width: 520px) {
  .scales-add-form { flex-wrap: wrap; }
  .scales-food-name-input { flex: 1 1 100%; }
  .scales-food-cal-input,
  .scales-weight-input,
  .scales-target-input { flex: 1 1 auto; }
}

.scales-food-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 10px 0 14px;
  max-height: 320px;
  overflow-y: auto;
}
.scales-food-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: rgba(255, 245, 230, 0.05);
  border: 1px solid rgba(255, 245, 230, 0.10);
  border-radius: 8px;
  color: var(--color-cream);
}
.scales-food-row .scales-food-name { flex: 1 1 auto; min-width: 0; }
.scales-food-row .scales-food-cal {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--color-amber);
  font-size: 14px;
}
.scales-food-delete,
.weight-log-delete {
  flex: 0 0 auto;
  background: rgba(180, 60, 30, 0.42);
  border: none;
  color: var(--color-cream);
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease, opacity 0.15s ease;
}
.scales-food-delete:hover,
.weight-log-delete:hover {
  background: rgba(220, 80, 40, 0.7);
}
.scales-empty {
  color: var(--color-cream-dim);
  font-style: italic;
  font-size: 13px;
  margin: 8px 0;
}

.scales-target-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  padding-top: 10px;
  border-top: 1px dashed rgba(255, 245, 230, 0.08);
}
.scales-target-label {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
}
.scales-target-unit {
  font-size: 12px;
  color: var(--color-cream-dim);
}

.scales-unit-toggle {
  background: rgba(255, 245, 230, 0.08);
  border: 1px solid rgba(255, 245, 230, 0.18);
  color: var(--color-cream);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s ease;
}
.scales-unit-toggle:hover { background: rgba(255, 245, 230, 0.14); }

/* Weight chart */
.weight-chart-wrap {
  width: 100%;
  margin: 12px 0;
  padding: 8px;
  background: rgba(0, 0, 0, 0.32);
  border: 1px solid rgba(255, 245, 230, 0.08);
  border-radius: 10px;
  min-height: 200px;
}
.weight-chart {
  width: 100%;
  height: 200px;
  display: block;
  color: var(--color-amber);
}
.weight-chart-line {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.weight-chart-dot {
  fill: currentColor;
}
.weight-chart-tick {
  fill: var(--color-cream-dim);
  font-family: var(--font-body);
  font-size: 10px;
}
.weight-chart-grid {
  stroke: rgba(255, 245, 230, 0.08);
  stroke-width: 1;
  stroke-dasharray: 2 4;
}
.weight-single {
  padding: 60px 0;
  text-align: center;
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--color-amber);
  letter-spacing: 0.04em;
}

.weight-log-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 220px;
  overflow-y: auto;
}
.weight-log-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  background: rgba(255, 245, 230, 0.04);
  border: 1px solid rgba(255, 245, 230, 0.08);
  border-radius: 8px;
  color: var(--color-cream);
  font-size: 13px;
}
.weight-log-date {
  flex: 1 1 auto;
  color: var(--color-cream-dim);
  letter-spacing: 0.04em;
}
.weight-log-value {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--color-amber);
}

/* ============================================================
   Meals sharing — invite-by-email partnership UI. Sits at the top
   of the Pantry page above the plan/grocery grid. Four states:
   solo (invite form), outgoing pending, incoming pending, active
   share. The whole content area is JS-rendered.
   ============================================================ */
/* .pantry-share now sits INSIDE .pantry-panel as a sibling of the
   grid, so it doesn't need its own positioning/width. */
.pantry-share {
  width: 100%;
}
.pantry-share-content {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pantry-share-content:empty { display: none; }

.pantry-share-active,
.pantry-share-invite,
.pantry-share-form {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  font-size: 13px;
  color: var(--color-cream);
}

.pantry-share-active {
  border-color: rgba(255, 138, 70, 0.32);
}
.pantry-share-status {
  flex: 1 1 auto;
  letter-spacing: 0.02em;
}
.pantry-share-status strong {
  color: var(--color-amber);
  font-weight: 600;
}

/* Incoming invite gets a slightly brighter border so it reads as
   "needs your attention". */
.pantry-share-invite--incoming {
  border-color: rgba(255, 200, 100, 0.45);
  background: rgba(40, 24, 12, 0.55);
}
.pantry-share-invite--outgoing {
  border-style: dashed;
  border-color: rgba(255, 245, 230, 0.18);
}
.pantry-share-msg {
  flex: 1 1 auto;
  letter-spacing: 0.02em;
}
.pantry-share-msg strong { color: var(--color-amber); font-weight: 600; }
.pantry-share-actions {
  display: inline-flex;
  gap: 6px;
  flex: 0 0 auto;
}

.pantry-share-form {
  flex-wrap: wrap;
}
.pantry-share-input {
  flex: 1 1 220px;
  min-width: 0;
  background: rgba(0, 0, 0, 0.32);
  border: 1px solid rgba(255, 245, 230, 0.18);
  border-radius: 8px;
  padding: 6px 10px;
  color: var(--color-cream);
  font-family: var(--font-body);
  font-size: 13px;
  outline: none;
  transition: border-color 0.15s ease;
}
.pantry-share-input::placeholder {
  color: rgba(255, 245, 230, 0.32);
}
.pantry-share-input:focus { border-color: var(--color-amber); }

.pantry-share-btn {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid rgba(255, 245, 230, 0.22);
  background: rgba(255, 245, 230, 0.05);
  color: var(--color-cream);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.pantry-share-btn:hover {
  background: rgba(255, 245, 230, 0.12);
  border-color: rgba(255, 245, 230, 0.36);
}
.pantry-share-btn--accept,
.pantry-share-btn--invite {
  background: rgba(255, 138, 70, 0.18);
  border-color: rgba(255, 138, 70, 0.55);
  color: var(--color-amber);
}
.pantry-share-btn--accept:hover,
.pantry-share-btn--invite:hover {
  background: rgba(255, 138, 70, 0.28);
  border-color: var(--color-amber);
}
.pantry-share-btn--leave,
.pantry-share-btn--decline,
.pantry-share-btn--cancel {
  color: rgba(255, 245, 230, 0.65);
}

/* ============================================================
   Meals — 5-day meal planner + aggregated grocery list.
   Two-column layout (plan on the left, sticky grocery panel on
   the right), stacking on narrow screens. Translucent dark panels,
   amber accents — matches the rest of the cream-on-dark palette.
   ============================================================ */
/* Pantry page outer panel — same dark-with-inner-cards pattern as
   .dailies-panel. Wider than .scales-panel (Scales) to hold the
   two-column meal-plan + grocery-list grid. */
.pantry-panel {
  width: min(980px, calc(100% - 32px));
  margin: 24px auto 0;
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.pantry-grid {
  display: grid;
  grid-template-columns: 1.7fr 1fr;
  gap: 18px;
  align-items: start;
}
@media (max-width: 760px) {
  .pantry-grid { grid-template-columns: 1fr; gap: 20px; }
}

/* ---- Left column: 5-day plan, as an inner card ---- */
.pantry-plan {
  display: flex;
  flex-direction: column;
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  padding: 6px 16px;
}
.pantry-day {
  padding: 14px 4px;
  border-bottom: 1px solid rgba(255, 245, 230, 0.10);
}
.pantry-day:last-child { border-bottom: none; }
.pantry-day.is-today {
  background: linear-gradient(to right,
    rgba(255, 138, 70, 0.14), transparent 70%);
  border-bottom: 1px solid rgba(255, 245, 230, 0.14);
  margin: 0 -8px;
  padding-left: 12px;
  padding-right: 12px;
  border-radius: 8px;
}
.pantry-day-label {
  font-family: 'Cinzel', serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
  margin-bottom: 7px;
}
.pantry-day.is-today .pantry-day-label {
  color: var(--color-amber);
}
.pantry-day-inputs {
  display: flex;
  gap: 12px;
  align-items: flex-end;
}
.pantry-meal-input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  color: var(--color-cream);
  background: transparent;
  border: none;
  border-bottom: 1.5px solid rgba(255, 245, 230, 0.20);
  padding: 4px 0;
  outline: none;
  transition: border-color 0.15s ease;
}
.pantry-meal-input::placeholder {
  color: rgba(255, 245, 230, 0.30);
  font-weight: 400;
  font-style: italic;
}
.pantry-meal-input:focus {
  border-bottom-color: var(--color-amber);
}
.pantry-grocery-input--day {
  flex: 0 0 150px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  color: var(--color-cream);
  background: transparent;
  border: none;
  border-bottom: 1.5px solid rgba(255, 245, 230, 0.20);
  padding: 4px 0;
  outline: none;
  transition: border-color 0.15s ease;
}
.pantry-grocery-input--day::placeholder {
  color: rgba(255, 245, 230, 0.30);
  font-weight: 400;
}
.pantry-grocery-input--day:focus {
  border-bottom-color: var(--color-amber);
}
@media (max-width: 520px) {
  .pantry-day-inputs { flex-direction: column; align-items: stretch; }
  .pantry-grocery-input--day { flex: 1 1 auto; }
}

/* Per-day grocery chips */
.pantry-day-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 8px;
}
.pantry-day-tag {
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--color-cream);
  background: rgba(255, 138, 70, 0.14);
  border: 1px solid rgba(255, 138, 70, 0.42);
  border-radius: 999px;
  padding: 2px 10px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, text-decoration-color 0.15s ease;
}
.pantry-day-tag:hover {
  background: rgba(255, 138, 70, 0.22);
  border-color: var(--color-amber);
  text-decoration: line-through;
  text-decoration-color: var(--color-amber);
}

/* ---- Right column: aggregated grocery list ---- */
.pantry-grocery-panel {
  position: sticky;
  top: 24px;
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  padding: 16px 18px 14px;
}
@media (max-width: 760px) {
  .pantry-grocery-panel { position: static; }
}
.pantry-grocery-title {
  font-family: 'Cinzel', serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-amber);
  margin-bottom: 8px;
}
.pantry-grocery-input--general {
  width: 100%;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  color: var(--color-cream);
  background: transparent;
  border: none;
  border-bottom: 1.5px solid rgba(255, 245, 230, 0.20);
  padding: 4px 0;
  margin-bottom: 12px;
  outline: none;
  transition: border-color 0.15s ease;
}
.pantry-grocery-input--general::placeholder {
  color: rgba(255, 245, 230, 0.30);
  font-weight: 400;
}
.pantry-grocery-input--general:focus {
  border-bottom-color: var(--color-amber);
}
.pantry-grocery-day-label {
  font-family: 'Cinzel', serif;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
  margin-top: 12px;
  margin-bottom: 4px;
}
.pantry-grocery-day-label:first-child { margin-top: 0; }

.pantry-grocery-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  border-bottom: 1px solid rgba(255, 245, 230, 0.06);
}
.pantry-grocery-checkbox {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid rgba(255, 138, 70, 0.5);
  background: transparent;
  cursor: pointer;
  flex-shrink: 0;
  margin: 0;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.pantry-grocery-checkbox:checked {
  background-color: var(--color-amber);
  border-color: var(--color-amber);
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 10 7' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolyline points='1,3.5 4,6.5 9,1' stroke='%231a0e08' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 10px 7px;
}
.pantry-grocery-text {
  flex: 1 1 auto;
  font-size: 13px;
  color: var(--color-cream);
  transition: opacity 0.15s ease;
}
.pantry-grocery-item.is-checked .pantry-grocery-text {
  text-decoration: line-through;
  text-decoration-color: rgba(255, 245, 230, 0.4);
  opacity: 0.45;
}
.pantry-grocery-delete {
  flex: 0 0 auto;
  background: none;
  border: none;
  color: rgba(255, 245, 230, 0.35);
  font-size: 14px;
  line-height: 1;
  padding: 0 0 0 4px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, color 0.15s ease;
}
.pantry-grocery-item:hover .pantry-grocery-delete { opacity: 1; }
.pantry-grocery-delete:hover { color: var(--color-amber); }
/* Touch devices have no hover; show the X always so it's reachable. */
@media (hover: none) {
  .pantry-grocery-delete { opacity: 0.55; }
}

.pantry-grocery-empty {
  font-size: 12px;
  color: var(--color-cream-dim);
  font-style: italic;
  padding: 4px 0;
}
.pantry-clear-btn {
  margin-top: 12px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: color 0.15s ease;
}
.pantry-clear-btn:hover { color: var(--color-amber); }

/* ============================================================
   The Storage — slim toolbar above the boon-style category list.
   The category boxes / item pills / drag-to-reorder all reuse
   the existing dailies/boon CSS, since the page renders the same
   .category-grid > .category-box > .item-pill structure.
   ============================================================ */
.storage-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  max-width: 760px;
  margin: 0 auto 8px;
  padding: 0 20px;
}
.storage-count {
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
}
.storage-toggle-completed {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--color-cream-dim);
  cursor: pointer;
  user-select: none;
}
.storage-toggle-completed input {
  margin: 0;
  accent-color: var(--color-amber);
}

/* ============================================================
   Settings page — account info + session controls inside the
   standard .dailies-panel outer box, with inner-card sections.
   ============================================================ */
.settings-panel {
  gap: 16px;
}
.settings-section {
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.settings-section-title {
  margin: 0 0 2px;
  font-family: 'Cinzel', serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-amber);
}
.settings-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
  border-bottom: 1px solid rgba(255, 245, 230, 0.06);
}
.settings-row:last-child { border-bottom: none; }
.settings-label {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
}
.settings-value {
  font-size: 14px;
  color: var(--color-cream);
  text-align: right;
  word-break: break-word;
}
.settings-hint {
  font-size: 12px;
  color: var(--color-cream-dim);
  font-style: italic;
  margin: 0;
}

/* A labelled input/value with its own column (name, passwords). */
.settings-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.settings-field .settings-label { margin-bottom: 2px; }

/* Inline cluster: input + button, or a couple of buttons. */
.settings-inline {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.settings-inline .text-input { flex: 1 1 200px; min-width: 0; }

/* A standalone action button (logout, change password, delete…). */
.settings-action { align-self: flex-start; margin-top: 2px; }

/* Inline save/validation feedback. */
.settings-feedback {
  font-size: 12px;
  min-height: 1em;
}
.settings-feedback.is-ok    { color: #8fd18f; }
.settings-feedback.is-error { color: #ff8a6a; }

/* lbs/kg segmented toggle. */
.settings-toggle {
  display: inline-flex;
  border: 1px solid var(--color-edge-dim);
  border-radius: 999px;
  overflow: hidden;
}
.settings-toggle-btn {
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 5px 16px;
  background: transparent;
  border: none;
  color: var(--color-cream-dim);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.settings-toggle-btn.is-active {
  background: rgba(255, 138, 70, 0.22);
  color: var(--color-amber);
}

/* Pantry-sharing rows inside settings. */
.settings-share { display: flex; flex-direction: column; gap: 8px; }
.settings-share-active,
.settings-share-invite {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--color-cream);
}
.settings-share-active strong,
.settings-share-invite strong { color: var(--color-amber); font-weight: 600; }

/* Danger zone — red-tinted section + confirm sub-panel. */
.settings-section--danger {
  border-color: rgba(217, 79, 58, 0.45);
}
.settings-section--danger .settings-section-title { color: #ff7a5a; }
.settings-delete-confirm {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px dashed rgba(217, 79, 58, 0.3);
}
.settings-delete-confirm[hidden] { display: none; }

/* Red action button (delete). */
.btn--danger {
  background: rgba(180, 50, 30, 0.25);
  border: 1px solid rgba(217, 79, 58, 0.6);
  color: #ffb6a3;
}
.btn--danger:hover:not(:disabled) {
  background: rgba(200, 60, 36, 0.4);
  border-color: #ff7a5a;
  color: #fff0ea;
}
.btn--danger:disabled { opacity: 0.5; cursor: default; }

/* ============================================================
   Settings list rows — the tidy iOS-style list. Most rows open a
   lightbox; a few (email, weight unit, log out) act inline.
   ============================================================ */
.settings-group { margin-bottom: 18px; }
.settings-group:last-child { margin-bottom: 0; }
.settings-group-title {
  margin: 0 0 8px;
  font-family: 'Cinzel', serif;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-amber);
  opacity: 0.85;
}
.settings-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  padding: 13px 16px;
  margin-bottom: 6px;
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  color: var(--color-cream);
  font: inherit;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.settings-list-row:last-child { margin-bottom: 0; }
button.settings-list-row:hover {
  background: rgba(40, 22, 12, 0.7);
  border-color: rgba(255, 245, 230, 0.20);
}
.settings-list-row--static { cursor: default; }
.settings-list-label { flex: 0 0 auto; font-size: 14px; }
.settings-list-value {
  flex: 1 1 auto;
  text-align: right;
  font-size: 13px;
  color: var(--color-cream-dim);
  word-break: break-word;
}
.settings-list-chevron {
  flex: 0 0 auto;
  color: var(--color-cream-dim);
  font-size: 18px;
  line-height: 1;
}
/* Push a trailing inline control (the unit toggle) to the right. */
.settings-list-row .settings-toggle { margin-left: auto; }
.settings-list-row--action .settings-list-label { color: var(--color-amber); }
.settings-list-row--danger .settings-list-label { color: #ff7a5a; }

/* ============================================================
   Lightbox / modal dialog.
   ============================================================ */
body.modal-open { overflow: hidden; }
/* The `hidden` attribute must always win, even over classes that set
   `display` (e.g. .btn { display: inline-flex }). Without this a hidden
   .btn still renders as an empty box, and toggling .hidden in JS has no
   visual effect. */
[hidden] { display: none !important; }
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.modal-overlay[hidden] { display: none; }
.modal {
  width: min(420px, 100%);
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  background: var(--color-shadow-deep);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 20px 22px 22px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
  animation: modalIn 160ms ease;
}
@keyframes modalIn {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
html.rl-touch .modal { animation: none; }
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.modal-title {
  margin: 0;
  font-family: 'Cinzel', serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-amber);
}
.modal-close {
  background: none;
  border: none;
  color: var(--color-cream-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
  transition: color 0.15s ease;
}
.modal-close:hover { color: var(--color-cream); }
.modal-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.modal-body .settings-label { margin-bottom: 2px; }
/* The shared .text-input is flex:1 1 180px (for inline add-forms). In a
   modal's vertical flex column that makes it grow to fill the height —
   force direct-child inputs back to natural one-line height. (The
   rollover <select> is inside .settings-inline, not a direct child, so
   it keeps its row sizing.) */
.modal-body > .text-input { flex: 0 0 auto; }

/* ============================================================
   Neglect-penalty banner — slim full-width strip that fires the
   day after the 4-AM rollover applies the embers haircut. Sits
   between the top-bar and the page main, gets dismissed (per-day)
   via localStorage. Reddish to read as a consequence, not a chirp.
   ============================================================ */
.neglect-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 10px 18px;
  margin: 0 auto;
  max-width: 760px;
  border: 1px solid rgba(217, 79, 58, 0.45);
  border-radius: 10px;
  background: rgba(60, 14, 8, 0.55);
  color: #ffdac9;
  font-size: 13px;
  letter-spacing: 0.02em;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.neglect-banner[hidden] { display: none; }
.neglect-banner-text {
  flex: 1 1 auto;
  text-align: center;
}
.neglect-banner-dismiss {
  flex: 0 0 auto;
  background: none;
  border: none;
  color: #ffdac9;
  font-size: 18px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 120ms ease;
}
.neglect-banner-dismiss:hover { opacity: 1; }

/* ============================================================
   Today's Offerings — three spotlighted habits at the top of the
   boon and charm pages. Reduces decision overload by surfacing two
   longest-untouched items plus one under-picked item per day.
   ============================================================ */
.offerings {
  margin: 14px 0 4px;
  padding: 14px 16px 16px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 153, 102, 0.22);
  border-radius: 14px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.offerings-title {
  margin: 0 0 10px;
  font-family: 'Cinzel', serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-cream);
  opacity: 0.88;
}
.offerings-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.offering-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 11px 13px 12px;
  min-height: 78px;
  background: rgba(255, 245, 230, 0.06);
  border: 1px solid rgba(255, 245, 230, 0.14);
  border-radius: 10px;
  color: var(--color-cream);
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: background 160ms ease, border-color 160ms ease, transform 90ms ease;
}
.offering-card:hover {
  background: rgba(255, 245, 230, 0.10);
  border-color: rgba(255, 245, 230, 0.24);
}
.offering-card:active { transform: translateY(1px); }
.offering-card.is-checked {
  opacity: 0.5;
  background: rgba(255, 245, 230, 0.03);
  border-color: rgba(255, 245, 230, 0.08);
}
.offering-cat {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.62;
}
.offering-name {
  font-size: 14px;
  line-height: 1.25;
  font-weight: 500;
}
.offering-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
}
.offering-value {
  font-size: 12px;
  font-weight: 600;
  opacity: 0.88;
}
@media (max-width: 600px) {
  .offerings-grid { grid-template-columns: 1fr; }
}

/* Delete X — on mouse devices, hidden by default and revealed on hover.
   On touch devices (no hover), shown always since there's no other way
   to reveal it. Confirm dialog catches accidents either way. */
.item-delete {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-size: 16px;
  line-height: 1;
  color: var(--color-cream);
  background: rgba(180, 60, 30, 0.42);
  flex-shrink: 0;
  transition: opacity 0.18s ease, background 0.18s ease;
  cursor: pointer;
  user-select: none;
  margin-left: 2px;
}

@media (hover: hover) {
  .item-pill .item-delete {
    opacity: 0;
    pointer-events: none;
  }
  .item-pill:hover .item-delete {
    opacity: 1;
    pointer-events: auto;
  }
}

@media (hover: none) {
  .item-pill .item-delete {
    opacity: 1;
    pointer-events: auto;
  }
}

.item-delete:hover {
  background: rgba(220, 80, 40, 0.72);
}

/* The whole item becomes draggable while it's being dragged.
   touch-action: none prevents the page from scrolling on touch. */
.item-pill {
  touch-action: pan-y;
}

/* Visual lift for the item being dragged. */
.item-pill.is-dragging {
  position: relative;
  z-index: 100;
  opacity: 0.9;
  cursor: grabbing;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.55);
  transition: none;
}

/* Drop indicators — a glowing edge on the side the dragged item would
   land if released here. Inset box-shadow so it doesn't affect layout. */
.item-pill.is-drop-above {
  box-shadow: inset 0 3px 0 var(--color-flame), 0 0 12px rgba(255, 122, 61, 0.4);
}

.item-pill.is-drop-below {
  box-shadow: inset 0 -3px 0 var(--color-flame), 0 0 12px rgba(255, 122, 61, 0.4);
}

.empty-hint {
  text-align: center;
  font-size: 12px;
  color: var(--color-cream-dim);
  font-style: italic;
  padding: 32px 16px;
  margin: 0;
}

/* ---------- Auth pages (login / register / forgot / reset) ---------- */
.auth-layout {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 16px 32px 32px;
  gap: 32px;
}

.auth-panel {
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 24px 22px;
  width: min(360px, calc(100% - 32px));
  display: flex;
  flex-direction: column;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Each labeled field is a tight vertical stack: small-caps label,
   then a single-line input directly below it. */
.auth-label {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  width: 100%;
}

.auth-label > span {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-cream-dim);
  font-weight: 500;
  padding-left: 2px;
}

.auth-form .text-input {
  flex: 0 0 auto;
  padding: 9px 14px;
  width: 100%;
}

.auth-error {
  font-size: 12px;
  color: #ff8b6b;
  margin: 0;
  letter-spacing: 0.02em;
  text-align: center;
  padding: 8px 12px;
  background: rgba(180, 50, 30, 0.18);
  border: 1px solid rgba(220, 90, 60, 0.35);
  border-radius: 6px;
}

.auth-success {
  font-size: 12px;
  color: var(--color-amber);
  margin: 0;
  letter-spacing: 0.02em;
  text-align: center;
  padding: 8px 12px;
  background: rgba(255, 138, 70, 0.12);
  border: 1px solid var(--color-edge);
  border-radius: 6px;
  line-height: 1.5;
}

.auth-success a,
.auth-error a {
  color: inherit;
  text-decoration: underline;
}

.auth-submit {
  margin-top: 4px;
  width: 100%;
  justify-content: center;
}

.auth-links {
  margin-top: 4px;
  display: flex;
  justify-content: center;
  gap: 10px;
  font-size: 11px;
  letter-spacing: 0.05em;
  color: var(--color-cream-dim);
  flex-wrap: wrap;
}

.auth-links a {
  color: var(--color-cream-dim);
  text-decoration: none;
  border-bottom: 1px dotted var(--color-edge-dim);
  transition: color 0.2s ease, border-color 0.2s ease;
  padding-bottom: 1px;
}

.auth-links a:hover {
  color: var(--color-amber);
  border-color: var(--color-flame);
}

/* ---------- Page transitions ---------- */
/* The top bar and vignette are intentionally NOT animated — they're the
   persistent shell. Only page content (.hub / .map-layout / .footnote)
   slides in and out. */

/* Note: backdrop-filter is intentionally NOT used on any panel that lives
   inside an animating container (.slot, .map-panel, .quest-panel,
   .dailies-panel). Chromium suppresses backdrop-filter while an ancestor
   is transforming and snaps it back in afterward; layer-promotion hacks
   (translateZ, isolation) work around the snap by killing the blur
   entirely. The dark rgba(8,4,2,0.78) panel background does most of the
   visual separation on its own. The persistent shell pills (.player,
   .stats) keep their blur — they never animate. */

/* Pre-entrance state: content is held offscreen-down until JS adds
   .is-entering. This avoids the "instant appear" you'd otherwise get on
   prerendered pages whose CSS animations already played in the background
   before you ever saw them. */
.hub:not(.is-entering),
.map-layout:not(.is-entering),
.footnote:not(.is-entering) {
  opacity: 0;
  transform: translateY(80px);
}

/* Entrance: triggered by JS, either at DOMContentLoaded (regular load)
   or at prerenderingchange (when a prerendered page becomes active). */
.hub.is-entering,
.map-layout.is-entering {
  animation: enterFromBottom 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.footnote.is-entering {
  animation: enterFromBottom 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.1s both;
}

@keyframes enterFromBottom {
  from { transform: translateY(80px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

/* Exit: triggered by JS adding .is-leaving before navigation.
   Slides further than the entrance so the motion clearly registers
   before the overlay finishes covering the screen. */
.hub.is-leaving,
.map-layout.is-leaving,
.footnote.is-leaving {
  animation: exitToBottom 0.55s cubic-bezier(0.55, 0, 0.85, 0.4) forwards;
}

@keyframes exitToBottom {
  to { transform: translateY(100px); opacity: 0; }
}

/* The fixed-position layer that holds the *destination* background while
   the outgoing page is animating out. Once it's fully opaque the script
   navigates, and the destination page renders with its real background
   underneath — no flash. */
.transition-overlay {
  position: fixed;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: #1a0d08;
  opacity: 0;
  transition: opacity 0.5s ease-out;
  pointer-events: none;
  z-index: 50;
}

.transition-overlay.is-active {
  opacity: 1;
  pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
  .hub:not(.is-entering),
  .map-layout:not(.is-entering),
  .footnote:not(.is-entering),
  .hub.is-entering,
  .map-layout.is-entering,
  .footnote.is-entering,
  .hub.is-leaving,
  .map-layout.is-leaving,
  .footnote.is-leaving {
    animation: none !important;
    opacity: 1;
    transform: none;
  }
  .transition-overlay {
    transition: opacity 0.15s ease;
  }
}

/* Touch devices (iPad, phones): skip all the slide/fade animations.
   The page just appears like a regular web page. The transition overlay
   in transitions.js is also disabled for touch (see IS_TOUCH check there).
   Keeps PC with the full cinematic feel; keeps iPad snappy and reliable.

   We have two selectors doing the same job:
     - @media (hover: none) and (pointer: coarse) — phones, most touch.
     - html.rl-touch — set by the inline pre-stamp script using
       navigator.maxTouchPoints, which is the only reliable signal on
       iPad in default Request-Desktop-Website mode (iPad otherwise lies
       to matchMedia and reports hover: hover, pointer: fine). */
@media (hover: none) and (pointer: coarse) {
  .hub:not(.is-entering),
  .map-layout:not(.is-entering),
  .footnote:not(.is-entering),
  .hub.is-entering,
  .map-layout.is-entering,
  .footnote.is-entering,
  .hub.is-leaving,
  .map-layout.is-leaving,
  .footnote.is-leaving {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .transition-overlay {
    display: none !important;
  }
}

html.rl-touch .hub:not(.is-entering),
html.rl-touch .map-layout:not(.is-entering),
html.rl-touch .footnote:not(.is-entering),
html.rl-touch .hub.is-entering,
html.rl-touch .map-layout.is-entering,
html.rl-touch .footnote.is-entering,
html.rl-touch .hub.is-leaving,
html.rl-touch .map-layout.is-leaving,
html.rl-touch .footnote.is-leaving {
  animation: none !important;
  opacity: 1 !important;
  transform: none !important;
}
html.rl-touch .transition-overlay {
  display: none !important;
}

/* ---------- Responsive ---------- */
@media (max-width: 760px) {
  .top-bar {
    padding: 16px;
    flex-direction: column;
    gap: 12px;
  }

  .stats {
    width: 100%;
    justify-content: center;
  }

  .stat {
    flex: 1;
    padding: 4px 10px;
  }

  .hub {
    gap: 32px;
    padding: 16px 16px 24px;
  }

  .title {
    letter-spacing: 0.12em;
  }

  .loadout {
    flex-direction: column;
    width: 100%;
    max-width: 320px;
    gap: 14px;
  }

  .slot {
    width: 100%;
    min-height: auto;
    flex-direction: row;
    text-align: left;
    padding: 16px;
    gap: 16px;
  }

  .slot-icon {
    width: 40px;
    height: 40px;
    margin-top: 0;
    flex-shrink: 0;
  }

  .slot-label {
    flex: 1;
    font-size: 14px;
  }

  .slot-hint {
    display: none;
  }

  .run-button {
    padding: 16px 32px;
    width: 100%;
    max-width: 320px;
  }
}

/* ---------- The Run (game viewport) ----------
   The page's wall image (.page-bg) sits behind everything as the cozy
   room. The .run-stage is the black-framed window into the game and is
   split into two vertically-stacked zones:
     - .run-stage-sky-zone — the platformer-style sky strip at the top,
       sized to the source image's native aspect ratio (4096×681 ≈ 6:1).
       The runner sprite lives inside this zone and animates in.
     - .run-stage-log — a black readout below the sky where run events
       scroll in chronologically.
   Below the stage, the HUD holds the equipped boon and charm slots. */

.run-stage-wrap {
  width: 100%;
  display: flex;
  justify-content: center;
  padding: 0 20px;
}

.run-stage {
  position: relative;
  width: 100%;
  max-width: 760px;
  /* Stage itself is transparent — the .run-stage-log (75% black) and
     .run-stage-sky-zone (image + 25% black overlay) handle their own
     fills, and the cozy room (runWall.png on .page-bg) shows through
     wherever they're translucent. */
  background-color: transparent;
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  overflow: hidden;
  box-shadow:
    0 12px 40px rgba(0, 0, 0, 0.55),
    inset 0 0 0 1px rgba(255, 255, 255, 0.04);
  display: flex;
  flex-direction: column;
}

/* The sky strip. <img> at width:100%/height:auto self-sizes the zone to
   the image's native aspect ratio — no math, no aspect-ratio property.
   line-height: 0 + vertical-align: top kill the phantom 3-4px baseline
   gap that browsers otherwise add below inline-level <img> elements. */
.run-stage-sky-zone {
  position: relative;
  width: 100%;
  overflow: hidden;
  line-height: 0;
  font-size: 0;
}

.run-stage-sky-img {
  display: block;
  width: 100%;
  height: auto;
  vertical-align: top;
}

/* Black wash over the sky, sitting between the sky image (no z-index)
   and the runner sprite (z-index: 2). Dims the clouds for atmosphere
   and so the runner has visual contrast. Darkens further when the
   run isn't current (death or post-9pm) so the painted-on message
   reads cleanly. */
.run-stage-sky-zone::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  pointer-events: none;
  z-index: 1;
  transition: background 0.5s ease;
}
.run-stage.is-not-current .run-stage-sky-zone::after {
  background: rgba(0, 0, 0, 0.72);
}

/* Centered "The runner fell." / "Returned to the hearth." message
   painted onto the sky. Sits above everything inside the sky-zone
   (img: z 0, dark wash: z 1, runner: z 2, this: z 3). */
.run-stage-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 3;
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--color-cream);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.85),
               0 0 22px rgba(0, 0, 0, 0.6);
  text-align: center;
  padding: 0 16px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.run-stage.is-not-current .run-stage-overlay {
  opacity: 1;
}

/* Wrapper for the runner sprite. Animating `left` on the anchor keeps
   the inner <img>'s `transform` free for the hover loop — two animations
   on the same transform fight each other otherwise.

   The animations are PAUSED by default. run.js adds .is-ready to the
   stage only when the run is currently active (not dead, not past 9 PM)
   so the fly-in/hover never play for a finished run. */
.run-runner-anchor {
  position: absolute;
  top: 50%;
  left: 33%;
  width: 13%;
  /* translate(-50%, -50%) centers the anchor on its (left, top) coords
     so the sprite's center lands at "1/3 from the left" of the strip,
     not the sprite's left edge. */
  transform: translate(-50%, -50%);
  z-index: 2;
  /* Delay 0.7s so the fly-in starts after .map-layout's entrance
     animation finishes. Overshoot easing for a satisfying landing. */
  animation: runnerFlyIn 1.8s cubic-bezier(0.34, 1.56, 0.64, 1) 0.7s both;
  animation-play-state: paused;
}
.run-stage.is-ready .run-runner-anchor {
  animation-play-state: running;
}

.run-runner {
  width: 100%;
  height: auto;
  display: block;
  /* Hover kicks in just after the fly-in settles (delay = 0.7 + 1.8). */
  animation: runnerHover 2.8s ease-in-out 2.5s infinite both;
  animation-play-state: paused;
}
.run-stage.is-ready .run-runner {
  animation-play-state: running;
}

@keyframes runnerFlyIn {
  from {
    left: -20%;
    transform: translate(-50%, -50%) rotate(-6deg);
  }
  to {
    left: 33%;
    transform: translate(-50%, -50%) rotate(0deg);
  }
}

@keyframes runnerHover {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-10px); }
}

/* Touch devices: skip the cinematic fly-in (and the hover, which depends
   on the fly-in's delay). The runner just appears at the 1/3 mark. */
html.rl-touch .run-runner-anchor,
html.rl-touch .run-runner {
  animation: none !important;
}
@media (hover: none) and (pointer: coarse) {
  .run-runner-anchor,
  .run-runner {
    animation: none !important;
  }
}

/* ---- In-stage log (black panel below the sky strip) ---- */

.run-stage-log {
  flex: 1 1 auto;
  min-height: 220px;
  padding: 14px 18px;
  overflow-y: auto;
  /* 75% black so the runWall room behind the page shows through at 25%
     intensity — keeps the stage from feeling like a hard black cutout. */
  background: rgba(0, 0, 0, 0.75);
  color: var(--color-cream);
  font-size: 13px;
  line-height: 1.55;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.run-stage-log-empty {
  color: rgba(245, 230, 211, 0.4);
  font-style: italic;
  font-size: 12px;
  text-align: center;
  padding: 16px 0;
  margin: auto;
}

.run-log-entry {
  padding: 5px 0;
  border-bottom: 1px solid rgba(255, 138, 70, 0.08);
  display: flex;
  gap: 12px;
  align-items: baseline;
  animation: logEntryIn 0.35s ease-out both;
}

.run-log-entry:last-child {
  border-bottom: none;
}

.run-log-entry-time {
  font-family: var(--font-display);
  font-size: 11px;
  color: var(--color-amber);
  letter-spacing: 0.06em;
  flex: 0 0 auto;
  min-width: 64px;
}

.run-log-entry-text {
  color: var(--color-cream);
}

@keyframes logEntryIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Touch devices: skip the per-entry fade-in too. Entries just appear. */
html.rl-touch .run-log-entry {
  animation: none !important;
}
@media (hover: none) and (pointer: coarse) {
  .run-log-entry {
    animation: none !important;
  }
}

/* ---- HUD below the stage: boon + charm slots ---- */

.run-hud {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 0 20px;
}

.run-loadout {
  display: flex;
  gap: 12px;
  flex: 0 0 auto;
}

.run-slot {
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 12px;
  padding: 12px 18px;
  min-width: 130px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 6px;
  justify-content: center;
}

.run-slot-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--color-cream-dim);
}

.run-slot-value {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--color-amber);
  line-height: 1;
}

.run-slot--empty .run-slot-value {
  color: var(--color-cream-dim);
  font-family: var(--font-body);
  font-size: 12px;
  font-style: italic;
  letter-spacing: 0.03em;
}

/* ---- Responsive: tighter padding on small screens ---- */
@media (max-width: 760px) {
  .run-stage-wrap {
    padding: 0 16px;
  }
  .run-hud {
    padding: 0 16px;
  }
  .run-loadout {
    flex-wrap: wrap;
    justify-content: center;
  }
  .run-slot {
    flex: 1 1 0;
    min-width: 0;
  }
}

/* ---- Touch devices: drop the sky picture and runner animation
   entirely. On phones and iPads the picture's native aspect ratio
   ate so much vertical space that the buttons fell below the fold.
   The .run-stage becomes pills + log only, which is the meaningful
   surface anyway. Death overlay message ("The runner fell.") would
   normally appear over the sky — on mobile, the log entry serves
   that role instead. Both selectors below catch the same device set
   (rl-touch class set by inline script + pure-CSS hover-none match);
   we list both so we're not relying solely on JS having run yet. */
html.rl-touch .run-stage-sky-zone,
html.rl-touch .run-runner-anchor {
  display: none;
}
@media (hover: none) and (pointer: coarse) {
  .run-stage-sky-zone,
  .run-runner-anchor {
    display: none;
  }
}

/* ============================================================
   Equip star on Boon / Charm items.
   Click toggles the item as equipped for the run. Solid star,
   dim when unequipped, amber-glow when equipped.
   ============================================================ */
.item-equip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  color: rgba(245, 230, 211, 0.28);
  cursor: pointer;
  user-select: none;
  transition: color 0.2s ease, background 0.2s ease, transform 0.15s ease;
  flex: 0 0 auto;
}
.item-equip:hover {
  color: var(--color-amber);
  background: rgba(255, 138, 70, 0.12);
}
.item-equip.is-equipped {
  color: var(--color-amber);
  text-shadow: 0 0 8px rgba(255, 170, 70, 0.7);
}
.item-equip.is-equipped:hover {
  background: rgba(255, 138, 70, 0.18);
  transform: scale(1.05);
}

/* ============================================================
   Run hero stats panel — HP bar, armor, attack, foes felled.
   Sits between the stage and the loadout slots.
   ============================================================ */
.run-stats {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: 0 20px;
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 12px;
  align-items: stretch;
}

.run-stat {
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 12px;
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  min-width: 0;
}

.run-stat-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--color-cream-dim);
}

.run-stat-value {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  color: var(--color-amber);
  line-height: 1;
}

.run-stat-value.is-buffed {
  color: #ffd28a;
  text-shadow: 0 0 6px rgba(255, 200, 100, 0.55);
}

.run-stat--hp {
  /* HP needs vertical room for the bar below the numeric. */
  gap: 6px;
}

.run-stat-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.run-hp-bar {
  height: 8px;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 999px;
  overflow: hidden;
  border: 1px solid rgba(255, 138, 70, 0.18);
}
.run-hp-fill {
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, #ff7a3d, #ffa55a);
  border-radius: 999px;
  transition: width 0.5s cubic-bezier(0.16, 1, 0.3, 1), background 0.3s ease;
}
.run-hp-fill.is-low {
  background: linear-gradient(90deg, #c84718, #ff7a3d);
}
.run-hp-fill.is-critical {
  background: linear-gradient(90deg, #8a1e0a, #c84718);
  animation: hpPulse 1.4s ease-in-out infinite;
}
@keyframes hpPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}
html.rl-touch .run-hp-fill.is-critical {
  animation: none;
}
@media (hover: none) and (pointer: coarse) {
  .run-hp-fill.is-critical { animation: none; }
}

/* ============================================================
   Ember-purchased action pills — sit between the sky strip and the
   log as a flush band. Not sticky, no negative margins; the flex
   column on .run-stage stacks sky-zone → pills → log with no gap.
   ============================================================ */
.run-pills {
  padding: 8px 14px;
  background: rgba(0, 0, 0, 0.88);
  border-bottom: 1px solid rgba(255, 138, 70, 0.18);
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}

.run-pills-embers {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  margin-right: 4px;
  padding-right: 10px;
  border-right: 1px solid rgba(255, 138, 70, 0.18);
}
.run-pills-embers-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--color-cream-dim);
}
.run-pills-embers-value {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  color: var(--color-amber);
}

.run-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid var(--color-edge);
  background: rgba(28, 16, 8, 0.85);
  color: var(--color-cream);
  font-family: var(--font-body);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease,
              transform 0.1s ease, opacity 0.15s ease;
}
.run-pill:hover:not(:disabled) {
  background: rgba(46, 26, 14, 0.92);
  border-color: var(--color-flame);
  transform: translateY(-1px);
}
.run-pill:disabled {
  opacity: 0.42;
  cursor: not-allowed;
}
.run-pill-name {
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.05em;
  color: var(--color-amber);
}
.run-pill-cost {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  color: var(--color-cream);
  background: rgba(0, 0, 0, 0.4);
  padding: 1px 7px;
  border-radius: 999px;
}

/* ============================================================
   Log entry color coding by type (defeat / hit / miss / etc).
   Subtle — just shift the timestamp color to match the event mood.
   ============================================================ */
.run-log-entry--win .run-log-entry-time,
.run-log-entry--strike .run-log-entry-time {
  color: #ffd28a;
}
.run-log-entry--hit .run-log-entry-time,
.run-log-entry--death .run-log-entry-time {
  color: #ff8a6e;
}
.run-log-entry--miss .run-log-entry-time {
  color: rgba(255, 200, 100, 0.55);
}
.run-log-entry--queued .run-log-entry-text,
.run-log-entry--preview .run-log-entry-text {
  font-style: italic;
  color: rgba(245, 230, 211, 0.72);
}
.run-log-entry--death .run-log-entry-text {
  color: #ff7a6e;
  font-weight: 600;
}

/* ============================================================
   Not-current state — runner is gone (fell or returned), and the
   painted-on overlay tells you which. The black log area below
   still shows the full record of the day.
   ============================================================ */
.run-stage.is-not-current .run-runner-anchor {
  display: none;
}

/* ============================================================
   Responsive: stack stats 2-up and buttons 2x2 below 760px.
   ============================================================ */
@media (max-width: 760px) {
  .run-stats {
    grid-template-columns: 1fr 1fr;
    padding: 0 16px;
  }
  .run-stat--hp {
    grid-column: 1 / -1;
  }
  /* Pills already wrap via flex-wrap; smaller screens just stack them
     into two rows under the embers readout. */
}

/* ============================================================
   Link from run.html to bonuses.html. A subtle pill below the
   stats panel.
   ============================================================ */
.run-bonuses-link {
  display: inline-block;
  align-self: center;
  margin: 0 auto;
  padding: 6px 14px;
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--color-cream);
  text-decoration: none;
  border: 1px solid var(--color-edge-dim);
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.75);
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease, transform 0.15s ease;
}
.run-bonuses-link:hover {
  color: var(--color-amber);
  border-color: var(--color-flame);
  background: rgba(0, 0, 0, 0.85);
  transform: translateY(-1px);
}

/* ============================================================
   Bonuses page — breakdown of where every stat number comes
   from. Grid of cards, one per stat, plus an Equipment card.
   ============================================================ */
.bonuses-grid {
  width: 100%;
  max-width: 880px;
  margin: 0 auto;
  padding: 0 20px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}

.bonus-card {
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.bonus-card--equipment {
  grid-column: 1 / -1;
}

.bonus-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 12px;
  border-bottom: 1px solid var(--color-edge-dim);
  padding-bottom: 10px;
}

.bonus-card-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--color-cream);
  margin: 0;
}

.bonus-card-total {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.bonus-card-total-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--color-cream-dim);
}

.bonus-card-total-value {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 700;
  color: var(--color-amber);
  line-height: 1;
}

.bonus-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.bonus-list-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 6px 0;
  border-bottom: 1px dotted rgba(255, 138, 70, 0.08);
  font-size: 13px;
}
.bonus-list-item:last-child {
  border-bottom: none;
}

.bonus-list-label {
  color: var(--color-cream-dim);
  flex: 1 1 auto;
  min-width: 0;
}

.bonus-list-value {
  font-family: var(--font-display);
  color: var(--color-amber);
  font-weight: 700;
  font-size: 14px;
  flex: 0 0 auto;
}

.bonus-list-item.is-zero .bonus-list-value {
  color: rgba(245, 230, 211, 0.32);
}
.bonus-list-item.is-zero .bonus-list-label {
  color: rgba(245, 230, 211, 0.42);
}

.bonus-card-hint {
  margin: 4px 0 0;
  font-size: 11px;
  font-style: italic;
  color: rgba(245, 230, 211, 0.55);
  line-height: 1.5;
}

/* Equipment card has two side-by-side blocks, one per slot. */
.bonus-equipment-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.bonus-equipment-block {
  background: rgba(255, 138, 70, 0.06);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.bonus-equipment-kind {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--color-cream-dim);
}

.bonus-equipment-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--color-amber);
  line-height: 1.2;
}

.bonus-equipment-name.is-empty {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 13px;
  color: var(--color-cream-dim);
}

.bonus-equipment-freshness {
  font-size: 11px;
  color: var(--color-cream-dim);
  letter-spacing: 0.04em;
}

.bonus-equipment-bonus {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--color-amber);
  font-weight: 700;
  margin-top: 2px;
}
.bonus-equipment-bonus.is-zero {
  color: rgba(245, 230, 211, 0.4);
  font-family: var(--font-body);
  font-style: italic;
  font-size: 12px;
  font-weight: 400;
}

/* Back link in the bonuses title block. */
.title-meta {
  margin: 8px 0 0;
  font-size: 12px;
}
.back-link {
  color: var(--color-cream-dim);
  text-decoration: none;
  border-bottom: 1px dotted var(--color-edge-dim);
  transition: color 0.2s ease, border-color 0.2s ease;
  padding-bottom: 1px;
}
.back-link:hover {
  color: var(--color-amber);
  border-color: var(--color-flame);
}

/* Responsive: stack cards on small screens. */
@media (max-width: 760px) {
  .bonuses-grid {
    grid-template-columns: 1fr;
    padding: 0 16px;
  }
  .bonus-equipment-row {
    grid-template-columns: 1fr;
  }
  .bonus-card-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  .bonus-card-total {
    align-items: flex-start;
  }
}

/* ============================================================
   Run-slot rendering when an equipped item is shown — name on
   the first line, compact stat summary on the second.
   ============================================================ */
.run-slot-name {
  display: block;
  font-family: var(--font-display);
  color: var(--color-amber);
  font-size: 15px;
  line-height: 1.1;
}
.run-slot-name.is-greater {
  color: #ffd28a;
  text-shadow: 0 0 6px rgba(255, 200, 100, 0.45);
}
.run-slot-substats {
  display: block;
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--color-cream-dim);
  margin-top: 4px;
  letter-spacing: 0.02em;
  line-height: 1.3;
}

/* ============================================================
   The Pack (inventory.html) — crafting + equipped + inventory.
   Outer panel mimics .dailies-panel so everything sits on a
   solid shadow background instead of floating on the wall image.
   ============================================================ */

.pack-panel {
  background: var(--color-shadow);
  border: 1px solid var(--color-edge);
  border-radius: 14px;
  padding: 24px;
  width: min(840px, calc(100% - 32px));
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.pack-box {
  background: rgba(20, 10, 5, 0.55);
  border: 1px solid var(--color-edge-dim);
  border-radius: 10px;
  padding: 18px 18px 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.pack-box-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.pack-box-title {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-amber);
  margin: 0;
}

.pack-box-counter {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--color-cream-dim);
}

.pack-box-hint {
  font-size: 11px;
  color: var(--color-cream-faint);
  font-style: italic;
  margin: 4px 0 0;
  letter-spacing: 0.02em;
}

/* ---- Forge buttons ---- */
.pack-forge-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.forge-button {
  background: rgba(28, 16, 8, 0.85);
  border: 1px solid var(--color-edge);
  border-radius: 10px;
  padding: 16px 14px;
  color: var(--color-cream);
  font-family: var(--font-body);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  transition: transform 0.15s ease, box-shadow 0.2s ease,
              background 0.2s ease, border-color 0.2s ease, opacity 0.2s ease;
}
.forge-button:hover:not(:disabled) {
  background: rgba(46, 26, 14, 0.9);
  border-color: var(--color-flame);
  transform: translateY(-1px);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45),
              0 0 18px rgba(255, 122, 61, 0.18) inset;
}
.forge-button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.forge-button--greater {
  background: linear-gradient(135deg, rgba(50, 36, 16, 0.92), rgba(28, 18, 8, 0.88));
  border-color: rgba(255, 200, 100, 0.55);
  box-shadow: 0 0 14px rgba(255, 200, 100, 0.10) inset;
}
.forge-button--greater:hover:not(:disabled) {
  background: linear-gradient(135deg, rgba(70, 50, 20, 0.95), rgba(40, 26, 12, 0.92));
  border-color: rgba(255, 220, 130, 0.9);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45),
              0 0 22px rgba(255, 200, 100, 0.22) inset;
}
.forge-name {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--color-amber);
  letter-spacing: 0.05em;
}
.forge-button--greater .forge-name {
  color: #ffd28a;
  text-shadow: 0 0 6px rgba(255, 200, 100, 0.35);
}
.forge-cost {
  font-size: 11px;
  color: var(--color-cream);
  letter-spacing: 0.04em;
}

/* ---- Equipped slots on the Pack page ---- */
.equipped-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.equipped-card {
  background: rgba(40, 22, 12, 0.7);
  border: 1px solid var(--color-edge);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.equipped-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--color-cream-dim);
}
.equipped-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--color-amber);
  line-height: 1.2;
}
.equipped-name.is-greater {
  color: #ffd28a;
  text-shadow: 0 0 6px rgba(255, 200, 100, 0.45);
}
.equipped-stats {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.equipped-stats .stat-line {
  font-size: 12px;
  color: var(--color-cream);
}

/* ---- Inventory grid ---- */
.inventory-grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.inventory-empty {
  text-align: center;
  font-style: italic;
  color: var(--color-cream-dim);
  font-size: 13px;
  padding: 16px 0;
  margin: 0;
}

.inv-group {
  background: rgba(40, 22, 12, 0.7);
  border: 1px solid var(--color-edge);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.inv-group-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-bottom: 1px dotted var(--color-edge-dim);
  padding-bottom: 8px;
}
.inv-group-name {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--color-amber);
  letter-spacing: 0.04em;
}
.inv-group-flavor {
  font-size: 11px;
  font-style: italic;
  color: var(--color-cream-dim);
}

.inv-instances {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.inv-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  background: rgba(255, 138, 70, 0.05);
  border: 1px solid var(--color-edge-dim);
  border-radius: 8px;
}
.inv-item--greater {
  background: linear-gradient(90deg, rgba(255, 200, 100, 0.10), rgba(220, 165, 60, 0.04));
  border-color: rgba(255, 200, 100, 0.45);
}
.inv-item-stats {
  font-size: 13px;
  color: var(--color-cream);
  flex: 1 1 auto;
  min-width: 0;
}
.inv-item-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 10px;
  font-family: var(--font-display);
  letter-spacing: 0.1em;
  color: #2a1a0a;
  background: linear-gradient(135deg, #ffd28a, #f0b056);
}
.inv-item-actions {
  display: flex;
  gap: 6px;
  flex: 0 0 auto;
}
.inv-action {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 6px 10px;
  border-radius: 6px;
  border: 1px solid var(--color-edge);
  background: var(--color-shadow);
  color: var(--color-cream);
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.inv-action--equip {
  background: linear-gradient(135deg, rgba(255, 138, 70, 0.22), rgba(255, 122, 61, 0.08));
  border-color: var(--color-flame);
  color: var(--color-amber);
}
.inv-action--equip:hover {
  background: linear-gradient(135deg, rgba(255, 138, 70, 0.4), rgba(255, 122, 61, 0.16));
}
.inv-action--scrap {
  color: var(--color-cream-dim);
}
.inv-action--scrap:hover {
  color: var(--color-amber);
  border-color: var(--color-flame);
}

@media (max-width: 760px) {
  .pack-forge-grid {
    grid-template-columns: 1fr;
  }
  .equipped-grid {
    grid-template-columns: 1fr;
  }
  .pack-currencies {
    padding: 0 16px;
  }
  .pack-section {
    padding: 0 16px;
  }
  .inv-item {
    flex-direction: column;
    align-items: flex-start;
  }
  .inv-item-actions {
    width: 100%;
    justify-content: flex-end;
  }
}
