/* ==========================================================================
   story.css — Taleweaver (story_time_generator.md). KDL 2026-06-27's direction:
   Story Time is assembled from existing parts. The story LOG inherits Lore's
   reading treatment (it carries .lore-read--leaf, which sets --measure: 62ch +
   the leaf surface); this file adds ONLY the beat rhythm, the entity tags, the
   "THE FATES OFFER" choice panel, the seed screen, and the roster. Reuses
   existing tokens + .btn / .list-row / .field — no new visual language, no new
   colour tokens, no border-radius.
   ========================================================================== */

.story {
  max-width: 70rem;
  margin: 0 auto 0 0;            /* left-anchored, like Lore */
}

.story__page-head,
.story__loop-head {
  margin-bottom: var(--space-md);
}

.story__loop-head {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  flex-wrap: wrap;
}

/* The tale's per-trope cover in the loop/detail header (batch, 2026-06-28). A
   compact framed tile beside the Back button + seed chips so the header carries
   the tale's art without dominating the reading column. object-fit:cover crops the
   illustrative tile into the frame; the glyph fallback fills the same box if the
   art is missing, so the header height never shifts. */
.story__cover {
  flex: 0 0 auto;
  width: 4.5rem;
  height: 4.5rem;
  margin: 0;
  display: block;
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: var(--color-surface-2, var(--color-surface));
}

.story__cover-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.story__cover-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--color-text-muted);
}

.story__cover-fallback svg {
  width: 55%;
  height: 55%;
}

.story__title {
  font-family: var(--font-heading);   /* JSL-Blackletter h1 identity moment */
}

/* Double-rule divider (the manuscript banner underline). */
.story__divider {
  border-top: 1px solid var(--color-border);
  box-shadow: 0 2px 0 0 var(--color-border);
  margin: 0 0 var(--space-lg);
}

/* List-forward landing (#4): title block + the "+ New Tale" affordance share the
   header row; the create form lives below, collapsed by default. */
.story__page-head--list {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
  /* Tighter than the shared --space-md base: the list-forward landing pulls the
     tales list up under the "+ Tale" controls so the section sits higher (less
     dead vertical space between the header and the list). */
  margin-bottom: var(--space-sm);
}

/* On the list landing the divider's only job is the thin manuscript underline
   directly beneath the header; the list leads right after it, so it needs only a
   small gap (the shared-tale view keeps the base --space-lg). */
.story__page-head--list + .story__divider {
  margin-bottom: var(--space-sm);
}

.story__page-head-text { min-width: 0; }

.story-new-toggle { flex: 0 0 auto; }

/* The collapsed-by-default seed/create panel sits below the tales list. */
.story-seed-panel {
  margin-top: var(--space-lg);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--color-border);
}

/* Seed chips on the loop header. */
.story__seedchips {
  display: flex;
  gap: var(--space-xs);
  flex-wrap: wrap;
}

.story-chip {
  font-family: var(--font-heading-ui);
  font-size: 0.68rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  padding: 0.15rem 0.5rem;
}

/* ==========================================================================
   SEED / SETUP screen
   ========================================================================== */
.story-seed {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  max-width: 52rem;
}

.story-seed__group {
  border: none;
  margin: 0;
  padding: 0;
}

.story-seed__legend {
  font-family: var(--font-heading-ui);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-accent);
  padding: 0;
  margin-bottom: var(--space-sm);
}

/* Trope tiles — multi-select .list-row tiles in a responsive grid. */
.story-seed__tropes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: var(--space-sm);
}

.story-trope {
  /* .list-row supplies the surface/border/hover/selected treatment. The cover
     thumb sits left of the label/blurb text column (batch, 2026-06-28). */
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

/* Cover thumbnail in the picker — a small fixed-size tile so the row height stays
   even whether or not the art loads (the glyph fallback fills the same box). The
   art is an illustrative "etching on black" tile; object-fit:cover crops it neatly
   into the square. (batch, 2026-06-28) */
.story-trope__thumb {
  flex: 0 0 auto;
  width: 3.25rem;
  height: 3.25rem;
  display: block;
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: var(--color-surface-2, var(--color-surface));
}

.story-trope__thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.story-trope__thumb-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--color-text-muted);
}

.story-trope__thumb-fallback svg {
  width: 55%;
  height: 55%;
}

/* The label + blurb stack to the right of the thumb. */
.story-trope__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs, 0.2rem);
  min-width: 0;
}

.story-trope__label {
  font-family: var(--font-heading);
  font-size: var(--text-h5, 1.05rem);
  font-weight: 600;
  color: var(--color-heading);
  letter-spacing: 0.02em;
}

.story-trope__blurb {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-style: italic;
  color: var(--color-text-muted);
  line-height: 1.4;
}

.story-seed__knobs {
  display: flex;
  gap: var(--space-md);
  flex-wrap: wrap;
}

.story-seed__knobs .field {
  flex: 1 1 8rem;
  min-width: 7rem;
}

.story-seed__actions {
  display: flex;
}

.story-seed__begin {
  letter-spacing: 0.12em;
}

/* ==========================================================================
   SAVED-TALES ROSTER (seed screen)
   ========================================================================== */
/* List-forward landing: the roster leads directly under the header's
   story__divider underline, so it needs no second top rule / large top band of
   its own (that stacked into an empty box of wasted vertical space). The divider
   above is the only separator. */
.story-roster {
  margin-top: 0;
}

.story-roster__title {
  font-family: var(--font-heading-ui);
  font-size: 0.9rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
  /* Trimmed from --space-md so "Your tales" sits closer to its list (part of
     slimming the section's vertical gap). */
  margin: 0 0 var(--space-sm);
}

.story-roster__empty {
  font-style: italic;
  margin: 0;
}

.story-roster__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.story-roster__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
  padding: var(--space-md);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
}

.story-roster__main { min-width: 0; flex: 1 1 16rem; }

.story-roster__name {
  font-family: var(--font-heading);
  font-size: var(--text-h4);
  font-weight: 600;
  color: var(--color-heading);
  margin: 0;
  word-break: break-word;
}

.story-roster__meta {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--color-text-muted);
  margin: 0.2rem 0 0;
}

.story-roster__actions {
  display: flex;
  gap: var(--space-sm);
  flex: 0 0 auto;
  flex-wrap: wrap;
}

/* Tale card (M-5, 2026-06-27) — the Taleweaver roster now uses the shared
   .char-card family as a .char-card-grid. The whole card opens the tale
   (Continue/Read); the corner button deletes. "Share to campaign" (B#9) is a
   third action that does not fit the card shell, so it sits as a quiet text
   button pinned to the bottom-right of the card, ABOVE the open button's hit
   area (its own click stops propagation). The card meta keeps the tone · turns ·
   status line. */
.tale-card .char-card__open {
  /* Reserve a little bottom room so the open hit-area never sits under the
     Share button (which is pinned bottom-right). */
  padding-bottom: var(--space-md);
}

/* Per-trope cover as the saved-card media (2026-06-28) inside the shared 5rem
   .char-card__portrait medallion. Without a sizing rule the cover rendered at its
   natural pixel size and overflowed the card; this matches the campaigns / maps /
   encounters roster-card default-img idiom VERBATIM — the illustrative tile shows
   WHOLE via object-fit:contain (cover would crop it into the circle) with a hair of
   padding off the circular border. If the art 404s, img-fallback.js swaps in the
   tale glyph span (sized by the shared .char-card__portrait-fallback rules). */
.tale-card .char-card__portrait .tale-card__default-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  padding: 0.35rem;
}

.tale-card .char-card__meta.tale-card__meta {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: normal;
  text-transform: none;
  color: var(--color-text-muted);
}

/* The open action ("Continue the tale" / "Read the tale") on its OWN line below
   the tone · turns meta — the card's verb, in the accent voice so it reads as the
   call to open rather than more grey meta. A little top space sets it apart from
   the meta line above. .char-card__body is flex-column, so this stacks naturally. */
.tale-card__action {
  margin-top: var(--space-2xs, 0.2rem);
  font-family: var(--font-heading-ui);
  font-size: 0.7rem;
  letter-spacing: var(--ls-cinzel-caps, 0.04em);
  text-transform: uppercase;
  color: var(--color-accent);
}

.tale-card__share {
  position: absolute;
  right: var(--space-sm);
  bottom: var(--space-xs);
  z-index: 2;
  appearance: none;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0.1rem 0.2rem;
  font-family: var(--font-heading-ui);
  font-size: 0.66rem;
  letter-spacing: var(--ls-cinzel-caps, 0.04em);
  text-transform: uppercase;
  color: var(--color-text-muted);
  opacity: 0;
  transition: opacity var(--transition-ui, 0.12s ease), color var(--transition-ui, 0.12s ease);
}

.tale-card:hover .tale-card__share,
.tale-card__share:focus-visible {
  opacity: 1;
}

.tale-card__share:hover {
  color: var(--color-accent);
}

.tale-card__share:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
  .tale-card__share {
    transition: none;
    opacity: 1;
  }
}

/* ==========================================================================
   THE STORY LOG — the manuscript. .lore-read--leaf supplies the leaf surface +
   --measure: 62ch. Beats accrete downward; the newest carries the live stripe.
   ========================================================================== */
.story-log {
  /* Inherits .lore-read--leaf. Cap height + scroll so the offer panel stays in
     view on long tales; the leaf itself is the scroll region. */
  max-height: 60vh;
  overflow-y: auto;
}

.story-log__heading {
  font-family: var(--font-heading-ui);
  font-size: 0.9rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-sm);
}

/* A committed beat. Double-rule divider between beats (the manuscript chapter
   break). Prose holds the 62ch measure inherited from the leaf. */
.story-beat {
  max-width: var(--measure, 62ch);
}

.story-beat + .story-beat {
  margin-top: var(--space-lg);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--color-border);
  box-shadow: 0 -2px 0 0 var(--color-border) inset;
}

/* The newest beat carries the universal 3px accent left-stripe (live content). */
.story-beat--live {
  border-left: 3px solid var(--color-accent);
  padding-left: var(--space-md);
  margin-left: calc(-1 * var(--space-md));
}

.story-beat__p {
  font-family: var(--font-body);
  font-size: 1.05rem;
  line-height: var(--lh-body);
  color: var(--color-text);          /* NEVER accent for body prose (KDL 2026-06-27 Do-Not #9) */
  margin: 0 0 var(--space-md);
}

.story-beat__p:last-child { margin-bottom: 0; }

/* The inked choice marker — the spine of the tale. Muted, italic. */
.story-beat__choice {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--color-text-muted);
  margin: var(--space-sm) 0 0;
}

.story-beat__choice-mark {
  color: var(--color-accent);
  font-style: normal;
  margin-right: 0.3em;
}

/* Fade-reveal of a newly-inked beat (KDL 2026-06-27 §2b — NOT the typewriter). The class
   is applied then removed on the next frame so the beat transitions from hidden
   to shown. Reduced-motion: the JS skips adding the class, so it is instant. */
.story-beat--revealing {
  opacity: 0;
  transform: translateY(4px);
}

.story-beat {
  transition: opacity var(--transition-reveal), transform var(--transition-reveal);
}

@media (prefers-reduced-motion: reduce) {
  .story-beat { transition: none; }
}

/* --- Inline rolled-entity tags (KDL 2026-06-27 §3.4) --------------------------------
   Accent-coloured, scannable, with a NON-COLOUR affordance: the type tag text
   carries the meaning, so colour is never the sole signal (WCAG 1.4.1). A faint
   Share-Tech-Mono roll annotation honours the procedural origin. */
.story-beat__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin: var(--space-sm) 0 0;
  max-width: var(--measure, 62ch);
}

.story-tag {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--color-border);
  border-left: 2px solid var(--color-accent);
  background-color: color-mix(in srgb, var(--color-accent) 6%, transparent);
}

.story-tag__type {
  font-family: var(--font-heading-ui);
  font-size: 0.6rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.story-tag__value {
  font-family: var(--font-body);
  font-size: 0.9rem;
  color: var(--color-accent);
}

.story-tag__roll {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--color-text-muted);
  opacity: 0.8;
}

/* ==========================================================================
   THE FATES OFFER — pinned choice panel below the log.
   ========================================================================== */
.story-fates {
  margin-top: var(--space-md);
}

.story-fates__divider {
  border-top: 1px solid var(--color-border);
  box-shadow: 0 2px 0 0 var(--color-border);
  margin-bottom: var(--space-md);
}

.story-fates__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  margin-bottom: var(--space-sm);
}

.story-fates__title {
  font-family: var(--font-heading-ui);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* The die that produced the offer — Share Tech Mono (the dice register). */
.story-fates__roll {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--color-accent);
}

.story-fates__rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: var(--measure-wide, 86ch);
}

/* Branch rows reuse .list-row; the A-D key sits as a leading marker. */
.story-branch {
  flex-direction: row;
  align-items: center;
  gap: var(--space-md);
}

.story-branch__key {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  font-family: var(--font-heading-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

.story-branch.is-selected .story-branch__key {
  color: var(--ink-on-accent, var(--color-bg));
  background-color: var(--color-accent);
  border-color: var(--color-accent);
}

.story-branch__label {
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: var(--lh-body);
  color: var(--color-text);
}

/* Commit: unchosen options fade + collapse (KDL 2026-06-27 §3.3). Reduced-motion -> the
   transition is disabled so it is an instant cut. */
.story-branch {
  transition: opacity var(--transition-ui), max-height var(--transition-ui);
  max-height: 12rem;
  overflow: hidden;
}

.story-branch--fading {
  opacity: 0;
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  border-width: 0;
}

@media (prefers-reduced-motion: reduce) {
  .story-branch { transition: none; }
}

.story-fates__actions {
  display: flex;
  gap: var(--space-sm);
  margin-top: var(--space-md);
  flex-wrap: wrap;
}

/* Ended state. */
.story-fates__ended {
  margin-top: var(--space-md);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-border);
}

.story-fates__ended-text {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-sm);
}

.story-fates__ended-actions {
  display: flex;
  gap: var(--space-sm);
}

/* Export modal toggle. */
.story-export__toggle {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-top: var(--space-sm);
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--color-text);
  cursor: pointer;
}

/* ==========================================================================
   B#12 — "Generate related" side panel. A read-only side-tool below the fates:
   the things this beat suggests, each one-click saveable into its own library.
   Reuses the fates divider/head idiom + .btn; no new visual language.
   ========================================================================== */
.story-related {
  margin-top: var(--space-md);
}

.story-related:empty {
  margin-top: 0;
}

.story-related__divider {
  border-top: 1px solid var(--color-border);
  box-shadow: 0 2px 0 0 var(--color-border);
  margin-bottom: var(--space-md);
}

.story-related__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  flex-wrap: wrap;
  margin-bottom: var(--space-sm);
}

.story-related__title {
  font-family: var(--font-heading-ui);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* The read-only reassurance: this side-tool never touches the tale. */
.story-related__hint {
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-style: italic;
}

/* In-panel Reroll do-over (gated; hidden in Hardcore mode). Right-aligned in the
   flex head so it reads as an action on the suggestion set, not part of the title. */
.story-related__reroll {
  margin-left: auto;
  align-self: center;
}

.story-related__note {
  margin: 0;
}

.story-related__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: var(--measure-wide, 86ch);
}

.story-related__card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
  padding: var(--space-sm) var(--space-md);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
}

.story-related__card.is-saved {
  opacity: 0.7;
}

.story-related__card-main { min-width: 0; flex: 1 1 16rem; }

.story-related__card-label {
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-heading);
  margin: 0;
  word-break: break-word;
}

.story-related__card-teaser {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 0.9rem;
  color: var(--color-text-muted);
  margin: 0.2rem 0 0;
}

.story-related__save {
  flex: 0 0 auto;
}

.story-related__save.is-done {
  opacity: 0.8;
}

/* #2b — richer rolled-field preview inside the candidate card. A compact
   key/value list (proprietor, notable details, …) so the user sees WHAT was
   rolled before saving. Display-only; styled like the encounter facts list. */
.story-related__preview {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: var(--space-xs) 0 0;
  padding: var(--space-xs) var(--space-sm);
  border-left: 2px solid var(--color-border);
}

.story-related__preview-row {
  display: flex;
  gap: var(--space-sm);
  align-items: baseline;
}

.story-related__preview-key {
  flex: 0 0 7rem;
  margin: 0;
  font-family: var(--font-heading-ui);
  font-size: 0.6rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.story-related__preview-val {
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.9rem;
  color: var(--color-text);
  word-break: break-word;
}

/* #2b — the "Open" link shown once a candidate is SAVED. A quiet text link that
   navigates to the saved record's section/viewer. Underlined affordance (not
   colour-only) for WCAG 1.4.1. */
.story-related__open {
  margin-top: var(--space-xs);
}

.story-related__open:empty {
  margin-top: 0;
}

.story-related__open-link {
  display: inline-flex;
  align-items: center;
  padding: 0;
  font-family: var(--font-heading-ui);
  font-size: 0.78rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-accent);
  background: transparent;
  border: none;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.story-related__open-link:hover {
  color: var(--color-accent-hover);
}

.story-related__open-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (max-width: 520px) {
  .story-related__preview-row { flex-direction: column; gap: 0.05rem; }
  .story-related__preview-key { flex: 0 0 auto; }
}

@media (max-width: 520px) {
  .story-related__card {
    flex-direction: column;
    align-items: stretch;
  }
}

/* ==========================================================================
   B#10 — character picker (seed screen) + the named attached party.
   ========================================================================== */
.story-seed__hint {
  font-size: 0.85rem;
  margin: 0 0 var(--space-sm);
}

/* #7 — party-mode either/or toggle. Two .list-row radios side by side (stacks on
   narrow viewports); selection rides the universal .is-selected accent. */

/* The INACTIVE composition panel is FULLY hidden, not just disabled (Ken). The
   size panel is a .field (components.css: display:flex), so the bare [hidden] UA
   rule (display:none) loses to .field's author display:flex at equal specificity
   and the control would otherwise stay visible. Force it down for either panel. */
[data-party-panel][hidden] {
  display: none !important;
}

.story-partymode {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}

.story-partymode__opt {
  gap: var(--space-2xs, 0.25rem);
}

.story-partymode__label {
  font-family: var(--font-heading);
  font-weight: 600;
  color: var(--color-heading);
  letter-spacing: 0.02em;
}

.story-partymode__hint {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-style: italic;
  color: var(--color-text-muted);
}

.story-seed__charpanel {
  margin-top: var(--space-md);
}

.story-charpicker__group + .story-charpicker__group {
  margin-top: var(--space-md);
}

.story-charpicker__legend {
  font-family: var(--font-heading-ui);
  font-size: 0.72rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-xs);
}

/* #8 — compact roster. Two-column grid on wider viewports (single column when
   narrow) inside a height-capped, scrollable well so a large roster never pushes
   the Begin action off-screen. */
.story-charpicker__rows {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: var(--space-2xs, 0.25rem);
  max-height: 17rem;
  overflow-y: auto;
}

/* A selectable character row — reuses the .list-row idiom; selection toggles the
   universal .is-selected accent. #8: denser padding + tighter type so each row is
   short; the name + meta still read left to right and keep the checkbox a11y. */
.story-charpick {
  flex-direction: row;
  align-items: baseline;
  gap: var(--space-sm);
  flex-wrap: wrap;
  padding: var(--space-2xs, 0.3rem) var(--space-sm);
}

.story-charpick__name {
  font-family: var(--font-body);
  font-size: 0.92rem;
  color: var(--color-text);
}

.story-charpick__meta {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--color-text-muted);
}

.story-charpicker__count {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--color-text-muted);
  margin: var(--space-sm) 0 0;
}

/* The named-party chips carry the accent edge to read apart from the seed chips. */
.story-chip--party {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* ==========================================================================
   B#11 — auto-save reassurance indicator.
   ========================================================================== */
.story__saved {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--color-text-muted);
  margin: 0;
  margin-left: auto;          /* push to the trailing edge of the loop head */
  flex: 0 0 auto;
}

/* ==========================================================================
   B#9 — share-to-campaign picker + the read-only shared manuscript.
   ========================================================================== */
.story-share__campaigns {
  list-style: none;
  margin: var(--space-sm) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.story-share__campaign {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  border: 1px solid var(--color-border);
  padding: var(--space-xs) var(--space-sm);
}

.story-share__campaign-name {
  font-family: var(--font-body);
  color: var(--color-text);
  min-width: 0;
  word-break: break-word;
}

/* The shared manuscript reuses the story log treatment; it just drops the height
   cap so the read-only tale reads as one continuous page in the overlay. */
.story-log--shared {
  max-height: none;
}

.story-shared__ended {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--color-text-muted);
  margin-top: var(--space-lg);
}

.story-shared__actions {
  margin-top: var(--space-lg);
}

/* Full read-only record (2026-07-01): a non-owner opening a shared tale sees the
   complete log + the fates that stood open — but no controls. The fates rows are
   inert <div>s here (not buttons), so neutralise any .list-row affordance that
   would falsely imply they are clickable (no pointer cursor, no hover shift). */
.story-fates--shared {
  margin-top: var(--space-lg);
}

.story-branch--readonly {
  cursor: default;
  background: transparent;
}

.story-branch--readonly:hover,
.story-branch--readonly:focus {
  background: transparent;
  border-color: var(--color-border);
  transform: none;
  box-shadow: none;
}

/* ==========================================================================
   D#2 — auto-campaign filed-count line (loop header area).
   ========================================================================== */
.story__campaign-line {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-md);
}

.story__campaign-line:empty { margin: 0; }

.story__campaign-label {
  border-left: 2px solid var(--color-accent);
  padding-left: 0.5rem;
}

/* ==========================================================================
   D#1 — per-step contextual prompt strip ("This step introduces…").
   Sits between the fates choices and the general related menu. Reuses the fates
   head idiom + .btn; the chips are compact secondary buttons.
   ========================================================================== */
.story-suggests {
  margin-top: var(--space-sm);
}

.story-suggests:empty { margin-top: 0; }

.story-suggests__head {
  margin-bottom: var(--space-xs);
}

.story-suggests__title {
  font-family: var(--font-heading-ui);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.story-suggests__chips {
  display: flex;
  gap: var(--space-xs);
  flex-wrap: wrap;
  max-width: var(--measure-wide, 86ch);
}

.story-suggests__chip {
  font-size: 0.85rem;
}

/* ==========================================================================
   D#3 — RAW encounter-check prompt + result card. Reuses the related divider/
   head idiom; the facts read as a compact key/value list.
   ========================================================================== */
.story-encounter {
  margin-top: var(--space-md);
}

.story-encounter:empty { margin-top: 0; }

/* Auto-prompted location-entry check: a contextual call-out (accent rule + inset)
   so the prompt reads as part of arriving somewhere, not a stray button. The
   manual "if you linger" prompt keeps the plain divider treatment. */
.story-encounter--entry {
  padding: var(--space-sm) var(--space-md) var(--space-md);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
}

.story-encounter--entry .story-encounter__divider {
  display: none;
}

.story-encounter--entry .story-encounter__prompt {
  margin-bottom: var(--space-md);
}

.story-encounter__divider {
  border-top: 1px solid var(--color-border);
  box-shadow: 0 2px 0 0 var(--color-border);
  margin-bottom: var(--space-md);
}

.story-encounter__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  flex-wrap: wrap;
  margin-bottom: var(--space-sm);
}

.story-encounter__title {
  font-family: var(--font-heading-ui);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.story-encounter__cite {
  font-family: var(--font-mono);
  font-size: 0.68rem;
}

/* The d6 register echoes the fates roll annotation. */
.story-encounter__roll {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--color-accent);
}

.story-encounter__prompt,
.story-encounter__clear {
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: var(--lh-body);
  color: var(--color-text);
  margin: 0 0 var(--space-sm);
  max-width: var(--measure, 62ch);
}

.story-encounter__clear {
  font-style: italic;
  color: var(--color-text-muted);
  margin-bottom: 0;
}

.story-encounter__facts {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  max-width: var(--measure, 62ch);
  margin-bottom: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
}

.story-encounter__fact {
  display: flex;
  gap: var(--space-sm);
  align-items: baseline;
}

.story-encounter__fact-key {
  flex: 0 0 7rem;
  font-family: var(--font-heading-ui);
  font-size: 0.62rem;
  letter-spacing: var(--ls-cinzel-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.story-encounter__fact-val {
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--color-text);
  word-break: break-word;
}

.story-encounter__actions {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
}

@media (max-width: 520px) {
  .story-roster__item,
  .story-branch {
    flex-direction: column;
    align-items: stretch;
  }
  .story-branch__key { align-self: flex-start; }
  .story-encounter__fact { flex-direction: column; gap: 0.1rem; }
  .story-encounter__fact-key { flex: 0 0 auto; }
}
