/* Dialogue 2.0 - module styles.
   Everything scoped under .dialogue2; nothing leaks into the site.
   All color and rhythm through variables: reskinning later is twelve
   lines, not a redesign. Dark by default. */

/* The app breaks out to full viewport width (below). 100vw includes the
   vertical scrollbar, so the breakout is a scrollbar-width wider than the
   document and the page grows a horizontal scrollbar. Clip it at the
   document, but ONLY on pages that actually contain the app (:has), so
   nothing leaks to the rest of the site; clip (not hidden) so the sticky
   player is untouched. */
body:has(.dialogue2) { overflow-x: clip; }

.dialogue2 {
  --d2-bg:        #16181d;
  --d2-surface:   #1e2128;
  --d2-surface2:  #262a33;
  --d2-border:    #333845;
  --d2-text:      #e6e8ec;
  --d2-text-dim:  #9aa1ad;
  --d2-accent:    #6aa9ff;
  --d2-accent-dim:#3a5b8c;
  /* The flow veil dissolves into the page's own background, not the
     transcript card, so the fading edges feel like part of the screen.
     Match the site background (black); reskin here if the page differs. */
  --d2-veil:      #000;
  --d2-radius:    8px;
  --d2-gap:       1rem;
  --d2-font:      system-ui, -apple-system, "Segoe UI", sans-serif;

  font-family: var(--d2-font);
  color: var(--d2-text);
  /* No slab of its own: the app sits directly on the site's background so
     only the inner containers carry surface color. */
  background: transparent;
  /* Full-bleed breakout of the theme's content column, then center the
     content up to --d2-max. The artifact deserves the screen. */
  --d2-max: 1600px;
  width: 100vw;
  max-width: 100vw;
  /* The padding lives INSIDE the 100vw, not on top of it. Without this the
     wrapper is 100vw plus two gutters wide unless the theme happens to
     reset box-sizing globally, and the right edge leaves the screen. */
  box-sizing: border-box;
  position: relative;
  left: 50%;
  margin-left: -50vw;
  padding: var(--d2-gap) max(var(--d2-gap), calc((100vw - var(--d2-max)) / 2));
  border-radius: 0;
  /* Belt to the braces below: nothing inside may widen the page. clip,
     never hidden, so the sticky player is untouched (clip makes no scroll
     container). Vertical overflow stays visible. */
  overflow-x: clip;
  overflow-y: visible;
}

.dialogue2 a { color: var(--d2-accent); }
.dialogue2 button {
  background: var(--d2-surface2);
  color: var(--d2-text);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .45rem .9rem;
  cursor: pointer;
  font: inherit;
}
.dialogue2 button:hover { border-color: var(--d2-accent-dim); }
.dialogue2 input, .dialogue2 select, .dialogue2 textarea {
  background: var(--d2-surface);
  color: var(--d2-text);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .45rem .6rem;
  font: inherit;
  width: 100%;
  box-sizing: border-box;
}

.dialogue2-loading, .dialogue2-empty {
  color: var(--d2-text-dim);
  padding: 2rem 0;
  text-align: center;
}
.dialogue2-gate { max-width: 400px; margin: 3rem auto; }

/* --- Artifact list ------------------------------------------------ */
.d2-list { display: flex; flex-direction: column; gap: .5rem; }
.d2-list-item {
  background: var(--d2-surface);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .8rem 1rem;
  cursor: pointer;
}
.d2-list-item:hover { border-color: var(--d2-accent-dim); }
.d2-list-item .d2-kind {
  color: var(--d2-text-dim);
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .06em;
}

/* --- Curator form ------------------------------------------------- */
.d2-curate {
  background: var(--d2-surface);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: var(--d2-gap);
  margin-top: var(--d2-gap);
  display: none;
}
.d2-curate.open { display: block; }
.d2-curate label { display: block; margin: .6rem 0 .2rem; color: var(--d2-text-dim); font-size: .85rem; }
.d2-curate textarea { min-height: 8rem; font-family: monospace; font-size: .8rem; }
.d2-curate .d2-actions { margin-top: .8rem; }

/* --- The spine: player + transcript ------------------------------- */
/* The artifact is the thing encountered; the transcript is its
   companion. Title, curated-by, and the curator strip now sit in a
   header ABOVE the spine (full width), so the video and the transcript
   are two aligned sibling panels rather than the video pushed down the
   left column by the header while the transcript starts at the top.
   Tops align (align-items: start); a JS pass matches the transcript box
   height to the video so the two panels are the same size. The split
   says the artifact leads: roughly 55/45 so the gutter has room to
   stand beside the text. */
.d2-artifact-head { margin-bottom: var(--d2-gap); }
.d2-spine { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: calc(var(--d2-gap) * 1.5); align-items: start; }
/* Grid items default to min-width:auto, which lets content (a wide video,
   an unbreakable string) force a column wider than its track. Safari in
   particular sizes the video column from the video's intrinsic width
   without this. */
.d2-spine > * { min-width: 0; }
@media (max-width: 800px) { .d2-spine { grid-template-columns: minmax(0, 1fr); } }

.d2-player-wrap { position: sticky; top: var(--d2-gap); min-width: 0; }
.d2-player-wrap video {
  /* Compressed chrome (Michael, 2026-08-08): the video yields about a
     quarter of its height so the constellation rides near the top of
     the screen. Width follows aspect; no letterboxing. The transcript
     matches this height via syncHeight. */
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: min(44vh, calc(100vh - 240px));
  margin: 0 auto;
  border-radius: var(--d2-radius);
  background: #000;
}
.d2-player-wrap audio {
  width: 100%;
  border-radius: var(--d2-radius);
  background: #000;
  display: block;
}
.d2-title { margin: 0; font-size: 1.1rem; font-weight: 600; }
.d2-headrow { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  margin-bottom: .55rem; }
.d2-headrow .d2-curated-by { margin: 0; }
.d2-headspacer { flex: 1; }
.d2-backbtn { font-size: .85rem; padding: .1rem .55rem; }
.d2-headbtn { font-size: .75rem; padding: .15rem .6rem; color: var(--d2-text-dim); }
#d2-strip-slot { margin-bottom: .55rem; }
#d2-strip-slot[hidden] { display: none !important; }

/* --- Transcript --------------------------------------------------- */
.d2-transcript {
  position: relative; /* gutter chips position against the scroll content */
  background: var(--d2-surface);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  /* Top room clears the fade so the first cue begins BELOW the gradient
     rather than tucked up under its most solid part; the fade is 34% of
     the pane, so ~42% lands the opening words in full view, near center.
     Bottom room lets the last cue scroll up clear of the bottom fade.
     Blank room, not a spacer element, so cue indices and gutter math are
     untouched. */
  /* Fallback only (audio / pre-metadata): height-relative vh, equal top
     and bottom, so the active line can center. In the normal case
     syncHeight sets exact top and bottom padding as ~half the video
     height, overriding these. */
  padding: 22vh 0;
  /* A JS pass sets an explicit pixel height here to match the video
     panel; this cap is the fallback when the media never reports a
     size (audio, load failure). */
  max-height: calc(100vh - 160px);
  overflow-y: auto;
  /* No ambient smooth scrolling (2026-09-14 pin, the hand wins). With
     scroll-behavior: smooth here, every programmatic scrollTop was
     animated, and Safari does not cancel that animation when a hand keeps
     scrolling, so the two added up and the pane lurched. Smoothness is
     now asked for per move in JS, never assumed. */
}
.d2-cue {
  display: flex;
  gap: .8rem;
  padding: .35rem 1rem;
  cursor: pointer;
  line-height: 1.55;
}
.d2-cue:hover { background: var(--d2-surface2); }
.d2-cue.active { background: var(--d2-surface2); box-shadow: inset 3px 0 0 var(--d2-accent); }
.d2-cue-time {
  color: var(--d2-text-dim);
  font-size: .75rem;
  font-variant-numeric: tabular-nums;
  padding-top: .25rem;
  min-width: 3.2rem;
  user-select: none;
  flex-shrink: 0;
}
.d2-cue-text { flex: 1 1 0; min-width: 0; overflow-wrap: anywhere; }
.d2-no-transcript { color: var(--d2-text-dim); padding: 1rem; }

.d2-remove {
  font-size: .7rem;
  padding: .1rem .5rem;
  margin-left: .6rem;
  color: var(--d2-text-dim);
}

/* --- Stage two: marking ------------------------------------------- */
.d2-dim { color: var(--d2-text-dim); font-size: .85rem; }

.d2-transcript-wrap { position: relative; }
.d2-return {
  position: absolute;
  bottom: .8rem;
  left: 50%;
  transform: translateX(-50%);
  font-size: .8rem;
  opacity: .92;
}

.d2-cue { position: relative; }
.d2-cue .d2-dot {
  position: relative;
  opacity: 0;
  color: var(--d2-text-dim);
  cursor: pointer;
  padding: 0 .35rem;
  align-self: flex-start;
  user-select: none;
  border-radius: 4px;
  transition: opacity .12s ease, color .12s ease, background .12s ease;
}
.d2-cue:hover .d2-dot,
.d2-cue .d2-dot:focus-visible { opacity: 1; }
.d2-cue .d2-dot:hover { color: var(--d2-accent); }
.d2-cue .d2-dot:focus-visible {
  outline: 2px solid var(--d2-accent);
  outline-offset: 1px;
}
.d2-cue.marked { box-shadow: inset 3px 0 0 var(--d2-accent-dim); }
.d2-cue.active { box-shadow: inset 3px 0 0 var(--d2-accent); }

/* A flagged line reads unmistakably as marked: the flag stays solid and
   lit, sits in a soft accent chip, and the line carries an accent edge.
   No guessing whether the click registered. */
.d2-cue.flagged .d2-dot {
  opacity: 1;
  color: var(--d2-accent);
  background: var(--d2-accent-dim);
}
.d2-cue.flagged { box-shadow: inset 3px 0 0 var(--d2-accent); }

/* The flag explains itself. Every first-time viewer reaches for it, so a
   plain-language hint sits beside it on hover or keyboard focus, instant
   (no native-title delay) and worded to the current state. It grows
   leftward from the right edge so it never widens the page. */
.d2-cue .d2-dot::after {
  content: "Flag this moment for later review";
  position: absolute;
  right: 100%;
  top: 50%;
  transform: translateY(-50%);
  margin-right: .45rem;
  white-space: nowrap;
  background: var(--d2-text);
  color: var(--d2-bg);
  font-size: .72rem;
  line-height: 1;
  padding: .35rem .5rem;
  border-radius: 4px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease;
  z-index: 5;
}
.d2-cue.flagged .d2-dot::after { content: "Flagged \2014 click to remove"; }
.d2-cue .d2-dot:hover::after,
.d2-cue .d2-dot:focus-visible::after { opacity: 1; }

/* A quick pop the instant you press, so the act is felt before the
   record round-trips and the lit state settles in. */
@keyframes d2-dot-pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.5); }
  100% { transform: scale(1); }
}
.d2-cue .d2-dot.d2-dot-just { animation: d2-dot-pop .28s ease; }

/* The tool rail: your tools' home, a narrow section down the side of
   the surface. Bare until a highlight fills it; a highlight activates
   it with the acts available on those words. It never floats over the
   room, so it never collides with a button or a thread. Struck text
   stays a face like any other: still selectable, still diggable,
   because a strike declares a change of mind, it does not erase the
   ground. Future tools (agree, cite, add) drop into this same rail. */
.d2-rail {
  flex: 0 0 22%;
  min-width: 8.5rem;
  align-self: stretch;
  border-left: 1px solid var(--d2-border);
  padding-left: .8rem;
  margin-left: .3rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
/* An explicit display beats the [hidden] user-agent rule, so hidden
   rails leaked as an empty box in the gutter. Make hidden win. */
.d2-rail[hidden] { display: none !important; }
.d2-rail-transcript {
  /* Docked to the right of the transcript when no room is open. */
  position: fixed;
  z-index: 45;
  top: 12vh;
  right: max(1rem, calc((100vw - 1100px) / 2));
  width: 12rem;
  max-height: 70vh;
  overflow-y: auto;
  background: var(--d2-surface);
  border: 1px solid var(--d2-accent-dim);
  border-left: 1px solid var(--d2-accent-dim);
  border-radius: var(--d2-radius);
  padding: .7rem .8rem;
  box-shadow: 0 8px 30px rgba(0,0,0,.5);
}
.d2-rail-where {
  font-size: .68rem;
  color: var(--d2-text-dim);
  margin: -.1rem 0 .3rem;
}
.d2-rail-head {
  font-size: .68rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .07em; color: var(--d2-accent);
}
.d2-rail-on {
  font-size: .72rem; color: var(--d2-text-dim); font-style: italic;
  border-left: 2px solid var(--d2-accent-dim);
  padding-left: .45rem;
  margin-bottom: .2rem;
}
.d2-rail-empty {
  font-size: .72rem; color: var(--d2-text-dim); font-style: italic;
  opacity: .8;
}
.d2-rail-hint {
  font-size: .68rem; color: var(--d2-text-dim); opacity: .7;
  margin-top: .2rem;
}
.d2-rail-tools { display: flex; flex-direction: column; gap: .3rem; }
.d2-tool {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--d2-surface2);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .45rem .55rem;
  cursor: pointer;
}
.d2-tool:hover { border-color: var(--d2-accent-dim); }
.d2-tool-label { display: block; font-size: .85rem; color: var(--d2-text); }
.d2-tool.dig .d2-tool-label { color: var(--d2-accent); }
.d2-tool-sub { display: block; font-size: .68rem; color: var(--d2-text-dim); margin-top: .05rem; }

/* A highlight held live glows a touch brighter, so the rail's "on ..."
   and the words on the face read as the same act. */
.d2-live-sel { background: rgba(106,169,255,.28); border-radius: 2px; }

/* The roster: who reached this face, a navigation aid in the rail.
   Ordered by how much each highlighted. Hover or tap paints their span
   on the words. When you hold a selection, people on your words stay
   lit and the rest fade, a mirror of your gesture, never a ranking. */
.d2-roster {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  margin-top: .3rem;
}
.d2-roster-name {
  display: flex;
  align-items: center;
  gap: .35rem;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: calc(var(--d2-radius) - 2px);
  padding: .35rem .4rem;
  cursor: pointer;
  color: var(--d2-text);
}
.d2-roster-name:hover, .d2-roster-name.active { background: var(--d2-surface2); }
.d2-roster-name.me .d2-roster-who { color: var(--d2-accent); }
.d2-roster-who { font-size: .82rem; }
.d2-roster-name.faded { opacity: .35; }
.d2-roster-digs {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: .2rem;
  font-size: .7rem;
  color: var(--d2-text-dim);
}

.d2-compose {
  position: fixed;
  z-index: 70;
  left: 50%;
  bottom: 2rem;
  transform: translateX(-50%);
  width: min(640px, calc(100vw - 2rem));
  background: var(--d2-surface2);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: var(--d2-gap);
  box-shadow: 0 8px 30px rgba(0,0,0,.55);
}
.d2-compose-quote {
  color: var(--d2-text-dim);
  font-style: italic;
  border-left: 3px solid var(--d2-accent-dim);
  padding-left: .7rem;
  margin-bottom: .6rem;
  max-height: 6rem;
  overflow-y: auto;
}
.d2-compose textarea { min-height: 5rem; }
.d2-compose .d2-actions { margin-top: .6rem; }

.d2-margin {
  margin-top: var(--d2-gap);
  background: var(--d2-surface);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .8rem 1rem;
  max-height: 40vh;
  overflow-y: auto;
}
.d2-margin-head {
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--d2-text-dim);
  margin-bottom: .6rem;
}
.d2-mark {
  padding: .5rem 0;
  border-top: 1px solid var(--d2-border);
  cursor: pointer;
}
.d2-mark:first-of-type { border-top: none; }
.d2-mark:hover { background: var(--d2-surface2); }
.d2-mark-time { color: var(--d2-text-dim); font-size: .75rem; font-variant-numeric: tabular-nums; }
.d2-mark-quote {
  color: var(--d2-text-dim);
  font-style: italic;
  font-size: .85rem;
  margin: .2rem 0;
}
.d2-mark-flag { display: flex; gap: .6rem; align-items: baseline; }

/* --- Stage three: reveal ------------------------------------------ */
.d2-cue.gathered { background: linear-gradient(90deg, var(--d2-surface2), transparent 70%); }
.d2-cue.gathered.pulse { animation: d2pulse 1.6s ease-out 1; }
@keyframes d2pulse {
  0%   { background: var(--d2-accent-dim); }
  100% { background: linear-gradient(90deg, var(--d2-surface2), transparent 70%); }
}
.d2-others-head { margin-top: 1rem; }
.d2-mark-author { font-size: .8rem; color: var(--d2-accent); }

/* --- Join / sign in ------------------------------------------------ */
.d2-identity { color: var(--d2-text-dim); font-size: .85rem; margin-bottom: var(--d2-gap); }
.d2-auth {
  background: var(--d2-surface);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: var(--d2-gap);
  margin-bottom: var(--d2-gap);
  max-width: 420px;
}
.d2-auth label { display: block; margin: .6rem 0 .2rem; color: var(--d2-text-dim); font-size: .85rem; }
.d2-auth .d2-actions { margin-top: .8rem; }
/* The door (v0.90.0): one form at a time, one primary button. */
.d2-door-reason { color: var(--d2-text-dim); font-size: .92rem; margin: 0 0 .7rem; line-height: 1.45; }
.d2-door-title { font-size: 1.05rem; font-weight: 600; color: var(--d2-text); margin: 0 0 .2rem; }
.d2-door-pane input { width: 100%; box-sizing: border-box; }
.d2-door-pane .d2-actions { margin-top: .9rem; display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.dialogue2 .d2-door-go { background: var(--d2-accent); border-color: var(--d2-accent); color: #0b0d12; font-weight: 600; }
.dialogue2 .d2-door-go:disabled { opacity: .6; cursor: default; }
.d2-door-alt { margin-top: .8rem; display: flex; justify-content: space-between; gap: .8rem;
  flex-wrap: wrap; font-size: .85rem; color: var(--d2-text-dim); }
.d2-door-alt a { color: var(--d2-accent); }
.d2-door .d2-askprev-panel { position: relative; max-width: 400px; border-color: var(--d2-accent); }
.d2-door label { display: block; margin: .6rem 0 .2rem; color: var(--d2-text-dim); font-size: .85rem; }
.dialogue2 .d2-door-x { position: absolute; top: .5rem; right: .5rem; }
.dialogue2 .d2-door-inline { padding: .1rem .55rem; font-size: .85rem; }
.d2-th-guest { padding: .8rem 0 .4rem; }
.d2-th-guest p { margin: 0 0 .7rem; color: var(--d2-text-dim); }

/* --- Chapters & release ------------------------------------------- */
.d2-chapter {
  display: flex;
  align-items: baseline;
  gap: .7rem;
  padding: .9rem 1rem .3rem;
  border-top: 1px solid var(--d2-border);
  margin-top: .4rem;
}
.d2-chapter:first-child { border-top: none; margin-top: 0; }
.d2-chapter-title {
  font-size: .8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--d2-accent);
}
.d2-chapter-span { font-size: .75rem; color: var(--d2-text-dim); font-variant-numeric: tabular-nums; }
.d2-ch-remove { font-size: .7rem; padding: .05rem .45rem; color: var(--d2-text-dim); }

.d2-draft { opacity: .92; }
.d2-draft-badge {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--d2-text-dim);
  border: 1px dashed var(--d2-border);
  border-radius: 4px;
  padding: 0 .35rem;
}
.d2-release { font-size: .75rem; padding: .15rem .6rem; border-color: var(--d2-accent-dim); }

/* --- Identity, attribution, and the curator strip ------------------ */

/* Who you are and what stance you hold here, unmissable but quiet. */
.d2-identity-strip {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  flex-wrap: wrap;
  font-size: .85rem;
  color: var(--d2-text-dim);
  margin-bottom: var(--d2-gap);
}
.d2-identity-strip strong { color: var(--d2-text); }
.d2-role {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .07em;
  border: 1px solid var(--d2-border);
  border-radius: 4px;
  padding: .05rem .45rem;
}
.d2-role-curator { color: var(--d2-accent); border-color: var(--d2-accent-dim); }

/* Plain attribution: every artifact names its curator, to everyone. */
.d2-curated-by { font-size: .8rem; color: var(--d2-text-dim); margin: -.3rem 0 .6rem; }

/* The curator strip: the editorial state of the space, on your own
   artifact only. State, never activity metrics. */
.d2-curator-strip {
  background: var(--d2-surface);
  border: 1px solid var(--d2-accent-dim);
  border-radius: var(--d2-radius);
  padding: .6rem .9rem;
  margin-bottom: var(--d2-gap);
  font-size: .85rem;
}
.d2-curator-strip-head {
  font-size: .7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--d2-accent);
  margin-bottom: .35rem;
}
.d2-curator-strip .d2-state-line { margin: .15rem 0; color: var(--d2-text); }
.d2-curator-strip .d2-state-line .d2-dim { color: var(--d2-text-dim); }

/* Development-only affordance; never present unless the site defines
   DIALOGUE2_DEV. Styled to look like scaffolding, not furniture. */
.d2-dev-reset {
  font-size: .7rem;
  padding: .05rem .5rem;
  border-style: dashed;
  color: var(--d2-text-dim);
}

/* --- Focus flow ---------------------------------------------------- */
/* While following playback the transcript is a flow, not a document:
   edges soften so the eye stays near now, and the scrollbar withdraws.
   Reaching in (hover) brings the scrollbar; actually scrolling lifts
   the veil (handled as the existing following=false state); play
   returns the flow. No toggle: the interface answers intent. */

.d2-fade {
  position: absolute;
  left: 0; right: 0;
  height: 34%;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  z-index: 2;
}
.d2-fade-top {
  top: 0;
  background: linear-gradient(to bottom,
    var(--d2-veil) 0%,
    color-mix(in srgb, var(--d2-veil) 72%, transparent) 12%,
    color-mix(in srgb, var(--d2-veil) 32%, transparent) 30%,
    transparent 56%);
  border-radius: var(--d2-radius) var(--d2-radius) 0 0;
}
.d2-fade-bottom {
  bottom: 0;
  background: linear-gradient(to top,
    var(--d2-veil) 0%,
    color-mix(in srgb, var(--d2-veil) 72%, transparent) 12%,
    color-mix(in srgb, var(--d2-veil) 32%, transparent) 30%,
    transparent 56%);
  border-radius: 0 0 var(--d2-radius) var(--d2-radius);
}
.d2-transcript-wrap.focused .d2-fade { opacity: 1; }

/* Scrollbar withdraws in flow, returns on reach-in. Its width never
   changes, only its visibility; a width change rewraps the text, which
   fires a scroll event, which read as the person scrolling. */
.d2-transcript { scrollbar-width: thin; }

/* --- Your distilled conversation (in development) ------------------- */
/* Marked out as in-progress on purpose: a dashed edge and a badge, so the
   group reads it as an early output rather than a finished surface. */
.d2-distilled {
  margin-top: calc(var(--d2-gap) * 1.5);
  padding: var(--d2-gap);
  border: 1px dashed var(--d2-accent-dim);
  border-radius: var(--d2-radius);
  background: color-mix(in srgb, var(--d2-surface) 55%, transparent);
}
.d2-distilled[hidden] { display: none; }
.d2-distilled-head { display: flex; align-items: center; gap: .6rem; margin-bottom: .5rem; }
.d2-distilled-title { font-size: 1.05rem; font-weight: 600; }
.d2-dev-badge {
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--d2-accent);
  border: 1px solid var(--d2-accent-dim);
  border-radius: 999px;
  padding: .1rem .5rem;
}
.d2-distilled-note {
  color: var(--d2-text-dim);
  font-size: .85rem;
  line-height: 1.55;
  max-width: 65ch;
  margin: 0 0 var(--d2-gap);
}
.d2-distilled-item { padding: .6rem 0; border-top: 1px solid var(--d2-border); }
.d2-distilled-item:first-of-type { border-top: 0; }
.d2-distilled-empty { padding: .4rem 0; }
.d2-transcript::-webkit-scrollbar { width: 8px; }
.d2-transcript::-webkit-scrollbar-thumb { background: var(--d2-border); border-radius: 4px; }
.d2-transcript-wrap.focused .d2-transcript { scrollbar-color: transparent transparent; }
.d2-transcript-wrap.focused .d2-transcript::-webkit-scrollbar-thumb { background: transparent; }
.d2-transcript-wrap.focused:hover .d2-transcript { scrollbar-color: auto; }
.d2-transcript-wrap.focused:hover .d2-transcript::-webkit-scrollbar-thumb { background: var(--d2-border); }

/* --- The reading margin: presence, not content -------------------- */
/* A small count per warm cue, right-aligned in a narrow rail inside
   the transcript scroll container so it flows with playback and
   inherits the fades and veil. It says a place is warm and whether you
   are already in it; it never shows what was said. */

.dialogue2 { --d2-gutter-w: 0px; }
@media (min-width: 1100px) { .dialogue2 { --d2-gutter-w: 92px; } }
@media (min-width: 1400px) { .dialogue2 { --d2-gutter-w: 96px; } }

.d2-transcript.has-gutter { padding-right: calc(var(--d2-gutter-w) + .6rem); }

.d2-presence {
  position: absolute;
  right: .5rem;
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: var(--d2-surface2);
  border: 1px solid var(--d2-border);
  border-radius: 999px;
  padding: .1rem .5rem;
  font-size: .75rem;
  color: var(--d2-text-dim);
  cursor: pointer;
  user-select: none;
  z-index: 1;
  white-space: nowrap;
}
.d2-presence:hover { border-color: var(--d2-accent-dim); color: var(--d2-text); }
.d2-presence.mine { border-color: var(--d2-accent-dim); }
.d2-presence-svg { fill: none; stroke: var(--d2-accent); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.d2-presence-svg circle { fill: none; }
.d2-presence-n { font-variant-numeric: tabular-nums; color: var(--d2-text); }
.d2-presence-you { color: var(--d2-accent); font-style: italic; }

/* --- The gather surface: where dialogue happens -------------------- */
/* Selection brings the caught marks up to meet you, in front of
   everything, with one place to respond to the text. Content lives
   here, never in the reading margin. */

.d2-gather {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: rgba(0,0,0,.55);
  /* Interim nudge: the dev site's own chrome sits over the top of the
     viewport, so the panel starts 100px lower to stay fully visible.
     Proper containment within the app surface is a later layout pass. */
  padding: calc(4vh + 100px) 1rem 4vh;
  overflow-y: auto;
}
/* The class sets display:flex, which would otherwise beat the browser's
   [hidden] rule and keep the surface painted after close. Make hidden
   win; the JS also toggles inline display as a belt. */
.d2-gather[hidden] { display: none !important; }
.d2-gather-panel {
  width: 100%;
  max-width: 820px;
  display: flex;
  align-items: stretch;
  gap: .3rem;
  background: var(--d2-surface);
  border: 1px solid var(--d2-accent-dim);
  border-radius: var(--d2-radius);
  padding: calc(var(--d2-gap) * 1.15);
  box-shadow: 0 12px 48px rgba(0,0,0,.6);
  line-height: 1.55;
}
.d2-room-main { flex: 1 1 auto; min-width: 0; }
/* Narrow screens: the rail drops below the room rather than squeezing
   it, still a section rather than a floating thing. */
@media (max-width: 620px) {
  .d2-gather-panel { flex-direction: column; }
  .d2-rail {
    flex-basis: auto;
    border-left: none;
    border-top: 1px solid var(--d2-border);
    padding-left: 0;
    padding-top: .6rem;
    margin-left: 0;
    margin-top: .4rem;
  }
  .d2-rail-tools { flex-direction: row; flex-wrap: wrap; }
  .d2-tool { width: auto; flex: 1 1 8rem; }
}
.d2-gather-head { display: flex; align-items: baseline; justify-content: space-between; }
.d2-gather-label {
  font-size: .7rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .07em; color: var(--d2-accent);
}
.d2-gather-close { font-size: .75rem; padding: .1rem .6rem; color: var(--d2-text-dim); }
.d2-gather-quote {
  margin: .6rem 0 1rem;
  padding-left: .7rem;
  border-left: 3px solid var(--d2-accent-dim);
  color: var(--d2-text);
  font-style: italic;
}
.d2-gather-section {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--d2-text-dim);
  margin: 1rem 0 .5rem;
  border-top: 1px solid var(--d2-border);
  padding-top: .7rem;
}
/* A private draft is editable in place until it enters the conversation:
   the body is a live textarea (autosaving), with a quiet status and a
   delete beneath it. Kept understated so editing feels like composing,
   not like operating a form. */
.d2-draft-edit {
  margin: .35rem 0 .1rem;
  min-height: 4.5rem;
  white-space: pre-wrap;
}
.d2-draft-tools {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: .6rem;
  margin-top: .15rem;
}
.d2-draft-saved {
  margin-right: auto;
  font-size: .72rem;
  color: var(--d2-text-dim);
  font-style: italic;
}
.d2-draft-delete {
  font-size: .72rem;
  padding: .1rem .5rem;
  color: var(--d2-text-dim);
  border-color: var(--d2-border);
}
.d2-draft-delete:hover { color: var(--d2-text); border-color: var(--d2-accent-dim); }
.d2-surfaced { padding: .5rem 0; }
.d2-surfaced.me { border-left: 2px solid var(--d2-accent-dim); padding-left: .5rem; margin-left: -.5rem; }
/* Mark bodies preserve the line breaks and paragraphs the author typed
   (or pasted); without this, HTML collapses newlines to single spaces and
   a multi-paragraph argument renders as one wall of text. wrap keeps long
   lines flowing normally. */
.d2-msg-body { white-space: pre-wrap; }
.d2-surfaced .d2-msg-body { margin-top: .15rem; user-select: text; cursor: text; }
.d2-surfaced .d2-mark-quote { user-select: text; cursor: text; }
.d2-gather-empty { color: var(--d2-text-dim); padding: .3rem 0 .2rem; }
/* The composer unfolded beneath the words it answers. Kept visually
   attached to its position: a quiet accent edge, the quoted anchor
   words, then the writing space. */
.d2-inline-compose {
  margin: .5rem 0 .8rem;
  padding: .4rem 0 .2rem .6rem;
  border-left: 2px solid var(--d2-accent-dim);
}
.d2-compose-on {
  font-size: .72rem;
  color: var(--d2-text-dim);
  font-style: italic;
  margin-bottom: .3rem;
}
.d2-inline-compose .d2-actions { margin-top: .4rem; }
#d2-room-cancel { color: var(--d2-text-dim); }
/* The curator's map of the dug mine. Heat classes shade the ground and
   the words by how many distinct people reached them, accumulated fact
   of walking; they are never applied to a comment or a person. */
.d2-map {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: rgba(0,0,0,.6);
  padding: calc(4vh + 100px) 1rem 4vh;
  overflow-y: auto;
}
.d2-map[hidden] { display: none !important; }
.d2-map-panel {
  width: 100%;
  max-width: 1060px;
  background: var(--d2-surface);
  border: 1px solid var(--d2-accent-dim);
  border-radius: var(--d2-radius);
  padding: calc(var(--d2-gap) * 1.15);
  box-shadow: 0 12px 48px rgba(0,0,0,.6);
}
.d2-map-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: .6rem; }
.d2-map-close { font-size: .75rem; padding: .1rem .6rem; color: var(--d2-text-dim); }
.d2-map-scroll { overflow-x: auto; }
.d2-map-scroll svg { display: block; }
.d2-map-detail {
  border-top: 1px solid var(--d2-border);
  margin-top: .8rem;
  padding-top: .8rem;
  font-size: .85rem;
}
.d2-map-detail-head { font-size: .75rem; color: var(--d2-text); margin-bottom: .5rem; }
.d2-map-ground { line-height: 1.6; margin-bottom: .7rem; color: var(--d2-text); }
.d2-map-person { padding: .12rem 0; }
.d2-map-name { font-weight: 600; }
.d2-map-agree { font-size: .78rem; color: var(--d2-accent); }
.d2-heat-1 { background: rgba(106,169,255,.14); }
.d2-heat-2 { background: rgba(106,169,255,.26); }
.d2-heat-3 { background: rgba(106,169,255,.38); }
.d2-heat-4 { background: rgba(106,169,255,.52); }
.d2-heat-5 { background: rgba(106,169,255,.66); }
.d2-tool-off { opacity: .45; cursor: not-allowed; }
.d2-tool-off:hover { background: inherit; }
/* The agreement control in the node bar. Names of those standing shown
   as presence, never a count that sorts. The agree control is an ICON
   in the node bar, sitting with the other node-bar marks; the step-back
   tools live in the rail, additive with the roster. */
.d2-agree-wrap {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  margin-left: .35rem;
  flex-wrap: wrap;
}
.d2-agree-names {
  font-size: .72rem;
  color: var(--d2-text-dim);
}
/* The control reads as what it is: a checkmark plus a word, "Agree" when
   you could stand, "Standing" when you do. Quiet by default but legible,
   filled accent when you stand, a ring when your step-back tools are up. */
.d2-agree-icon {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  height: 22px;
  padding: 0 .55rem;
  border: 1px solid var(--d2-border);
  border-radius: 999px;
  color: var(--d2-text);
  background: var(--d2-surface2);
  cursor: pointer;
  font-size: .72rem;
  line-height: 1;
}
.d2-agree-label { line-height: 1; }
.d2-agree-icon:hover { border-color: var(--d2-accent-dim); color: var(--d2-text); }
.d2-agree-icon.on {
  color: var(--d2-accent);
  border-color: var(--d2-accent);
  background: rgba(106,169,255,.14);
}
.d2-agree-icon.active {
  box-shadow: 0 0 0 2px rgba(106,169,255,.35);
}
.d2-agree-svg { display: block; flex-shrink: 0; }
/* The step-back tools in the rail: they reuse the .d2-tool look, so the
   only extra treatment is the section wrapper. */
.d2-agree-tools { margin-bottom: .6rem; }
.d2-agree-keep { opacity: .8; }
/* The reason composer under the bar reads as a stepping-back act, not a
   reply: a warmer edge and a quiet label distinguish it. */
.d2-withdraw-compose {
  border-left: 2px solid var(--d2-accent);
  background: rgba(106,169,255,.05);
  padding-left: .6rem;
}
.d2-withdraw-compose .d2-compose-on { color: var(--d2-accent); font-style: normal; }
/* Chapter agreement, at the chapter's end. Same treatment as node
   agreement, sitting in the chapter-end band. */
.d2-chagree-wrap {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-left: .6rem;
  flex-wrap: wrap;
}
.d2-chagree {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: .72rem;
  padding: .1rem .55rem;
  border: 1px solid var(--d2-border);
  border-radius: 999px;
  color: var(--d2-text-dim);
  background: transparent;
}
.d2-chagree:hover { border-color: var(--d2-accent-dim); color: var(--d2-text); }
.d2-chagree.on {
  color: var(--d2-accent);
  border-color: var(--d2-accent);
  background: rgba(106,169,255,.12);
}
.d2-chagree-remove, .d2-chagree-remove-why {
  font-size: .7rem; padding: .1rem .5rem;
  border: 1px solid var(--d2-border); border-radius: 999px;
  background: transparent; color: var(--d2-text-dim);
}
.d2-chagree-remove:hover, .d2-chagree-remove-why:hover {
  border-color: var(--d2-accent-dim); color: var(--d2-text);
}
.d2-chagree-compose { margin-top: .5rem; }
.d2-gather-hint { font-size: .7rem; color: var(--d2-text-dim); margin-top: .4rem; }
.d2-gather textarea {
  width: 100%; min-height: 4.5rem; box-sizing: border-box;
  background: var(--d2-surface2); color: var(--d2-text);
  border: 1px solid var(--d2-border); border-radius: var(--d2-radius);
  padding: .5rem; font-family: inherit;
}
.d2-gather .d2-actions { margin-top: .6rem; }

/* --- The vein: replies threading inside a surfaced mark ------------ */
/* The thread renders wherever a mark is shown (the gather surface, or
   the narrow-screen list). One soft rule per depth; depth is where
   people dug, never a ranking, so nothing is sized or floated by it. */

.d2-chip-who { font-size: .72rem; color: var(--d2-accent); }
.d2-chip-who.me { color: var(--d2-text); }

.d2-thread {
  margin-top: .35rem;
  border-left: 2px solid var(--d2-border);
  padding-left: .5rem;
}
.d2-thread .d2-thread { margin-top: .2rem; }
.d2-reply { padding: .2rem 0; }
.d2-reply.me { border-left: 2px solid var(--d2-accent-dim); margin-left: -.55rem; padding-left: .45rem; }
.d2-reply-re { font-size: .72rem; color: var(--d2-text-dim); font-style: italic; }
.d2-reply .d2-msg-body { margin-top: .1rem; user-select: text; cursor: text; }

/* --- Chapter ends -------------------------------------------------- */
/* The close of a declared stretch, as visible as its opening: a thin
   rule with a quiet label. The curator declaring the next chapter and
   the participant waiting on a unit both read the same line. */
.d2-chapter-end {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .35rem 1rem .55rem;
}
.d2-chapter-end::before {
  content: "";
  flex: 1;
  border-top: 1px solid var(--d2-border);
}
.d2-chapter-end-label {
  font-size: .7rem;
  color: var(--d2-text-dim);
  letter-spacing: .04em;
  white-space: nowrap;
}
.d2-curator-strip .d2-state-chapter { margin-left: 1rem; }

/* --- The room's floor: the face with spans painted on it ----------- */
/* Your net is painted; touching a person lights their span beside
   yours on the words themselves. The passage is the map; paint, not
   numbers, carries the relation. */
.d2-room-floor {
  margin: .6rem 0 1rem;
  padding: .5rem .7rem;
  border-left: 3px solid var(--d2-accent-dim);
  background: var(--d2-surface2);
  border-radius: 0 var(--d2-radius) var(--d2-radius) 0;
  max-height: 11rem;
  overflow-y: auto;
  line-height: 1.55;
}
.d2-seg.net { background: rgba(106, 169, 255, .16); border-radius: 2px; }
.d2-seg.lit {
  background: rgba(106, 169, 255, .34);
  border-radius: 2px;
  box-shadow: 0 1px 0 var(--d2-accent);
}
.d2-seg.net.lit { background: rgba(106, 169, 255, .45); }

/* --- People in the room: presence before content ------------------- */
/* A row per person, placed by relation to your reach; content stays
   collapsed until the person is a chosen step. Depth beneath shows as
   presence, the margin's own vocabulary recurring inward. */
.d2-person { border-top: 1px solid var(--d2-border); }
.d2-person:last-of-type { border-bottom: 1px solid var(--d2-border); }
.d2-person-head {
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: .6rem;
  background: none;
  border: none;
  border-radius: 0;
  padding: .7rem .15rem;
  text-align: left;
  cursor: pointer;
}
.d2-person-head:hover { border: none; background: var(--d2-surface2); }
.d2-person.open > .d2-person-head { background: var(--d2-surface2); }
.d2-person-rel {
  color: var(--d2-text-dim);
  font-size: .74rem;
  font-style: italic;
}
.d2-vein {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: .74rem;
  color: var(--d2-text-dim);
}
.d2-chamber { padding: .35rem .15rem 1rem 1rem; }
.d2-chamber .d2-msg-body { user-select: text; cursor: text; line-height: 1.6; }

/* Struck and appended edits: the record's history shown in place. The
   original is never destroyed, only marked; an append shows the words
   it revises above the correction. */
.d2-struck {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  color: var(--d2-text-dim);
  opacity: .75;
}
.d2-append {
  margin-top: .5rem;
  padding: .4rem .6rem;
  border-left: 2px solid var(--d2-accent-dim);
  background: var(--d2-surface2);
  border-radius: 0 var(--d2-radius) var(--d2-radius) 0;
  line-height: 1.55;
}
.d2-append-who {
  display: block;
  font-size: .72rem;
  color: var(--d2-text-dim);
  margin-bottom: .1rem;
}
.d2-append-re {
  display: block;
  font-size: .72rem;
  color: var(--d2-text-dim);
  font-style: italic;
}

/* --- The rope: the chambers behind you, open and lit --------------- */
.d2-trail {
  font-size: .72rem;
  color: var(--d2-text-dim);
  margin: .35rem 0 .2rem;
}
.d2-trail-step {
  background: none;
  border: none;
  padding: 0;
  font-size: .72rem;
  color: var(--d2-accent);
  cursor: pointer;
}
.d2-trail-step:hover { border: none; text-decoration: underline; }
.d2-trail-sep { color: var(--d2-text-dim); }
.d2-trail-here { color: var(--d2-text); }

/* --- Step-wise chambers: nested faces indent one quiet step --------- */
.d2-chamber .d2-person { margin-left: .35rem; }
.d2-chamber .d2-face-body { user-select: text; cursor: text; }

/* ------------------------- The living surface ---------------------- */
/* Curator-only, full width beneath the spine. Deposits laid out in media
   time; the ground shaded by who reached it, never the comments; the
   people container bounded, membership by proximity, never merit. */
.d2-living {
  margin-top: calc(var(--d2-gap) * 1.2);
  background: var(--d2-surface);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
}
.d2-living[hidden] { display: none !important; }
.d2-living-inner { padding: .8rem 1rem 1rem; }
.d2-living-head {
  display: flex; align-items: baseline; gap: .5rem;
  margin-bottom: .7rem;
}
.d2-living-head .d2-dim { flex: 1; }
.d2-living-close { font-size: .75rem; padding: .1rem .6rem; color: var(--d2-text-dim); }

/* The people container: as many faces as fit, then an honest "+N others".
   Faces are distance-ordered, never merit-ordered; each keeps its hue. */
.d2-living-people {
  display: flex; flex-wrap: wrap; align-items: center; gap: .3rem;
  min-height: 30px; margin-bottom: .6rem;
}
.d2-living-face {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%;
  font-size: .66rem; font-weight: 600; letter-spacing: .02em;
  color: #10131a;
  background: hsl(var(--d2-face-h, 210) 55% 62%);
  box-shadow: 0 0 0 1px rgba(0,0,0,.25) inset;
  cursor: default; user-select: none;
}
.d2-living-more { font-size: .72rem; color: var(--d2-text-dim); margin-left: .2rem; }
.d2-living-quiet { font-size: .78rem; color: var(--d2-text-dim); font-style: italic; }

/* The track: one axis in media time. Click the ground to move the
   playhead; deposits sit where they anchored. */
.d2-living-track {
  position: relative; height: 56px;
  background: var(--d2-surface2);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  cursor: pointer; overflow: hidden;
}
.d2-living-ground-row { position: absolute; inset: 0; }
.d2-living-ground {
  position: absolute; bottom: 0; height: 100%;
  background: var(--d2-accent-dim);
}
.d2-living-playhead {
  position: absolute; top: 0; bottom: 0; left: 0; width: 2px;
  background: var(--d2-accent);
  box-shadow: 0 0 6px var(--d2-accent);
  pointer-events: none; z-index: 3;
}
.d2-living-frontier {
  position: absolute; top: 0; bottom: 0; left: 0; width: 0;
  border-left: 1px dashed var(--d2-text-dim);
  pointer-events: none; z-index: 2;
}
.d2-living-frontier[hidden] { display: none; }
.d2-living-frontier-lab {
  position: absolute; top: 2px; left: 3px;
  font-size: .6rem; color: var(--d2-text-dim); white-space: nowrap;
}

/* A deposit: one equal marker at its moment. Depth (a vein beneath) reads
   as a ring, never a larger dot; nothing is sized or sorted by count. */
.d2-living-deposit {
  position: absolute; top: 50%; left: 0;
  transform: translate(-50%, -50%);
  width: 16px; height: 16px; padding: 0;
  background: transparent; border: 0; border-radius: 50%;
  cursor: pointer; z-index: 4;
  display: flex; align-items: center; justify-content: center;
}
.d2-living-deposit::after {
  content: ""; width: 11px; height: 11px; border-radius: 50%;
  background: hsl(var(--d2-face-h, 210) 55% 62%);
  box-shadow: 0 0 0 1px rgba(0,0,0,.3);
  transition: transform .12s ease;
}
.d2-living-deposit.vein::after {
  box-shadow: 0 0 0 1px rgba(0,0,0,.3), 0 0 0 3px hsl(var(--d2-face-h, 210) 55% 62% / .35);
}
.d2-living-deposit.me::after { box-shadow: 0 0 0 2px var(--d2-accent); }
.d2-living-deposit:hover { border: 0; }
.d2-living-deposit:hover::after { transform: scale(1.35); }
.d2-living-foot { margin-top: .5rem; font-size: .72rem; }

/* ------------------------------------------------------------------ *
   Constellation over the words (curator-only, additive). Who gathered on
   top; their real words beneath; the walk-and-keep line the curator draws
   is theirs alone. Reuses the app theme variables, not the mockup palette.
 * ------------------------------------------------------------------ */
/* FOUR SEPARATE CONTAINERS (Michael, 2026-08-11): the constellation is
   no longer one enclosing panel. The wrapper is transparent chrome; the
   map column and the talk column are each their OWN boxed container,
   sitting in the same grid as the video and transcript above, so the
   four quadrants read as four containers right off the bat. */
.d2-constellation {
  margin-top: calc(var(--d2-gap) * 1.2);
}
.d2-constellation[hidden] { display: none !important; }
.d2-con-inner { padding: 0; }
.d2-con-q-map, .d2-con-q-talk {
  background: var(--d2-surface);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .5rem .8rem .8rem;
}
/* The talk container adds NOTHING of its own to what stands inside it
   (Michael, 2026-08-11): the room renders exactly as it always has; the
   box is only a venue. */
.d2-con-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .35rem; }
.d2-con-head .d2-dim { flex: 1; }
.d2-con-close { font-size: .75rem; padding: .1rem .6rem; color: var(--d2-text-dim); }

.d2-con-skywrap {
  position: relative;
  background: var(--d2-surface2);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  overflow: hidden;
}
.d2-con-hint {
  position: absolute; left: .6rem; top: .4rem; z-index: 2;
  font-size: .68rem; color: var(--d2-text-dim);
}
.d2-con-sky { display: block; width: 100%; height: auto; }

/* DOUBLED (2026-08-11), then ENHANCED (Michael, same day): "everything
   just seems very muted." Glows, swells, veins, tethers, and the
   selected rings all speak up; what is chosen must be unmistakable. */
.d2-con-halo { fill: rgba(255,255,255,.03); stroke: rgba(255,255,255,.1); }
.d2-con-glbl { fill: var(--d2-text-dim); font-size: 15px; }
.d2-con-vein { stroke: rgba(255,255,255,.32); stroke-width: 2.6; fill: none; }

.d2-con-node { cursor: pointer; }
.d2-con-dot { transition: r .12s ease, filter .15s ease; }
.d2-con-node:hover .d2-con-dot { r: 21;
  filter: drop-shadow(0 0 8px rgba(255,255,255,.5)); }
.d2-con-tag {
  font-size: 15px; font-weight: 700; fill: #10131a;
  text-anchor: middle; dominant-baseline: central; pointer-events: none;
}
.d2-con-nm {
  font-size: 14px; font-weight: 600; fill: var(--d2-text-dim);
  text-anchor: middle; pointer-events: none;
}
/* GATHERED: unmistakable. A thick accent ring, a strong halo, and a
   slight swell; you can tell across the room what is in the tray. */
.d2-con-node.sel .d2-con-dot {
  stroke: var(--d2-accent) !important; stroke-width: 5 !important;
  r: 21;
  filter: drop-shadow(0 0 10px var(--d2-accent)) drop-shadow(0 0 20px var(--d2-accent));
}
/* WHERE YOU ARE: the star whose room you are standing in. White, not
   accent: the accent means gathered for a connection; this means here. */
.d2-con-node.here .d2-con-dot {
  stroke: #fff !important; stroke-width: 4 !important;
  filter: drop-shadow(0 0 10px rgba(255,255,255,.95));
}

.d2-con-kept {
  fill: none; stroke: var(--d2-accent); stroke-opacity: .6;
  stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 4px var(--d2-accent));
}
.d2-con-inprog {
  fill: none; stroke: var(--d2-accent); stroke-width: 3;
  stroke-dasharray: 6 5; stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 8px var(--d2-accent));
}

/* the reading column: real comment bodies, newest large on top, prior ones
   condensing so the path never becomes a wall */
/* FOUR QUADRANTS (Michael, 2026-08-11): the constellation is the MAP and
   sits under the video; the room is the TALK and sits under the
   transcript. The grid mirrors the spine (1.2fr 1fr) so the surface
   reads as two columns: the artifact above, its life below. The map
   moves you; the room reveals where you are. */
.d2-con-quad { display: grid; grid-template-columns: 1.2fr 1fr;
  gap: calc(var(--d2-gap) * 1.5); align-items: stretch; }
@media (max-width: 800px) { .d2-con-quad { grid-template-columns: 1fr; } }
.d2-con-q-map, .d2-con-q-talk { min-width: 0; }
/* ONE HEIGHT, ONE RUNWAY (Michael, 2026-08-11): the talk container
   stands exactly as tall as the map column, always, so the wheel has a
   constant surface to scroll time on; a quiet stretch never collapses
   the box or freezes the glide. The map sets the height; the current
   fills it and clips; the room scrolls itself inside it. */
.d2-con-q-talk { display: flex; flex-direction: column; min-height: 0; }
.d2-con-q-talk .d2-con-read { flex: 1 1 0; min-height: 0; overflow: hidden; }
.d2-con-q-talk .d2-con-roomwrap { flex: 1 1 0; min-height: 0;
  max-height: none; overflow: auto; }
.d2-con-read { min-width: 0; margin-top: 0;
  display: flex; flex-wrap: wrap; gap: .6rem;
  align-content: flex-start; }

/* THE CURRENT (Michael, 2026-08-11): the talk quadrant's default state.
   Whatever the aperture holds stands in the list, newest on top; the
   wheel moves the clock, never an inner scrollbar, so motion always
   means time. */
.d2-cur-head { flex: 1 1 100%; font-size: .68rem; margin-bottom: .2rem; }
.d2-cur-item { flex: 1 1 100%; display: flex; gap: .45rem;
  align-items: flex-start; padding: .35rem .3rem;
  border-radius: var(--d2-radius); cursor: pointer;
  border: 1px solid transparent; }
.d2-cur-item:hover { background: var(--d2-surface2); }
.d2-cur-item.sel { border-color: var(--d2-accent-dim); }
.d2-cur-reply { opacity: .92; }
.d2-cur-pick { flex: 0 0 auto; cursor: pointer; color: var(--d2-text-dim);
  font-size: 1.1rem; line-height: 1; margin-top: .05rem; font-style: normal;
  transition: transform .12s ease, color .12s ease; }
.d2-cur-pick:hover { color: var(--d2-accent); transform: scale(1.25); }
.d2-cur-pick.on { color: var(--d2-accent);
  text-shadow: 0 0 8px var(--d2-accent), 0 0 16px var(--d2-accent);
  transform: scale(1.25); }
.d2-cur-item.sel { border-color: var(--d2-accent);
  background: var(--d2-accent-dim);
  box-shadow: 0 0 8px var(--d2-accent-dim); }
.d2-cur-body { min-width: 0; }
.d2-cur-who { font-weight: 600; font-size: .82rem; }
.d2-cur-tag { font-size: .6rem; color: var(--d2-text-dim);
  border: 1px solid var(--d2-border); border-radius: 4px;
  padding: 0 .3rem; margin-left: .4rem; text-transform: uppercase;
  letter-spacing: .03em; vertical-align: middle; }
.d2-cur-txt { margin-top: .15rem; font-size: .85rem; }
/* condensed consistently: three lines, then read more */
.d2-cur-txt.clamped { display: -webkit-box; -webkit-line-clamp: 3;
  -webkit-box-orient: vertical; overflow: hidden; }
.d2-cur-more { display: block; background: none; border: 0; padding: 0;
  margin-top: .1rem; font-size: .72rem; color: var(--d2-accent);
  cursor: pointer; opacity: .8; }
.d2-cur-more:hover { opacity: 1; }
@keyframes d2curIn {
  0% { transform: translateY(-8px); opacity: 0; }
  100% { transform: none; opacity: 1; }
}
.d2-cur-new { animation: d2curIn .45s ease; }
/* the inline composer: the gesture completes where it began */
.d2-cur-compose { flex: 1 1 100%; margin: .1rem 0 .5rem; }
.d2-cur-quote { font-size: .78rem; color: var(--d2-text-dim);
  border-left: 2px solid var(--d2-accent); padding: .15rem .5rem;
  margin-bottom: .3rem; }
.d2-cur-compose textarea { width: 100%; min-height: 64px; resize: vertical;
  background: var(--d2-surface2); color: var(--d2-text);
  border: 1px solid var(--d2-border); border-radius: var(--d2-radius);
  padding: .45rem .55rem; font: inherit; font-size: .85rem; }
.d2-cur-compose > div:last-child { margin-top: .3rem; display: flex;
  gap: .5rem; align-items: center; }
/* touching an item in the current lights its star on the map */
.d2-con-node.glow .d2-con-dot { stroke: #fff !important; stroke-width: 3 !important;
  filter: drop-shadow(0 0 9px rgba(255,255,255,.85)); }
.d2-con-read .d2-con-empty { flex: 1 1 100%; }
.d2-con-vth { flex: 1 1 220px; min-width: 200px;
  border: 1px solid var(--d2-border); border-radius: var(--d2-radius);
  padding: .45rem .5rem; align-self: flex-start; }
.d2-con-vth-head { font-size: .66rem; color: var(--d2-text-dim);
  margin-bottom: .3rem; }
.d2-con-vr { display: flex; gap: .45rem; align-items: flex-start;
  padding: .3rem .3rem; border-radius: var(--d2-radius); cursor: pointer;
  border: 1px solid transparent; }
.d2-con-vr:hover { background: var(--d2-surface2); }
.d2-con-vr.lit { background: var(--d2-surface2); border-color: var(--d2-border); }
.d2-con-vr.sel { border-color: var(--d2-accent-dim); }
.d2-con-pick-off { visibility: hidden; }
.d2-con-vth-solo { flex: 1 1 100%; }
.d2-con-reply { display: none; margin-left: auto; flex-shrink: 0;
  font-size: .68rem; padding: .05rem .5rem; color: var(--d2-text-dim); }
.d2-con-vr:hover .d2-con-reply { display: inline-block; }
.d2-con-compose { margin: .2rem 0 .5rem; }
.d2-con-compose textarea { width: 100%; min-height: 64px; resize: vertical;
  background: var(--d2-surface2); color: var(--d2-text);
  border: 1px solid var(--d2-border); border-radius: var(--d2-radius);
  padding: .45rem .55rem; font: inherit; font-size: .85rem; }
.d2-con-compose > div { margin-top: .3rem; display: flex; gap: .5rem;
  align-items: center; }
.d2-con-chipg { display: inline-flex; align-items: center; gap: .3rem;
  border: 1px solid var(--d2-border); border-radius: 999px;
  padding: .1rem .55rem; margin: 0 .3rem .2rem 0; font-size: .7rem; }
.d2-con-chipg i { font-style: normal; cursor: pointer;
  color: var(--d2-text-dim); padding: 0 .1rem; }
.d2-con-chipg i:hover { color: var(--d2-accent); }
.d2-con-relate { margin: .1rem 0 .45rem; }
@media (max-width: 900px) {
  .d2-con-tactile { display: block; }
  .d2-con-read { margin-top: .7rem; }
}
.d2-con-empty, .d2-con-hintline {
  color: var(--d2-text-dim); font-size: .78rem; padding: .6rem .2rem;
}
.d2-con-empty { text-align: center; padding: 1.4rem .2rem; }
.d2-con-rc {
  display: flex; gap: .6rem; align-items: flex-start;
  padding: .6rem .55rem; border-radius: var(--d2-radius);
  border: 1px solid transparent; cursor: pointer; margin-bottom: .4rem;
  transition: background .12s ease;
}
.d2-con-rc:hover { background: var(--d2-surface2); }
.d2-con-rc.top { background: var(--d2-surface2); border-color: var(--d2-border); }
.d2-con-rc.sel { border-color: var(--d2-accent); background: var(--d2-accent-dim); }
.d2-con-rc.cond { padding: .35rem .55rem; opacity: .92; }
.d2-con-pick {
  width: 16px; height: 16px; border-radius: 50%; flex: 0 0 auto; margin-top: .15rem;
  border: 1.5px solid var(--d2-text-dim); transition: all .12s ease;
}
.d2-con-rc:hover .d2-con-pick { border-color: var(--d2-accent); }
.d2-con-rc.sel .d2-con-pick {
  background: var(--d2-accent); border-color: var(--d2-accent);
  box-shadow: 0 0 6px var(--d2-accent);
}
.d2-con-chip {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .64rem; font-weight: 700; color: #10131a;
  box-shadow: 0 0 0 1px rgba(0,0,0,.25) inset;
}
.d2-con-rc.cond .d2-con-chip { width: 22px; height: 22px; font-size: .58rem; }
.d2-con-body { min-width: 0; }
.d2-con-who { font-weight: 600; font-size: .82rem; }
.d2-con-when { color: var(--d2-text-dim); font-weight: 400; font-size: .7rem; margin-left: .4rem; }
.d2-con-txt { margin-top: .15rem; }
.d2-con-rc.top .d2-con-txt { font-size: 1.02rem; line-height: 1.45; }
.d2-con-rc.cond .d2-con-txt {
  font-size: .78rem; color: var(--d2-text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* THE TRAY, a fixed home under the map (Michael, 2026-08-11): always
   standing so nothing slides when a person is ringed. It rests dim;
   holding something wakes it; two gathered arms the line. */
.d2-con-relate {
  margin-top: .6rem; padding: .7rem .6rem;
  border-top: 1px solid var(--d2-border);
}
.d2-con-relate[hidden] { display: none; }
.d2-con-relate .d2-con-types, .d2-con-relate .d2-con-rr {
  opacity: .4; transition: opacity .2s ease; }
.d2-con-relate.holding .d2-con-types, .d2-con-relate.holding .d2-con-rr {
  opacity: .75; }
.d2-con-relate.armed .d2-con-types, .d2-con-relate.armed .d2-con-rr {
  opacity: 1; }
.d2-con-relate.armed { border-top-color: var(--d2-accent); }
.d2-con-relate.armed .d2-con-draw { box-shadow: 0 0 10px var(--d2-accent-dim); }
.d2-con-mem { font-size: .84rem; margin-bottom: .5rem; }
.d2-con-mem b { color: var(--d2-text); }
.d2-con-join { color: var(--d2-text-dim); }
.d2-con-types { display: flex; flex-wrap: wrap; gap: .8rem; margin-bottom: .5rem; font-size: .8rem; }
.d2-con-types span {
  color: var(--d2-text-dim); cursor: pointer;
  padding-bottom: .1rem; border-bottom: 2px solid transparent;
}
.d2-con-types span.on { color: var(--d2-text); border-color: var(--d2-accent); }
.d2-con-rr { display: flex; gap: .5rem; align-items: center; }
.d2-con-rr input {
  flex: 1 1 auto; background: var(--d2-surface2); color: var(--d2-text);
  border: 1px solid var(--d2-border); border-radius: var(--d2-radius);
  padding: .5rem .6rem; font: inherit;
}
.d2-con-draw {
  background: var(--d2-accent-dim); border: 1px solid var(--d2-accent);
  color: var(--d2-text); padding: .5rem .8rem; border-radius: var(--d2-radius);
}
.d2-con-clear { background: transparent; border: 0; color: var(--d2-text-dim); padding: .5rem .3rem; }

/* kept lines, this session only */
.d2-con-keeps { margin-top: .5rem; }
.d2-con-keeps-head { font-size: .74rem; color: var(--d2-text-dim); margin-bottom: .35rem; }
.d2-con-keep {
  padding: .4rem .55rem; border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius); margin-bottom: .35rem; background: var(--d2-surface2);
}
.d2-con-badge {
  display: inline-block; font-size: .62rem; text-transform: uppercase;
  letter-spacing: .03em; padding: .05rem .35rem; border-radius: 4px;
  border: 1px solid var(--d2-border); color: var(--d2-text-dim); vertical-align: middle;
}
.d2-con-badge.question { color: var(--d2-accent); border-color: var(--d2-accent); }
.d2-con-keep-names { font-size: .8rem; font-weight: 600; margin-left: .3rem; }
.d2-con-keep-note { font-size: .8rem; color: var(--d2-text-dim); margin-top: .15rem; }
.d2-con-foot { margin-top: .6rem; font-size: .72rem; text-align: center; }

/* ------------------------------------------------------------------ *
 * The fisheye (curator-only): one door — watch it fill in, freeze,
 * read who gathered, connect. Additive; reuses the constellation's
 * reading/connect styles (.d2-con-*) beneath its own timeline.
 * ------------------------------------------------------------------ */
.d2-fisheye {
  margin: .5rem 0 0; background: var(--d2-surface); border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius); overflow: hidden;
}
.d2-fisheye[hidden] { display: none !important; }
.d2-fx-inner { padding: .8rem 1rem 1rem; }
.d2-fx-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .5rem; }
.d2-fx-head .d2-dim { flex: 1; }
.d2-fx-close { font-size: .75rem; padding: .1rem .6rem; color: var(--d2-text-dim); }

.d2-fx-peoplewrap { min-height: 30px; margin-bottom: .3rem; }
.d2-fx-track {
  position: relative; height: 46px; margin: .2rem 0 .1rem;
  border-radius: var(--d2-radius); background: var(--d2-surface2);
  border: 1px solid var(--d2-border); cursor: crosshair; overflow: hidden;
}
.d2-fx-aperture {
  position: absolute; top: 0; bottom: 0; background: var(--d2-accent-dim);
  border-left: 1px solid var(--d2-accent); border-right: 1px solid var(--d2-accent);
  opacity: .5; pointer-events: none;
}
.d2-fx-aperture[hidden] { display: none; }
.d2-fx-playhead {
  position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px;
  background: var(--d2-accent); pointer-events: none; transition: left .08s linear;
}
.d2-fx-dep {
  position: absolute; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px;
  padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer;
  transition: left .12s ease;
}
.d2-fx-dep::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: hsl(var(--d2-face-h), 45%, 55%); box-shadow: 0 0 0 1px rgba(0,0,0,.3) inset;
  transition: transform .12s ease;
}
.d2-fx-dep.vein::after { box-shadow: 0 0 0 2px hsl(var(--d2-face-h), 55%, 70%), 0 0 0 3px rgba(0,0,0,.25); }
.d2-fx-dep.me::after { box-shadow: 0 0 0 2px var(--d2-accent); }
.d2-fx-dep:hover::after { transform: scale(1.4); }

.d2-fx-foot {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin-top: .45rem; font-size: .74rem;
}
.d2-fx-frozen { color: var(--d2-accent); font-weight: 600; }
.d2-fx-foot button {
  font-size: .72rem; padding: .15rem .55rem; border-radius: var(--d2-radius);
  border: 1px solid var(--d2-border); background: var(--d2-surface2); color: var(--d2-text);
}
.d2-fx-foot .d2-fx-release { color: var(--d2-text-dim); }
.d2-fx-foot .d2-dim { margin-left: auto; }

.d2-fx-explore { margin-top: .7rem; border-top: 1px solid var(--d2-border); padding-top: .6rem; }
.d2-fx-explore[hidden] { display: none; }
.d2-fx-skywrap { border-radius: var(--d2-radius); background: rgba(0,0,0,.12); padding: .3rem; }
.d2-fx-nav { font-size: .72rem; margin-top: .35rem; }
.d2-fx-engage {
  margin-top: .45rem; font-size: .74rem; padding: .3rem .7rem;
  border-radius: var(--d2-radius); border: 1px solid var(--d2-accent);
  background: var(--d2-accent-dim); color: var(--d2-text); cursor: pointer;
}
.d2-con-engage {
  margin-top: .45rem; font-size: .74rem; padding: .3rem .7rem;
  border-radius: var(--d2-radius); border: 1px solid var(--d2-accent);
  background: var(--d2-accent-dim); color: var(--d2-text); cursor: pointer;
}
/* THE DOCK: the same room, living in the 40% column beside the map.
   Same element and ids as the overlay; only the venue changes. */
.d2-con-roomwrap { flex: 1 1 0; min-width: 0; max-height: 64vh; overflow: auto; }
.d2-con-roomwrap[hidden] { display: none !important; }
.d2-gather.d2-dock {
  position: static; inset: auto; z-index: auto; display: block;
  background: none; padding: 0; overflow: visible;
}
.d2-gather.d2-dock .d2-gather-panel {
  width: 100%; max-width: none; margin: 0; box-shadow: none;
  flex-direction: column;
}
.d2-gather.d2-dock .d2-rail { position: static; width: auto; max-width: none;
  border-left: none; border-top: 1px solid var(--d2-border);
  margin-top: .5rem; padding-top: .5rem; }
/* THE THREAD (base): the conversation beneath the video and transcript,
   in the order of the video. A scroll box so it can follow the playhead
   without moving the page. */
.d2-thread {
  margin-top: calc(var(--d2-gap) * 1.5);
  /* Locked: only the video bar and the transcript move it. */
  max-height: 64vh; overflow: hidden;
  border: 1px solid var(--d2-border); border-radius: var(--d2-radius);
  background: var(--d2-surface); padding: calc(var(--d2-gap) * .9);
  line-height: 1.55;
}
.d2-thread[hidden] { display: none !important; }
.d2-th-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
  margin-bottom: .6rem; }
.d2-th-title { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--d2-accent); font-weight: 600; }
.d2-th-headbtn { margin-left: auto; font-size: .78rem; padding: .15rem .6rem; }
.d2-th-empty { padding: .4rem 0; }
.d2-th-root { border-top: 1px solid var(--d2-border); padding: .7rem 0 .5rem;
  border-left: 3px solid transparent; margin-left: -.6rem; padding-left: .6rem;
  transition: border-color .2s ease, background .2s ease; }
.d2-th-root.current { border-left-color: var(--d2-accent); background: rgba(106,169,255,.05); }
.d2-th-source { display: block; width: 100%; text-align: left; background: none;
  border: none; padding: 0 0 .35rem; cursor: pointer; color: var(--d2-text-dim);
  font-size: .85rem; border-radius: 0; }
.d2-th-source:hover { color: var(--d2-text); border-color: transparent; }
.d2-th-time { color: var(--d2-accent); font-variant-numeric: tabular-nums; }
.d2-th-quote { font-style: italic; }
.d2-th-msg { padding: .2rem 0 .3rem; }
.d2-th-who { font-size: .82rem; color: var(--d2-text-dim); margin-bottom: .1rem; }
.d2-th-msg.mine > .d2-th-who { color: var(--d2-accent); }
.d2-th-on { font-size: .8rem; color: var(--d2-text-dim); font-style: italic; }
.d2-th-body { white-space: pre-wrap; }
.d2-th-agree { font-size: .8rem; color: var(--d2-text-dim); margin-top: .15rem; }
.d2-th-kids { margin-left: 1.1rem; padding-left: .8rem; border-left: 1px solid var(--d2-border);
  margin-top: .35rem; }
.d2-th-more { font-size: .78rem; padding: .1rem .55rem; margin: .25rem 0 0 1.1rem; }
.d2-th-composer { margin: .5rem 0 .6rem; padding: .6rem .7rem;
  border: 1px solid var(--d2-accent-dim); border-radius: var(--d2-radius);
  background: var(--d2-surface2); }
.d2-th-composer textarea { width: 100%; box-sizing: border-box; margin: .35rem 0;
  resize: vertical; }
.d2-th-actions { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap;
  font-size: .85rem; }
.d2-chapstrip { display: flex; width: 100%; margin: .25rem 0 0; align-items: flex-start; }
.d2-chapstrip[hidden] { display: none !important; }
.d2-chap { flex: 0 0 auto; box-sizing: border-box; min-width: 0; cursor: pointer;
  background: none; border: none; padding: 0 3px 0 0; text-align: left; border-radius: 0; }
.d2-chap::before { content: ''; display: block; height: 3px; border-radius: 2px;
  background: var(--d2-border); transition: background .2s ease; }
.d2-chap:hover::before { background: var(--d2-accent-dim); }
.d2-chap.current::before { background: var(--d2-accent); }
.d2-chap-title { display: block; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: .68rem; line-height: 1.4; margin-top: .15rem;
  color: var(--d2-text-dim); }
.d2-chap:hover .d2-chap-title, .d2-chap.current .d2-chap-title { color: var(--d2-text); }
.d2-chap-gap { flex: 0 0 auto; min-width: 0; height: 3px; align-self: flex-start; }
.d2-th-chname { flex: 1 1 10rem; min-width: 8rem; font-size: .85rem; padding: .2rem .45rem; }
.d2-th-tools { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap;
  margin: .1rem 0 .5rem; padding-top: .45rem; border-top: 1px dashed var(--d2-border); }
.d2-th-tools-label { font-size: .78rem; color: var(--d2-text-dim); margin-right: .2rem; }
.d2-th-ask { font-size: .8rem; padding: .12rem .6rem; border-radius: 999px; }
.d2-th-ask.on { border-color: var(--d2-accent); color: var(--d2-accent);
  background: rgba(106,169,255,.12); }
.d2-th-tools-curator { border-top-style: solid; }
.d2-th-chapter { font-size: .8rem; padding: .12rem .6rem; }
.d2-th-asked { font-size: .8rem; color: var(--d2-text-dim); margin-top: .15rem; font-style: italic; }
.dialogue2-intro { max-width: 46rem; margin: 0 auto 1.2rem; line-height: 1.6; }
.d2-askprev { position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,.7);
  display: flex; align-items: flex-start; justify-content: center; padding: 8vh 1rem; overflow-y: auto; }
.d2-askprev-panel { width: 100%; max-width: 640px; background: var(--d2-surface);
  border: 1px solid var(--d2-accent-dim); border-radius: var(--d2-radius); padding: 1rem 1.2rem;
  box-shadow: 0 12px 48px rgba(0,0,0,.6); line-height: 1.5; }
.d2-askprev-head { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--d2-accent); font-weight: 600; margin-bottom: .6rem; }
.d2-askprev-item { border-top: 1px solid var(--d2-border); padding: .6rem 0; }
.d2-askprev-subj { font-weight: 600; margin: .2rem 0; }
.d2-askprev-body { white-space: pre-wrap; font-family: inherit; font-size: .88rem;
  color: var(--d2-text-dim); margin: 0; }
.d2-th-tail { pointer-events: none; }
.d2-version { font-size: .72rem; color: var(--d2-text-dim); opacity: .7; margin-left: .5rem;
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.d2-list > .d2-version, .d2-version:first-child { display: inline-block; margin: 0 0 .4rem; }
/* The lit span in the transcript: the context everyone is looking at. */
#d2-transcript .d2-cue.d2-th-lit { background: rgba(106,169,255,.13); }
#d2-transcript .d2-cue.d2-th-lit .d2-cue-text { color: var(--d2-text); }

.d2-room-pick {
  float: right; margin: .3rem .35rem 0 .3rem; cursor: pointer;
  color: var(--d2-text-dim); font-size: 1.1rem; line-height: 1;
  transition: transform .12s ease, color .12s ease;
}
.d2-room-pick:hover { color: var(--d2-accent); transform: scale(1.25); }
.d2-room-pick.on { color: var(--d2-accent); transform: scale(1.25);
  text-shadow: 0 0 8px var(--d2-accent), 0 0 16px var(--d2-accent); }

/* the chain back to the opening, lit when a comment is read */
.d2-fx-linepath {
  fill: none; stroke: var(--d2-accent); stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round; opacity: .8;
  filter: drop-shadow(0 0 4px var(--d2-accent));
}
.d2-con-node.onpath .d2-con-dot { stroke: var(--d2-accent); stroke-width: 2.6; }

/* One timeline: the rail lives at the top of the sky svg; a separator
   marks where the field begins; the zone is one unbroken box. */
.d2-con-sep { stroke: var(--d2-border); stroke-width: 1; opacity: .7; }
.d2-con-sky { touch-action: none; }
.d2-conf-axis { stroke: var(--d2-border); stroke-width: 2; }
.d2-conf-span { stroke: var(--d2-accent); stroke-width: 9; opacity: .24;
  stroke-linecap: round; }
.d2-conf-span.near { opacity: .45; }
.d2-conf-drop { stroke: var(--d2-border); stroke-width: 1; stroke-dasharray: 2 4; }
.d2-conf-ph { stroke: var(--d2-text); stroke-opacity: .7; stroke-width: 2; }
.d2-conf-now, .d2-conf-quiet { fill: var(--d2-text-dim); font-size: 14px; }
.d2-conf-node { cursor: pointer; }
.d2-conf-dot { transition: r .12s ease; }
.d2-conf-node:hover .d2-conf-dot { r: 17; }
.d2-conf-tag { font-size: 11px; font-weight: 700; fill: #10131a; text-anchor: middle; dominant-baseline: central; pointer-events: none; }
.d2-conf-nm { font-size: 9.5px; font-weight: 600; fill: var(--d2-text-dim); text-anchor: middle; pointer-events: none; }

/* One clock: the sky reacts to the lens. Out-of-aperture gatherings dim,
   never hide; the universe stays whole, the lens decides emphasis. */
.d2-con-g, .d2-con-tethline { transition: opacity .35s ease; }
.d2-con-outap { opacity: .22; }

/* The people strip: the room above the band. Frontier-honest presence:
   each face stays only as far as that person truly listened. */
.d2-con-people { margin-bottom: .3rem; }
.d2-cp-hint { font-size: .66rem; color: var(--d2-text-dim); margin-bottom: .15rem; }
/* DOUBLED (Michael, 2026-08-11): the faces were too small to read. */
.d2-cp-row { display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-end; min-height: 62px; justify-content: center; }
.d2-cp-face { display: inline-flex; flex-direction: column; align-items: center; gap: .15rem;
  transition: transform .25s ease; }
.d2-cp-face i { display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%; border: 2px solid;
  font-style: normal; font-size: .82rem; font-weight: 700; color: #10131a;
  transition: transform .25s ease, box-shadow .25s ease; }
.d2-cp-face b { font-size: .72rem; font-weight: 600; color: var(--d2-text-dim); max-width: 84px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.d2-cp-face.now { transform: translateY(-3px); }
.d2-cp-face.now i { transform: scale(1.5); box-shadow: 0 0 14px var(--d2-accent), 0 0 26px var(--d2-accent); }
@keyframes d2cpArrive {
  0% { transform: scale(.4); opacity: 0; }
  60% { transform: scale(1.45); opacity: 1; }
  100% { transform: scale(1); }
}
.d2-cp-face.arrive i { animation: d2cpArrive .9s ease; }

/* The sky is born with the clock: a gathering stays unseen until attention
   first reaches its moment, then brightens and remains. FAINT, NEVER GONE
   (Michael, 2026-08-11): the map is navigation now, and a map that hides
   the territory ahead made connections between distant parts impossible
   to draw. What the visit has not reached stands as a ghost you can still
   click; arrival is what lights it. */
.d2-con-unrev { opacity: .12; }

/* True flow: the rail and the sky share one bent scale. The aperture is
   always present in the plane; its handles are the only control. */
.d2-conf-zone { fill: var(--d2-accent); opacity: .12; pointer-events: none; }
.d2-con-zonebg { fill: var(--d2-accent); opacity: .09; pointer-events: none; }
.d2-con-apbar { display: flex; align-items: center; gap: .6rem;
  margin-bottom: .3rem; font-size: .66rem; }
.d2-con-apstrip { position: relative; flex: 1; height: 12px;
  border-radius: 999px; background: var(--d2-surface2);
  border: 1px solid var(--d2-border); touch-action: none; }
.d2-con-apstrip::before { content: ''; position: absolute; left: 50%; top: 2px;
  bottom: 2px; width: 1px; background: var(--d2-border); }
.d2-con-apfill { position: absolute; top: 2px; bottom: 2px;
  background: var(--d2-accent); opacity: .32; border-radius: 999px;
  pointer-events: none; }
.d2-con-aph { position: absolute; top: -5px; width: 14px; height: 22px;
  border-radius: 6px; background: var(--d2-accent); opacity: .8;
  cursor: ew-resize; transition: opacity .15s ease, box-shadow .15s ease; }
.d2-con-aph:hover { opacity: 1; box-shadow: 0 0 10px var(--d2-accent); }
#d2-con-apval { color: var(--d2-text-dim); min-width: 84px; text-align: right; }
.d2-con-tethline { stroke: rgba(255,255,255,.28); stroke-width: 1.8; }
.d2-con-satline { stroke: var(--d2-accent); stroke-width: 1.6; opacity: .55;
  stroke-dasharray: 3 4; }
.d2-con-sat { cursor: pointer; }
.d2-con-far .d2-con-tag { display: none; }
.d2-con-far .d2-con-halo, .d2-con-far .d2-con-glbl { display: none; }
.d2-con-far { opacity: .5; }
.d2-con-tallbtn { position: absolute; right: .6rem; top: .35rem; z-index: 2;
  font-size: .68rem; padding: .05rem .5rem; color: var(--d2-text-dim); }
.d2-cp-more { align-self: center; font-size: .62rem; font-weight: 600;
  color: var(--d2-text-dim); border: 1px solid var(--d2-border);
  border-radius: 999px; padding: .15rem .5rem; }

/* The correction tool + toolkit container (v0.86-v0.87.2), in the
   app's own variables per the first law of this file. The toolkit is
   the composer card itself: regions inside it, the curator region a
   darker inset well, one close X. */

/* The curator's correction mark and its immediate hover. */
.d2-fix {
  margin-left: .35rem;
  font-size: .8em;
  color: var(--d2-accent);
  cursor: help;
  user-select: none;
}
.d2-fix-lit {
  background: rgba(106, 169, 255, .22);
  color: inherit;
  border-radius: 3px;
  padding: 0 .08em;
}
.d2-cue { position: relative; }
.d2-fix-tip {
  position: absolute;
  left: 3.2rem;
  top: 100%;
  z-index: 30;
  background: var(--d2-surface2);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .25rem .6rem;
  font-size: .8rem;
  color: var(--d2-text);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .5);
  white-space: nowrap;
  max-width: 90%;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

/* The frontier rail's fix compose (same tool, other venue). */
.d2-fixcompose { margin-top: .6rem; }
.d2-fixcompose input[type="text"] {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  padding: .35rem .5rem;
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  background: var(--d2-surface2);
  color: var(--d2-text);
}
.d2-fixcompose .d2-actions { margin-top: .45rem; }
.d2-fix-note { margin-top: .4rem; font-size: .8rem; }

/* The marks-stand annotation in the thread. */
.d2-th-fixnote {
  margin: .15rem 0 .3rem 1.4rem;
  font-size: .8rem;
  font-style: italic;
  color: var(--d2-text-dim);
}

/* The toolkit container: the composer card is the container; only the
   head row and the regions are new. No second border fighting it. */
.d2-tk-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: .1rem;
}
.d2-tk-head .d2-th-on { margin: 0; }
.dialogue2 .d2-tk-close {
  border: 0;
  background: none;
  font-size: 1.2rem;
  line-height: 1;
  padding: 0 .15rem;
  color: var(--d2-text-dim);
  cursor: pointer;
}
.dialogue2 .d2-tk-close:hover { color: var(--d2-text); background: none; border: 0; }
.d2-tk-section + .d2-tk-section { margin-top: .6rem; }

/* The curator region: a darker inset well, visibly another space. */
.d2-tk-curator {
  background: rgba(0, 0, 0, .28);
  border: 1px solid var(--d2-border);
  border-radius: var(--d2-radius);
  padding: .45rem .65rem .55rem;
}
.d2-tk-label {
  font-size: .68rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--d2-text-dim);
  margin-bottom: .15rem;
}
/* Inside the well the rows need no dashed dividers of their own:
   parallel lines, label - field - action, hint tucked beneath. */
.d2-tk-curator .d2-th-tools {
  border-top: 0;
  margin: .3rem 0 0;
  padding-top: 0;
}
.d2-tk-curator .d2-th-tools-label { min-width: 5.2rem; }
.d2-tk-curator input[type="text"] { flex: 1 1 10rem; min-width: 8rem; }
.d2-th-fixhint { flex-basis: 100%; margin-top: .05rem; font-size: .75rem; }

/* --- The generic base (v0.89.0) ------------------------------------ */
/* The posted thread is a plain list at page height: nothing clipped,
   nothing locked to the playhead. */
.d2-thread.d2-thread-free { max-height: none; overflow: visible; }
.d2-th-head .d2-th-headbtn + .d2-th-rulesbtn { margin-left: .4rem; }
.d2-th-rulesbtn { opacity: .8; }
.d2-th-acts { display: flex; gap: .4rem; margin-top: .3rem; }
.d2-th-act { font-size: .78rem; padding: .1rem .6rem; border-radius: 999px; }
.d2-th-act.on { border-color: var(--d2-accent); color: var(--d2-accent);
  background: rgba(106,169,255,.12); }
.d2-th-reach { font-size: .76rem; color: var(--d2-text-dim); opacity: .85;
  margin-left: .35rem; white-space: nowrap; }
.d2-th-reachnote { font-size: .8rem; margin-top: .35rem; }
.d2-chapbar { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap;
  margin: .35rem 0 0; font-size: .82rem; }
.d2-chapbar[hidden] { display: none !important; }
.d2-chapbar-title { color: var(--d2-text); font-weight: 600; }
.d2-chapbar-agree { font-size: .78rem; }
.d2-gates label { display: inline-flex; align-items: center; gap: .3rem; margin: 0 .8rem 0 .4rem; }
.d2-rules-list { margin: .2rem 0 .7rem 1.1rem; padding: 0; }
.d2-rules-list li { margin: .3rem 0; }

/* The rules note stands out from the page it covers. */
.d2-rules .d2-askprev-panel { max-width: 520px; background: var(--d2-surface, #1e2128);
  border-color: var(--d2-accent); }

/* Your own number beside your name (v0.91.0): a mirror, quiet. */
.d2-whoami { font-size: .85rem; color: var(--d2-text-dim); white-space: nowrap; }
.d2-whoami strong { color: var(--d2-text); font-weight: 600; }
.d2-myreach { font-variant-numeric: tabular-nums; }
.d2-myreach:not(:empty)::before { content: "\00B7\00A0"; opacity: .7; }
