/* talkr/style.css — General Conference Map
 * Loaded after ../callings/lds.css -- reuses its --lds-* tokens and
 * --font-body/--font-mono rather than redefining a palette, matching the
 * pattern boom/style.css already establishes for this domain's tools. */

/* Speaker-role colors -- see classifyRole()/ROLE_COLOR_VAR in script.js.
   Picked to sit clearly apart from --lds-accent (already means "decade
   label"/"hover role text") and --lds-blue-light. --role-apostle
   deliberately echoes tools/study's own dark-mode apostle teal (#5cbfae)
   as a small intentional callback between the two tools; the other three
   are new. Default/uncategorized fill stays --lds-surface-2 (no new
   token needed). */
:root {
  --role-prophet: #f2ead6;         /* warm ivory -- the most singular category, reads as "reverent/luminous" against the dark field */
  --role-apostle: #5cbfae;         /* teal -- the Twelve, a steady collective */
  --role-firstpresidency: #e08a8a; /* soft coral */
  --role-woman: #b48ee0;           /* soft violet -- Relief Society / Young Women / Primary general presidencies */
  /* Tracking-level fill -- see LEVEL_COLOR_VARS/levelColor() in script.js.
     level = count of read/listened/watched true (0-3), same formula
     tools/study's map already uses. A blue progression toward
     --lds-blue-light (an existing token, not a new hue) rather than one
     color per verb -- read vs. listened vs. watched don't need separate
     hues on the map itself, just "how much," so this stays a single
     gradient the role-highlight rings never compete with. */
  --level-1: #2e5590;
  --level-2: #3f70b8;
  /* Conference markers -- one block-width square per conference (see
     script.js's confMarkers/markerFontPx), colored by season instead of
     an "A"/"O" text suffix. Both light enough that a dark marker-text
     color reads clearly against either. Distinct from every other token
     already in use: not a role hue (ivory/teal/coral/violet), not the
     level-color blue family, not --lds-accent's amber. */
  --conf-april: #b8e0a8;   /* pastel spring green */
  --conf-october: #d9853f; /* warm autumn rust */
  --conf-marker-text: #14202e; /* dark, deliberately not --lds-bg -- needs to sit on light pastel/rust fills, not the page's own navy */

  /* Custom-speaker ring colors -- 8 slots, reusing tools/study's own
     dark-mode custom-speaker palette verbatim (its comment already
     explains the choice: "roughly the practical limit for a human to
     tell that many ring colors apart at a glance" -- proven, not
     re-derived here). talkr is single-theme dark, so only the one set
     is needed (tools/study also has a light-mode set for its light/dark
     toggle, not applicable here). */
  --custom-0: #a394d6;
  --custom-1: #d68aa8;
  --custom-2: #5cc0dc;
  --custom-3: #b8c95c;
  --custom-4: #d68f5c;
  --custom-5: #8aa8d6;
  --custom-6: #b06fb0;
  --custom-7: #5cc9a8;

  /* Favorite/Taught corner flags (see draw()'s per-block flag pass).
     Favorite reuses --lds-accent directly (already "starred" in the talk
     modal, no reason for a second gold). Taught is a fresh emerald,
     picked to sit clearly apart from --role-apostle's cooler teal and
     --conf-april's much lighter pastel green -- distinct hue, not just a
     distinct shade of one already in use. */
  --taught: #4fae7a;
}

/* Fill the real viewport, no page scroll -- overrides lds.css's own
   `body { min-height: 100vh; }` (same-selector cascade, this file loads
   after lds.css). Matches boom/style.css's exact body rule so the map
   grows to use the actual window instead of sitting at a fixed block size
   with dead space below it. */
body {
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.talkr-nav-title {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--lds-text-dim);
  margin-left: 0.5rem;
  flex: 1;
}

/* Map / All Talks -- the only two views this single page switches
   between (see setView() in script.js); toolbar/legend/highlight/speaker
   controls stay in the DOM either way but hide themselves when they
   wouldn't do anything (nothing to highlight without the map showing),
   same principle tools/study's own render() already applies to its
   map-only role-filter toolbar. */
.talkr-view-tabs { display: flex; gap: 0.3rem; margin-right: 1rem; }
.talkr-view-tab {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.7rem;
  border-radius: 4px;
  border: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-view-tab:hover { border-color: var(--lds-accent-dim); color: var(--lds-text); }
.talkr-view-tab.on { background: color-mix(in srgb, var(--lds-accent) 18%, transparent); border-color: var(--lds-accent); color: var(--lds-accent); }

.talkr-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 1.2rem;
  background: var(--lds-surface);
  border-bottom: 1px solid var(--lds-border);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  color: var(--lds-text-dim);
}
.talkr-count { color: var(--lds-accent); }

/* Backup/Restore -- localStorage is the *only* copy of a visitor's marks/
   favorites/notes (by design, see the plan doc's persistence decision),
   which means a cleared cache or a new device loses everything with zero
   recovery path. Same JSON-backup shape as tools/study's own exportJson()/
   handleImportFile(), simplified for talkr's single `progress` store (no
   playlists yet). Small, quiet toolbar buttons -- this is a safety net,
   not something that needs to compete for attention with the map itself. */
.talkr-data-actions { display: flex; align-items: center; gap: 0.35rem; }
.talkr-data-btn {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  padding: 0.25rem 0.55rem;
  border-radius: 4px;
  border: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-data-btn:hover { border-color: var(--lds-accent-dim); color: var(--lds-text); }

/* Legend for the map's three *default* colored squares (talk block,
   April marker, October marker) -- everything else (level shading, role
   rings, Prophet tint) is a state change a visitor causes themselves and
   reads fine from the toolbar controls that trigger it, but the three
   colors present on first load with no interaction had nothing
   explaining them. Small and quiet on purpose, same visual weight as
   .talkr-hint right next to it, not a competing focal point. */
.talkr-legend {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.03em;
  color: var(--lds-text-dim);
}
.talkr-legend-item { display: inline-flex; align-items: center; gap: 0.3rem; }
.talkr-swatch {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 2px;
  display: inline-block;
}
.talkr-swatch-april { background: var(--conf-april); }
.talkr-swatch-october { background: var(--conf-october); }
.talkr-swatch-favorite { background: var(--lds-accent); }
.talkr-swatch-taught { background: var(--taught); }
/* Fallback only -- draw() in script.js sets the real value inline once
   the map first renders, computed from the exact same mixHex() call
   that colors Prophet talks on the map itself, so the legend can never
   drift out of sync with what's actually drawn. This is just what shows
   for the instant before that first draw. */
#legendSwatchProphet { background: #3e577a; }

/* Role highlight toggles -- default state is deliberately quiet (dim
   border, dim text, transparent background), same "calm unless asked"
   instinct as the map itself now follows. Matches tools/study's own
   .map-filter-btn treatment (see wireRoleFilterToolbar there) rather than
   inventing new interaction language for the same concept -- same labels
   too ("A Prophet's Voice", "Apostle Talks", etc.), so anyone who's used
   that tool recognizes this immediately. */
.talkr-highlight {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.talkr-highlight-label { color: var(--lds-text-dim); }
.talkr-filter-btn {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  padding: 0.25rem 0.55rem;
  border-radius: 4px;
  border: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-filter-btn:hover { border-color: var(--lds-accent-dim); }
.talkr-filter-btn.on[data-role="prophet"] { background: color-mix(in srgb, var(--role-prophet) 18%, transparent); border-color: var(--role-prophet); color: var(--role-prophet); }
.talkr-filter-btn.on[data-role="apostle"] { background: color-mix(in srgb, var(--role-apostle) 18%, transparent); border-color: var(--role-apostle); color: var(--role-apostle); }
.talkr-filter-btn.on[data-role="firstpresidency"] { background: color-mix(in srgb, var(--role-firstpresidency) 18%, transparent); border-color: var(--role-firstpresidency); color: var(--role-firstpresidency); }
.talkr-filter-btn.on[data-role="woman"] { background: color-mix(in srgb, var(--role-woman) 18%, transparent); border-color: var(--role-woman); color: var(--role-woman); }

/* Custom-speaker row -- its own toolbar-like strip below the main
   toolbar rather than crammed into it, since up to 8 chips plus the
   "+ Add Speaker" button is real width the hint/legend/highlight/count
   cluster doesn't have room to spare. See renderCustomSpeakerSlots()/
   openSpeakerPicker() in script.js. */
.talkr-speaker-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.4rem 1.2rem;
  background: var(--lds-surface);
  border-bottom: 1px solid var(--lds-border);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--lds-text-dim);
}
.talkr-custom-speakers { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.talkr-custom-speaker-chip { display: inline-flex; align-items: center; gap: 0.15rem; }
/* Slot color drives both the chip's own accent and the map ring drawn
   for that speaker (see draw()'s custom-speaker ring pass) -- one
   source of truth, --custom-N, read by both CSS (here) and JS
   (themeColor('--custom-N')) so they can never drift apart. */
.talkr-custom-speaker-btn {
  font-family: var(--font-body);
  font-size: 0.72rem;
  padding: 0.25rem 0.55rem;
  border-radius: 4px 0 0 4px;
  border: 1px solid var(--lds-border-mid);
  border-right: none;
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.talkr-custom-speaker-btn:hover { color: var(--lds-text); }
.talkr-custom-speaker-btn.on[data-slot="0"] { background: color-mix(in srgb, var(--custom-0) 20%, transparent); border-color: var(--custom-0); color: var(--custom-0); }
.talkr-custom-speaker-btn.on[data-slot="1"] { background: color-mix(in srgb, var(--custom-1) 20%, transparent); border-color: var(--custom-1); color: var(--custom-1); }
.talkr-custom-speaker-btn.on[data-slot="2"] { background: color-mix(in srgb, var(--custom-2) 20%, transparent); border-color: var(--custom-2); color: var(--custom-2); }
.talkr-custom-speaker-btn.on[data-slot="3"] { background: color-mix(in srgb, var(--custom-3) 20%, transparent); border-color: var(--custom-3); color: var(--custom-3); }
.talkr-custom-speaker-btn.on[data-slot="4"] { background: color-mix(in srgb, var(--custom-4) 20%, transparent); border-color: var(--custom-4); color: var(--custom-4); }
.talkr-custom-speaker-btn.on[data-slot="5"] { background: color-mix(in srgb, var(--custom-5) 20%, transparent); border-color: var(--custom-5); color: var(--custom-5); }
.talkr-custom-speaker-btn.on[data-slot="6"] { background: color-mix(in srgb, var(--custom-6) 20%, transparent); border-color: var(--custom-6); color: var(--custom-6); }
.talkr-custom-speaker-btn.on[data-slot="7"] { background: color-mix(in srgb, var(--custom-7) 20%, transparent); border-color: var(--custom-7); color: var(--custom-7); }
/* Off (paused, not removed) still shows a dim ring of its own slot color
   as a border, so a temporarily-hidden speaker doesn't visually vanish
   from the chip row -- same "you can tell it's still reserved" cue
   tools/study's own inactive chip gives via a dimmer border. */
.talkr-custom-speaker-btn:not(.on)[data-slot="0"] { border-color: color-mix(in srgb, var(--custom-0) 45%, var(--lds-border-mid)); }
.talkr-custom-speaker-btn:not(.on)[data-slot="1"] { border-color: color-mix(in srgb, var(--custom-1) 45%, var(--lds-border-mid)); }
.talkr-custom-speaker-btn:not(.on)[data-slot="2"] { border-color: color-mix(in srgb, var(--custom-2) 45%, var(--lds-border-mid)); }
.talkr-custom-speaker-btn:not(.on)[data-slot="3"] { border-color: color-mix(in srgb, var(--custom-3) 45%, var(--lds-border-mid)); }
.talkr-custom-speaker-btn:not(.on)[data-slot="4"] { border-color: color-mix(in srgb, var(--custom-4) 45%, var(--lds-border-mid)); }
.talkr-custom-speaker-btn:not(.on)[data-slot="5"] { border-color: color-mix(in srgb, var(--custom-5) 45%, var(--lds-border-mid)); }
.talkr-custom-speaker-btn:not(.on)[data-slot="6"] { border-color: color-mix(in srgb, var(--custom-6) 45%, var(--lds-border-mid)); }
.talkr-custom-speaker-btn:not(.on)[data-slot="7"] { border-color: color-mix(in srgb, var(--custom-7) 45%, var(--lds-border-mid)); }

.talkr-custom-speaker-remove {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  padding: 0.25rem 0.4rem;
  border-radius: 0 4px 4px 0;
  border: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-custom-speaker-remove:hover { border-color: #d68a8a; color: #d68a8a; }

.talkr-add-speaker-btn {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.03em;
  padding: 0.25rem 0.55rem;
  border-radius: 4px;
  border: 1px dashed var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-add-speaker-btn:hover { border-color: var(--lds-accent-dim); color: var(--lds-text); }
.talkr-max-speakers-note { font-style: italic; opacity: 0.75; }

/* Speaker picker -- a compact floating panel anchored under the
   "+ Add Speaker" button (position:fixed, JS-positioned, same idea as
   the map's own hover tooltip), not a full centered modal -- this is a
   quick add-one-and-go action, not a destination. Sorted by talk count
   by default (see script.js's speakersByCount) with a live filter box,
   same tools/study convention: "scrolling past 500+ names to find
   someone is exactly the problem count-sorting solves; the filter box
   then covers the opposite case (you know the name, don't want to
   scroll)." */
.talkr-speaker-picker {
  position: fixed;
  z-index: 500;
  width: 260px;
  max-height: 340px;
  display: flex;
  flex-direction: column;
  background: rgba(5, 14, 30, 0.98);
  border: 1px solid var(--lds-border-mid);
  border-radius: 6px;
  box-shadow: 0 6px 28px rgba(0, 0, 0, 0.65);
  overflow: hidden;
}
.talkr-speaker-picker.hidden { display: none; }
.talkr-speaker-picker-search {
  margin: 0.5rem 0.5rem 0.35rem;
  padding: 0.4rem 0.55rem;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--lds-border-mid);
  border-radius: 4px;
  color: var(--lds-text);
  font-family: var(--font-body);
  font-size: 0.82rem;
}
.talkr-speaker-picker-search:focus { outline: none; border-color: var(--lds-blue-light); }
.talkr-speaker-picker-list { overflow-y: auto; padding-bottom: 0.4rem; }
.talkr-speaker-picker-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--lds-text);
}
.talkr-speaker-picker-item:hover { background: rgba(255, 255, 255, 0.06); }
.talkr-speaker-picker-item span:first-child { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.talkr-speaker-picker-item .count { font-size: 0.68rem; color: var(--lds-text-dim); font-family: var(--font-mono); }
.talkr-speaker-picker-empty { padding: 0.6rem 0.75rem; font-size: 0.8rem; color: var(--lds-text-dim); font-style: italic; }


.talkr-layout {
  flex: 1; /* fills whatever's left below .lds-nav/.talkr-toolbar/.talkr-footer exactly, no magic-number calc(100vh - Npx) needed -- same trick boom/style.css's .boom-layout uses */
  min-height: 0; /* lets a flex child shrink below its content size, or overflow-y below never gets a chance to kick in */
  overflow-y: auto; /* fallback only -- the auto-fit block-size search in script.js should make this rarely/never actually engage */
  overflow-x: hidden;
}

/* All Talks -- the flat list view (see setView()/renderAllTalksView() in
   script.js). Same flex:1/min-height:0 fill as .talkr-layout, but its
   own internal scroll lives on .talkr-all-list specifically (below the
   fixed search/sort bar) rather than the whole view, so the controls
   stay pinned while the list scrolls under them. */
.talkr-all-view {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--lds-bg);
}
.talkr-all-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 0.6rem 1.2rem;
  border-bottom: 1px solid var(--lds-border);
  background: var(--lds-surface);
}
.talkr-all-search {
  flex: 1 1 240px;
  max-width: 360px;
  padding: 0.4rem 0.65rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--lds-border-mid);
  border-radius: 5px;
  color: var(--lds-text);
  font-family: var(--font-body);
  font-size: 0.85rem;
}
.talkr-all-search:focus { outline: none; border-color: var(--lds-blue-light); }
.talkr-all-sort { display: flex; gap: 0.3rem; }
.talkr-sort-btn {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.6rem;
  border-radius: 4px;
  border: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-sort-btn:hover { border-color: var(--lds-accent-dim); color: var(--lds-text); }
.talkr-sort-btn.on { background: color-mix(in srgb, var(--lds-accent) 18%, transparent); border-color: var(--lds-accent); color: var(--lds-accent); }
.talkr-all-count { margin-left: auto; color: var(--lds-accent); font-family: var(--font-mono); font-size: 0.68rem; }
.talkr-all-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  max-width: 920px;
  width: 100%;
  margin: 0 auto;
  padding: 0 1.2rem;
}

/* Playlists -- data model + creation UI only this pass (sharing is a
   separate later pass, see script.js's big comment). Chip row reuses
   .talkr-custom-speaker-chip/-btn/-remove and .talkr-add-speaker-btn
   verbatim (same "pick or create, small pill, X to remove" shape
   already proven for custom speakers) rather than a second copy. */
.talkr-playlists-view {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--lds-bg);
}
.talkr-playlists-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0.6rem 1.2rem;
  border-bottom: 1px solid var(--lds-border);
  background: var(--lds-surface);
}
.talkr-playlist-chip-count { font-size: 0.62rem; opacity: 0.75; }
.talkr-playlist-detail {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  max-width: 760px;
  width: 100%;
  margin: 0 auto;
  padding: 0 1.2rem;
}
.talkr-playlist-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1rem 0.3rem 0.5rem;
}
.talkr-playlist-rename-input {
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border: none;
  border-bottom: 1px dashed var(--lds-border-mid);
  color: var(--lds-accent);
  font-family: var(--font-mono);
  font-size: 1rem;
  font-weight: 700;
  padding: 0.15rem 0;
}
.talkr-playlist-rename-input:focus { outline: none; border-bottom-color: var(--lds-blue-light); }
/* Same visual weight as the rename input, minus the "you can edit this"
   affordance -- a provided/default playlist's name isn't yours to
   change. See renderPlaylistsView()'s `info.isDefault` branch. */
.talkr-playlist-detail-title {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  color: var(--lds-accent);
  font-family: var(--font-mono);
  font-size: 1rem;
}
.talkr-playlist-empty { padding: 1rem 0.3rem; color: var(--lds-text-dim); font-style: italic; font-size: 0.85rem; }

/* Shared-playlist banner (?t=/?p= link) -- deliberately visually distinct
   from the visitor's own playlists below it (amber-bordered box, not
   just another row) since it's a different kind of thing: read-only
   until explicitly saved. See renderSharedPlaylistBanner() in script.js. */
.talkr-shared-playlist-banner {
  max-width: 760px;
  width: 100%;
  margin: 0.75rem auto 0;
  padding: 0 1.2rem;
}
.talkr-shared-playlist-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.9rem 1rem;
  border: 1px solid var(--lds-accent-dim);
  border-radius: 6px;
  background: color-mix(in srgb, var(--lds-accent) 8%, transparent);
  margin-bottom: 0.5rem;
}
.talkr-shared-playlist-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--lds-text-dim);
}
.talkr-shared-playlist-name { margin: 0.15rem 0 0.25rem; color: var(--lds-accent); }
.talkr-shared-playlist-actions { display: flex; gap: 0.5rem; flex-shrink: 0; }
.talkr-playlist-share-btn { margin-left: auto; }
/* Lighter than a full talkr-conf-row on purpose -- no R/L/W/T/Fav/Notes,
   just what a playlist actually needs: order and membership. Reuses
   .talkr-conf-row-title/-title-btn/-meta and .talkr-conf-status-btn/
   -fav-btn for the move/remove buttons rather than inventing new ones. */
.talkr-playlist-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  border-bottom: 1px solid var(--lds-border);
  padding: 0.5rem 0.3rem;
}
.talkr-playlist-row-main { flex: 1 1 auto; min-width: 0; }
.talkr-playlist-row-controls { display: flex; align-items: center; gap: 0.2rem; flex: 0 0 auto; }

/* Add-to-playlist popup contents (the shell itself reuses
   .talkr-speaker-picker -- see getOrCreatePlaylistMenu() in script.js). */
.talkr-playlist-menu-list { max-height: 240px; overflow-y: auto; }
.talkr-playlist-menu-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--lds-text);
}
.talkr-playlist-menu-item:hover { background: rgba(255, 255, 255, 0.06); }
.talkr-playlist-menu-item span:first-of-type { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.talkr-playlist-menu-item .count { font-size: 0.68rem; color: var(--lds-text-dim); font-family: var(--font-mono); }
.talkr-playlist-menu-new {
  display: flex;
  gap: 0.4rem;
  padding: 0.5rem;
  border-top: 1px solid var(--lds-border-mid);
}
.talkr-playlist-menu-new .talkr-speaker-picker-search { flex: 1 1 auto; margin: 0; }

/* Footer reuses callings/lds.css's shared .lds-footer (same blurb/suite/
   home-link structure as talk/ and conf/'s footers) but tighter -- the
   default 2rem padding + 3 full lines is sized for a scrolling prose page,
   not a fixed-height flex sibling stealing room from the map above it.
   flex-shrink: 0 (not the default 1) so it always keeps its full natural
   height -- computeLayout() in script.js just reads canvasView's real
   remaining space each time, so the map's auto-fit block size adapts to
   whatever room is actually left automatically, no coordination needed. */
.talkr-footer {
  flex-shrink: 0;
  padding: 0.6rem 1.2rem;
  font-size: 0.6rem;
}
.talkr-footer .lds-footer-blurb { margin-bottom: 0.35rem; }
.talkr-footer .lds-footer-suite { margin-bottom: 0.25rem; }

.talkr-canvas-view {
  position: relative;
  height: 100%; /* not min-height:100% -- script.js reads canvasView.clientHeight as the real auto-fit budget, so this needs to be an exact, reliable number, not a floor */
  padding: 0; /* deliberately 0, matching boom/style.css's .boom-canvas-view -- keeps clientWidth/clientHeight == canvas size with no padding-math needed in script.js; breathing room is drawn as an offset inside the canvas coordinate system instead */
  /* Opaque flat background -- boom/style.css's own .boom-canvas-view already
     does this (background: #0a1e38) and talkr should have from the start.
     Without it, the ~1px gaps between blocks (and the empty space around
     labels) show lds.css's page-wide `body` radial-gradient bleeding
     through, which shifts brightness across the page -- confirmed as
     exactly what Ian was seeing ("General Conference years appearing in
     different shades and colors in spots"), not a perception thing. */
  background: var(--lds-bg);
}

#talkrCanvas {
  display: block;
  cursor: pointer;
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
}

/* Loading state -- same structure as boom/style.css's .boom-loading, kept
   as its own copy rather than promoted to a shared lds.css rule since only
   two tools use it so far; worth promoting later if a third tool wants it. */
.talkr-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 60vh;
  gap: 1rem;
}
.talkr-spinner {
  width: 32px;
  height: 32px;
  border: 2px solid var(--lds-border-mid);
  border-top-color: var(--lds-accent);
  border-radius: 50%;
  animation: talkr-spin 0.8s linear infinite;
}
@keyframes talkr-spin { to { transform: rotate(360deg); } }

/* Hover tooltip -- same shape as boom/style.css's .boom-verse-tip, own copy
   for the same reason as .talkr-loading above. */
.talkr-tip {
  position: fixed;
  z-index: 500;
  background: rgba(5, 14, 30, 0.97);
  border: 1px solid var(--lds-border-mid);
  border-radius: 5px;
  padding: 0.55rem 0.85rem 0.65rem;
  max-width: 340px; /* narrower than before on purpose -- the excerpt line reads better wrapped to a few short lines than stretched wide */
  min-width: 200px;
  box-shadow: 0 6px 28px rgba(0, 0, 0, 0.65);
  pointer-events: none;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--lds-text);
}
.talkr-tip-title { display: block; font-weight: 700; margin-bottom: 0.15rem; }
.talkr-tip-meta {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--lds-text-dim);
}
.talkr-tip-meta .role { color: var(--lds-accent); }
.talkr-tip-excerpt {
  display: block;
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--lds-border);
  font-size: 0.76rem;
  font-style: italic;
  color: var(--lds-text-dim);
  line-height: 1.55;
}

.hidden { display: none !important; }

/* Talk detail panel -- reuses callings/lds.css's shared .lds-modal-overlay/
   .lds-modal (same password-modal component every page with one already
   gets for free) rather than inventing new modal chrome, just widened via
   .talkr-modal since this needs room for a title, speaker/role, three
   status buttons, and a notes textarea, not a single password field. */
.talkr-modal {
  position: relative;
  max-width: 480px;
}
.talkr-modal-close {
  position: absolute;
  top: 0.75rem;
  right: 0.85rem;
  background: none;
  border: none;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-modal-close:hover { color: var(--lds-text); }
.talkr-modal-meta {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--lds-text-dim);
  margin-bottom: 0.5rem;
}
.talkr-modal .lds-modal > h3 { margin-bottom: 0.25rem; } /* lds-modal's own h3 rule already sets most of this -- see lds.css */
.talkr-modal-speaker { font-size: 0.85rem; color: var(--lds-text); margin-bottom: 1rem; }
.talkr-modal-speaker .role { color: var(--lds-text-dim); font-style: italic; }

/* Editorial summary + opening-paragraph preview -- see openTalkModal()/
   sync-corpus.js's extractSummary()/extractPreview(). Summary reads as a
   pull-quote (left accent border, larger italic text, same visual weight
   the Church's own kicker gets on their page); preview is plain body
   copy underneath it, clearly a second, lesser tier. */
.talkr-modal-summary {
  font-size: 0.95rem;
  font-style: italic;
  color: var(--lds-text);
  border-left: 2px solid var(--lds-accent);
  padding-left: 0.75rem;
  margin: 0 0 0.75rem;
  line-height: 1.6;
}
.talkr-modal-preview {
  font-size: 0.82rem;
  color: var(--lds-text-dim);
  line-height: 1.65;
  margin: 0 0 1rem;
}

/* Scaffolding for playlist/player, both explicitly not built yet (Phase 3
   for the player; playlists aren't scoped at all yet) -- real `disabled`
   buttons, not a fake-clickable no-op, so it's honest about what's
   actually there. Claims the layout space now so neither needs a redesign
   later when they do become real. */
.talkr-modal-actions { display: flex; gap: 0.5rem; margin-bottom: 0.85rem; }
/* Real and clickable, deliberately styled apart from the still-scaffolded
   dashed buttons next to it (Playlist/Play) -- a solid border reads as
   "this one actually works" at a glance, honest in both directions.
   Builds a link with ONLY ?talk=<id> (see wireTalkModal()'s share
   handler in script.js) -- not the sender's own current view/search/sort
   state, which has nothing to do with "look at this talk." */
.talkr-share-btn {
  font-family: var(--font-body);
  font-size: 0.78rem;
  padding: 0.4rem 0.85rem;
  border-radius: 5px;
  border: 1px solid var(--lds-border-mid);
  background: none;
  color: var(--lds-text);
  cursor: pointer;
}
.talkr-share-btn:hover { border-color: var(--lds-blue-light); color: var(--lds-blue-light); }
.talkr-share-btn.copied { border-color: var(--lds-accent); color: var(--lds-accent); }
.talkr-modal-controls { display: flex; gap: 0.4rem; margin-bottom: 0.85rem; }
.talkr-status-btn {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  padding: 0.35rem 0.9rem;
  border-radius: 5px;
  border: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-status-btn:hover { border-color: var(--lds-accent-dim); }
.talkr-status-btn.on { background: color-mix(in srgb, var(--lds-accent) 18%, transparent); border-color: var(--lds-accent); color: var(--lds-accent); }
.talkr-fav-btn {
  margin-left: auto; /* pushes the star to the far right of the controls row, same "set apart from the R/L/W/T group" visual tools/study's fav-btn gets */
  background: none;
  border: none;
  font-size: 1.15rem;
  line-height: 1;
  color: var(--lds-border-mid);
  cursor: pointer;
}
.talkr-fav-btn.on { color: var(--lds-accent); } /* reuses the existing amber accent -- stars are conventionally gold anyway, no need for a new token */
.talkr-modal-notes {
  width: 100%;
  min-height: 4.5rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--lds-border-mid);
  border-radius: 4px;
  color: var(--lds-text);
  font-family: var(--font-body);
  font-size: 0.85rem;
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.85rem;
  resize: vertical;
}
.talkr-modal-notes:focus { outline: none; border-color: var(--lds-blue-light); }
.talkr-modal-link { display: inline-block; font-size: 0.8rem; }

/* Conference-list panel -- opens on clicking a year marker (see
   openConfModal()/markerAtPixel() in script.js). Reuses the same shared
   .lds-modal-overlay/.lds-modal shell as the talk detail panel, just
   wider and with its own scrollable list instead of a single talk's
   fields.
   Single column, not two -- two columns raised a real "which direction
   is chronological, rows or columns?" question (it was rows, via CSS
   Grid auto-placement, but that's not obvious at a glance), and one
   column leaves real room for inline R/L/W/T/Favorite/Notes controls
   per row -- see openConfModal()'s big comment in script.js. */
.talkr-conf-modal {
  max-width: 620px;
}
.talkr-conf-list {
  max-height: 66vh;
  overflow-y: auto;
  margin-top: 0.25rem;
}
.talkr-conf-row {
  border-bottom: 1px solid var(--lds-border);
  padding: 0.45rem 0.3rem;
}
.talkr-conf-row:hover { background: rgba(255, 255, 255, 0.04); }
/* Its own nowrap flex row, separate from .talkr-conf-row itself, so the
   controls group can never get pushed to a second line the way it could
   when the notes-box's flex-basis:100% trick shared the same flex
   container as main+controls (confirmed as a real, reproducible layout
   bug on a long-meta row, not a one-off). main still shrinks via
   min-width:0 and wraps its own text internally; controls stays put. */
.talkr-conf-row-top {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.4rem;
}
/* A plain div, not a button -- it holds two *separately* clickable
   pieces (the title button opens the talk, the speaker link filters All
   Talks to them), which can't nest inside one shared <button> in valid
   HTML. See renderTalkRowHtml() in script.js. */
.talkr-conf-row-main {
  display: block;
  flex: 1 1 auto;
  min-width: 0; /* lets title/meta actually wrap/ellipsize instead of forcing the row wider */
}
.talkr-conf-row-title-btn {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-body);
  color: var(--lds-text);
}
.talkr-conf-row-title { display: block; font-size: 0.84rem; line-height: 1.35; margin-bottom: 0.15rem; }
/* Full-text search hit that didn't also match title/speaker -- says
   *that* the word is in there, not *where* (the index only knows which
   talk, never which sentence, on purpose -- see script.js). */
.talkr-body-match-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.03em;
  color: var(--lds-text-dim);
  border: 1px solid var(--lds-border-mid);
  border-radius: 100px;
  padding: 0.05rem 0.4rem;
  margin-bottom: 0.15rem;
}
/* Search term highlight -- title/speaker (always) and, when one was
   found, a short snippet drawn only from the already-published excerpt
   preview (see script.js's extractPreviewSnippet()). */
mark.talkr-search-hit {
  background: color-mix(in srgb, var(--lds-accent) 35%, transparent);
  color: var(--lds-text);
  border-radius: 2px;
  padding: 0 0.05em;
}
.talkr-search-snippet {
  display: block;
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--lds-text-dim);
  font-style: italic;
  margin: 0.1rem 0 0.25rem;
}
.talkr-conf-row-date {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--lds-accent-dim);
  margin-bottom: 0.1rem;
}
.talkr-conf-row-meta {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--lds-text-dim);
}
.talkr-conf-row-meta .role { color: var(--lds-accent); }
/* The speaker name itself -- a real link to "all talks by them" (see
   filterAllTalksBySpeaker() in script.js), styled to read as text first,
   link second (no underline until hover) since it sits inline with the
   role text right after it and shouldn't look like a stray blue link. */
.talkr-speaker-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}
.talkr-speaker-link:hover { color: var(--lds-blue-light); text-decoration: underline; }
.talkr-conf-session-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--lds-accent);
  padding: 0.7rem 0.3rem 0.3rem;
  border-bottom: 1px solid var(--lds-border-mid);
}
.talkr-conf-session-header:first-child { padding-top: 0.1rem; }
/* Conference-level divider, All Talks list only (Date sort) -- one level
   above the session header, bolder/larger so the hierarchy reads at a
   glance (conference > session > talk). See groupByConfAndSession()/
   renderAllTalksView() in script.js. */
.talkr-all-conf-header {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--lds-accent);
  padding: 1.1rem 0.3rem 0.35rem;
  border-bottom: 2px solid var(--lds-accent-dim);
}
.talkr-all-conf-header:first-child { padding-top: 0.25rem; }

/* Mark-all groups -- ported from tools/study's own mark-batch-buttons,
   same "R L W T" letter set as the per-row controls but a visually
   distinct pill (outlined group, not individual buttons) so "mark this
   whole scope" doesn't get mistaken for one more row's own status
   toggles. Two scopes reuse the identical markup/behavior: the whole
   conference (.talkr-conf-batch-row, under the title) and each session
   (inline in its header) -- see renderMarkBatchGroup() in script.js. */
.talkr-conf-batch-row { margin: 0.35rem 0 0.15rem; }
.talkr-mark-batch-group {
  display: inline-flex;
  border: 1px solid var(--lds-border-mid);
  border-radius: 5px;
  overflow: hidden;
}
.talkr-mark-batch-btn {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  width: 1.3rem;
  height: 1.3rem;
  line-height: 1.3rem;
  text-align: center;
  padding: 0;
  border: none;
  border-right: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-mark-batch-btn:last-child { border-right: none; }
.talkr-mark-batch-btn:hover { color: var(--lds-text); }
.talkr-mark-batch-btn.on { background: color-mix(in srgb, var(--lds-accent) 18%, transparent); color: var(--lds-accent); }
.talkr-conf-session-header .talkr-mark-batch-btn {
  width: 1.15rem;
  height: 1.15rem;
  line-height: 1.15rem;
  font-size: 0.56rem;
}

/* Inline controls -- same shape/labels as tools/study's own
   renderTalkRow() (single-letter status buttons, star favorite,
   speech-bubble notes toggle), just sized down for list density. */
.talkr-conf-row-controls { display: flex; align-items: center; gap: 0.2rem; flex: 0 0 auto; }
.talkr-conf-status-btn {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  width: 1.35rem;
  height: 1.35rem;
  line-height: 1.35rem;
  text-align: center;
  padding: 0;
  border-radius: 4px;
  border: 1px solid var(--lds-border-mid);
  background: transparent;
  color: var(--lds-text-dim);
  cursor: pointer;
}
.talkr-conf-status-btn:hover { border-color: var(--lds-accent-dim); }
.talkr-conf-status-btn.on { background: color-mix(in srgb, var(--lds-accent) 18%, transparent); border-color: var(--lds-accent); color: var(--lds-accent); }
.talkr-conf-fav-btn, .talkr-conf-notes-btn {
  background: none;
  border: none;
  font-size: 0.9rem;
  line-height: 1;
  padding: 0 0.15rem;
  color: var(--lds-border-mid);
  cursor: pointer;
}
.talkr-conf-fav-btn.on { color: var(--lds-accent); }
.talkr-conf-notes-btn.has-notes { color: var(--lds-blue-light); }
.talkr-conf-notes-btn:hover, .talkr-conf-fav-btn:hover { color: var(--lds-text); }
.talkr-conf-notes-box {
  flex-basis: 100%;
  margin-top: 0.3rem;
}
.talkr-conf-notes-box textarea {
  width: 100%;
  min-height: 3.2rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--lds-border-mid);
  border-radius: 4px;
  color: var(--lds-text);
  font-family: var(--font-body);
  font-size: 0.8rem;
  padding: 0.45rem 0.6rem;
  resize: vertical;
}
.talkr-conf-notes-box textarea:focus { outline: none; border-color: var(--lds-blue-light); }

/* ── Progress view ── stat-card grid + by-decade breakdown, see
   renderProgressView(). Shape ported from tools/study's own equivalent,
   restyled with this file's tokens rather than tools/study's palette. */
.talkr-progress-view {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 1.5rem 2rem 3rem;
  background: var(--lds-bg);
}
.talkr-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}
.talkr-stat-card {
  background: var(--lds-surface);
  border: 1px solid var(--lds-border);
  border-radius: 8px;
  padding: 1rem 1.1rem;
  text-align: center;
}
.talkr-stat-num {
  font-family: var(--font-mono);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--lds-accent);
  line-height: 1.2;
}
.talkr-stat-label {
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--lds-text-dim);
  margin-top: 0.25rem;
}
.talkr-progress-bar {
  height: 0.35rem;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 100px;
  overflow: hidden;
  margin: 0.5rem 0 0.35rem;
}
.talkr-progress-bar-fill {
  height: 100%;
  background: var(--lds-blue-light);
}
.talkr-next-up-btn {
  display: block;
  width: 100%;
  max-width: 26rem;
  margin: 0 auto 2rem;
  background: none;
  border: 1px solid var(--lds-border-mid);
  border-radius: 6px;
  color: var(--lds-text);
  font-family: var(--font-body);
  font-size: 0.85rem;
  padding: 0.7rem 1rem;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.talkr-next-up-btn:hover:not(:disabled) { border-color: var(--lds-accent-dim); color: var(--lds-accent); }
.talkr-next-up-btn:disabled { color: var(--lds-text-dim); cursor: default; opacity: 0.7; }
.talkr-progress-subhead {
  font-size: 0.9rem;
  color: var(--lds-text-dim);
  font-weight: 600;
  margin-bottom: 0.75rem;
}

/* ── Persistent mini-player / queue ── one real <video> (script.js's
   stagePlayer), reparented between .talkModalPlayerSlot (large, native
   controls, while the modal's open on the talk that's playing) and
   .talkr-stage's own slot (small, custom transport) otherwise. Direct
   .mp4/.mp3 URLs from assets.churchofjesuschrist.org -- an audio-only file
   in a <video> element just renders as a compact audio bar, same
   one-element-handles-both approach tools/study's own player proved out. */
.talkr-modal-player-wrap { margin: 0.85rem 0; }
.talkr-modal-player-slot video {
  width: 100%;
  border-radius: 6px;
  background: #000;
  max-height: 22rem;
  display: block;
}
.talkr-modal-transport {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.5rem;
}
.talkr-queue-status {
  font-size: 0.72rem;
  color: var(--lds-text-dim);
  font-family: var(--font-mono);
}

.talkr-stage-transport {
  font-size: 0.95rem;
  background: none;
  border: 1px solid var(--lds-border-mid);
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  flex-shrink: 0;
  color: var(--lds-text);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.talkr-stage-transport:hover:not(:disabled) { border-color: var(--lds-accent-dim); color: var(--lds-accent); }
.talkr-stage-transport:disabled { opacity: 0.35; cursor: default; }
.talkr-stage-playpause { font-size: 0.85rem; }

/* Fixed bottom bar -- lives outside every view/modal in the HTML on
   purpose (see index.html's comment), so it's never touched by a view
   switch or a modal close. Only ever shown while a talk is loaded and the
   talk modal isn't currently showing that exact talk (see
   refreshStageDocking()). */
.talkr-stage {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 45;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.5rem 1rem;
  background: var(--lds-surface-2);
  border-top: 1px solid var(--lds-border-mid);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.35);
}
.talkr-stage-video-slot {
  width: 3.2rem;
  height: 2.4rem;
  flex-shrink: 0;
  border-radius: 4px;
  overflow: hidden;
  background: #000;
}
.talkr-stage-video-slot video { width: 100%; height: 100%; object-fit: cover; display: block; }
.talkr-stage-restore {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  flex: 1 1 auto;
  min-width: 0;
  cursor: pointer;
  border-radius: 4px;
  padding: 0.15rem 0.3rem;
  margin: -0.15rem -0.3rem;
  transition: background 0.15s;
}
.talkr-stage-restore:hover, .talkr-stage-restore:focus-visible { background: rgba(255, 255, 255, 0.06); outline: none; }
.talkr-stage-info { flex: 1 1 auto; min-width: 0; }
.talkr-stage-title {
  font-size: 0.85rem;
  color: var(--lds-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.talkr-stage-seek {
  height: 4px;
  border-radius: 3px;
  background: var(--lds-border-mid);
  margin-top: 0.35rem;
  cursor: pointer;
}
.talkr-stage-seek-fill { height: 100%; border-radius: 3px; background: var(--lds-accent); width: 0%; }
.talkr-stage-fav, .talkr-stage-close {
  background: none;
  border: none;
  color: var(--lds-text-dim);
  font-size: 1.1rem;
  cursor: pointer;
  flex-shrink: 0;
  transition: color 0.15s;
}
.talkr-stage-pip {
  background: none;
  border: 1px solid var(--lds-border-mid);
  border-radius: 5px;
  color: var(--lds-text-dim);
  font-family: var(--font-body);
  font-size: 0.9rem;
  padding: 0.3rem 0.5rem;
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color 0.15s, color 0.15s;
}
.talkr-stage-pip:hover { border-color: var(--lds-accent-dim); color: var(--lds-accent); }
.talkr-stage-pip.on { border-color: var(--lds-accent); color: var(--lds-accent); }
#talkModalPip { font-size: 0.78rem; margin-left: auto; }
.talkr-stage-fav:hover, .talkr-stage-close:hover { color: var(--lds-accent); }
.talkr-stage-fav.on { color: var(--lds-accent); }
.talkr-stage-close { font-size: 1.3rem; }

/* Queue-start buttons -- reused verbatim across All Talks, the conference
   modal, and playlist detail (all just hand startQueue() a talk array). */
.talkr-play-list-btn {
  font-family: var(--font-body);
  font-size: 0.78rem;
  padding: 0.35rem 0.8rem;
  border-radius: 100px;
  border: 1px solid var(--lds-border-mid);
  background: none;
  color: var(--lds-text);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.talkr-play-list-btn:hover { border-color: var(--lds-accent-dim); color: var(--lds-accent); }

/* Room so the fixed mini-bar doesn't cover the last row of a scrollable
   view. The Map's canvas isn't included here on purpose -- its height is
   computed in JS from the real viewport, not CSS padding, so padding
   alone wouldn't be respected there; left as a known minor overlap for
   this pass rather than threading stage-bar height into computeLayout(). */
body.talkr-stage-active .talkr-all-view,
body.talkr-stage-active .talkr-playlists-view,
body.talkr-stage-active .talkr-progress-view {
  padding-bottom: 4.5rem;
}

@media (max-width: 700px) {
  .talkr-stage-title { max-width: 8rem; }
  .talkr-nav-title { display: none; } /* same breakpoint boom/style.css hides its nav title at */
  .talkr-toolbar { font-size: 0.6rem; flex-wrap: wrap; }
}
