/* ═════════════════════════════════════════════
   BOTTOM SHEET SYSTEM
   Was entirely missing — #bottom-sheet, #sheet-backdrop,
   the nav rail, tabs, journal/quest/dossier/profile content
   had no CSS at all, so toggling .open had nothing to show.
   ═════════════════════════════════════════════ */

#sheet-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(4, 3, 2, 0.6);
  z-index: 30;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

#sheet-backdrop.open {
  opacity: 1;
  pointer-events: all;
}

#bottom-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 31;
  height: 78vh;
  max-height: 720px;
  background: #110e0a;
  border-top: 1px solid #4a3a1e;
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -8px 30px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
  transform: translateY(100%);
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

#bottom-sheet.open {
  transform: translateY(0);
}

/* The visible pill is only 4px tall — far too small a target to
   reliably grab for the drag-to-close gesture (initSheetDragToClose,
   ui.js). background-clip: content-box keeps the painted bar exactly
   the same small size, while the element's actual box (what touches
   land on) extends into the padding around it — a much bigger
   invisible touch target with zero visual change. Margin is reduced
   to compensate for the added padding, so the sheet's overall top
   spacing looks the same as it did before. */
#sheet-handle {
  width: 40px;
  height: 4px;
  border-radius: 2px;
  background: #3a2a1a;
  background-clip: content-box;
  box-sizing: content-box;
  padding: 12px 30px;
  margin: 0 auto;
  flex-shrink: 0;
  touch-action: none; /* this element's whole job is the drag gesture */
}

#sheet-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ── Horizontal tab bar (bottom of sheet) ── */
#sheet-nav {
  flex-shrink: 0;
  display: flex;
  flex-direction: row;
  border-top: 1px solid #201a10;
  background: #0e0b07;
  padding-bottom: env(safe-area-inset-bottom, 0);
}

.nav-btn {
  flex: 1;
  background: none;
  border: none;
  border-top: 2px solid transparent;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 4px 8px;
  color: #5a4a2a;
  cursor: pointer;
  font-family: 'Courier New', monospace;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}

.nav-icon-wrap { position: relative; display: inline-flex; }

.nav-icon { font-size: 18px; line-height: 1; }

.nav-label {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav-btn.active {
  color: #f4c840;
  background: rgba(244, 200, 64, 0.06);
  border-top-color: #f4c840;
}

/* Soft glow on the active tab's icon, on top of the existing color/
   border change above — an .icon-glyph is an inline SVG (utils.js),
   so this needs drop-shadow rather than text-shadow to actually show.
   Also gives the icon a brief pop the moment a tab becomes active
   (switchTab just toggled this class on), rather than an instant
   color swap with nothing to catch the eye. */
.nav-btn.active .nav-icon .icon-glyph {
  filter: drop-shadow(0 0 4px rgba(244, 200, 64, 0.75));
  animation: navIconActivate 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes navIconActivate {
  0%   { transform: scale(0.75); }
  60%  { transform: scale(1.25); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .nav-btn.active .nav-icon .icon-glyph { animation: none; }
}

/* Unread dot (Journal tab) — see addJournalEntry / updateJournalUnreadBadge
   (journal.js) and the clearing side in switchTab (ui.js). Hidden by
   default; .visible pops it in rather than just appearing instantly. */
.nav-unread-dot {
  position: absolute;
  top: -2px;
  right: -5px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #f4c840;
  box-shadow: 0 0 4px rgba(244, 200, 64, 0.8);
  transform: scale(0);
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.nav-unread-dot.visible { transform: scale(1); }
/* Already-active tab doesn't need its own unread dot — opening the tab
   is exactly what clears it, so the two states never actually overlap
   in practice, but this guards against the dot flashing on then
   instantly off if ever they did coincide for a frame. */
.nav-btn.active .nav-unread-dot { transform: scale(0) !important; }

/* ── Panel content ── */
#sheet-content {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 16px 18px 32px;
}

.tab-panel { display: none; }
.tab-panel.active { display: block; }

.journal-empty,
.dossier-empty {
  text-align: center;
  color: #5a4a2a;
  font-size: 13px;
  line-height: 1.8;
  padding: 60px 20px;
}

/* The unlit lantern (lanternHtml({ unlit: true }), utils.js) dropped
   into the three empty states (journal, quests, dossier) — smaller
   than the reveal-card size it's normally used at, and reusing this
   block's own text color/padding rhythm rather than its own margins. */
.journal-empty .reveal-lantern,
.dossier-empty .reveal-lantern {
  width: 40px;
  height: 54px;
  margin: 0 auto 14px;
}

/* ── Journal entries ── */
.journal-day-sep {
  text-align: center;
  margin: 18px 0 12px;
}

.journal-day-sep span {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #4a3a1e;
}

.journal-entry {
  margin-bottom: 10px;
  padding: 12px 14px;
  border-radius: 8px;
  background: rgba(255,255,255,0.02);
  border-left: 3px solid #3a2a1a;
}

.je-meta {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #6a5a3a;
  margin-bottom: 5px;
}

.je-time { opacity: 0.6; margin-left: 2px; text-transform: none; letter-spacing: 0; }

.je-text {
  font-size: 14px;
  line-height: 1.65;
  color: #c8b88a;
}

/* Locus/gate bio fragments — a recalled memory, not field-report prose,
   so it gets its own voice: serif italic instead of the app's usual
   monospace/sans chrome, softer colour, and a bit more line-height to
   read comfortably as a longer passage rather than a short log line. */
.je-memory-text {
  font-family: Georgia, 'Times New Roman', serif;
  font-style: italic;
  color: #d4c49a;
  line-height: 1.75;
}

/* Tier 1 — character transmissions.
   ALL characters — named or hidden — render in the same purple now.
   Colour no longer distinguishes WHO is speaking (the name itself,
   printed plainly in the meta line, already does that); it only
   distinguishes CATEGORY — character vs quest vs field note.

   NOTE: this replaces a three-way bug where .je-char-entry's own
   colour (#c8a84e), .char-default's (#3a2a1a), and .cp-entry's
   (#4a6a4a) below were all silently dead — a higher-specificity
   generic `[class*="char-"]` rule was overriding every one of them to
   a 4th, unintended colour (#9a8452), regardless of tier. That rule
   is gone; tier colours now come from explicit, single-purpose
   classes with no cross-tier interference. */
.je-char-entry {
  border-left-color: #7b4fd4;
  background: rgba(123,79,212,0.05);
  font-family: Georgia, 'Times New Roman', serif;
}
.je-char-entry .je-text { font-family: Georgia, serif; font-size: 15px; }
.je-char-entry.je-continuation {
  margin-top: -6px;
  padding-top: 2px;
}

/* The hidden/unrevealed '???' voice keeps one small extra flourish on
   top of the shared purple — italic text — since "an unknown presence"
   is still tonally distinct from a named person's dialogue, even once
   both use the same identity colour. */
.char-unknown-entity .je-text { color: #b89ce0; font-style: italic; }
.char-default { border-left-color: #3a2a1a; }

/* The Atlas voice — the survey system itself, not an NPC, so it
   deliberately breaks from the shared character-purple (.je-char-entry)
   into the same warm gold used everywhere else in the app for "this is
   the game telling you something", rather than reading as one more
   person's dialogue mixed in with everyone else's. Used exactly once,
   for the permanent Atlas Chapter Complete entry. */
.char-atlas.je-char-entry {
  border-left-color: #c8a84e;
  background: rgba(200,168,78,0.07);
}
.char-atlas .je-text { color: #f0d488; font-style: normal; }

/* Tier 2 — CP discovery / system field note.
   Gold — reusing the exact shade .je-char-entry used before characters
   moved to purple, now free. Plain checkpoint discovery (no quest, no
   character) was visually gold before the specificity-bug fix above
   too, just via an accidental override rather than its own declared
   colour — this makes that gold intentional and correct instead of a
   side effect, rather than leaving it on the green it was never
   actually supposed to render as. */
.cp-entry {
  font-family: 'Courier New', Courier, monospace;
  border-left-color: #c8a84e;
  background: rgba(200,168,78,0.05);
}
/* .je-text now inherits the base 14px size — previously overridden to
   13px here for no clear reason, just an inconsistency worth removing
   for readability. */

/* Quest-tagged override — wins over both tiers' own colour above.
   While gathering clues for an active investigation, "this belongs to
   Quest X" is the more useful scanning signal than "who said it" (the
   character's name is still right there as plain text regardless).
   Explicit compound selectors per tier, each at equal (two-class)
   specificity, so which one wins is never a source-order accident —
   same lesson as the char-entry bug above. */
.je-char-entry.je-quest-tagged,
.cp-entry.je-quest-tagged,
.journal-entry.je-quest-tagged {
  border-left-color: #6adabc;
  background: rgba(106,218,188,0.05);
}

/* Tier 3 — relic / item pickups */
.je-relic-entry {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin-bottom: 6px;
  background: rgba(255,255,255,0.02);
  border-radius: 6px;
  border-left: 2px solid #4a3a1e;
  font-size: 12px;
}

.je-icon { width: 14px; height: 14px; flex-shrink: 0; color: #c8a84e; }
.je-icon svg { width: 100%; height: 100%; display: block; }
.je-relic-name { color: #d4bc80; flex: 1; }
.je-relic-src { color: #5a4a2a; font-size: 11px; white-space: nowrap; }

/* Quest-tagged relic pickups — same green as Tiers 1 & 2's
   .je-quest-tagged, applied here separately since .je-relic-entry has
   its own fixed border (#4a3a1e) at equal specificity to the shared
   rule, so a compound selector is needed to guarantee this wins. */
.je-relic-entry.je-quest-tagged {
  border-left-color: #6adabc;
  background: rgba(106,218,188,0.05);
}

/* ── Entry badges ──
   Additive tags layered onto whichever tier an entry already renders
   as — never a substitute for the character/CP styling above. Quest
   colors match the existing "done" teal from the Quests tab
   (qd-step--done, ql-pill--done: #6adabc); locus/gate colors match
   the on-map log-entry colors of the same name (map.css) so the
   journal echoes the map's own vocabulary instead of inventing one. */
.je-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 10px;
  letter-spacing: 0.03em;
  text-transform: none;
  padding: 1px 6px;
  border-radius: 10px;
  margin-right: 6px;
  white-space: nowrap;
  vertical-align: middle;
}

.je-badge-quest {
  color: #6adabc;
  background: rgba(106, 218, 188, 0.10);
  border: 1px solid rgba(106, 218, 188, 0.35);
}

/* Resolved investigations get a filled pill rather than an outline —
   a small "stamped" distinction for the entry that actually closes
   out a thread the player's been following, vs. every step along the way. */
.je-badge-quest-done {
  color: #0c0a07;
  background: #6adabc;
  font-weight: 600;
  border: 1px solid #6adabc;
}

.je-badge-locus {
  color: #6f48b8;               /* matches .log-entry.locus .log-meta in map.css */
  background: rgba(111, 72, 184, 0.10);
  border: 1px solid rgba(111, 72, 184, 0.30);
}

.je-badge-gate {
  color: #8a5cc4;               /* matches .log-entry.gate .log-meta in map.css */
  background: rgba(138, 92, 196, 0.10);
  border: 1px solid rgba(138, 92, 196, 0.30);
}

/* Quest-completion entries get a stronger teal wash + inset ring on
   top of the green .je-quest-tagged border every quest entry already
   has — completion is the same colour family, just visually louder,
   rather than a different colour competing for attention. Applied via
   an explicit .je-quest-done class from journal.js rather than a
   :has() selector, since this needs to render reliably on whatever
   mobile browser a player happens to have. */
.je-quest-done {
  background: rgba(106, 218, 188, 0.06);
  box-shadow: inset 0 0 0 1px rgba(106, 218, 188, 0.18);
}

/* Relic pickups delivered by a quest's final step — rare, since most
   relics land mid-quest — get the same filled-pill treatment inline
   instead of the outline .je-badge-quest, consistent with the rule
   above: completion is always the filled/bolder variant. */
.je-relic-quest-done {
  box-shadow: inset 0 0 0 1px rgba(106, 218, 188, 0.25);
}

/* ── Quest list ── */
.ql-section-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #8a7040;
  margin-bottom: 8px;
}

.ql-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 6px;
  border-bottom: 1px solid #201a10;
  cursor: pointer;
}
.ql-row:last-child { border-bottom: none; }

.ql-row--tracked {
  background: rgba(244, 200, 64, 0.05);
  border-radius: 6px;
  padding-left: 8px;
  padding-right: 8px;
}

.ql-row-name { font-size: 14px; color: #c8b88a; }
.ql-done-mark { color: #6adabc; margin-right: 6px; }
.ql-row-character { font-size: 11px; color: #5a4a2a; margin-top: 2px; }

.ql-row-right { display: flex; align-items: center; gap: 8px; }

.ql-tracking-badge {
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #0c0a07;
  background: #f4c840;
  padding: 2px 7px;
  border-radius: 10px;
}

/* Same shape as the tracking badge above, its own color (--quest-green,
   already used for quest content elsewhere) so the two read as related
   but distinct tags — both can be showing at once, since a freshly
   activated quest is very often also auto-tracked (activateQuest,
   engine.js) when nothing else currently is. Shown only on the render
   where the quest is SEEN to become active (_checkJustActivated,
   quests.js) — never replayed just from reopening the quest list on
   something that was already active. Fades out on its own after a few
   seconds rather than needing to be dismissed (animation-fill-mode:
   forwards holds it at opacity 0, not display:none, so the row's
   layout never jumps when it disappears). */
.ql-new-badge {
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #0c0a07;
  background: var(--quest-green);
  padding: 2px 7px;
  border-radius: 10px;
  animation: qlNewBadgeFade 0.4s ease-in 4s forwards;
}
@keyframes qlNewBadgeFade {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

/* One-shot highlight sweep across the whole row, same render it first
   appears. A soft green wash that brightens in, holds briefly, then
   fades back to the row's normal background — reads as "something
   just landed here" without needing the badge to carry the whole
   signal on its own. */
.ql-row--new {
  animation: qlRowNewHighlight 2.2s ease-out both;
}
@keyframes qlRowNewHighlight {
  0%   { background: rgba(109,143,118,0.22); }
  70%  { background: rgba(109,143,118,0.1); }
  100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .ql-new-badge { animation: none; opacity: 1; }
  .ql-row--new  { animation: none; }
}

.ql-pill {
  font-size: 11px;
  color: #7a6030;
  background: rgba(255,255,255,0.04);
  padding: 2px 9px;
  border-radius: 10px;
}
.ql-pill--done { color: #6adabc; background: rgba(106,218,188,0.08); }

/* ── Progress ring ──
   Sits beside the fraction pill — same info, but glanceable without
   reading the numbers. Rotated -90deg so the fill starts at 12
   o'clock instead of 3. Track/fill share the pill's default gold vs.
   done-teal palette. See _progressRingSVG (quests.js) for the markup. */
.ql-ring {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  transform: rotate(-90deg);
}
.ql-ring-track {
  fill: none;
  stroke: rgba(255,255,255,0.08);
  stroke-width: 4;
}
.ql-ring-fill {
  fill: none;
  stroke: #7a6030;
  stroke-width: 4;
  stroke-linecap: round;
  transition: stroke-dasharray 0.4s ease;
}
.ql-ring--done .ql-ring-fill { stroke: #6adabc; }

/* ── Completion burst ──
   Added only on the render where a quest/survey is SEEN to flip to
   done — never on a plain re-render of something already finished (see
   _checkJustCompleted, quests.js). A snap-and-settle pulse: the ring
   overshoots past full size, dips back under, then rests — plus a
   brief teal glow on the fill so the moment reads as a small event
   rather than the pill just silently changing color. transform-origin
   center keeps the scale centered on the ring itself, not the row. */
.ql-ring--burst {
  transform-origin: 50% 50%;
  animation: qlRingBurst 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.ql-ring--burst .ql-ring-fill {
  animation: qlRingBurstGlow 0.6s ease-out both;
}
@keyframes qlRingBurst {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.4); }
  70%  { transform: scale(0.92); }
  100% { transform: scale(1); }
}
@keyframes qlRingBurstGlow {
  0%   { filter: drop-shadow(0 0 0 rgba(106,218,188,0)); }
  40%  { filter: drop-shadow(0 0 5px rgba(106,218,188,0.95)); }
  100% { filter: drop-shadow(0 0 0 rgba(106,218,188,0)); }
}
@media (prefers-reduced-motion: reduce) {
  .ql-ring--burst,
  .ql-ring--burst .ql-ring-fill { animation: none !important; }
}

.ql-chevron { color: #4a3a1e; font-size: 16px; }

/* ── Quest detail ── */
.qd-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 18px;
}

.qd-back {
  background: none;
  border: none;
  color: #8a7a50;
  font-size: 13px;
  cursor: pointer;
  padding: 4px 0;
  font-family: inherit;
}

.qd-track-btn {
  background: none;
  border: 1px solid #4a3a1e;
  color: #c8a84e;
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: 14px;
  cursor: pointer;
  font-family: inherit;
}
.qd-track-btn--active { background: #f4c840; color: #0c0a07; border-color: #f4c840; }

.qd-eyebrow {
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #5a4a2a;
  margin-bottom: 5px;
}

.qd-name { font-size: 19px; color: #e8dcb8; margin-bottom: 4px; }
.qd-character { font-size: 12px; color: #a084d8; margin-bottom: 10px; }
.qd-description { font-size: 14px; line-height: 1.6; color: #a09060; }

/* Soft fade rather than a hard full-width line — a solid rule reads as
   "new section starts here" (almost like a different quest), a fade
   reads as a continuation of the same card. Used uniformly wherever
   .qd-divider appears (here, and before completion text below). */
.qd-divider {
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(200,168,78,0.18), transparent);
  margin: 12px 0;
}

.qd-steps-section { margin-top: 0; }

.qd-steps-header {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  padding: 0 0 10px;
  -webkit-tap-highlight-color: transparent;
}

.qd-steps-label {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #5a4a2a;
}

.qd-steps-count {
  font-size: 11px;
  color: #7a6a48;
  background: rgba(255,255,255,0.03);
  padding: 1px 7px;
  border-radius: 9px;
}

.qd-steps-chevron {
  margin-left: auto;
  color: #5a4a2a;
  font-size: 14px;
  transform: rotate(90deg);
  transition: transform 0.2s ease;
}
.qd-steps-chevron--open { transform: rotate(-90deg); }

/* The single "what to do next" line — shown only while the full
   checklist is collapsed, same role as a BOTW-style current-objective
   hint: one clear next step instead of the whole list up front. */
.qd-current-objective {
  font-size: 13px;
  line-height: 1.5;
  color: #d4bc80;
  background: rgba(244,200,64,0.05);
  border-left: 2px solid rgba(244,200,64,0.4);
  padding: 8px 10px;
  border-radius: 0 4px 4px 0;
  margin-bottom: 4px;
}

.qd-steps {
  display: none;
  padding-top: 4px;
}
.qd-steps.qd-steps--open { display: block; }

.qd-step { display: flex; gap: 10px; padding: 8px 0; }
.qd-step-slot { width: 16px; flex-shrink: 0; color: #4a3a1e; font-size: 14px; text-align: center; }
.qd-step--done .qd-step-slot { color: #6adabc; }

/* ── Check-off animation ──
   Added only on the render where a step/gate is SEEN to flip to done
   (_checkJustCompleted, quests.js) — never replayed just from
   reopening a quest's detail view on something finished earlier.
   transform-origin centers the pop on the slot itself rather than the
   row it sits in. */
.qd-step-slot--checked {
  transform-origin: 50% 50%;
  animation: qdStepCheckPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes qdStepCheckPop {
  0%   { transform: scale(0.3); opacity: 0.4; }
  55%  { transform: scale(1.5); opacity: 1; }
  80%  { transform: scale(0.85); }
  100% { transform: scale(1); opacity: 1; }
}
.qd-gate-done--checked {
  animation: qdGateDoneCheck 0.5s ease-out both;
}
@keyframes qdGateDoneCheck {
  0%   { opacity: 0;   transform: translateY(-3px); }
  60%  { opacity: 1;   transform: translateY(0); }
  100% { opacity: 1;   transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .qd-step-slot--checked,
  .qd-gate-done--checked { animation: none !important; }
}
.qd-step-label { font-size: 13px; color: #8a7a50; }
.qd-step--done .qd-step-label { color: #c8b88a; }
.qd-step-relic { font-size: 10px; color: #c8a84e; margin-left: 6px; }

/* The actual clue/hint text, rereadable once a step is done — quieter
   than the label above it since it's supplementary detail, not the
   primary scan line, but no longer buried exclusively in the Journal.
   Shared by both regular done-steps and a done gate's own step.text
   (see quests.js) — muted enough to sit under either. */
.qd-step-text {
  font-size: 12px;
  line-height: 1.5;
  color: #6a5a3e;
  margin-top: 4px;
}
.qd-no-steps { color: #5a4a2a; font-size: 13px; }

/* Current (next incomplete) step — a quiet highlight so it stands out
   from completed and not-yet-relevant steps once the list is expanded. */
.qd-step--current {
  background: rgba(244,200,64,0.04);
  border-radius: 6px;
  margin: 0 -8px;
  padding: 8px;
}
.qd-step--current .qd-step-slot { color: #f4c840; }
.qd-step--current .qd-step-label { color: #e8dcb8; }
.qd-gate--current { border-color: rgba(244,200,64,0.35); }

.qd-gate {
  margin: 12px 0;
  padding: 14px;
  border: 1px solid #3a2a4a;
  border-radius: 8px;
  background: rgba(123, 79, 212, 0.05);
}
.qd-gate--done { border-color: #2a3a2a; background: rgba(106,218,188,0.04); }

.qd-gate-label { font-size: 13px; color: #c9a8e8; margin-bottom: 8px; }
.qd-gate--done .qd-gate-label { color: #6adabc; }

.qd-gate-progress {
  height: 4px;
  background: #201a10;
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 4px;
}
.qd-gate-progress-fill { height: 100%; background: #9b5fd4; transition: width 0.3s ease; }
.qd-gate-progress-label { font-size: 10px; color: #6a5a80; margin-bottom: 8px; }

.qd-gate-done { font-size: 12px; color: #6adabc; }

.qd-gate-btn {
  width: 100%;
  padding: 10px;
  background: #9b5fd4;
  color: #0c0a07;
  border: none;
  border-radius: 6px;
  font-size: 12px;
  font-weight: bold;
  letter-spacing: 0.03em;
  cursor: pointer;
  font-family: inherit;
}

.qd-gate-hint { font-size: 11px; color: #6a5a80; font-style: italic; }

.qd-completion-text { font-size: 14px; line-height: 1.6; color: #a09060; font-style: italic; }

/* ── Dossier ── */
.dossier-chars { display: flex; flex-direction: column; gap: 14px; }

.dossier-char {
  border: 1px solid #241c10;
  border-radius: 8px;
  padding: 14px;
  background: rgba(255,255,255,0.015);
}

/* Permanent mark once every fragment for this character has been
   delivered (see the isBioComplete check in dossier.js) — the point is
   that this stays visible on every future visit to this tab, not just
   for the one moment showBiographicalSurveyComplete() plays. Same warm
   gold as the Atlas journal voice / other "this is complete" signals
   elsewhere, not the character's usual purple, since it's marking an
   achievement rather than more of the character's own voice. */
.dossier-char--bio-complete {
  border-color: rgba(200,168,78,0.4);
  background: rgba(200,168,78,0.04);
}

/* One-shot — only on the render where this card is SEEN to cross into
   bio-complete (justBioCompleted, dossier.js), never on a later visit
   to an already-finished card. A brighter version of the permanent
   gold wash above, settling down into it rather than replacing it —
   .dossier-char--bio-complete's own border/background stay in the
   cascade underneath and simply show once this finishes. */
.dossier-char--bio-burst {
  animation: dossierBioBurst 1.8s ease-out both;
}
@keyframes dossierBioBurst {
  0%   { border-color: rgba(200,168,78,0.4); background: rgba(200,168,78,0.04); }
  25%  { border-color: rgba(240,212,136,0.95); background: rgba(200,168,78,0.16); }
  100% { border-color: rgba(200,168,78,0.4); background: rgba(200,168,78,0.04); }
}

.dossier-char-name { font-size: 15px; color: #e8dcb8; }

.dossier-char-role {
  font-size: 11px;
  color: #a084d8;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-top: 2px;
}

.dossier-char-desc { font-size: 13px; color: #8a7a50; line-height: 1.6; margin-top: 6px; }

.dossier-char-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  margin-top: 10px;
  font-size: 11px;
}
/* Same color, same weight, same non-italic style, same structure
   (icon + short status phrase) — these two, and the hidden-character
   card around the gate line (see .dossier-char, above, now with no
   --hidden override), are meant to be visually indistinguishable from
   a normal character's, source aside. Previously the gate line
   (".dossier-no-anchor") was muted, italicized flavor text in its own
   violet-tinted card — different enough to read as a different KIND of
   content, not just a different source of the same kind of tag. */
.dossier-gate-name,
.dossier-locus-name { color: #c8a84e; }
.dossier-frag-count { color: #5a4a2a; }

/* Always its own full-width row beneath the locus/fragment-count row
   above, regardless of how much space they leave — a badge squeezed
   into whatever gap space-between happens to leave between the other
   two would wrap unpredictably depending on name length. */
.dossier-bio-complete-badge {
  width: 100%;
  margin-top: 6px;
  color: #f0d488;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* Pop-and-settle, same technique as .ql-ring--burst (sheet.css) — a
   brief overshoot past full size before resting, so the badge's first
   appearance reads as a small event rather than text just showing up. */
.dossier-bio-complete-badge--burst {
  display: inline-block;
  transform-origin: 0% 50%;
  animation: dossierBioBadgePop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes dossierBioBadgePop {
  0%   { transform: scale(0.6); opacity: 0; }
  60%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .dossier-char--bio-burst,
  .dossier-bio-complete-badge--burst { animation: none !important; }
}

.dossier-fragments { margin-top: 10px; }
.dossier-fragment { font-size: 13px; line-height: 1.6; color: #c8b88a; padding: 6px 0; }
.dossier-fragment--reveal { color: #f4c840; }
.dossier-fragment--locked { color: #4a3a1e; font-style: italic; }
.dossier-fragment-rule { height: 1px; background: #201a10; margin: 4px 0; }
.dossier-fragment-rule--reveal { background: #6a5a20; }

.dossier-section-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #8a7040;
  margin: 22px 0 10px;
}

.dossier-fieldkit { display: flex; flex-direction: column; gap: 8px; }
.fk-relic {
  display: flex;
  gap: 10px;
  padding: 10px;
  border: 1px solid #241c10;
  border-radius: 6px;
  align-items: flex-start;
}
.fk-icon { width: 20px; height: 20px; flex-shrink: 0; color: #c8a84e; margin-top: 1px; }
.fk-icon svg { width: 100%; height: 100%; display: block; }
.fk-relic-body { flex: 1; min-width: 0; }
.fk-relic-name { font-size: 13px; color: #d4bc80; }
.fk-relic-desc { font-size: 12px; color: #8a7a50; margin-top: 2px; line-height: 1.55; }
.fk-relic-provenance { font-size: 10px; color: #4a3a1e; margin-top: 4px; }

.dossier-sigils { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.dossier-sigil { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.dossier-sigil-svg { width: 56px; height: 56px; }
.dossier-sigil-name { font-size: 10px; color: #8a7a50; text-align: center; }
.dossier-sigil--locked .dossier-sigil-empty {
  width: 56px; height: 56px;
  border: 1px dashed #241c10;
  border-radius: 50%;
}

/* ── Profile tab ── */
.profile-account-hero {
  padding: 16px;
  border: 1px solid #241c10;
  border-radius: 8px;
  margin-bottom: 20px;
  text-align: center;
}
.pah-eyebrow {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #5a4a2a;
  margin-bottom: 6px;
}
.pah-body { font-size: 13px; color: #8a7a50; line-height: 1.55; margin-bottom: 12px; }

/* Google's rendered button is a fixed-width block element, not inline —
   .profile-account-hero's text-align:center has no effect on it, so it
   needs its own flex container to actually center. */
.pah-google-btn-container { display: flex; justify-content: center; }

.pah-linked-row { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 14px; }
.pah-avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; }
.pah-avatar-fallback {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: #1a1510;
  display: flex; align-items: center; justify-content: center;
  color: #c8a84e;
  font-size: 16px;
}
.pah-linked-info { min-width: 0; }
.pah-linked-name { font-size: 13px; color: #c8b88a; }
.pah-linked-badge { font-size: 10px; color: #6adabc; margin-top: 2px; }

.pah-account-actions { display: flex; justify-content: space-between; align-items: center; }
.pah-switch-action { display: flex; align-items: center; gap: 8px; }
.pah-action-label { font-size: 11px; color: #8a7a50; }
.pah-unlink-btn {
  background: none;
  border: 1px solid #4a2a2a;
  color: #c07070;
  font-size: 11px;
  padding: 5px 11px;
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
}

/* Full-width, its own row — a bigger/more standalone action than the
   inline switch/unlink controls above it, and neutral (not alarming
   red like Unlink) since signing out is safe whenever this button is
   even shown — it only renders in the Google-linked state. */
.pah-logout-btn {
  width: 100%;
  margin-top: 12px;
  padding: 9px;
  background: none;
  border: 1px solid #3a2a1a;
  color: #8a7a50;
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
}

.profile-section-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #8a7040;
  margin-bottom: 10px;
}

.profile-stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.pstat { border: 1px solid #241c10; border-radius: 8px; padding: 12px; text-align: center; }
.pstat-value { font-size: 20px; color: #f4c840; }
.pstat-label { font-size: 10px; color: #5a4a2a; text-transform: uppercase; letter-spacing: 0.06em; margin-top: 4px; }

.settings-row {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid #201a10;
  font-size: 12px;
  color: #8a7a50;
}
.settings-value { color: #c8b88a; }

.about-block { margin-bottom: 12px; }
.about-title { font-size: 11px; color: #8a7a50; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 4px; }
.about-body { font-size: 12px; color: #9a8455; line-height: 1.6; }
.about-body a { color: #8a7a50; }

.about-replay-btn {
  display: block;
  margin-top: 8px;
  padding: 0;
  background: none;
  border: none;
  color: #c8a84e;
  font-size: 12px;
  letter-spacing: 0.03em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s;
}
.about-replay-btn:hover { color: #e8c85e; }