/* ==========================================================================
   Stories Gallery — chart-card tab #4
   --------------------------------------------------------------------------
   Two display states inside #chart-stories-view:
     1. Gallery (.stories-gallery)        — grid of icon tiles
     2. Stage   (.stories-stage)          — one story expanded with chrome

   The story canvas itself (.story-canvas) is sized in canonical EXPORT
   pixels (1200×675 / 1080×1350 / 1080×1080) so the on-screen preview
   matches future PNG exports 1:1. CSS scales the canvas to fit the
   stage area via a transform on .story-canvas-fit.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Container & state
   -------------------------------------------------------------------------- */

.chart-stories-view {
  padding: 16px 0 8px;
}

.chart-stories-view[hidden] {
  display: none;
}

.stories-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 60px 24px;
  color: var(--text-muted, #6b6760);
  text-align: center;
}

.stories-empty[hidden] { display: none; }

.stories-empty i {
  width: 36px;
  height: 36px;
  opacity: 0.6;
}

/* --------------------------------------------------------------------------
   Gallery — grid of tiles
   -------------------------------------------------------------------------- */

.stories-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
  padding: 8px 16px;
}

.stories-gallery[hidden] { display: none; }

.story-tile {
  /* Reset native button styles — these tiles are large click targets. */
  appearance: none;
  background: var(--surface-alt, #fafaf9);
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.08));
  border-radius: 14px;
  padding: 24px 20px;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: transform 120ms ease-out, box-shadow 120ms ease-out, border-color 120ms ease-out;
  min-height: 168px;
}

.story-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px -8px rgba(31, 35, 40, 0.18);
  border-color: rgba(31, 35, 40, 0.18);
}

.story-tile:focus-visible {
  outline: 2px solid var(--accent-color, #1f5faa);
  outline-offset: 2px;
}

.story-tile-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: linear-gradient(135deg, #f0ebe0, #faf8f3);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #1a1814;
}

.story-tile-icon i {
  width: 22px;
  height: 22px;
}

.story-tile-name {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-primary, #1a1814);
  letter-spacing: -0.005em;
}

.story-tile-desc {
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-muted, #6b6760);
  flex: 1 1 auto;
}

.story-tile-aspects {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}

.story-tile-aspect-chip {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 7px;
  border-radius: 4px;
  background: rgba(31, 35, 40, 0.06);
  color: var(--text-muted, #6b6760);
  letter-spacing: 0.02em;
  font-feature-settings: "tnum" 1;
}

/* --------------------------------------------------------------------------
   Stage — chrome bar + canvas fit wrapper
   -------------------------------------------------------------------------- */

.stories-stage {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 4px 8px 16px;
}

.stories-stage[hidden] { display: none; }

.story-stage-chrome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 4px 8px;
  flex-wrap: wrap;
}

.story-stage-back {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 8px;
  padding: 7px 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary, #1a1814);
  cursor: pointer;
  transition: background 120ms ease-out, border-color 120ms ease-out;
}

.story-stage-back:hover {
  background: rgba(31, 35, 40, 0.04);
  border-color: rgba(31, 35, 40, 0.2);
}

.story-stage-back i {
  width: 14px;
  height: 14px;
}

/* Aspect switcher segmented control. Mirrors the look of
   .chart-scale-segmented for visual coherence with the working app. */
.story-aspect-switcher {
  display: inline-flex;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface-alt, #fafaf9);
}

.story-aspect-segment {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 7px 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted, #6b6760);
  cursor: pointer;
  border-right: 1px solid var(--border-color, rgba(31, 35, 40, 0.08));
  letter-spacing: 0.02em;
  font-feature-settings: "tnum" 1;
}

.story-aspect-segment:last-child { border-right: 0; }
.story-aspect-segment:hover { background: rgba(31, 35, 40, 0.04); color: #1a1814; }
.story-aspect-segment.is-active {
  background: #1a1814;
  color: #faf8f3;
}

/* Linear / Log y-axis toggle. Same segmented look as the aspect
   switcher so the toolbar reads as a coherent set of controls. */
.story-scale-toggle {
  display: inline-flex;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface-alt, #fafaf9);
}

.story-scale-segment {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 7px 12px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted, #6b6760);
  cursor: pointer;
  border-right: 1px solid var(--border-color, rgba(31, 35, 40, 0.08));
  letter-spacing: 0.02em;
}

.story-scale-segment:last-child { border-right: 0; }
.story-scale-segment:hover { background: rgba(31, 35, 40, 0.04); color: #1a1814; }
.story-scale-segment.is-active {
  background: #1a1814;
  color: #faf8f3;
}

/* Side-table toggle — single pill button (binary on/off). Visually
   matches the scale toggle for chrome consistency, but reserves room
   for the leading checkmark glyph so toggling on doesn't shift the
   adjacent controls. The check fades in/out via opacity rather than
   display:none so the layout stays stable. */
.story-side-table-toggle {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 8px;
  background: var(--surface-alt, #fafaf9);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-muted, #6b6760);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}

.story-side-table-toggle:hover {
  background: rgba(31, 35, 40, 0.04);
  color: #1a1814;
}

.story-side-table-toggle.is-active {
  background: #1a1814;
  color: #faf8f3;
  border-color: #1a1814;
}

.story-side-table-toggle-check {
  display: inline-block;
  width: 12px;
  text-align: center;
  /* Hidden by default — pre-reserved horizontal space avoids a shift
     when the user toggles the button on. */
  opacity: 0;
  transition: opacity 120ms ease;
  font-size: 13px;
  line-height: 1;
}

.story-side-table-toggle.is-active .story-side-table-toggle-check {
  opacity: 1;
}

.story-side-table-toggle-label {
  white-space: nowrap;
}

/* Headline-size slider in the stage chrome. Lets the user dial in the
   right type size for whatever they're posting (Twitter card, deck slide,
   social card). Lives between Back and the aspect switcher; styled to
   look like a tool, not navigation. */
.story-headline-slider {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 8px;
  background: var(--surface-alt, #fafaf9);
  color: var(--text-muted, #6b6760);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  font-feature-settings: "tnum" 1;
  cursor: ew-resize;
}

.story-headline-slider-icon {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-size: 18px;
  font-weight: 700;
  color: #1a1814;
  line-height: 1;
  user-select: none;
}

.story-headline-slider input[type="range"] {
  appearance: none;
  -webkit-appearance: none;
  width: 140px;
  height: 4px;
  background: rgba(31, 35, 40, 0.15);
  border-radius: 2px;
  outline: none;
  cursor: ew-resize;
}

.story-headline-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #1a1814;
  cursor: ew-resize;
  border: 2px solid #faf8f3;
  box-shadow: 0 1px 3px rgba(31, 35, 40, 0.25);
}

.story-headline-slider input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #1a1814;
  cursor: ew-resize;
  border: 2px solid #faf8f3;
  box-shadow: 0 1px 3px rgba(31, 35, 40, 0.25);
}

.story-headline-slider-readout {
  min-width: 44px;
  text-align: right;
  font-family: "Inter", system-ui, sans-serif;
  color: var(--text-primary, #1a1814);
}

/* Race-animation play / stop / replay button. Sits in the stage chrome
   between the headline slider and the aspect switcher. Tri-state:
     - idle    → subtle filled button reading "▶ Play"
     - playing → bordered "■ Stop" so the user knows tapping it cancels
     - done    → subtle dotted "↻ Replay" hinting at "go again"
   Designed to read as the only ACTION button on the toolbar — the
   other controls are mode/state switches. */
.story-play-button {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 8px;
  background: #1a1814;
  color: #faf8f3;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}

.story-play-button:hover { background: #000; }
.story-play-button:focus-visible {
  outline: 2px solid var(--accent-primary, #0e8a5f);
  outline-offset: 2px;
}
.story-play-button:disabled {
  background: rgba(31, 35, 40, 0.08);
  color: var(--text-muted, #6b6760);
  cursor: not-allowed;
}

.story-play-button[data-state="playing"] {
  background: var(--surface-alt, #fafaf9);
  color: #1a1814;
  border-color: rgba(31, 35, 40, 0.3);
}
.story-play-button[data-state="playing"]:hover {
  background: rgba(31, 35, 40, 0.04);
}

.story-play-button[data-state="done"] {
  background: var(--surface-alt, #fafaf9);
  color: var(--text-primary, #1a1814);
  border-color: rgba(31, 35, 40, 0.18);
}
.story-play-button[data-state="done"]:hover {
  background: rgba(31, 35, 40, 0.06);
}

.story-play-glyph {
  display: inline-block;
  width: 12px;
  text-align: center;
  font-size: 11px;
  line-height: 1;
}

/* Suspense-headline input — sets the headline shown WHILE the chart
   is animating. Wide enough for ~40 chars at 12px so the user can fit
   "Comparing AAPL, MSFT, NVDA, GOOG and AMZN" comfortably. Visually
   matches the headline slider so the toolbar reads as a coherent
   control set. */
.story-suspense-input {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 12px;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 8px;
  background: var(--surface-alt, #fafaf9);
  color: var(--text-muted, #6b6760);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  min-width: 220px;
  max-width: 360px;
  transition: border-color 120ms ease, background 120ms ease;
}

.story-suspense-input:focus-within {
  border-color: rgba(31, 35, 40, 0.4);
  background: #fff;
}

.story-suspense-input-icon {
  font-family: "Fraunces", Georgia, serif;
  font-size: 22px;
  font-weight: 700;
  color: #1a1814;
  line-height: 0.6;
  user-select: none;
  /* Tighten optical alignment — the curly quote glyph sits too high
     in most fonts; pull it down to the input baseline. */
  margin-top: 6px;
}

/* Letter glyphs (e.g. "T" for the final-headline input) sit on the
   baseline already; reset the curly-quote nudge so they don't drop
   below the field. Smaller font also reads more like a label badge
   than a giant Fraunces quote mark. */
.story-suspense-input.is-letter-glyph .story-suspense-input-icon {
  font-size: 14px;
  margin-top: 0;
  letter-spacing: 0.04em;
  /* Bump the right-side breathing room a hair so the smaller glyph
     doesn't feel crammed against the input field. */
  padding-right: 2px;
}

.story-suspense-input-field {
  appearance: none;
  border: 0;
  outline: none;
  background: transparent;
  flex: 1 1 auto;
  min-width: 0;
  padding: 4px 0;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary, #1a1814);
  letter-spacing: 0.01em;
}

.story-suspense-input-field::placeholder {
  color: var(--text-muted, #6b6760);
  font-style: italic;
  opacity: 0.85;
}

.story-suspense-input-field:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

/* --------------------------------------------------------------------------
   Metric multi-picker — split-button style trigger that opens a checkbox
   popover. Visually consistent with the other toolbar controls (rounded
   pill, muted surface, dark text on hover) but anchored relative so the
   popover can position absolute below it.
   -------------------------------------------------------------------------- */
.story-metric-picker {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.story-metric-picker-trigger {
  appearance: none;
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  background: var(--surface-alt, #fafaf9);
  color: var(--text-primary, #1a1814);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  border-radius: 8px;
  padding: 6px 10px 6px 12px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 140px;
  max-width: 220px;
  transition: border-color 120ms ease, background 120ms ease;
}

.story-metric-picker-trigger:hover {
  border-color: rgba(31, 35, 40, 0.32);
  background: #fff;
}

.story-metric-picker.is-open .story-metric-picker-trigger {
  border-color: rgba(31, 35, 40, 0.4);
  background: #fff;
}

.story-metric-picker-trigger:focus-visible {
  outline: 2px solid var(--accent-primary, #0e8a5f);
  outline-offset: 2px;
}

.story-metric-picker-icon {
  font-family: "Fraunces", Georgia, serif;
  font-size: 16px;
  font-weight: 700;
  color: var(--text-muted, #6b6760);
  line-height: 1;
  flex: 0 0 auto;
  user-select: none;
}

.story-metric-picker-label {
  flex: 1 1 auto;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--text-primary, #1a1814);
}

.story-metric-picker-chev {
  font-size: 10px;
  line-height: 1;
  color: var(--text-muted, #6b6760);
  flex: 0 0 auto;
  transition: transform 120ms ease;
}

.story-metric-picker.is-open .story-metric-picker-chev {
  transform: rotate(180deg);
}

/* ---- Popover ---------------------------------------------------------- */
.story-metric-picker-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;                       /* anchor to the trigger's left edge */
  z-index: 50;
  min-width: 220px;
  padding: 10px;
  background: #fff;
  color: var(--text-primary, #1a1814);
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.06);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* `display: flex` above wins over the `hidden` attribute's implicit
   `display: none` — re-assert hiding so a closed menu actually hides. */
.story-metric-picker-menu[hidden] { display: none; }

.story-metric-picker-heading {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted, #6b6760);
  margin: 2px 4px 6px 4px;
}

.story-metric-picker-options {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.story-metric-picker-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 100ms ease;
  user-select: none;
}

.story-metric-picker-option:hover {
  background: rgba(31, 35, 40, 0.05);
}

.story-metric-picker-option.is-checked {
  background: rgba(14, 138, 95, 0.08);
}

.story-metric-picker-option input[type="checkbox"] {
  appearance: none;
  width: 14px;
  height: 14px;
  border: 1.5px solid rgba(31, 35, 40, 0.35);
  border-radius: 3px;
  background: #fff;
  cursor: pointer;
  flex: 0 0 auto;
  position: relative;
  transition: border-color 120ms ease, background 120ms ease;
}

.story-metric-picker-option input[type="checkbox"]:hover {
  border-color: var(--accent-primary, #0e8a5f);
}

.story-metric-picker-option input[type="checkbox"]:checked {
  background: var(--accent-primary, #0e8a5f);
  border-color: var(--accent-primary, #0e8a5f);
}

/* Pure-CSS checkmark — drawn as a rotated rectangle "tick." Sized so
   it sits crisply inside the 14×14 box at 1× and 2× device pixels. */
.story-metric-picker-option input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 3px;
  top: 0px;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.story-metric-picker-option-label {
  flex: 1 1 auto;
  color: var(--text-primary, #1a1814);
  letter-spacing: 0.01em;
}

.story-metric-picker-option.is-checked .story-metric-picker-option-label {
  color: var(--accent-primary, #0e8a5f);
}

/* Tiny aspect-shape glyphs drawn purely in CSS — gives the segmented
   control a recognizable visual cue beyond the text. */
.story-aspect-icon {
  display: inline-block;
  border: 1.5px solid currentColor;
  border-radius: 1.5px;
  flex: 0 0 auto;
}
.story-aspect-icon[data-aspect="16:9"] { width: 16px; height: 9px; }
.story-aspect-icon[data-aspect="4:5"]  { width: 8px;  height: 10px; }
.story-aspect-icon[data-aspect="1:1"]  { width: 10px; height: 10px; }

/* --------------------------------------------------------------------------
   Canvas fit wrapper — scales the canonical-pixel canvas to the
   available stage width while preserving aspect.
   --------------------------------------------------------------------------
   Strategy: container-query-friendly. The wrapper sets aspect-ratio so
   it claims the right shape; the inner .story-canvas is pixel-sized,
   absolutely positioned at top-left, and scaled via transform: scale()
   set inline by JS based on the wrapper's measured width.

   For v1 (no JS measure-and-scale yet) we use width:100% on the
   canvas and rely on CSS `transform-origin: top left` plus a width-
   based scale calculated via the modern `attr()` would be ideal, but
   that's not yet supported in all browsers. So the fallback below uses
   simple max-width: 100% on the canvas itself with `aspect-ratio` set
   on the wrapper. The canvas is already absolutely positioned so the
   wrapper's intrinsic size will dictate everything once we add the
   scale transform — see TODO at the bottom.
   -------------------------------------------------------------------- */

.story-canvas-fit {
  width: 100%;
  background: transparent;
  border-radius: 14px;
  overflow: hidden;
  position: relative;
  box-shadow: 0 12px 40px -16px rgba(31, 35, 40, 0.18),
              0 0 0 1px rgba(31, 35, 40, 0.06);
}

.story-canvas-fit[data-aspect="16:9"] { aspect-ratio: 1200 / 675; }
.story-canvas-fit[data-aspect="4:5"]  { aspect-ratio: 1080 / 1350; max-width: 540px; margin: 0 auto; }
.story-canvas-fit[data-aspect="1:1"]  { aspect-ratio: 1 / 1; max-width: 720px; margin: 0 auto; }

/* Canvas is absolute-positioned to top-left of fit wrapper; we scale
   it down with transform so 1200×675 fits inside whatever width the
   wrapper has. The transform origin keeps top-left aligned. JS would
   ideally set the scale precisely; for now CSS does it via a calc()
   trick using the wrapper's width via a CSS variable. The variable is
   set by JS in a ResizeObserver — kept simple here with a default
   that works for most desktop widths. */
.story-canvas-fit .story-canvas {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
  /* Scale is set inline by stories/index.js based on measured width.
     Default 0.7 keeps things sane before the observer fires. */
  transform: scale(var(--story-canvas-scale, 0.7));
}

/* --------------------------------------------------------------------------
   The canvas itself (poster contents). Most styling is applied inline
   by storyFrame.js (so SVG export inherits everything cleanly), but a
   few selectors stay here:
     - emphasis (<em>) inside the headline gets the editorial italic
       + accent-color treatment
     - the brand mark inside .story-canvas swaps to the white-on-dark
       variant if/when we add a dark-themed story background
   -------------------------------------------------------------------- */

.story-canvas .story-headline em {
  font-style: italic;
  color: #0e8a5f;          /* editorial green accent — the money number */
  font-variation-settings: "opsz" 144, "wght" 800, "SOFT" 30, "WONK" 1;
  font-feature-settings: "tnum" 1;
  display: inline;
  /* Optical kerning around italic tokens. Fraunces Italic Black has
     steeply slanted right edges (the tail of "6" in "$17,826", the
     overhang of "L" in "SOXL") that visually crash into the next
     upright glyph — most painfully into a lowercase "in" that often
     follows the money number. A tiny right margin restores breathing
     room without looking like a deliberate gap. The left margin is
     half as much because the italic's left edge is closer to vertical
     and the upper-left of the next italic glyph rarely overlaps. */
  margin-right: 0.07em;
  margin-left: 0.03em;
}

/* Edge cases — when the italic token sits at the very start or end
   of the headline we don't want phantom margins eating into the
   headline's optical width (which would force an unnecessary font-
   size shrink in `_fitHeadlineToWidth`). */
.story-canvas .story-headline em:first-child {
  margin-left: 0;
}
.story-canvas .story-headline em:last-child {
  margin-right: 0;
}

.story-canvas .story-headline .story-headline-token {
  display: inline;
}

/* When the headline winner LOST money (e.g. all-bear comparison set)
   we still want the emphasis to read "the protagonist" — not "bad"
   green. A future tweak in heroGrowth.js can add a class on the canvas
   to swap this color to a warm rust accent. For now, green is the
   default storytelling accent. */

/* Subhead percent-gain accent — appended to the right of the period /
   date-range so the subhead reads like a magazine caption:
       "Past 3 years · Apr 27, 2023 → Apr 23, 2026 · +801%"
   The color is set inline (per render) to match the WINNER'S line color
   so the subhead is visually keyed to the chart. We only style the
   weight + slight optical bump here; do not override `color`. */
.story-canvas .story-subhead .story-subhead-pct,
.story-canvas .story-subhead .story-subhead-return {
  font-style: normal;
  font-weight: 700;
  font-feature-settings: "tnum" 1;
  /* Tiny letter-spacing tightening — bold tabular figures otherwise
     read slightly looser than the rest of the muted subhead. */
  letter-spacing: -0.005em;
}

.story-canvas .story-subhead .story-subhead-period {
  color: var(--story-ink-muted, #6b6760);
  font-weight: 500;
}

.story-canvas .story-subhead .story-subhead-return {
  display: inline-flex;
  align-items: baseline;
  gap: 0.16em;
  white-space: nowrap;
}

.story-canvas .story-subhead .story-subhead-return-ticker {
  font-weight: 800;
  letter-spacing: 0.02em;
}

.story-canvas .story-subhead .story-subhead-return-value {
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Export controls — split-button (Export ⌄) + popover with format /
   resolution / fps pickers, plus a fullscreen progress overlay shown
   while frames are being encoded.
   --------------------------------------------------------------------------
   Visual language: matches the play button (dark filled "primary"
   action) so the export reads as the natural next step after Play. The
   chevron uses the same dark fill split into a second face. The popover
   uses the same border / radius / surface-alt tones as the suspense
   input + headline slider so the toolbar reads as one family.
   -------------------------------------------------------------------------- */
.story-export {
  position: relative;            /* anchor for absolutely-positioned popover */
  display: inline-flex;
  align-items: stretch;
  border-radius: 8px;
  /* Outer border lives on the wrapper so the split between main + chev
     is a single 1px line instead of two stacked borders. */
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  overflow: visible;             /* popover can escape the wrapper */
  background: #1a1814;
  color: #faf8f3;
  font-family: inherit;
}

.story-export-main,
.story-export-chev {
  appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  transition: background 120ms ease;
}

.story-export-main {
  gap: 6px;
  padding: 7px 12px 7px 14px;
  border-right: 1px solid rgba(255, 255, 255, 0.12);
  /* Pill the left side so the wrapper border looks like one shape */
  border-radius: 8px 0 0 8px;
}
.story-export-main:hover { background: rgba(255, 255, 255, 0.08); }

.story-export-chev {
  padding: 7px 8px;
  border-radius: 0 8px 8px 0;
}
.story-export-chev:hover { background: rgba(255, 255, 255, 0.08); }
.story-export-chev i {
  width: 14px;
  height: 14px;
  display: inline-block;
}

.story-export-main:focus-visible,
.story-export-chev:focus-visible {
  outline: 2px solid var(--accent-primary, #0e8a5f);
  outline-offset: 2px;
}

.story-export-main:disabled,
.story-export-chev:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

/* When the popover is open, accent the chevron so it's clear which
   half of the split-button is "active." */
.story-export.is-open .story-export-chev {
  background: rgba(255, 255, 255, 0.12);
}

/* ---- Popover ---------------------------------------------------------- */
.story-export-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;                      /* anchor to the chevron edge */
  z-index: 50;                   /* above stage canvas; below modals */
  min-width: 260px;
  padding: 10px;
  background: #fff;
  color: var(--text-primary, #1a1814);
  border: 1px solid var(--border-color, rgba(31, 35, 40, 0.12));
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.06);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* `display: flex` above wins over the implicit `display: none` that
   the HTML `hidden` attribute carries — so a closed menu would still
   render. Re-assert visibility hiding here so `hidden` actually hides. */
.story-export-menu[hidden] { display: none; }

.story-export-section + .story-export-section {
  /* Subtle divider between sections — easier to scan than relying on
     gap alone, especially with three sections stacked. */
  padding-top: 10px;
  border-top: 1px solid rgba(31, 35, 40, 0.06);
}

.story-export-section-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted, #6b6760);
  margin-bottom: 4px;
}

.story-export-options {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.story-export-option {
  appearance: none;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  padding: 8px 10px;
  border-radius: 6px;
  display: grid;
  grid-template-columns: 64px 1fr;
  align-items: baseline;
  gap: 10px;
  font-family: inherit;
  font-size: 12px;
  color: var(--text-primary, #1a1814);
  transition: background 100ms ease;
}
.story-export-option:hover { background: rgba(31, 35, 40, 0.05); }
.story-export-option.is-selected {
  background: rgba(14, 138, 95, 0.08);
}
.story-export-option.is-selected .story-export-option-label {
  color: var(--accent-primary, #0e8a5f);
}

.story-export-option-label {
  font-weight: 700;
  letter-spacing: 0.01em;
}

.story-export-option-hint {
  color: var(--text-muted, #6b6760);
  font-size: 11px;
  font-weight: 500;
}

/* ---- Progress overlay ------------------------------------------------- */
/* Lives on document.body so it stays put even if the user scrolls the
   chart card. Fixed-position; semi-transparent backing so the user can
   still see *what* is being exported but can't accidentally interact
   with it. */
.story-export-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(15, 14, 12, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Backdrop blur to push focus to the card. Falls back gracefully on
     browsers without backdrop-filter support. */
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.story-export-overlay[hidden] { display: none; }

.story-export-overlay-card {
  background: #fff;
  color: var(--text-primary, #1a1814);
  border-radius: 14px;
  padding: 28px 32px;
  min-width: 320px;
  max-width: 420px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  font-family: inherit;
}

.story-export-overlay-spinner {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid rgba(31, 35, 40, 0.12);
  border-top-color: var(--accent-primary, #0e8a5f);
  animation: story-export-spin 800ms linear infinite;
}

@keyframes story-export-spin {
  to { transform: rotate(360deg); }
}

.story-export-overlay-message {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-align: center;
  color: var(--text-primary, #1a1814);
  /* Tabular figures so the "frame N / M" counter doesn't visually
     jitter as the digits change. */
  font-variant-numeric: tabular-nums;
}

.story-export-overlay-progress {
  width: 100%;
  height: 4px;
  border-radius: 2px;
  background: rgba(31, 35, 40, 0.08);
  overflow: hidden;
}

.story-export-overlay-progress-bar {
  height: 100%;
  width: 0;
  background: var(--accent-primary, #0e8a5f);
  transition: width 120ms ease;
}

