/* Modals — create-space / add-topic dialogs, reference pills */

/* Create Space / Add topic modals */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh var(--space-4) var(--space-4);
  background: rgba(22, 22, 29, 0.38);
  backdrop-filter: blur(2px);
}

.modal-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  width: min(480px, 100%);
  padding: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.modal-card-topic {
  width: min(600px, 100%);
}

/* ── Create space — an invitation, not a bare form ──────────────────────────
   A quiet header (eyebrow + heading + one line on what a space is) over a
   single name field, framed to nudge a reviewer into starting one (M8). */
.create-space-card {
  gap: var(--space-4);
}

.create-space-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.create-space-eyebrow {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.create-space-intro {
  display: grid;
  gap: var(--space-2);
}

.create-space-intro h2 {
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.15;
}

.create-space-intro p {
  margin: 0;
  color: var(--muted);
  font-family: var(--font-reading);
  font-size: 0.92rem;
  line-height: var(--line-reading);
}

.create-space-card .field {
  display: grid;
  gap: var(--space-2);
}

.create-space-card .field label {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.create-space-card .field input {
  width: 100%;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.94rem;
}

.create-space-card .field input:focus {
  border-color: var(--accent);
  outline: 0;
}

.create-space-card .field input::placeholder {
  color: var(--muted);
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.modal-head h2 {
  margin: 0;
  font-size: 1.1rem;
  line-height: var(--line-ui);
}

.modal-close {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--muted);
  font-size: 1.2rem;
  line-height: 1;
}

.modal-close:hover,
.modal-close:focus-visible {
  background: var(--soft);
  color: var(--ink);
}

.modal-form {
  display: grid;
  gap: var(--space-4);
}

.modal-form .actions {
  justify-content: flex-end;
}

.modal-error {
  margin: 0;
  color: var(--clay);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.4;
  /* Always occupy its space so toggling the message never shifts the layout. */
  visibility: hidden;
}

.modal-error.is-visible {
  visibility: visible;
}

.modal-note {
  margin: 0;
  color: var(--muted);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.4;
}

.profile-card {
  gap: var(--space-4);
}

.profile-card .modal-head h2 {
  font-size: 1.5rem;
  line-height: 1.15;
}

.profile-card .field {
  display: grid;
  gap: var(--space-2);
}

.profile-card .field label {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.profile-card .field input {
  width: 100%;
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.94rem;
}

.profile-card .field input:focus {
  border-color: var(--accent);
  outline: 0;
}

.profile-card .field input:disabled {
  background: var(--soft);
  color: var(--muted);
  opacity: 1;
}

.profile-card .modal-error {
  display: none;
}

.profile-card .modal-error.is-visible {
  display: block;
}

.profile-card .actions {
  justify-content: flex-start;
}

.modal-form input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.reference-input-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-2);
}

.reference-pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.reference-pill {
  display: inline-flex;
  min-width: 0;
  max-width: 100%;
  min-height: 34px;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--soft);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.82rem;
}

.reference-pill.is-dragging {
  opacity: 0.45;
}

.reference-drag {
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
  cursor: grab;
  touch-action: none;
}

.reference-order {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.reference-pill.is-drop-target {
  border-color: var(--accent);
}

.reference-pill-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.reference-pill button {
  display: inline-grid;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  padding: 0;
  place-items: center;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
}

.reference-pill button:hover,
.reference-pill button:focus-visible {
  background: var(--panel);
  color: var(--ink);
  outline: 0;
}

/* ── Topic creation flow (docs/topic-creation.md) ───────────────────────────
   Three steps over one pasted source. Unlike the small modals above this one
   is a fixed frame — pinned head and foot, only the body scrolls — so the step
   tabs and the primary action never move as the content changes height. */

/* Top-anchored, not centered. A centered card re-centres itself every time its
   content changes height — expanding the chapter list, or adding an excerpt row
   — which threw the head, the steps and every row upward, out from under the
   cursor. Pinned at the top, the frame grows downward into the space it has and
   nothing already on screen moves. */
.modal-overlay:has(.modal-card-flow) {
  align-items: flex-start;
  padding: 7vh var(--space-4) var(--space-5);
}

/* Focusable (tabindex="-1") so a re-render can hand focus back to the dialog,
   which is what keeps Escape working — but it never draws a ring itself. */
.modal-card-flow:focus {
  outline: 0;
}

.modal-card-flow {
  /* Heat has one colour across the flow — the flames' rule, the timeline's halo.
     It lives here rather than on .flow-heat-card because the timeline marks need
     it too, and the two were drifting: amber flames, blue halo. */
  --flow-heat: #d97706;
  gap: 0;
  width: min(620px, 100%);
  max-height: 100%;
  padding: 0;
  overflow: hidden;
  background: var(--paper);
}

.flow-head {
  flex: 0 0 auto;
  padding: var(--space-3) var(--space-4) 0;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}

.flow-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.flow-crumb {
  overflow: hidden;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.07em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.flow-steps {
  display: flex;
  gap: var(--space-5);
  padding-top: var(--space-3);
}

.flow-step {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 0 var(--space-2);
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--muted);
}

.flow-step-n {
  display: grid;
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  font-family: var(--font-mono);
  font-size: 0.7rem;
}

.flow-step-label {
  font-family: var(--font-ui);
  font-size: 0.84rem;
  font-weight: 620;
}

.flow-step[data-done="true"] {
  color: var(--ink);
}

.flow-step[data-done="true"] .flow-step-n {
  border-color: var(--accent);
  color: var(--accent);
}

.flow-step[aria-current="true"] {
  border-bottom-color: var(--accent);
  color: var(--ink);
}

.flow-step[aria-current="true"] .flow-step-n {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--color-on-accent);
}

.flow-step:disabled {
  opacity: 1;
  color: color-mix(in srgb, var(--muted) 55%, var(--paper));
}

.flow-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-4);
  overflow-y: auto;
}

.flow-foot {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--line);
  background: var(--panel);
}

.flow-foot-note {
  flex: 1 1 auto;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  line-height: 1.45;
}

.flow-foot .btn {
  min-height: 38px;
  font-size: 0.9rem;
  white-space: nowrap;
}

.flow-foot .btn.secondary.danger {
  border-color: color-mix(in srgb, var(--clay) 42%, var(--line));
  color: var(--clay);
}

.flow-foot .btn.secondary.danger:hover,
.flow-foot .btn.secondary.danger:focus-visible {
  background: color-mix(in srgb, var(--clay) 8%, var(--panel));
}

/* The confirmation's own Delete is the filled one — at the point of asking,
   the destructive answer is the thing you came for and shouldn't be hunted. */
.flow-foot .btn.danger.flow-delete-confirm {
  border: 1px solid var(--clay);
  background: var(--clay);
  color: var(--color-on-accent);
}

.flow-foot .btn.danger.flow-delete-confirm:hover,
.flow-foot .btn.danger.flow-delete-confirm:focus-visible {
  background: color-mix(in srgb, var(--clay) 84%, #000);
}

/* The way out — Cancel in the editor, Keep Draft in the delete confirmation.
   One style for both, because they are the same verb: leave things as they are.
   Bordered and inked they read as another button competing with Save; quieter
   than the verbs beside them is the whole point, so no border, no fill, and
   muted text until you are actually on it. The foot then reads left to right in
   increasing weight — back out, then the destructive verb, then the primary. */
.flow-foot .btn.flow-cancel {
  border: 0;
  background: transparent;
  color: var(--muted);
  font-weight: 620;
}

.flow-foot .btn.flow-cancel:hover,
.flow-foot .btn.flow-cancel:focus-visible {
  background: transparent;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.flow-heading {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 1.02rem;
  line-height: var(--line-ui);
}

/* A heading that carries its own add verb, the way the Spaces and Sources
   headings do. The button is sized down from the standard 32px to sit level
   with a 1.02rem heading rather than tower over it — same trick as My Stuff. */
.flow-heading-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.flow-heading-add {
  width: 28px;
  height: 28px;
  font-size: 1.04rem;
}

/* Room mode has no stepper to sit under, so the heading takes its place in the
   head — same slot, same rhythm. */
.flow-room-mode-heading {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-bottom: var(--space-3);
}

.flow-room-heading-icon,
.flow-room-title-icon {
  flex: 0 0 auto;
  color: var(--muted);
}

.flow-room-heading-icon {
  width: 21px;
  height: 18px;
}

.flow-room-heading-icon svg {
  width: 21px;
  height: 18px;
}

.flow-sub {
  margin: var(--space-1) 0 0;
  color: var(--muted);
  font-family: var(--font-ui);
  font-size: 0.88rem;
  line-height: var(--line-reading);
}

.flow-field {
  display: grid;
  gap: var(--space-2);
}

.flow-label {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The lane primitive a field's value becomes, sitting in the label — a
   monochrome SVG in source, so it inherits the label's colour here. */
.flow-label-icon {
  display: inline-flex;
  width: 0.95rem;
  height: 0.95rem;
  margin-right: 0.4em;
  /* The label is uppercase micro-type with no descenders, so the glyph has to
     sit below its baseline to read as level with the words. */
  vertical-align: -0.34em;
}

.flow-label-icon .primitive-icon,
.flow-label-icon svg {
  display: block;
  width: 0.95rem;
  height: 0.95rem;
}

.flow-label-icon svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.flow-input,
.flow-textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.92rem;
  line-height: var(--line-reading);
}

.flow-input {
  min-height: 42px;
  padding: 0 var(--space-3);
}

.flow-textarea {
  height: auto;
  padding: var(--space-3);
  font-family: var(--font-reading);
  resize: vertical;
}

.flow-url-input {
  font-family: var(--font-mono);
  font-size: 0.84rem;
}

/* The resolved source — the whole of what step 1 produces. */
.flow-detected {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--soft);
}

.flow-detected.has-controls {
  align-items: flex-start;
}

.flow-detected .play-link {
  margin-bottom: 0;
}

.flow-source-play {
  position: relative;
  margin-top: 2px;
  padding: 0;
  background: transparent;
  color: var(--color-youtube);
}

.flow-source-play:hover,
.flow-source-play:focus-visible {
  color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

.flow-source-play.is-playing::after {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  content: "II";
  color: var(--color-on-accent);
  font-family: var(--font-ui);
  font-size: 0.48rem;
  font-weight: 800;
  line-height: 1;
}

.flow-source-play.is-playing path {
  opacity: 0;
}

.flow-detected-body {
  flex: 1 1 auto;
  min-width: 0;
}

.flow-detected-title {
  font-family: var(--font-ui);
  font-size: 0.94rem;
  font-weight: 700;
  line-height: var(--line-ui);
}

.flow-detected-meta {
  margin-top: 3px;
  overflow: hidden;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flow-detected-link:hover {
  color: var(--accent);
  text-decoration: underline;
}

.flow-suggest-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  justify-content: flex-start;
  margin: -2px 0 0;
}

.flow-rows + .flow-suggest-row {
  margin-top: var(--space-3);
  padding-top: var(--space-4);
  border-top: 1px solid color-mix(in srgb, var(--line) 72%, transparent);
}

.flow-suggest-button {
  min-height: 32px;
  max-width: 100%;
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--ink);
  font-size: 0.82rem;
  font-weight: 680;
}

.flow-suggest-button:hover {
  background: var(--soft);
}

.flow-suggest-notice {
  color: var(--muted);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  line-height: var(--line-ui);
  animation: flow-suggest-notice-fade 2.2s ease forwards;
}

@keyframes flow-suggest-notice-fade {
  0%,
  70% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

@media (max-width: 520px) {
  .flow-suggest-row {
    justify-content: flex-start;
  }

  .flow-suggest-button {
    width: auto;
  }
}

.flow-timeline-controls {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.flow-detected .flow-timeline-wrap {
  margin-top: var(--space-5);
}

.flow-detected .flow-timeline::before {
  border-color: color-mix(in srgb, var(--line) 82%, var(--panel));
  background: var(--panel);
}

.flow-timeline-stack {
  display: grid;
  flex: 1 1 auto;
  min-width: 0;
  gap: var(--space-2);
}

.flow-playhead-range {
  position: absolute;
  z-index: 2;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.flow-audio-frame {
  position: fixed;
  top: 0;
  left: -100vw;
  width: 1px;
  height: 1px;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

/* The timeline: the same set as the rows below, read as where-on-the-source. */
.flow-timeline-wrap {
  display: grid;
  gap: var(--space-2);
}

.flow-timeline {
  position: relative;
  height: 24px;
}

.flow-timeline::before {
  position: absolute;
  top: 50%;
  right: 0;
  left: 0;
  height: 8px;
  content: "";
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--soft);
  transform: translateY(-50%);
}

.flow-timeline:has(.flow-playhead-range:focus-visible)::before {
  border-color: var(--accent);
}

.flow-playhead-bar {
  position: absolute;
  z-index: 3;
  top: 0;
  bottom: 2px;
  width: 2px;
  border-radius: 1px;
  background: var(--ink);
  pointer-events: none;
  transform: translateX(-50%);
}

.flow-playhead-label {
  position: absolute;
  z-index: 5;
  top: -14px;
  min-width: 28px;
  max-width: 54px;
  padding: 0 3px;
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  pointer-events: none;
  text-align: center;
  transform: translateX(-50%);
}

.flow-playhead-label.is-start {
  transform: translateX(0);
}

.flow-playhead-label.is-end {
  transform: translateX(-100%);
}

.flow-mark {
  position: absolute;
  z-index: 4;
  top: 50%;
  width: 11px;
  height: 11px;
  margin: 0;
  padding: 0;
  border-radius: 3px;
  background: var(--paper);
  box-shadow: inset 0 0 0 1.5px var(--line);
  transform: translate(-50%, -50%) rotate(45deg);
}

.flow-mark:hover {
  box-shadow: inset 0 0 0 1.5px var(--accent);
}

.flow-mark:hover,
.flow-mark:focus-visible {
  z-index: 11;
  transform: translate(-50%, -50%) rotate(45deg) scale(1.22);
}

.flow-mark.is-picked {
  background: var(--accent);
  box-shadow: none;
}

/* Heat is the amber halo; blue stays reserved for "picked". They were both accent,
   so a hot mark and a chosen mark said the same thing in the same colour — and
   the halo disagreed with the flames on the row below it. */
.flow-mark.is-heated {
  box-shadow:
    inset 0 0 0 1.5px color-mix(in srgb, var(--flow-heat) 72%, var(--line)),
    0 0 0 var(--heat-size, 4px) color-mix(in srgb, var(--flow-heat) 26%, transparent);
}

.flow-mark.is-picked.is-heated {
  box-shadow: 0 0 0 var(--heat-size, 4px) color-mix(in srgb, var(--flow-heat) 32%, transparent);
}

.flow-mark.is-heated:hover,
.flow-mark.is-heated:focus-visible {
  box-shadow:
    inset 0 0 0 1.5px var(--flow-heat),
    0 0 0 var(--heat-size, 4px) color-mix(in srgb, var(--flow-heat) 34%, transparent);
}

.flow-mark.is-picked:hover,
.flow-mark.is-picked:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 24%, transparent);
}

.flow-mark-tooltip {
  position: absolute;
  bottom: calc(50% + 13px);
  left: 50%;
  z-index: 10;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  width: max-content;
  max-width: 190px;
  padding: 4px var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 620;
  line-height: var(--line-ui);
  opacity: 0;
  pointer-events: none;
  text-align: left;
  transform: translate(-50%, 2px);
  transition: opacity 120ms ease, transform 120ms ease;
  white-space: normal;
}

.flow-mark:hover + .flow-mark-tooltip,
.flow-mark:focus-visible + .flow-mark-tooltip {
  opacity: 1;
  transform: translate(-50%, 0);
}

.flow-mark:hover + .flow-mark-tooltip.is-start,
.flow-mark:focus-visible + .flow-mark-tooltip.is-start {
  transform: translate(0, 0);
}

.flow-mark:hover + .flow-mark-tooltip.is-end,
.flow-mark:focus-visible + .flow-mark-tooltip.is-end {
  transform: translate(-100%, 0);
}

.flow-mark-tooltip-time {
  flex: 0 0 auto;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}

.flow-mark-tooltip-title {
  min-width: 0;
}

.flow-timeline-scale {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-variant-numeric: tabular-nums;
}

/* The moment list. AI-suggested rows use the question as the label. */
.flow-rows {
  display: grid;
  gap: var(--space-2);
}

.flow-row-set {
  --flow-row-heat-indent: calc(18px + 56px + (2 * var(--space-3)));
  display: grid;
  gap: var(--space-1);
}

.flow-row {
  display: grid;
  grid-template-columns: 18px minmax(58px, 68px) minmax(0, 1fr) auto;
  width: 100%;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  text-align: left;
}

.flow-row:focus-within,
.flow-row:hover {
  border-color: var(--accent);
}

/* A time nobody can parse. The row keeps its shape — the line under it is the
   correction, and the flow's forward verb is already dead while it shows. */
.flow-row.is-bad-time,
.flow-row.is-bad-time:hover,
.flow-row.is-bad-time:focus-within {
  border-color: var(--urgent);
}

.flow-time-error {
  margin: 0;
  padding: 0 var(--space-3);
  color: var(--urgent);
  font: 600 0.78rem var(--font-ui);
  line-height: var(--line-ui);
}

.flow-row.is-picked {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.flow-row-add {
  border-style: dashed;
  background: transparent;
}

.flow-row-add {
  display: flex;
  justify-content: center;
  cursor: pointer;
}

.flow-box {
  display: grid;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  padding: 0;
  place-items: center;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--color-on-accent);
  font-size: 0.7rem;
  line-height: 1;
}

.flow-box[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent);
}

.flow-box:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.flow-time-cell {
  position: relative;
  display: block;
  min-width: 0;
}

.flow-ts-button,
.flow-ts-input,
.flow-row-title-input {
  min-width: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.92rem;
  line-height: var(--line-ui);
}

.flow-ts-button,
.flow-ts-input {
  width: 100%;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}

.flow-ts-button {
  padding: 2px 3px;
  text-align: left;
}

/* Transport on a timestamp. The glyph shares the button with the label and its
   space is reserved at rest, so revealing it never shifts the time under the
   cursor. On a pointer it waits for the row (a list of ▶s is noise); on touch
   there is no hover to wait for, so it is simply there. */
.flow-ts-button,
.flow-chapter-ts {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.flow-transport-glyph {
  display: inline-grid;
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  place-items: center;
  opacity: 0;
  transition: opacity 120ms ease;
}

.flow-transport-glyph svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
}

/* Which cue is playing is state, not a hint: it shows on every device, always.
   The glyph alone carries it — colouring the label too made a resting row shout
   in accent, and read as selection rather than playback. */
.flow-ts-button.is-playing .flow-transport-glyph,
.flow-chapter-ts.is-playing .flow-transport-glyph {
  opacity: 1;
}

@media (hover: hover) {
  .flow-row:hover .flow-transport-glyph,
  .flow-row:focus-within .flow-transport-glyph,
  .flow-chapter:hover .flow-transport-glyph,
  .flow-chapter:focus-within .flow-transport-glyph {
    opacity: 1;
  }
}

@media (hover: none) {
  .flow-transport-glyph {
    opacity: 1;
  }
}

.flow-ts-button:not(:disabled) {
  cursor: pointer;
}

.flow-ts-button:disabled {
  opacity: 0.7;
}

.flow-ts-input {
  display: none;
}

.flow-time-cell.is-editing .flow-ts-button,
.flow-time-cell.is-editing .flow-ts-edit {
  display: none;
}

.flow-time-cell.is-editing .flow-ts-input {
  display: block;
}

.flow-ts-edit {
  position: absolute;
  top: 50%;
  left: calc(100% - 14px);
  display: grid;
  width: 18px;
  height: 18px;
  padding: 0;
  place-items: center;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  opacity: 0;
  transform: translateY(-50%);
  transition: opacity 120ms ease, color 120ms ease, background 120ms ease, border-color 120ms ease;
}

.flow-ts-edit svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.flow-time-cell:hover .flow-ts-edit,
.flow-time-cell:focus-within .flow-ts-edit {
  opacity: 1;
}

.flow-row-title-input {
  width: 100%;
  font-weight: 620;
  overflow: hidden;
  resize: none;
  white-space: pre-wrap;
  word-break: normal;
  overflow-wrap: anywhere;
}

.flow-ts-button:not(:disabled):hover,
.flow-ts-input:hover,
.flow-ts-input:focus,
.flow-ts-edit:hover,
.flow-ts-edit:focus,
.flow-row-title-input:hover,
.flow-row-title-input:focus {
  border-color: var(--line);
  background: var(--paper);
  outline: 0;
}

/* Lit while you are pointing at it or tabbed to it — not after. Clicking a
   timestamp leaves it focused, and on `:focus` the accent and underline stayed
   on a row the cursor had left, which read as a selected state. */
.flow-ts-button:not(:disabled):hover,
.flow-ts-button:focus-visible {
  border-color: transparent;
  background: transparent;
  color: var(--accent);
  text-decoration: underline;
}

.flow-ts-input:focus,
.flow-ts-edit:focus,
.flow-row-title-input:focus {
  border-color: var(--accent);
}

/* The timestamp is a link-shaped control, not a field: an accent border on focus
   boxed it like an input — a pill around ⏸ 00:00 — right next to the real input
   it toggles into. Colour and underline carry hover and focus; a ring appears
   only for keyboard focus, and never draws a box around the glyph. */
.flow-ts-button:focus {
  border-color: transparent;
  outline: 0;
}

.flow-ts-button:focus-visible,
.flow-chapter-ts:focus-visible {
  border-radius: var(--radius-sm);
  outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
  outline-offset: 1px;
}

.flow-ts-input::placeholder,
.flow-row-title-input::placeholder,
.flow-row-add .flow-row-title {
  color: var(--muted);
}

.flow-row-add .flow-row-title {
  flex: 0 0 auto;
}

.flow-row-add:hover .flow-row-title {
  color: var(--accent);
}

.flow-row-remove {
  flex: 0 0 auto;
  padding: 0 var(--space-1);
  background: transparent;
  color: var(--muted);
  font-size: 1.05rem;
  line-height: 1;
}

.flow-row-remove:hover {
  color: var(--urgent);
}

.flow-heat-card {
  position: relative;
  display: inline-grid;
  width: fit-content;
  max-width: calc(100% - var(--flow-row-heat-indent));
  align-items: center;
  gap: var(--space-1);
  justify-self: start;
  margin-left: var(--flow-row-heat-indent);
  border: 0;
  border-left: 2px solid color-mix(in srgb, var(--flow-heat) 42%, var(--line));
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  font-family: var(--font-ui);
  padding: var(--space-1) 0 var(--space-1) var(--space-3);
  text-align: left;
}

.flow-heat-card:hover,
.flow-heat-card[aria-expanded="true"] {
  border-color: var(--flow-heat);
  color: var(--ink);
}

.flow-heat-flames,
.flow-heat-meta {
  position: relative;
}

.flow-heat-flames {
  font-size: 0.92rem;
  line-height: 1;
  white-space: nowrap;
}

.flow-heat-meta {
  color: var(--muted);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flow-moment-comments {
  margin-left: var(--flow-row-heat-indent);
  border-left: 1px solid var(--line);
  padding: 0 0 0 var(--space-3);
}

.flow-moment-comment-group + .flow-moment-comment-group {
  border-top: 1px solid var(--line);
}

.flow-moment-comment-heading {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0;
  padding-top: var(--space-3);
  text-transform: uppercase;
}

/* The video's own chapters (M5): a compact optional reference list. */
.flow-chapters {
  display: grid;
  width: 100%;
  justify-items: start;
  gap: var(--space-2);
  margin: 0;
}

/* Same button as .flow-suggest-button / .flow-probe-open — the step's three
   optional tools read as one set. */
.flow-chapters-toggle {
  display: inline-flex;
  width: auto;
  min-height: 32px;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  font-weight: 680;
}

.flow-chapters-toggle:hover,
.flow-chapters-toggle:focus-visible {
  background: var(--soft);
  outline: 0;
}

/* Points down while the list is closed, up while it's open — the rotation is
   the whole animation, so one glyph covers both. */
.flow-chapters-caret {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  color: var(--clay);
  font-size: 1rem;
  line-height: 1;
  transform: rotate(90deg);
  transition: transform 0.15s ease;
}

.flow-chapters-toggle[aria-expanded="true"] .flow-chapters-caret {
  transform: rotate(-90deg);
}

.flow-chapters-label {
  flex: 0 0 auto;
}

.flow-chapters-count {
  flex: 0 0 auto;
  min-width: 18px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--soft) 64%, transparent);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.64rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* The list scrolls inside its own box instead of growing the modal. A source can
   have thirty chapters, and expanding them used to add all thirty to the card's
   height at once — which, on a centered card, threw the whole dialog upward and
   moved the excerpt rows out from under the cursor. Bounded here, opening the
   list costs the same space every time. */
.flow-chapters-list {
  display: grid;
  width: 100%;
  max-height: min(232px, 38vh);
  gap: 0;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
  overscroll-behavior: contain;
}

.flow-chapter {
  position: relative;
  display: grid;
  grid-template-columns: 18px minmax(58px, 68px) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
}

.flow-chapter::before {
  content: "";
  width: 18px;
  height: 18px;
}

.flow-chapter + .flow-chapter {
  border-top: 0;
}

.flow-chapter + .flow-chapter::after {
  position: absolute;
  top: 0;
  right: var(--space-3);
  left: calc(18px + (2 * var(--space-3)));
  height: 1px;
  content: "";
  background: color-mix(in srgb, var(--line) 60%, transparent);
}

.flow-chapter-ts {
  padding: 2px 3px;
  background: transparent;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  text-align: left;
}

.flow-chapter-ts:not(:disabled):hover,
.flow-chapter-ts:not(:disabled):focus-visible {
  color: var(--accent);
  outline: 0;
  text-decoration: underline;
}

.flow-chapter-label {
  min-width: 0;
  overflow: hidden;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.86rem;
  line-height: var(--line-ui);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flow-chapter-add {
  flex: 0 0 auto;
  padding: 3px var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 0.76rem;
  font-weight: 620;
}

.flow-chapter-add:not(:disabled):hover,
.flow-chapter-add:not(:disabled):focus-visible {
  border-color: var(--accent);
  color: var(--accent);
  outline: 0;
}

.flow-chapter-add:disabled {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  opacity: 0.8;
}

/* Step 3 — rooms are cycled, not stacked. */
.flow-roomnav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.flow-arrow {
  display: grid;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1;
}

.flow-arrow:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}

.flow-roomnav-center {
  position: relative;
  display: flex;
  flex: 0 0 auto;
  width: 104px;
  height: 32px;
  align-items: center;
  justify-content: center;
}

.flow-roomnav-count {
  color: var(--muted);
  font-family: var(--font-ui);
  font-size: 0.96rem;
  font-weight: 700;
  line-height: 1.05;
  transform: translateY(1px);
}

.flow-dots {
  position: absolute;
  top: calc(50% + 14px);
  left: 50%;
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  gap: 5px;
  transform: translateX(-50%);
}

.flow-dot {
  width: 5px;
  height: 5px;
  padding: 0;
  border-radius: 50%;
  background: var(--line);
}

.flow-dot[aria-current="true"] {
  width: 7px;
  height: 7px;
  background: var(--accent);
}

.flow-roomcard {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  overflow: hidden;
}

.flow-roomcard-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line);
  background: var(--soft);
}

/* The source moment this room is linked to (e.g. 21:13) — a quiet timestamp
   chip beside the room icon, so the author sees where in the video it lives. */
.flow-room-ts {
  flex: 0 0 auto;
  width: 74px;
  padding: 2px var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--muted);
  font: 600 0.72rem var(--font-ui);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

input.flow-room-ts:hover {
  border-color: color-mix(in srgb, var(--accent) 34%, var(--line));
}

input.flow-room-ts:focus {
  border-color: var(--accent);
  color: var(--ink);
  outline: 0;
}

input.flow-room-ts::placeholder {
  color: var(--muted);
}

input.flow-room-ts.is-bad-time,
input.flow-room-ts.is-bad-time:hover,
input.flow-room-ts.is-bad-time:focus {
  border-color: var(--urgent);
  color: var(--urgent);
}

/* Inside the room card the message sits between the head and the fields, so it
   carries the card's own gutter rather than the row's. */
.flow-roomcard .flow-time-error {
  padding: var(--space-2) var(--space-3) 0;
}

/* The room's one title, edited where it is read — there is no Title field
   below, because that was the AI title and the room title, twice. */
.flow-room-title {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--space-1) var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 700;
  line-height: var(--line-ui);
}

.flow-room-title-icon {
  width: 20px;
  height: 18px;
}

.flow-room-title-icon svg {
  width: 20px;
  height: 18px;
}

input.flow-room-title:hover {
  border-color: var(--line);
}

input.flow-room-title:focus {
  border-color: var(--accent);
  background: var(--paper);
  outline: 0;
}

.flow-room-title::placeholder {
  color: var(--muted);
  font-weight: 500;
}

/* Locked state: the same card as a confirmation. The title keeps its weight but
   drops the input's padding/hover so it reads as a heading, not a field. */
.flow-room-title-static {
  border-color: transparent;
  padding-left: var(--space-2);
  cursor: default;
}

.flow-room-title-static:hover {
  border-color: transparent;
}

.flow-roomcard-body {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-3);
}

/* A locked field's value: reading type under the label, no input chrome — the
   card is a decision to confirm, not a form to fill. */
.flow-value {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-reading);
  font-size: 0.92rem;
  line-height: var(--line-reading);
  white-space: pre-wrap;
}

/* Mobile is a full-screen sheet regardless of the desktop chrome. */
@media (max-width: 640px) {
  .modal-overlay:has(.modal-card-flow) {
    padding: 0;
  }

  .modal-card-flow {
    width: 100%;
    height: 100%;
    max-height: 100%;
    border: 0;
    border-radius: 0;
  }

  .flow-steps {
    gap: var(--space-4);
  }

  .flow-roomcard-head {
    gap: var(--space-2);
  }

  .flow-row {
    grid-template-columns: 18px minmax(60px, 76px) minmax(0, 1fr);
    gap: var(--space-2);
  }

  .flow-row-remove {
    grid-column: 3;
    justify-self: start;
  }

  .flow-heat-card,
  .flow-moment-comments {
    max-width: 100%;
    margin-left: calc(18px + var(--space-2));
  }

  .flow-foot {
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  .flow-foot-note {
    flex: 1 0 100%;
  }
}

.owner-line-button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  background: transparent;
  color: color-mix(in srgb, var(--muted) 68%, var(--paper));
  font-family: var(--font-ui);
  font-size: 0.8rem;
  vertical-align: middle;
}

.owner-line-button:hover {
  color: var(--ink);
}

/* ── The comments probe (V6) ──────────────────────────────────────────────────
   An experiment inside step 2, not a feature: does viewer-written timestamp
   chatter cluster tightly enough to anchor rooms on chapterless videos? Styled
   plainly on purpose — the comments are shown raw so the diagnostic line can be
   checked against them. This whole block goes when the question is answered.
   See docs/topic-creation.md. */
.flow-probe-open {
  min-height: 32px;
  max-width: 100%;
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 680;
}

.flow-probe-block {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: flex-start;
  margin: -2px 0 0;
}

.flow-probe-open:hover {
  background: var(--soft);
}

/* What the run found reads as the button's own caption, not as a new section of
   the modal. It used to sit under a full-width rule at body size, which gave a
   one-line diagnostic the weight of a heading and cut the block in two — the
   answer looked like it belonged to the step rather than to the button that
   fetched it. Sized and coloured like the other secondary copy in the flow, set
   close under the control, no rule. */
.flow-probe-note,
.flow-probe-summary {
  flex: 0 0 100%;
  margin: 0;
  /* Indented to the button's own label — its 12px padding plus the 1px border —
     so the answer hangs off the words that fetched it rather than starting a
     fresh column at the modal's edge. */
  padding-left: calc(var(--space-3) + 1px);
  color: var(--muted);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  line-height: var(--line-ui);
}

.flow-probe-note {
  margin-top: var(--space-2);
}

.flow-probe {
  flex: 0 0 100%;
  margin-top: var(--space-2);
}

/* The count is the deliverable — it keeps the ink while the sentence around it
   stays quiet. */
.flow-probe-summary strong {
  color: var(--ink);
  font-weight: 680;
}

/* Sits inline at the end of the sentence that explains the failure, so the
   remedy is where the reason is rather than back up at a greyed-out button. */
.flow-probe-retry {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  margin-left: var(--space-2);
  padding: 0 var(--space-2);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: var(--radius-pill);
  background: var(--panel);
  color: var(--accent-dark);
  font: 640 0.78rem var(--font-ui);
  cursor: pointer;
}

.flow-probe-retry.is-retrying {
  border-color: var(--line);
  color: var(--muted);
  cursor: default;
}

.flow-probe-retry:hover,
.flow-probe-retry:focus-visible {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--panel));
  color: var(--accent-dark);
  outline: 0;
}

.flow-probe-comment {
  border-bottom: 1px solid var(--line);
  font-size: 0.85rem;
  padding: var(--space-2) 0;
}
.flow-probe-comment.is-stamped { background: var(--paper-2, transparent); }
.flow-probe-meta { color: var(--muted); font-size: 0.75rem; }
.flow-probe-text { color: var(--ink); white-space: pre-wrap; }
