/* ── RabbitHole: immersive horizontal canvas ── */

.rabbit-hole-shell {
  --pane-width: 540px;
  display: flex;
  flex-direction: column;
  height: 100dvh;
  container-type: inline-size;
}

.rabbit-hole-toolbar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 1rem;
  background: var(--bs-tertiary-bg);
  border-bottom: var(--bs-border-width) solid var(--bs-border-color);
}

.rabbit-hole-toolbar-heading {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-width: 0;
}

.rabbit-hole-toolbar-title {
  font-size: 1rem;
  font-weight: 600;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rabbit-hole-toolbar-actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.rabbit-hole-exit kbd,
.rabbit-hole-minimap-label kbd {
  margin-left: 0.5rem;
  padding: 0.1rem 0.35rem;
  font-size: 0.7em;
  color: inherit;
  background: transparent;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.25rem;
  text-transform: none;
}

.rabbit-hole-scroll-container {
  flex: 1 1 0;
  min-height: 0;
  overflow-x: auto;
  overflow-y: hidden;
  /* Depth pressure: --rabbit-hole-depth (set on the shell as the centered
     pane changes) tints the backdrop further down a branch chain */
  background-color: color-mix(in srgb, var(--depth-tint) calc(min(var(--rabbit-hole-depth, 0), 6) * 9%), transparent);
  transition: background-color 0.8s ease;
  scroll-behavior: auto; /* JS manages smooth scrolling */
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  /* The mini-map strip below doubles as the scrollbar */
  scrollbar-width: none;
}

.rabbit-hole-scroll-container::-webkit-scrollbar {
  display: none;
}

.rabbit-hole-panes {
  display: flex;
  gap: 1rem;
  height: 100%;
  min-width: 100%;
  width: max-content;
  /* enough inline room for the first and last panes to snap to center */
  padding: 1rem max(1rem, calc(50vw - var(--pane-width) / 2));
}

/* Turbo appends nodes inside this target; display: contents lets the panes
   and the trailing frontier pane share one flex row */
.rabbit-hole-nodes {
  display: contents;
}

.rabbit-hole-pane {
  flex: 0 0 min(var(--pane-width), calc(100vw - 2rem));
  /* nowrap titles must truncate, not inflate the pane past its flex basis */
  min-width: 0;
  scroll-snap-align: center;
  animation: paneFadeIn 0.3s ease-out;
  transition: opacity 0.3s ease;
}

/* Reading focus: the centered pane is crisp, its neighbors recede until
   hovered or interacted with */
.rabbit-hole-pane:not(.is-current):not(:hover):not(:focus-within) {
  opacity: 0.55;
}

/* Off-center panes are previews: clicking anywhere on one centers it, so the
   whole pane advertises itself as a single target */
.rabbit-hole-pane:not(.is-current),
.rabbit-hole-pane:not(.is-current) :is(a, button, input, textarea) {
  cursor: pointer;
}

/* Content wrapper fills the pane so the card can size to 100% */
.rabbit-hole-pane-content {
  height: 100%;
}

/* Card fills the pane */
.rabbit-hole-pane .card {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.rabbit-hole-pane .card-body {
  /* Anchors the reading tick, which springs between stops in this pane */
  position: relative;
  overflow-y: auto;
  flex: 1 1 0;
  min-height: 0;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
  /* Bleed room for the reading tick: overflow-y clips sideways too, so pull
     the padding box out past the card's left edge to let the tick straddle
     it instead of being cut off at the prose gutter */
  --reading-tick-bleed: 1rem;
  margin-left: calc(-1 * var(--reading-tick-bleed));
  padding-left: calc(var(--bs-card-spacer-x) + var(--reading-tick-bleed));
}

/* Safari has no scrollbar-width/color; give it the same slim thumb */
.rabbit-hole-pane .card-body::-webkit-scrollbar {
  width: 6px;
}

.rabbit-hole-pane .card-body::-webkit-scrollbar-track {
  background: transparent;
}

.rabbit-hole-pane .card-body::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 999px;
}

.rabbit-hole-pane .card-body::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
}

/* Keyboard reading: the tick and glide are the wayfinding, so the scrollbar
   thumb steps aside. Transparent rather than removed: the gutter keeps its
   width and the prose never reflows. */
.rabbit-hole-pane .card-body.is-keyboard-reading {
  scrollbar-color: transparent transparent;
}

.rabbit-hole-pane .card-body.is-keyboard-reading::-webkit-scrollbar-thumb,
.rabbit-hole-pane .card-body.is-keyboard-reading::-webkit-scrollbar-thumb:hover {
  background: transparent;
}

.rabbit-hole-pane-title {
  overflow: hidden;
}

.rabbit-hole-pane-title h5,
.rabbit-hole-pane-title span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@keyframes paneFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .rabbit-hole-pane {
    animation: none;
  }
}

/* Reading focus highlight */
[data-reading-focus-target="container"] > turbo-frame > .card {
  transition: opacity 0.4s ease, box-shadow 0.4s ease, transform 0.4s ease;
}

[data-reading-focus-target="container"] > turbo-frame > .card.focus-current {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 20%, transparent),
              0 4px 16px color-mix(in srgb, var(--accent) 8%, transparent);
  transform: scale(1.01);
}

/* The frontier pane: last stop on the canvas, gathers open threads */
.rabbit-hole-frontier .card {
  border-style: dashed;
  background: transparent;
}

.rabbit-hole-frontier-body {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  text-align: center;
}

/* Center the stack when it's short without clipping it when it's tall:
   unlike justify-content: center, auto margins collapse to zero on overflow,
   so the title and ask form stay reachable at the top of the scrollport */
.rabbit-hole-frontier-body > :first-child {
  margin-top: auto;
}

.rabbit-hole-frontier-body > :last-child {
  margin-bottom: auto;
}

/* With no open threads the trailing area is hidden and its auto margin dies
   with it, so the ask form becomes the stack's bottom edge and takes over */
.rabbit-hole-frontier-body:has(> .rabbit-hole-frontier-threads:empty) > .rabbit-hole-frontier-prompt {
  margin-bottom: auto;
}

.rabbit-hole-frontier-title {
  font-size: 1.35rem;
  margin: 0;
}

.rabbit-hole-frontier-prompt {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.35rem 0.35rem 0.35rem 1.1rem;
}

.rabbit-hole-frontier-prompt:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}

.rabbit-hole-frontier-prompt input {
  flex: 1;
  min-width: 0;
  font: inherit;
  color: inherit;
  background: transparent;
  border: none;
}

.rabbit-hole-frontier-prompt input:focus {
  outline: none;
}

.rabbit-hole-frontier-prompt .btn {
  flex: none;
  width: 2.4rem;
  height: 2.4rem;
  padding: 0;
  display: grid;
  place-items: center;
}

.rabbit-hole-frontier-kicker {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0.5rem 0 -0.5rem;
  text-align: left;
}

/* No open threads: the whole area steps aside, kicker included */
.rabbit-hole-frontier-kicker:has(+ .rabbit-hole-frontier-threads:empty),
.rabbit-hole-frontier-threads:empty {
  display: none;
}

.rabbit-hole-frontier-threads {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  text-align: left;
}

/* One branch per row: icon disc, prompt with its hook beneath, chevron.
   The rows live at the bottom of each pane; the frontier clones them. */
.rabbit-hole-branches {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.branch-thread {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  text-align: left;
  color: inherit;
  text-decoration: none;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 0.8rem;
  padding: 0.55rem 0.8rem 0.55rem 0.55rem;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}

.branch-thread:hover,
.branch-thread:focus-visible {
  color: inherit;
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px var(--bs-border-color-translucent);
}

.branch-thread-icon {
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: 0.6rem;
  background: var(--wash);
  color: var(--accent-deep);
  display: grid;
  place-items: center;
  transition: background 0.18s ease, color 0.18s ease;
}

.branch-thread:hover .branch-thread-icon,
.branch-thread:focus-visible .branch-thread-icon {
  background: var(--accent);
  color: #fff;
}

.branch-btn-socratic .branch-thread-icon {
  background: var(--moss-wash);
  color: var(--moss);
}

.branch-btn-socratic:hover .branch-thread-icon,
.branch-btn-socratic:focus-visible .branch-thread-icon {
  background: var(--moss);
  color: #fff;
}

/* Already explored: the row jumps to its pane instead of generating one */
.branch-thread-taken .branch-thread-icon {
  background: color-mix(in srgb, var(--moss) 12%, transparent);
  color: var(--bs-success);
}

.branch-thread-taken:hover .branch-thread-icon,
.branch-thread-taken:focus-visible .branch-thread-icon {
  background: var(--bs-success);
  color: #fff;
}

/* Generation failed: the row still leads to its pane, which explains */
.branch-thread-failed .branch-thread-icon {
  background: color-mix(in srgb, var(--bs-warning) 12%, transparent);
  color: var(--bs-warning);
}

.branch-thread-failed:hover .branch-thread-icon,
.branch-thread-failed:focus-visible .branch-thread-icon {
  background: var(--bs-warning);
  color: #fff;
}

.branch-thread-main {
  flex: 1;
  min-width: 0;
}

.branch-thread-prompt {
  display: block;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.88rem;
  line-height: 1.3;
}

.branch-thread-hook {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.78rem;
  color: var(--muted);
  line-height: 1.35;
  margin-top: 0.1rem;
}

/* At the bottom of a narrative the prompts speak for themselves; hooks
   stay in the markup for the frontier's clones, where choosing needs them */
.rabbit-hole-branches .branch-thread-hook {
  display: none;
}

/* Numbered keycaps fade in once the reading cursor reaches the branch
   rows; they always keep their seat so nothing shifts when they appear */
.branch-thread-key {
  flex: none;
  padding: 0.1rem 0.4rem;
  font-size: 0.7rem;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.25rem;
  opacity: 0;
  transition: opacity 0.18s ease;
}

.rabbit-hole-branches:has(.is-reading) .branch-thread-key {
  opacity: 1;
}

.branch-thread-chevron {
  flex: none;
  font-size: 0.75rem;
  color: var(--muted);
  transition: transform 0.18s ease, color 0.18s ease;
}

.branch-thread:hover .branch-thread-chevron,
.branch-thread:focus-visible .branch-thread-chevron {
  transform: translateX(3px);
  color: var(--accent);
}

/* The mini-map: the whole rabbit hole in one strip along the bottom edge */
.rabbit-hole-minimap {
  /* Anchors the tree overlay, which expands from the strip's top edge */
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.4rem 1rem 0.55rem;
  background: var(--bs-tertiary-bg);
  border-top: var(--bs-border-width) solid var(--bs-border-color);
}

/* The label doubles as the tree-overlay toggle */
.rabbit-hole-minimap-label {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

.rabbit-hole-minimap-label:hover {
  color: var(--accent);
}

.rabbit-hole-minimap-label i {
  font-size: 0.6rem;
  transition: transform 0.25s ease;
}

.rabbit-hole-minimap-label[aria-expanded="true"] i {
  transform: rotate(180deg);
}

.rabbit-hole-minimap-scroll {
  flex: 1;
  min-width: 0;
  overflow-x: auto;
}

/* Scoped to the strip's scroller: the tree overlay svg inside the same
   footer sizes itself and must not inherit the strip's fixed height.
   Height matches MINIMAP_HEIGHT in the rabbit_hole controller */
.rabbit-hole-minimap-scroll svg {
  display: block;
  height: 64px;
}

/* The strip stays a flat spine: honest about sequence, quiet about
   structure; the tree overlay is where branching lives */
.rabbit-hole-minimap-spine {
  stroke: var(--line);
  stroke-width: 2;
}

/* Accent trail along the spine that tracks the canvas scroll position */
.rabbit-hole-minimap-progress {
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0.65;
}

.rabbit-hole-minimap svg.is-static .rabbit-hole-minimap-progress,
.rabbit-hole-minimap svg.is-static .rabbit-hole-minimap-track {
  display: none;
}

.rabbit-hole-minimap-stub {
  stroke: var(--line);
  stroke-width: 1.5;
  stroke-dasharray: 3 3;
}

.rabbit-hole-minimap-node {
  fill: var(--card);
  stroke: var(--accent);
  stroke-width: 2;
  cursor: pointer;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.18s ease, fill 0.25s ease, stroke 0.25s ease;
}

.rabbit-hole-minimap-node:hover,
.rabbit-hole-minimap-node.is-linked {
  transform: scale(1.3);
}

/* Bookmarked narratives carry their gold onto the map, current or not */
.rabbit-hole-minimap-node.is-bookmarked,
.rabbit-hole-minimap-stop.is-current .rabbit-hole-minimap-node.is-bookmarked {
  fill: var(--bs-warning, #ffc107);
  stroke: var(--bs-warning, #ffc107);
}

/* A stop whose narrative is still generating breathes until it lands */
.rabbit-hole-minimap-node.is-generating {
  animation: minimap-generating 1.5s ease-in-out infinite;
}

/* A dot that is both new and generating pops in, then starts breathing;
   without this the entrance animation (declared later) wins and the
   pulse never runs */
.rabbit-hole-minimap-node.is-entering.is-generating {
  animation: minimap-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) backwards,
             minimap-generating 1.5s ease-in-out 0.45s infinite;
}

@keyframes minimap-generating {
  50% { fill: var(--wash); stroke-opacity: 0.4; }
}

/* Off-center stops recede, mirroring the pane fade in the canvas above.
   Stubs and branch dots fade via opacity, but the pane dot recedes via a
   washed-out stroke over a fully opaque fill: group opacity would let the
   spine bleed through the circle */
.rabbit-hole-minimap-stop .rabbit-hole-minimap-stub,
.rabbit-hole-minimap-stop .rabbit-hole-minimap-open,
.rabbit-hole-minimap-stop .rabbit-hole-minimap-taken {
  opacity: 0.45;
  transition: opacity 0.25s ease;
}

.rabbit-hole-minimap-stop .rabbit-hole-minimap-node:not(.is-bookmarked) {
  stroke: color-mix(in srgb, var(--accent) 50%, var(--bs-tertiary-bg));
}

.rabbit-hole-minimap-stop:is(.is-current, .is-linked, :hover, :focus-within) .rabbit-hole-minimap-stub,
.rabbit-hole-minimap-stop:is(.is-current, .is-linked, :hover, :focus-within) .rabbit-hole-minimap-open,
.rabbit-hole-minimap-stop:is(.is-current, .is-linked, :hover, :focus-within) .rabbit-hole-minimap-taken {
  opacity: 1;
}

.rabbit-hole-minimap-stop:is(.is-current, .is-linked, :hover, :focus-within) .rabbit-hole-minimap-node:not(.is-bookmarked) {
  stroke: var(--accent);
}

.rabbit-hole-minimap-stop.is-current .rabbit-hole-minimap-node {
  fill: var(--accent);
}

/* Soft pulsing halo that glides along the spine to the centered pane */
.rabbit-hole-minimap-halo {
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s ease;
  pointer-events: none;
}

.rabbit-hole-minimap-halo circle {
  fill: var(--accent);
  opacity: 0.18;
  transform-box: fill-box;
  transform-origin: center;
  animation: minimap-halo-pulse 2.6s ease-in-out infinite;
}

@keyframes minimap-halo-pulse {
  0%, 100% { transform: scale(1); opacity: 0.18; }
  50% { transform: scale(1.35); opacity: 0.08; }
}

.rabbit-hole-minimap-open {
  fill: var(--paper);
  stroke: var(--muted);
  stroke-width: 1.5;
  cursor: pointer;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.18s ease, stroke 0.18s ease;
}

.rabbit-hole-minimap-open:hover {
  transform: scale(1.5);
  stroke: var(--accent);
}

/* A branch that was taken stays on the map, colored in; its stub goes solid */
.rabbit-hole-minimap-stub-taken {
  stroke: var(--accent);
  stroke-dasharray: none;
  opacity: 0.6;
}

.rabbit-hole-minimap-taken {
  fill: var(--accent);
  /* Same-color stroke so the footprint matches the outlined open dots */
  stroke: var(--accent);
  stroke-width: 1.5;
  cursor: pointer;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.18s ease;
}

.rabbit-hole-minimap-taken:hover,
.rabbit-hole-minimap-taken.is-linked {
  transform: scale(1.5);
}

.rabbit-hole-minimap-frontier {
  /* Opaque strip-colored fill so the spine can't show through the dashes */
  fill: var(--bs-tertiary-bg);
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 4 4;
  cursor: pointer;
  transform-box: fill-box;
  transform-origin: center;
  animation: minimap-frontier-spin 8s linear infinite;
}

@keyframes minimap-frontier-spin {
  to { stroke-dashoffset: -16; }
}

.rabbit-hole-minimap-plus {
  fill: var(--accent);
  font: 700 13px var(--display);
  cursor: pointer;
  transform-box: fill-box;
  transform-origin: center;
  animation: minimap-plus-breathe 3.2s ease-in-out infinite;
}

@keyframes minimap-plus-breathe {
  50% { opacity: 0.45; }
}

/* A dot popping in when a turbo-streamed pane lands on the trail */
.rabbit-hole-minimap-node.is-entering {
  animation: minimap-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
}

/* Branches springing onto a stop once its narrative finishes loading,
   staggered by inline animation-delay set in the renderer */
.rabbit-hole-minimap-open.is-entering,
.rabbit-hole-minimap-taken.is-entering {
  animation: minimap-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
}

.rabbit-hole-minimap-stub.is-entering {
  animation: minimap-fade 0.5s ease backwards;
}

/* First render: the spine draws itself and the stops arrive one by one,
   staggered by inline animation-delay set in the renderer */
.rabbit-hole-minimap svg.is-intro .rabbit-hole-minimap-spine {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: minimap-draw 0.7s ease-out forwards;
}

.rabbit-hole-minimap svg.is-intro .rabbit-hole-minimap-node,
.rabbit-hole-minimap svg.is-intro .rabbit-hole-minimap-open,
.rabbit-hole-minimap svg.is-intro .rabbit-hole-minimap-taken,
.rabbit-hole-minimap svg.is-intro .rabbit-hole-minimap-frontier,
.rabbit-hole-minimap svg.is-intro .rabbit-hole-minimap-plus {
  animation-name: minimap-pop;
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
  animation-fill-mode: backwards;
  animation-iteration-count: 1;
}

.rabbit-hole-minimap svg.is-intro .rabbit-hole-minimap-stub {
  animation: minimap-fade 0.5s ease backwards;
}

@keyframes minimap-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes minimap-pop {
  from { transform: scale(0); }
}

@keyframes minimap-fade {
  from { opacity: 0; }
}

/* Clicking a dot should not leave a focus ring (the browser default is a
   jarring blue on SVG, and clicks can land focus on the SVG root itself);
   keyboard focus gets a branded stroke instead */
.rabbit-hole-minimap-scroll svg:focus,
.rabbit-hole-minimap-scroll svg :focus {
  outline: none;
}

.rabbit-hole-minimap-scroll svg :focus-visible {
  outline: none;
  stroke: var(--accent-deep);
  stroke-width: 4;
}

/* Scroll thumb: the mini-map doubles as the canvas scrollbar, and pressing
   anywhere on the strip jumps there; the faint track hints at that */
.rabbit-hole-minimap-track {
  stroke: var(--line);
  stroke-width: 4;
  stroke-linecap: round;
  opacity: 0.45;
}

.rabbit-hole-minimap-thumb {
  fill: var(--accent);
  opacity: 0.4;
  cursor: grab;
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.rabbit-hole-minimap-thumb:hover {
  opacity: 0.75;
  transform: scaleY(1.5);
}

.rabbit-hole-minimap-thumb:active,
.rabbit-hole-minimap svg.is-scrubbing .rabbit-hole-minimap-thumb {
  opacity: 1;
  transform: scaleY(1.5);
  cursor: grabbing;
}

/* Floating themed tooltip for map stops, replacing the native <title> */
.rabbit-hole-minimap-tooltip {
  position: fixed;
  z-index: 1080;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--bs-border-radius-sm);
  box-shadow: 0 6px 18px rgba(30, 24, 48, 0.16);
  padding: 0.3rem 0.65rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: 0.78rem;
  line-height: 1.3;
  max-width: 280px;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.rabbit-hole-minimap-tooltip.is-visible {
  opacity: 1;
  transform: none;
}

.rabbit-hole-minimap-tooltip-kicker {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Jumping to an open thread from the map spotlights its branch button */
@keyframes thread-flash {
  30% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 35%, transparent); }
}

.thread-flash {
  animation: thread-flash 1.1s ease;
}

/* Keyboard cheat sheet: a quiet card over the canvas, toggled by ? */
.rabbit-hole-help {
  position: fixed;
  inset: 0;
  z-index: 1070;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--bs-body-bg) 55%, transparent);
  backdrop-filter: blur(2px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease, visibility 0.2s;
}

.rabbit-hole-shell.is-help-open .rabbit-hole-help {
  opacity: 1;
  visibility: visible;
}

.rabbit-hole-help-card {
  min-width: 19rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 1rem;
  box-shadow: 0 18px 44px rgba(30, 24, 48, 0.22);
  padding: 1.25rem 1.5rem;
}

.rabbit-hole-help-title {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.9rem;
}

.rabbit-hole-help-rows {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 0.55rem 1rem;
  font-size: 0.85rem;
}

.rabbit-hole-help-keys {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--muted);
}

.rabbit-hole-help-keys kbd {
  padding: 0.1rem 0.4rem;
  font-size: 0.72rem;
  color: inherit;
  background: transparent;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.25rem;
}

/* Signup gate: the endowment moment for guests, same quiet overlay
   treatment as the cheat sheet */
.rabbit-hole-gate {
  position: fixed;
  inset: 0;
  z-index: 1080;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--bs-body-bg) 55%, transparent);
  backdrop-filter: blur(2px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease, visibility 0.2s;
}

.rabbit-hole-gate.is-open {
  opacity: 1;
  visibility: visible;
}

.rabbit-hole-gate-card {
  max-width: 26rem;
}

.rabbit-hole-gate-title {
  font-family: var(--display);
  font-weight: 600;
  margin-bottom: 0.75rem;
}

.rabbit-hole-gate-tally {
  margin: 0.75rem 0 0;
  color: var(--muted);
}

/* Tree overlay: the whole rabbit hole as a real tree, expanded from the
   strip for orientation. The strip itself stays the everyday scrollbar */
.rabbit-hole-tree {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  z-index: 10;
  max-height: min(60vh, 30rem);
  overflow: auto;
  /* A soft lavender wash emanating from the mini-map strip below, settling
     into card by mid-panel, in both themes */
  background: var(--card);
  background: linear-gradient(0deg, color-mix(in srgb, var(--wash) 65%, var(--card)), var(--card) 60%);
  border-top: var(--bs-border-width) solid var(--bs-border-color);
  box-shadow: 0 -14px 32px rgba(30, 24, 48, 0.14);
  padding: 1rem 1.25rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
}

.rabbit-hole-tree.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.rabbit-hole-tree svg {
  display: block;
}

/* Opening the map re-grows the rabbit hole in rabbit_hole order: each edge
   draws toward its node, which pops in with its label as the edge arrives */
.rabbit-hole-tree svg.is-replay .rabbit-hole-tree-edge {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  /* "both": hidden until its turn, and it must KEEP the drawn state after
     finishing; backwards alone reverts each edge to hidden */
  animation: minimap-draw 0.5s ease-out both;
  animation-delay: var(--replay-delay, 0ms);
}

.rabbit-hole-tree svg.is-replay .rabbit-hole-tree-node circle {
  animation: minimap-pop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
  animation-delay: var(--replay-delay, 0ms);
}

.rabbit-hole-tree svg.is-replay .rabbit-hole-tree-node text {
  animation: minimap-fade 0.4s ease backwards;
  animation-delay: var(--replay-delay, 0ms);
}

.rabbit-hole-tree-edge {
  stroke: var(--line);
  stroke-width: 2;
  fill: none;
  transition: stroke 0.18s ease;
}

/* Lineage trace: pointing at a node lights its path back to the root */
.rabbit-hole-tree-edge.is-lineage {
  stroke: var(--accent);
}

.rabbit-hole-tree-node.is-lineage circle {
  stroke: var(--accent-deep);
}

.rabbit-hole-tree-node.is-lineage text {
  fill: var(--ink);
}

.rabbit-hole-tree-node {
  cursor: pointer;
}

.rabbit-hole-tree-node circle {
  fill: var(--card);
  stroke: var(--accent);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.18s ease;
}

.rabbit-hole-tree-node:hover circle {
  transform: scale(1.25);
}

.rabbit-hole-tree-node.is-current circle {
  fill: var(--accent);
}

.rabbit-hole-tree-node text {
  fill: var(--muted);
  font: 400 11.5px var(--display);
  transition: fill 0.18s ease;
}

.rabbit-hole-tree-node:hover text {
  fill: var(--ink);
}

.rabbit-hole-tree-node.is-current text {
  fill: var(--ink);
  font-weight: 600;
}

.rabbit-hole-tree svg :focus {
  outline: none;
}

.rabbit-hole-tree-node:focus-visible circle {
  stroke: var(--accent-deep);
  stroke-width: 4;
}

@media (prefers-reduced-motion: reduce) {
  .rabbit-hole-minimap svg *,
  .rabbit-hole-minimap-tooltip,
  .rabbit-hole-tree,
  .rabbit-hole-tree-node circle,
  .rabbit-hole-tree-node text,
  .thread-flash {
    animation: none !important;
    transition: none !important;
  }
}

[data-reading-focus-target="container"] > turbo-frame > .card.focus-receded {
  opacity: 0.55;
}

body.reading-focus-active::after {
  content: '';
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 1000;
  pointer-events: none;
  animation: focusOverlayIn 0.4s ease;
}

@keyframes focusOverlayIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

body.reading-focus-active [data-reading-focus-target="container"] {
  position: relative;
  z-index: 1001;
  padding-bottom: 50vh;
}

body.reading-focus-active [data-reading-focus-target="toggle"] {
  position: relative;
  z-index: 1001;
}

/* RabbitHole narrative */

.narrative p {
  margin-bottom: 1rem;
}

.narrative p:last-of-type {
  margin-bottom: 0;
}

/* The reading cursor: up/down light one paragraph at a time, then each
   branch row. A single accent tick per pane springs between stops (offsets
   set by the rabbit_hole controller), straddling the pane's left edge
   rather than highlighting over the prose. */
.rabbit-hole-reading-tick {
  position: absolute;
  top: 0;
  /* 1.21rem left of the prose edge: the card-body's padding is its spacer
     plus the overflow bleed, so subtract from that */
  left: calc(var(--bs-card-spacer-x) + var(--reading-tick-bleed) - 1.21rem);
  width: 6px;
  border-radius: 3px;
  background: var(--accent);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1),
              height 0.5s cubic-bezier(0.34, 1.56, 0.64, 1),
              opacity 0.2s ease;
}

.rabbit-hole-reading-tick.is-visible {
  opacity: 0.55;
}

@media (prefers-reduced-motion: reduce) {
  .rabbit-hole-reading-tick {
    transition: none;
  }
}

/* Inner glow on card-body while generating */
.card:has([id$="_status"] .spinner-border) > .card-body {
  position: relative;
  overflow: hidden;
}

.card:has([id$="_status"] .spinner-border) > .card-body::before {
  content: '';
  position: absolute;
  inset: 0;
  /* RabbitHole panes bleed their card-body left for the reading tick;
     keep the glow aligned with the card's own edge */
  left: var(--reading-tick-bleed, 0px);
  /* card-body has no radius of its own; round the bottom to match the card */
  border-radius: 0 0 var(--bs-card-inner-border-radius, 0.875rem) var(--bs-card-inner-border-radius, 0.875rem);
  box-shadow: inset 0 0 30px color-mix(in srgb, var(--accent) 12%, transparent);
  animation: innerGlow 2s ease-in-out infinite;
  pointer-events: none;
  z-index: 1;
}

@keyframes innerGlow {
  0%, 100% { box-shadow: inset 0 0 40px color-mix(in srgb, var(--accent) 15%, transparent); }
  50% { box-shadow: inset 0 0 80px color-mix(in srgb, var(--accent) 30%, transparent); }
}

/* Honest wait state while the full narrative is generated */
.rabbit-hole-waiting {
  display: grid;
  align-content: start;
  gap: 1.5rem;
  min-height: 10rem;
}

.rabbit-hole-waiting-copy {
  display: grid;
  gap: 0.35rem;
  max-width: 36rem;
}

.rabbit-hole-waiting-copy p {
  max-width: 52ch;
}

.rabbit-hole-waiting-skeleton {
  display: grid;
  gap: 0.65rem;
}

.rabbit-hole-waiting-skeleton span {
  display: block;
  width: 100%;
  height: 0.65rem;
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--accent) 8%, transparent) 25%,
    color-mix(in srgb, var(--accent) 20%, transparent) 50%,
    color-mix(in srgb, var(--accent) 8%, transparent) 75%
  );
  background-size: 200% 100%;
  animation: rabbit_holeWaitingShimmer 1.8s ease-in-out infinite;
}

.rabbit-hole-waiting-skeleton span:nth-child(2) {
  width: 88%;
}

.rabbit-hole-waiting-skeleton span:nth-child(3) {
  width: 62%;
}

@keyframes rabbit_holeWaitingShimmer {
  from { background-position: 100% 0; }
  to { background-position: -100% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .rabbit-hole-waiting-skeleton span {
    animation: none;
    background: color-mix(in srgb, var(--accent) 12%, transparent);
  }
}

/* The greeting settles in word by word */
.greeting-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.4em);
  animation: greetingSettle 0.5s ease-out forwards;
  animation-delay: calc(var(--i) * 70ms);
}

@keyframes greetingSettle {
  to { opacity: 1; transform: translateY(0); }
}

/* Curiosity chips under the prompt: quiet invitations, one click to try one */
.prompt-suggestions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

.prompt-suggestion {
  border: 1px solid var(--bs-border-color);
  background: transparent;
  color: var(--bs-secondary-color);
  border-radius: 999px;
  padding: 0.25rem 0.85rem;
  font-size: 0.875rem;
  transition: color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

.prompt-suggestion:hover {
  color: var(--bs-primary);
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  transform: translateY(-1px);
}

@media (prefers-reduced-motion: reduce) {
  .greeting-word {
    animation: none;
    opacity: 1;
    transform: none;
  }

  .prompt-suggestion:hover {
    transform: none;
  }
}

/* The sponge absorbs it: a clipped paragraph squishes and rebounds,
   bulging sideways as it compresses, in time with the confetti */
.narrative-clip-squish {
  animation: clipSquish 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes clipSquish {
  35% { transform: scale(1.01, 0.94); }
}

.narrative-annotation {
  cursor: pointer;
  border-radius: 2px;
  transition: background-color 0.15s;
}

[data-has-entity] { background-color: rgba(59, 130, 246, 0.12); }
[data-has-fact]    { background-color: rgba(234, 179, 8, 0.12); }
[data-has-passage] { background-color: rgba(234, 179, 8, 0.12); }
[data-has-word]    { background-color: rgba(34, 197, 94, 0.12); }

[data-has-entity][data-has-fact],
[data-has-entity][data-has-passage] {
  background: linear-gradient(rgba(59, 130, 246, 0.12), rgba(59, 130, 246, 0.12)),
              linear-gradient(rgba(234, 179, 8, 0.12), rgba(234, 179, 8, 0.12));
}

[data-has-entity][data-has-word] {
  background: linear-gradient(rgba(59, 130, 246, 0.12), rgba(59, 130, 246, 0.12)),
              linear-gradient(rgba(34, 197, 94, 0.12), rgba(34, 197, 94, 0.12));
}

[data-has-fact][data-has-word],
[data-has-passage][data-has-word] {
  background: linear-gradient(rgba(234, 179, 8, 0.12), rgba(234, 179, 8, 0.12)),
              linear-gradient(rgba(34, 197, 94, 0.12), rgba(34, 197, 94, 0.12));
}

[data-has-entity][data-has-fact][data-has-word],
[data-has-entity][data-has-passage][data-has-word] {
  background: linear-gradient(rgba(59, 130, 246, 0.12), rgba(59, 130, 246, 0.12)),
              linear-gradient(rgba(234, 179, 8, 0.12), rgba(234, 179, 8, 0.12)),
              linear-gradient(rgba(34, 197, 94, 0.12), rgba(34, 197, 94, 0.12));
}

.narrative-annotation:hover,
.narrative-annotation.highlight {
  filter: brightness(0.85);
}

a.narrative-clip {
  background-color: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 2px;
  color: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
  text-underline-offset: 0.15em;
  cursor: pointer;
  transition: background-color 0.15s;
}

a.narrative-clip:hover {
  background-color: color-mix(in srgb, var(--accent) 25%, transparent);
  color: inherit;
}

/* Clip highlight shimmer */
.narrative-clip-shimmer {
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    transparent 35%,
    color-mix(in srgb, var(--accent) 40%, transparent) 50%,
    transparent 65%,
    transparent 100%
  );
  background-size: 300% 100%;
  background-position: 100% 0;
  animation: clip-shimmer 1s ease-out;
}

@keyframes clip-shimmer {
  100% {
    background-position: -50% 0;
  }
}

/* Question intent: inline input anchored to the selection */
.narrative-question-box {
  position: fixed;
  z-index: 1050;
  flex-direction: column;
  width: min(440px, calc(100vw - 2rem));
  background: var(--bs-body-bg);
  border: 1px solid color-mix(in srgb, var(--accent) 80%, transparent);
  border-radius: 0.5rem;
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.25), 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
  overflow: hidden;
}

.narrative-question-box input,
.narrative-question-box textarea {
  font-size: 0.9rem;
  width: 100%;
  padding: 0.5rem 0.65rem;
  border: none;
  background: transparent;
  color: var(--bs-body-color);
  outline: none;
}

/* Prediction textareas auto-grow from one line via JS, never by hand;
   the lifted card background sets the field apart from the box around it */
.narrative-question-box textarea {
  resize: none;
  overflow-y: hidden;
  width: auto;
  align-self: stretch;
  margin: 0.4rem 0.65rem 0.1rem;
  padding: 0.4rem 0.55rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
}

.narrative-question-box textarea:focus {
  border-color: var(--accent);
}

.narrative-question-hint {
  font-size: 0.75rem;
  color: var(--bs-secondary-color);
  padding: 0.3rem 0.65rem;
  border-top: 1px solid var(--bs-border-color);
  background: color-mix(in srgb, var(--bs-emphasis-color) 3%, transparent);
}

.narrative-question-hint kbd {
  font-size: 0.7rem;
}

/* Socratic prediction box: question-box chrome with the guess-form's accent */
.narrative-guess-box {
  border-color: color-mix(in srgb, var(--accent) 70%, transparent);
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.25), 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

.narrative-guess-box-prompt {
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.35;
  padding: 0.5rem 0.65rem 0;
}

/* Selection held visible while the question input is open */
.narrative-clip-pending {
  background: color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 2px;
}

/* Clip toast */
.clip-toast {
  position: fixed;
  bottom: 0;
  right: 0;
  margin: 1rem;
  padding: 0.4rem 0.75rem;
  background: var(--accent);
  color: #fff;
  border-radius: 0.375rem;
  font-size: 0.875rem;
  font-weight: 500;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s, transform 0.2s;
}

/* Same saturated fill as .btn-primary: the lifted dark accent is too light
   behind white text */
[data-bs-theme="dark"] .clip-toast {
  background: var(--accent-fill);
}

.clip-toast-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Clip confetti */
.clip-confetti {
  position: fixed;
  width: 6px;
  height: 6px;
  pointer-events: none;
  animation: clip-confetti-burst 0.6s ease-out forwards;
}

.clip-confetti-circle {
  border-radius: 50%;
}

.clip-confetti-square {
  border-radius: 1px;
}

.clip-confetti-star {
  width: 0;
  height: 0;
  background: none !important;
  border-left: 3px solid transparent;
  border-right: 3px solid transparent;
  border-bottom: 6px solid currentColor;
  color: inherit;
}

@keyframes clip-confetti-burst {
  0% {
    opacity: 1;
    transform: translate(0, 0) rotate(0) scale(1);
  }
  70% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate(var(--dx), var(--dy)) rotate(var(--rot)) scale(0.3);
  }
}

a.narrative-entity {
  color: var(--bs-link-color);
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

a.narrative-entity:hover {
  color: var(--bs-link-hover-color, var(--bs-link-color));
}

/* Branch popover styling */
.branch-popover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  border-color: color-mix(in srgb, var(--accent) 25%, transparent);
  max-width: 280px;
}

.branch-popover .popover-header {
  padding: 0.75rem 1rem;
  font-weight: 600;
  background-color: color-mix(in srgb, var(--accent) 6%, transparent);
  border-bottom-color: color-mix(in srgb, var(--accent) 12%, transparent);
}

.branch-popover .popover-body {
  padding: 0.5rem 1rem 1rem;
  color: var(--bs-body-color);
}

/* Hook-only popovers (bottom branch buttons): Bootstrap still renders the
   header element, empty and hidden, so match the body that follows it */
.branch-popover .popover-header:empty + .popover-body {
  padding: 1rem;
}

.narrative-branch {
  color: var(--bs-primary);
  text-decoration: none;
  cursor: pointer;
  margin-left: 0.2em;
  font-size: 0.85em;
  opacity: 0.7;
  transition: opacity 0.2s, color 0.2s;
}

.narrative-branch:hover {
  opacity: 1;
}

.narrative-branch-complete {
  color: var(--bs-success);
  opacity: 0.8;
}

.narrative-branch-complete:hover {
  color: var(--bs-success);
  opacity: 1;
}

.narrative-branch-failed,
.narrative-branch-failed:hover {
  color: var(--bs-warning);
}

/* A branch taken mid-read completes off-screen; a few soft pulses announce
   it's ready without pulling the reader away */
.narrative-branch-ripened {
  animation: narrative-branch-ripen 1.2s ease-in-out 3;
}

@keyframes narrative-branch-ripen {
  50% {
    opacity: 1;
    text-shadow: 0 0 0.6em color-mix(in srgb, var(--moss) 90%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .narrative-branch-ripened {
    animation: none;
  }
}

/* Socratic prediction: the guess the reader locked in before revealing */
.rabbit-hole-guess {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.6rem 0.8rem;
  border-radius: 0.65rem;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  border-left: 3px solid color-mix(in srgb, var(--accent) 70%, transparent);
}

.rabbit-hole-guess-icon {
  flex-shrink: 0;
  margin-top: 0.15rem;
  font-size: 0.85rem;
  color: var(--accent);
}

.rabbit-hole-guess-label {
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--bs-primary-text-emphasis);
  margin-bottom: 0.1rem;
}

.rabbit-hole-guess-text {
  font-size: 0.9rem;
  font-style: italic;
  line-height: 1.45;
  color: var(--bs-body-color);
}

/* Socratic prediction form: shown before the child node is generated */
.rabbit-hole-guess-form {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.85rem;
  border-radius: 0.65rem;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  animation: guessFormIn 0.2s ease-out;
}

@keyframes guessFormIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

.rabbit-hole-guess-form-icon {
  flex-shrink: 0;
  margin-top: 0.15rem;
  color: var(--accent);
}

.rabbit-hole-guess-form-body {
  flex: 1 1 auto;
  min-width: 0;
}

.rabbit-hole-guess-form-prompt {
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.35;
}

.rabbit-hole-guess-form-hint {
  margin: 0;
  font-size: 0.8rem;
  color: var(--bs-secondary-color);
}

.rabbit-hole-guess-form-input {
  resize: none;
  overflow-y: hidden;
  background-color: var(--card);
}

.rabbit-hole-guess-form-input:focus {
  border-color: color-mix(in srgb, var(--accent) 60%, transparent);
  box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--accent) 15%, transparent);
  /* Bootstrap's .form-control:focus resets to body-bg; stay on card */
  background-color: var(--card);
}


/* ── RabbitHole: the find counter and its review panel ── */

/* The canvas and the panel share a grid row; opening the panel grows its
   track, which pushes the canvas rather than covering it. */
.rabbit-hole-body {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 0px;
  transition: grid-template-columns 0.34s cubic-bezier(0.32, 0.72, 0.35, 1);
}

.rabbit-hole-body.panel-open {
  grid-template-columns: 1fr min(380px, 82vw);
}

/* ── The pill ── */

.rabbit-hole-suggestions-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  background: var(--bs-body-bg);
  color: var(--bs-primary-text-emphasis);
  font-weight: 600;
  font-size: 0.8rem;
  transition: border-color 0.3s ease, color 0.3s ease;
}

.rabbit-hole-suggestions-pill:hover {
  border-color: var(--accent);
}

.rabbit-hole-suggestions-count {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

/* A new find has landed: a quick nudge, nothing that pulls the eye off the page */
.rabbit-hole-suggestions-pill.bump {
  animation: pillBump 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes pillBump {
  35% { transform: scale(1.09, 0.92); }
}

.rabbit-hole-suggestions-pill.is-open {
  border-color: var(--accent);
  background: var(--wash);
}

.rabbit-hole-suggestions-pill.is-settled {
  color: var(--moss);
  border-color: color-mix(in srgb, var(--moss) 50%, transparent);
}

/* ── The panel ── */

.rabbit-hole-suggestions-panel {
  min-width: 0;
  overflow: hidden;
  /* Same surface as the narrative panes: this reads as part of the reading */
  background: var(--card);
  border-left: var(--bs-border-width) solid var(--bs-border-color);
  display: flex;
  flex-direction: column;
}

/* Fixed width while the track animates, so the content doesn't reflow
   through the slide; the parent's overflow clips it instead. */
.rabbit-hole-suggestions-panel-inner {
  width: min(380px, 82vw);
  height: 100%;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease 0.06s, visibility 0s linear 0.34s;
}

.rabbit-hole-body.panel-open .rabbit-hole-suggestions-panel-inner {
  opacity: 1;
  visibility: visible;
  transition-delay: 0.06s, 0s;
}

/* The chips are the panel's header: the close button rides along with them */
.rabbit-hole-suggestions-filters {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.7rem 0.9rem 0.7rem 1.15rem;
  flex-wrap: wrap;
  border-bottom: var(--bs-border-width) solid var(--bs-border-color);
}

.rabbit-hole-suggestions-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  border: 1px solid var(--bs-border-color);
  background: transparent;
  color: var(--bs-secondary-color);
  font-weight: 600;
  font-size: 0.76rem;
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.rabbit-hole-suggestions-chip:hover {
  border-color: var(--accent);
  color: var(--bs-primary-text-emphasis);
}

.rabbit-hole-suggestions-chip-dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
}

.rabbit-hole-suggestions-chip[data-family="fact"] .rabbit-hole-suggestions-chip-dot { background: var(--gold); }
.rabbit-hole-suggestions-chip[data-family="passage"] .rabbit-hole-suggestions-chip-dot { background: var(--sea); }
.rabbit-hole-suggestions-chip[data-family="word"] .rabbit-hole-suggestions-chip-dot { background: var(--moss); }

.rabbit-hole-suggestions-chip-n {
  font-variant-numeric: tabular-nums;
  opacity: 0.85;
}

.rabbit-hole-suggestions-chip.is-active {
  background: var(--wash);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--bs-primary-text-emphasis);
}

/* An empty chip recedes but stays clickable */
.rabbit-hole-suggestions-chip.is-empty {
  opacity: 0.5;
}

.rabbit-hole-suggestions-close {
  margin-left: auto;
  border: 0;
  background: none;
  color: var(--bs-secondary-color);
  padding: 0.2rem 0.35rem;
  line-height: 1;
}

.rabbit-hole-suggestions-close:hover {
  color: var(--bs-body-color);
}

.rabbit-hole-suggestions-scroll {
  overflow-y: auto;
  flex: 1;
  padding-bottom: 1rem;
}

.rabbit-hole-suggestions-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rabbit-hole-suggestions-empty {
  padding: 1.25rem 1.15rem;
  font-size: 0.8rem;
  color: var(--bs-secondary-color);
  margin: 0;
}

.rabbit-hole-suggestions-footer {
  padding: 0.6rem 1.15rem 0.75rem;
  border-top: var(--bs-border-width) solid var(--bs-border-color);
  font-size: 0.73rem;
  color: var(--bs-secondary-color);
  flex-shrink: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.rabbit-hole-suggestions-footer a {
  color: var(--bs-secondary-color);
}

/* ── Rows ── */

.rabbit-hole-suggestion {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 0.7rem 1.15rem;
  font-size: 0.875rem;
  border-bottom: var(--bs-border-width) solid color-mix(in srgb, var(--bs-border-color) 55%, transparent);
  transition: background-color 0.2s ease;
}

.rabbit-hole-suggestion.is-filtered-out {
  display: none;
}

.rabbit-hole-suggestion.just-landed {
  animation: suggestionLand 0.4s ease-out;
}

@keyframes suggestionLand {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

.rabbit-hole-suggestion-dot {
  flex-shrink: 0;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  margin-top: 0.5rem;
}

.rabbit-hole-suggestion-fact .rabbit-hole-suggestion-dot { background: var(--gold); }
.rabbit-hole-suggestion-passage .rabbit-hole-suggestion-dot { background: var(--sea); }
.rabbit-hole-suggestion-word .rabbit-hole-suggestion-dot { background: var(--moss); }

.rabbit-hole-suggestion-body {
  flex: 1;
  min-width: 0;
}

.rabbit-hole-suggestion-actions {
  display: flex;
  gap: 0.35rem;
  flex-shrink: 0;
  margin-top: 0.35rem;
}

/* button_to wraps each control in a form; it shouldn't add a gap of its own */
.rabbit-hole-suggestion-actions form {
  margin: 0;
}

.rabbit-hole-suggestion-btn {
  width: 1.9rem;
  height: 1.9rem;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid var(--bs-border-color);
  background: transparent;
  padding: 0;
  font-size: 0.8rem;
}

.rabbit-hole-suggestion-btn.keep {
  color: var(--moss);
  border-color: color-mix(in srgb, var(--moss) 45%, transparent);
}

.rabbit-hole-suggestion-btn.keep:hover {
  background: var(--moss);
  color: #fff;
}

.rabbit-hole-suggestion-btn.pass {
  color: var(--bs-secondary-color);
}

.rabbit-hole-suggestion-btn.pass:hover {
  background: var(--wash);
  color: var(--bs-body-color);
}

.rabbit-hole-suggestion-undo {
  border: 0;
  background: none;
  font-size: 0.8rem;
  color: var(--bs-secondary-color);
  text-decoration: underline;
  padding: 0;
}

.rabbit-hole-suggestion-undo:hover {
  color: var(--bs-body-color);
}

.rabbit-hole-suggestion.is-accepted {
  background: color-mix(in srgb, var(--moss-wash) 70%, transparent);
}

.rabbit-hole-suggestion-kept {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--moss);
  font-weight: 600;
  font-size: 0.78rem;
  margin-top: 0.15rem;
}

.rabbit-hole-suggestion.is-rejected .rabbit-hole-suggestion-body,
.rabbit-hole-suggestion.is-rejected .rabbit-hole-suggestion-dot {
  opacity: 0.45;
}

@media (prefers-reduced-motion: reduce) {
  .rabbit-hole-suggestions-pill.bump,
  .rabbit-hole-suggestion.just-landed {
    animation: none;
  }

  .rabbit-hole-body,
  .rabbit-hole-suggestions-panel-inner {
    transition: none;
  }
}

@container (max-width: 820px) {
  .rabbit-hole-suggestions-word {
    display: none;
  }
}

/* No room to sit beside the reading, so the panel takes the screen */
@container (max-width: 640px) {
  .rabbit-hole-body.panel-open {
    grid-template-columns: 0px 1fr;
  }

  .rabbit-hole-body.panel-open .rabbit-hole-scroll-container {
    visibility: hidden;
  }
}
