/* Scene panel, inventory, act replay, save panel, tooltips */

/* ── Scene panel — tertiary weight (location, actors, objects) ── */
.scene-panel { border: 1px solid color-mix(in srgb, var(--border-color) 60%, transparent); background: color-mix(in srgb, var(--panel-bg) 50%, transparent); font-size: 0.75rem; }
.scene-panel-header { padding: 0.45rem 1rem; border-bottom: 1px solid color-mix(in srgb, var(--border-color) 50%, transparent); display: flex; justify-content: space-between; align-items: center; }
.scene-panel-header h3 { font-family: 'Cinzel', 'Palatino Linotype', serif; font-size: 0.65rem; font-weight: 400; letter-spacing: 0.12em; color: var(--text-muted); }
.scene-toggle-btn { background: transparent; border: 1px solid var(--border-color); color: var(--text-muted); padding: 0.18rem 0.45rem; cursor: pointer; font-family: 'Cinzel', serif; font-size: 0.58rem; letter-spacing: 0.1em; }
.scene-toggle-btn:hover { color: var(--text-mid); border-color: var(--text-dim); }
.scene-panel-body { padding: 0.75rem 1rem; }
/* The picture of where the player is standing. The copy the browser picks is
   at least 480px wide (Portrait::SCENE_LIMITS) so it stays sharp on a dense
   display, and the sidebar is a 320px column: without width: 100% it renders
   at its native size and runs off the right edge. The 16:9 box holds the space
   while it loads, so the words under it do not jump. */
.scene-image { margin-bottom: 0.75rem; }
.scene-image .lightbox-trigger { height: auto; }
.scene-image-img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; border: 1px solid var(--border-subtle); }
/* The frame a picture will land in, while it is being drawn — the same size
   as the picture, so nothing moves when it arrives. The shimmer is what says
   "in progress" rather than "empty"; it stops for a player who has asked
   their system to reduce motion, and the words still say it. Shared by the
   panel and the story's card (games/_scene_image_placeholder). */
.scene-image-placeholder {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px dashed var(--border-subtle);
  background: color-mix(in srgb, var(--panel-bg) 70%, transparent);
}
.scene-image-placeholder::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--text-muted) 14%, transparent) 50%, transparent 80%);
  transform: translateX(-100%);
  animation: scene-image-shimmer 1.8s ease-in-out infinite;
}
.scene-image-placeholder-label { position: relative; font-family: 'Lora', Georgia, serif; font-style: italic; font-size: 0.72rem; color: var(--text-muted); }
@keyframes scene-image-shimmer { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .scene-image-placeholder::before { animation: none; } }
/* A picture that exists but is still downloading holds a tone rather than an
   empty box; once it loads it covers this. */
.scene-image-img, .scene-card-image-img { background: color-mix(in srgb, var(--panel-bg) 70%, transparent); }
.scene-image-actions { margin-top: 0.5rem; }
.scene-image-actions form, .scene-image-actions .panel-action-btn { width: 100%; }
.scene-description { font-family: 'Lora', Georgia, serif; font-style: italic; color: var(--text-dim); font-size: 0.72rem; line-height: 1.5; margin-bottom: 0.75rem; border-bottom: 1px solid var(--border-subtle); padding-bottom: 0.5rem; }
/* Inventory panel — secondary weight (reuses scene-panel, override via parent) */
#inventory-panel .scene-panel { border: 1px solid var(--border-color); background: var(--panel-bg); font-size: 0.78rem; }
#inventory-panel .scene-panel-header { background: var(--panel-header); border-bottom: 1px solid var(--border-color); padding: 0.5rem 1rem; }
#inventory-panel .scene-panel-header h3 { font-size: 0.68rem; color: var(--theme-accent); opacity: 0.7; }

.scene-section-label { font-family: 'Cinzel', serif; color: var(--text-dim); font-size: 0.55rem; text-transform: uppercase; letter-spacing: 0.2em; margin: 0.6rem 0 0.2rem; }
.actor-item, .object-item, .exit-item { padding: 0.22rem 0; color: var(--text-mid); }
.actor-name, .object-name { color: var(--text-bright); }
/* The face beside a name. A fixed box in every state — picture, initial or
   nothing — so a drawing landing mid-read does not shunt the list under the
   player's eyes. */
.actor-item { display: flex; align-items: center; gap: 0.45rem; }
.actor-avatar { flex: 0 0 auto; width: 1.85rem; height: 1.85rem; }
.actor-avatar .lightbox-trigger { display: block; width: 100%; height: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
.actor-avatar-img,
.actor-avatar-blank {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 1px solid var(--border-subtle);
  object-fit: cover;
  background: color-mix(in srgb, var(--panel-bg) 70%, transparent);
}
.actor-avatar-blank {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  font-family: 'Cinzel', serif;
  font-size: 0.62rem;
  color: var(--text-muted);
  border-style: dashed;
}
/* The same shimmer the scene placeholder uses, so "a picture is coming" reads
   the same wherever it appears. */
.actor-avatar-drawing::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--text-muted) 14%, transparent) 50%, transparent 80%);
  transform: translateX(-100%);
  animation: scene-image-shimmer 1.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .actor-avatar-drawing::before { animation: none; } }
/* Someone the story has finished with keeps their picture, greyed. */
.actor-item.actor-dead .actor-avatar-img { filter: grayscale(1); opacity: 0.65; }
.exit-label { color: var(--color-exit); cursor: pointer; }
.exit-label:hover { color: var(--color-exit-hover); }
.scene-empty { font-family: 'Lora', Georgia, serif; font-style: italic; color: var(--text-dim); }

/* Hover tooltips */
.actor-item, .object-item, .scene-description, .travel-blocked,
.hero-card-portrait-actions { position: relative; }
.scene-description[data-tooltip],
.actor-item[data-tooltip],
.object-item[data-tooltip],
.hero-card-portrait-actions[data-tooltip] { cursor: help; }
.actor-item[data-tooltip]:hover::after,
.object-item[data-tooltip]:hover::after,
.travel-blocked[data-tooltip]:hover::after,
.hero-card-portrait-actions[data-tooltip]:hover::after,
.scene-description[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  left: 0;
  top: 100%;
  z-index: 10;
  background: var(--panel-bg);
  border: 1px solid var(--border-color);
  color: var(--text-mid);
  font-family: 'Lora', Georgia, serif;
  font-style: italic;
  font-size: 0.72rem;
  line-height: 1.5;
  padding: 0.35rem 0.5rem;
  white-space: normal;
  width: 220px;
  pointer-events: none;
}

/* Save panel */
.save-panel { border: 1px solid color-mix(in srgb, var(--border-color) 60%, transparent); background: color-mix(in srgb, var(--panel-bg) 50%, transparent); padding: 0.65rem 1rem; font-size: 0.75rem; }
.save-panel-header { font-family: 'Cinzel', serif; font-size: 0.58rem; letter-spacing: 0.18em; color: var(--text-muted); text-transform: uppercase; margin-bottom: 0.5rem; display: flex; justify-content: space-between; align-items: center; }
/* Two real buttons instead of a column of cramped glyphs — the slots live in
   the dialogs these open. */
.save-panel-actions { display: flex; gap: 0.5rem; }
.save-panel-actions .dialog-host { flex: 1; }
.panel-action-btn { width: 100%; background: transparent; border: 1px solid var(--border-color); color: var(--text-mid); padding: 0.5rem 0.75rem; cursor: pointer; font-family: 'Cinzel', serif; font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; }
.panel-action-btn:hover { color: var(--theme-accent); border-color: var(--theme-accent); }
/* A link wearing the panel button, so it has to be told to fill the row. */
.sidebar-exit .panel-action-btn { display: block; box-sizing: border-box; text-align: center; text-decoration: none; }
.save-panel-summary { margin-top: 0.5rem; color: var(--text-muted); font-family: 'Lora', Georgia, serif; font-size: 0.65rem; font-style: italic; }

/* Slot pickers inside a dialog: each row is a full-width target rather than a
   glyph you have to aim at. */
.slot-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.slot-item form { margin: 0; }
.slot-btn { width: 100%; display: flex; flex-direction: column; align-items: flex-start; gap: 0.15rem; background: transparent; border: 1px solid var(--border-color); color: var(--text-mid); padding: 0.65rem 0.8rem; cursor: pointer; text-align: left; font-family: inherit; }
.slot-btn:hover:not(:disabled) { border-color: var(--theme-accent); color: var(--theme-accent); }
.slot-btn:disabled { opacity: 0.5; cursor: default; }
.slot-btn.is-empty .slot-detail { font-style: italic; }
.slot-name { font-family: 'Cinzel', serif; font-size: 0.72rem; letter-spacing: 0.06em; }
.slot-detail { color: var(--text-muted); font-family: 'Lora', Georgia, serif; font-size: 0.68rem; }
.slot-empty-state { color: var(--text-muted); font-family: 'Lora', Georgia, serif; font-style: italic; font-size: 0.75rem; margin: 0; }

/* The map picker's Stay button */
.btn-decline { background: transparent; border: 1px solid var(--border-color); color: var(--text-muted); padding: 0.3rem 1rem; cursor: pointer; font-family: 'Cinzel', serif; font-size: 0.72rem; letter-spacing: 0.1em; }
.btn-decline:hover { color: var(--text-mid); border-color: var(--text-dim); }

/* ── High-contrast mode selector ── */
.contrast-control {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.8rem 1rem 0;
}
.contrast-label {
  font-family: 'Cinzel', serif;
  font-size: 0.55rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-right: 0.25rem;
}
.contrast-btn {
  background: transparent;
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  padding: 0.15rem 0.5rem;
  cursor: pointer;
  font-family: 'Cinzel', serif;
  font-size: 0.55rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
}
.contrast-btn:hover { color: var(--text-mid); }
.contrast-btn.active {
  color: var(--theme-bg);
  background: var(--theme-accent);
  border-color: var(--theme-accent);
}

/* ── Legal links at bottom of sidebar ── */
.panel-legal {
  padding: 1.2rem 1rem 0.8rem;
  text-align: center;
  font-family: 'Lora', Georgia, serif;
  font-style: italic;
  font-size: 0.6rem;
  letter-spacing: 0.06em;
}
.panel-legal a {
  color: var(--theme-text);
  text-decoration: none;
  opacity: 0.35;
  transition: opacity 0.3s ease;
}
.panel-legal a:hover { opacity: 0.7; }
.panel-legal span {
  margin: 0 0.4em;
  color: var(--theme-text);
  opacity: 0.2;
}

/* ── Sidebar inline help tooltips ── */
.sidebar-help {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 0.35rem;
}

.sidebar-help-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1rem;
  height: 1rem;
  border: 1px solid var(--border-color);
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  font-family: 'Lora', Georgia, serif;
  font-size: 0.55rem;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
  transition: color 0.2s, border-color 0.2s;
}
.sidebar-help-btn:hover {
  color: var(--text-muted);
  border-color: var(--text-dim);
}

.sidebar-help-bubble {
  position: fixed;
  width: 220px;
  padding: 0.5rem 0.65rem;
  background: var(--theme-bg);
  border: 1px solid var(--border-color);
  font-family: 'Lora', Georgia, serif;
  font-style: italic;
  font-size: 0.68rem;
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: normal;
  text-transform: none;
  color: var(--text-mid);
  z-index: 100;
  animation: sidebarHelpReveal 0.15s ease-out both;
}
@keyframes sidebarHelpReveal {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ── World map — the nine regions, laid out on World::Region::SLOTS ── */
.world-map { padding: 0.35rem 0; }
.world-map-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); gap: 0.3rem; }
.world-map-region {
  position: relative;
  border: 1px solid color-mix(in srgb, var(--border-color) 70%, transparent);
  background: color-mix(in srgb, var(--panel-bg) 60%, transparent);
  padding: 0.4rem 0.45rem;
  min-height: 3.1rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  cursor: help;
}
.world-map-region-name { font-family: 'Cinzel', 'Palatino Linotype', serif; font-size: 0.6rem; letter-spacing: 0.06em; color: var(--text-mid); line-height: 1.3; }
.world-map-region.is-here { border-color: var(--theme-accent); background: color-mix(in srgb, var(--theme-accent) 12%, transparent); }
.world-map-region.is-here .world-map-region-name { color: var(--text-bright); }
.world-map-here { font-family: 'Cinzel', serif; font-size: 0.5rem; text-transform: uppercase; letter-spacing: 0.18em; color: var(--theme-accent); margin-top: 0.2rem; }
.world-map-region[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  left: 0;
  top: 100%;
  z-index: 10;
  background: var(--panel-bg);
  border: 1px solid var(--border-color);
  color: var(--text-mid);
  font-family: 'Lora', Georgia, serif;
  font-size: 0.68rem;
  line-height: 1.4;
  padding: 0.4rem 0.5rem;
  width: 15rem;
  pointer-events: none;
}
/* Default is down-and-right, which walks a right-hand or bottom cell out of
   whatever is holding the map — in a dialog that means scrollbars and a
   description you cannot finish reading. Edge cells open inward instead. */
.world-map-region[data-col="3"][data-tooltip]:hover::after { left: auto; right: 0; }
.world-map-region[data-row="3"][data-tooltip]:hover::after { top: auto; bottom: 100%; }

/* Travel picker — the map, but the regions are buttons */
.travel-picker { padding: 0.75rem 1rem; }
.travel-picker-prompt { font-family: 'Cinzel', serif; font-size: 0.7rem; letter-spacing: 0.12em; color: var(--text-muted); text-transform: uppercase; margin-bottom: 0.6rem; }
.world-map-form { display: contents; }
button.world-map-region { font: inherit; text-align: left; width: 100%; cursor: pointer; }
button.world-map-region.is-target:hover { border-color: var(--color-exit); background: color-mix(in srgb, var(--color-exit) 10%, transparent); }
button.world-map-region.is-target:hover .world-map-region-name { color: var(--color-exit-hover); }
.world-map-distance { font-family: 'Cinzel', serif; font-size: 0.5rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--text-dim); margin-top: 0.2rem; }
.travel-picker-stay { margin-top: 0.7rem; }

/* Fog — unvisited neighbours are reachable but unnamed; the rest is grid only */
.world-map-region.is-unknown { border-style: dashed; opacity: 0.75; }
.world-map-region.is-unknown .world-map-region-name { color: var(--text-dim); font-style: italic; }
button.world-map-region.is-unknown:hover { opacity: 1; border-color: var(--color-exit); }
.world-map-region.is-fog { border-color: color-mix(in srgb, var(--border-color) 25%, transparent); background: color-mix(in srgb, var(--panel-bg) 20%, transparent); cursor: default; }

/* ── Reference screens — the map, and the hero card and journal to come ──
   A row of dialog triggers in the sidebar. The screens themselves open in a
   modal over a lazy turbo-frame, or stand alone at their own URL; the map used
   to live inline in this column and was far too cramped for it. */
/* Sized to their labels, not to equal thirds. Equal columns are fine in English
   and clip the moment a translation is longer: "Podróżuj" needs room "Mapa"
   is not using. Wrapping is the safety net for a language longer still. */
.reference-links { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0 0.85rem 0.6rem; }
/* :empty is no use — ERB leaves whitespace behind. Element children is the
   question being asked, so ask it directly. */
.reference-links:not(:has(> *)) { display: none; }
.reference-links > * { flex: 1 1 auto; }
.reference-links .panel-action-btn { width: 100%; padding-left: 0.45rem; padding-right: 0.45rem; white-space: nowrap; }
.travel-blocked { display: block; cursor: help; }
/* Stat points waiting on the hero card, counted on the corner of the button
   that opens it. Pinned to the corner rather than set beside the label, so it
   takes no width from a row that is sized to its labels. */
.panel-action-btn:has(> .panel-action-badge) { position: relative; }
.panel-action-badge { position: absolute; top: -0.45rem; right: -0.35rem; min-width: 1rem; height: 1rem; padding: 0 0.25rem; box-sizing: border-box; border-radius: 0.5rem; background: var(--theme-accent); color: var(--theme-bg); font-family: 'Lora', Georgia, serif; font-size: 0.62rem; font-weight: bold; line-height: 1rem; letter-spacing: 0; text-align: center; box-shadow: 0 0 6px color-mix(in srgb, var(--theme-accent) 60%, transparent); }
.panel-action-badge[hidden] { display: none; }

/* The Rest menu: a disclosure, not a dialog — four choices need no screen of
   their own. The summary is styled as the same button as its neighbours. */
.rest-menu { position: relative; }
.rest-menu > summary { list-style: none; text-align: center; }
.rest-menu > summary::-webkit-details-marker { display: none; }
.rest-menu[open] > summary { color: var(--theme-accent); border-color: var(--theme-accent); }
.rest-menu-choices { position: absolute; left: 0; right: 0; top: calc(100% + 0.25rem); z-index: 10; display: flex; flex-direction: column; gap: 0.25rem; padding: 0.35rem; background: var(--panel-bg); border: 1px solid var(--border-color); }
.rest-choice { background: transparent; border: 1px solid transparent; color: var(--text-mid); padding: 0.4rem 0.5rem; cursor: pointer; text-align: left; font-family: 'Lora', Georgia, serif; font-size: 0.75rem; }
.rest-choice:hover { color: var(--theme-accent); border-color: var(--theme-accent); }
.panel-action-btn:disabled { opacity: 0.4; cursor: help; }
.panel-action-btn:disabled:hover { color: var(--text-mid); border-color: var(--border-color); }
.dialog-frame-loading { font-family: 'Cinzel', serif; font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); text-align: center; padding: 2rem 0; margin: 0; }

/* Given the whole dialog to itself, the map can afford cells you can read. */
.app-dialog:has(.reference-screen) { max-width: min(34rem, calc(100vw - 2rem)); }
.reference-screen .world-map-region { min-height: 4.6rem; padding: 0.55rem 0.6rem; }
.reference-screen .world-map-region-name { font-size: 0.72rem; }
.reference-screen .world-map-distance, .reference-screen .world-map-here { font-size: 0.55rem; }
.reference-note { font-family: 'Lora', Georgia, serif; font-size: 0.7rem; line-height: 1.5; color: var(--text-dim); margin: 0.9rem 0 0; }
.reference-back { font-family: 'Cinzel', serif; font-size: 0.65rem; letter-spacing: 0.1em; margin: 1.2rem 0 0; }

/* Standalone visit: no game chrome around it, so the screen supplies its own. */
body:has(.reference-screen) > .container > turbo-frame > .reference-screen,
body:has(.reference-screen) > .container > .reference-screen {
  max-width: 34rem;
  margin: 2rem auto;
  padding: 1.25rem;
  border: 1px solid var(--border-color);
  background: var(--panel-bg);
}

/* ── The rooms the player has walked, and the walks — World::SceneGraph ──
   Sits under the world map in the same dialog, or alone in it when the game
   was started without a map. Labels are ordinary HTML so they wrap, inherit
   the theme's fonts and can carry a tooltip; only the roads are SVG, stretched
   underneath in the same percentage space the labels are positioned in. */
.scene-graph-panel { margin-top: 1.4rem; }
.reference-screen .world-map + .reference-note + .scene-graph-panel { border-top: 1px solid var(--border-subtle); padding-top: 1.1rem; }
.scene-graph-heading {
  font-family: 'Cinzel', serif; font-size: 0.62rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.7rem;
}
/* One line of rooms per row. Deep worlds grow downward and the dialog scrolls;
   they never squeeze, which is what a fixed height would do to a twelve-room
   prison. The scale beside the plot shares the height so its distances land
   level with the rooms they measure. */
.scene-graph-plot { display: flex; gap: 0.5rem; }
.scene-graph-scale, .scene-graph {
  position: relative;
  height: calc(var(--graph-lines, 1) * 4.4rem);
  min-height: 4.4rem;
}
.scene-graph-scale { flex: 0 0 4.2rem; }
.scene-graph { flex: 1 1 auto; min-width: 0; }
.scene-graph-step {
  position: absolute;
  right: 0;
  transform: translateY(-50%);
  font-family: 'Cinzel', serif; font-size: 0.5rem; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--text-dim); white-space: nowrap;
}
.scene-graph-roads { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.scene-graph-roads line {
  stroke: color-mix(in srgb, var(--border-color) 85%, transparent);
  stroke-width: 1px;
  stroke-linecap: round;
}
.scene-graph-node {
  position: absolute;
  transform: translate(-50%, -50%);
  /* A definite width, not shrink-to-fit: an absolutely positioned box sizes
     itself against the space between its left edge and the container's, so a
     room at 90% across got a tenth of the width and broke its name mid-word.
     Its share of the line, less a gutter — see World::SceneGraph#place — and
     capped so a room alone on its line is a label rather than a banner. */
  width: min(calc(var(--slot, 20) * 1% - 0.5rem), 9rem);
  box-sizing: border-box;
  padding: 0.3rem 0.4rem;
  text-align: center;
  border: 1px solid color-mix(in srgb, var(--border-color) 70%, transparent);
  background: var(--panel-bg);
  cursor: help;
}
.scene-graph-name {
  display: block;
  font-family: 'Cinzel', 'Palatino Linotype', serif;
  font-size: 0.6rem; letter-spacing: 0.05em; line-height: 1.3;
  color: var(--text-mid);
  overflow-wrap: break-word;
}
.scene-graph-here { display: block; font-family: 'Cinzel', serif; font-size: 0.48rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--theme-accent); margin-top: 0.15rem; }
.scene-graph-node.is-here { border-color: var(--theme-accent); background: color-mix(in srgb, var(--theme-accent) 12%, transparent); }
.scene-graph-node.is-here .scene-graph-name { color: var(--text-bright); }
/* Dormant: the story has moved on from it, but the player still walked there
   and a room that vanished off the map between visits would read as a bug. */
.scene-graph-node.is-dormant { border-style: dashed; opacity: 0.6; }

/* The node is lifted, not the bubble. translate() on .scene-graph-node makes
   each room its own stacking context, so a z-index on the ::after can only
   raise it above its own box — every room drawn later in the document still
   paints over it. Raising the hovered room raises what hangs off it. */
.scene-graph-node:hover { z-index: 20; }
.scene-graph-node[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  background: var(--panel-bg);
  border: 1px solid var(--border-color);
  color: var(--text-mid);
  font-family: 'Lora', Georgia, serif;
  font-style: italic;
  font-size: 0.68rem;
  line-height: 1.45;
  padding: 0.35rem 0.5rem;
  width: 13rem;
  text-align: left;
  pointer-events: none;
}
/* Opens away from whichever edge it is nearest, so a room in the bottom-right
   does not push the dialog into scrollbars. */
.scene-graph-node[data-side="left"]:hover::after { left: 0; }
.scene-graph-node[data-side="right"]:hover::after { right: 0; }
.scene-graph-node[data-vside="top"]:hover::after { top: 100%; }
.scene-graph-node[data-vside="bottom"]:hover::after { bottom: 100%; }

/* Journal — the compressed history, which the turn log has scrolled past.
   Scrolls inside its own box rather than on the dialog, so the map's hover
   tooltips still have somewhere to escape to. */
.journal-entries { max-height: 60vh; overflow-y: auto; padding-right: 0.4rem; }
.journal-heading {
  font-family: 'Cinzel', serif; font-size: 0.62rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-muted); margin: 1.2rem 0 0.5rem;
  padding-bottom: 0.3rem; border-bottom: 1px solid var(--border-subtle);
}
.journal-entries > .journal-heading:first-child { margin-top: 0; }
.journal-entry + .journal-entry { margin-top: 0.9rem; }
.journal-span { font-family: 'Cinzel', serif; font-size: 0.55rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--text-dim); margin-bottom: 0.2rem; }
.journal-text { font-family: 'Lora', Georgia, serif; font-size: 0.8rem; line-height: 1.6; color: var(--text-mid); margin: 0; }
/* The origin is the hero's own account, not a chronicle entry — set apart. */
.journal-entry.is-origin .journal-text { color: var(--text-muted); font-style: italic; }
.journal-entry.is-note .journal-text { font-size: 0.75rem; color: var(--text-muted); }

/* -- Hero portrait -- */
/* The image arrives at 2:3 (1280x1920) as a whole standing figure, so the full
   view keeps that aspect and the small ones are square crops taken from a band
   off the top -- see Portrait#avatar_transformations. */
.hero-portrait {
  aspect-ratio: 2 / 3;
  width: 100%;
  max-width: 260px;
  margin: 0 auto 0.75rem;
  border: 1px solid var(--border-color);
  background: rgba(0, 0, 0, 0.35);
  overflow: hidden;
}
.hero-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hero-portrait.is-pending {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Lora', Georgia, serif;
  font-style: italic;
  font-size: 0.7rem;
  color: var(--text-muted);
  text-align: center;
  padding: 0 1rem;
}

.sidebar-game-identity {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
/* The avatar is a lightbox trigger, and .lightbox-trigger fills its box by
   default — right for the portrait card, wrong in a flex row, where it would
   push the title aside. */
.sidebar-hero-avatar-trigger {
  width: auto;
  height: auto;
  flex: 0 0 40px;
}
.sidebar-hero-avatar {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border: 1px solid var(--border-color);
  object-fit: cover;
  display: block;
}

.portrait-gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.5rem 0;
}
.portrait-gallery form { line-height: 0; }
.portrait-gallery button {
  padding: 0;
  border: 1px solid var(--border-color);
  background: none;
  cursor: pointer;
  line-height: 0;
}
.portrait-gallery button.is-selected { border-color: var(--theme-accent); }
/* In play the tiles are lightbox triggers, and .lightbox-trigger fills its box
   by default — which in a wrapping flex row means every tile claims the full
   width and the gallery comes out as a column. Same trap as the sidebar avatar
   above. */
.portrait-gallery .lightbox-trigger {
  width: auto;
  height: auto;
  /* Over the picker's pointer: these tiles open the painting, they do not pick it. */
  cursor: zoom-in;
}
.portrait-gallery img {
  width: 56px;
  height: 56px;
  object-fit: cover;
  display: block;
}
/* The heading the gallery gets once it stops being a chooser: without it a row
   of tiles nobody can pick from reads as a broken picker. */
.portrait-gallery-label {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.65;
  margin-top: 0.6rem;
}
.portrait-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
/* Why a portrait attempt drew nothing — games/_portrait_notice. Inside the
   placeholder it inherits the pending line's italic; under the redraw button it
   carries its own. */
.portrait-notice { display: block; line-height: 1.45; }
.portrait-notice a { color: inherit; text-decoration: underline; }
.portrait-attempt-notice {
  margin: 0.4rem 0 0;
  font-family: 'Lora', Georgia, serif;
  font-style: italic;
  font-size: 0.7rem;
  color: var(--text-muted);
}
.portrait-allowance {
  font-family: 'Lora', Georgia, serif;
  font-style: italic;
  font-size: 0.68rem;
  color: var(--text-muted);
}

/* Where a picture would have been, when the month's images are spent. One
   sentence and a way forward — a spent allowance is not a refusal, and the
   setting stays on. */
.image-allowance-notice { font-family: 'Lora', Georgia, serif; font-style: italic; font-size: 0.68rem; line-height: 1.4; color: var(--text-muted); }
.image-allowance-notice a { color: var(--theme-accent); }
.scene-image-spent { padding: 0.5rem 0.75rem; text-align: center; }
.actor-allowance { padding: 0.3rem 0 0.1rem; }
