/**
 * The Quiet Interview — components, as plain CSS.
 *
 * The upstream design system ships its eight components as React (`.jsx` with
 * inline style objects). This project has no React and will not get one on a
 * capture surface (D7), so the components are translated here rather than
 * imported: one class per component, one modifier per prop, same tokens, same
 * values. The mapping is 1:1 and deliberately boring — a diff against the
 * upstream `.jsx` should be readable line by line.
 *
 *   libs/PresenceDot  -> .ds-presence      libs/StatusLine -> .ds-status
 *   libs/Button       -> .ds-btn           libs/MicButton  -> .ds-mic
 *   interview/SpokenLine -> .ds-said       interview/ThreadNote -> .ds-note
 *   interview/ThreadRail -> .ds-rail       interview/ThreadSheet -> .ds-sheet
 *
 * Two props are expressed as CSS custom properties rather than modifiers,
 * because their upstream values are computed from list position rather than
 * chosen from a set:
 *
 *   --note-op     ThreadNote's answered opacity, max(.35, .75 - depth * .15)
 *   --mic-size    MicButton's `size`, default 50px
 *
 * One prop is expressed as a theme rule rather than a prop. Upstream,
 * PresenceDot takes variant="dot" | "hair" and every screen passes "hair"
 * under the night theme and "dot" otherwise. Here the theme decides, so the
 * two can never disagree.
 *
 * `.ds-room` and its parts are the layout the UI kit's InterviewRoom and
 * PhoneInterview compose out of these primitives; the kit itself is React and
 * is not imported.
 */

/* ---------- PresenceDot ---------- */
/* Paper: a breathing dot. Night: a pulsing 14px hairline. */

.ds-presence {
  position: relative;
  display: inline-block;
  width: 8px;
  height: 8px;
  flex: 0 0 auto;
}
.ds-presence::before,
.ds-presence::after {
  content: "";
  position: absolute;
  border-radius: 50%;
}
.ds-presence::before {
  inset: 0;
  background: var(--accent-new);
  animation: ds-breathe var(--dur-breathe) ease-in-out infinite;
}
.ds-presence::after {
  inset: 2px;
  background: var(--accent-new);
}
.ds-presence[data-live="false"]::before {
  background: transparent;
  border: 1px solid var(--text-faint);
  box-sizing: border-box;
  animation: none;
}
.ds-presence[data-live="false"]::after { display: none; }

[data-theme="night"] .ds-presence { width: 14px; height: 1px; }
[data-theme="night"] .ds-presence::before {
  border-radius: 0;
  border: 0;
  background: var(--accent-new);
  animation: ds-hair var(--dur-hair) ease-in-out infinite;
}
[data-theme="night"] .ds-presence::after { display: none; }
[data-theme="night"] .ds-presence[data-live="false"]::before {
  background: var(--text-faint);
  animation: none;
}

/* ---------- StatusLine ---------- */

.ds-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
}
.ds-status__state {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.ds-status__right {
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- Button ---------- */
/* Hover and press are opacity only — no color shift, no lift, no scale. */

.ds-btn {
  font: inherit;
  font-family: var(--font-mono);
  font-size: var(--meta);
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
  padding: 14px 24px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  opacity: 1;
  transition: opacity var(--dur-settle) var(--ease-calm);
  white-space: nowrap;
}
.ds-btn--sm { padding: 10px 18px; }
.ds-btn--primary {
  background: var(--control-fill);
  color: var(--control-ink);
  border-color: var(--control-border);
}
.ds-btn--outline {
  background: transparent;
  color: var(--text-said);
  border-color: var(--rule);
  border-radius: 2px;
}
/*
 * DIVERGENCE from upstream: the rule. See design/README.md.
 *
 * Upstream `--quiet` is text and nothing else — no case change, no tracking,
 * no border — which reads as a control only while something pill-shaped sits
 * beside it. In the listening phase the only neighbour is a mic circle and a
 * mono sentence in the same size and colour, and `That's everything` was read
 * as the system announcing that everything was done. It is the control that
 * ends the session, and it is not allowed to be invisible (P7, D15a: stopping
 * must be as easy as continuing).
 *
 * A hairline under the text. `.ds-btn` already reserves a 1px transparent
 * border, so only the colour changes and nothing reflows. The pill radius has
 * to go with it — inherited from `.ds-btn` it bends a bottom-only border up at
 * both ends into a smile, which is the kind of thing that only exists once a
 * border-less variant grows a border.
 *
 * `--text-faint`, not `--rule`, which is what this reached for first. `--rule`
 * is 1.14:1 against the night page and 1.34:1 against paper — an underline
 * nobody can see, in the room that is the default whenever the OS is in dark
 * mode. `--text-faint` measures 2.02 and 1.95, present in both rooms and still
 * lighter than the label above it.
 *
 * The LABEL is `--text-trailed`, one step off upstream's `--text-quiet`, for
 * the same reason: 3.08:1 (night) and 2.40:1 (paper) is below WCAG AA in both
 * rooms, on the control that lets someone stop. `--text-trailed` gives 4.86 and
 * 3.45 — night clears AA, paper does not, and cannot from this palette: its
 * ramp steps 3.45 -> 12.22 with nothing in between. Recorded in
 * design/README.md item 4 rather than closed with a colour the system does not
 * have. Ambient chrome (status line, hints, empty states) keeps `--text-quiet`
 * — this is the control step, not a palette-wide shift.
 */
.ds-btn--quiet {
  background: transparent;
  color: var(--text-trailed);
  padding: 0 0 2px;
  text-transform: none;
  letter-spacing: 0;
  border-bottom-color: var(--text-faint);
  border-radius: 0;
}
.ds-btn:not(:disabled):hover { opacity: .74; }
.ds-btn:not(:disabled):active { opacity: .6; }
.ds-btn:disabled { opacity: .4; cursor: default; }
.ds-btn:focus-visible { outline: 1px solid var(--accent-new); outline-offset: 3px; }

/* ---------- MicButton ---------- */

.ds-mic {
  --mic-size: 50px;
  width: var(--mic-size);
  height: var(--mic-size);
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  background: var(--control-fill);
  border: 1px solid var(--control-border);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  transition: background var(--dur-settle) var(--ease-calm);
}
.ds-mic__cap {
  width: calc(var(--mic-size) * .18);
  height: calc(var(--mic-size) * .28);
  border-radius: calc(var(--mic-size) * .1);
  background: var(--control-ink);
  opacity: .75;
  transition: opacity var(--dur-settle) var(--ease-calm);
}
.ds-mic[data-state="recording"] .ds-mic__cap { opacity: 1; }
.ds-mic[data-state="off"] { background: transparent; border-color: var(--rule); }
.ds-mic[data-state="off"] .ds-mic__cap { background: var(--text-quiet); }
.ds-mic:focus-visible { outline: 1px solid var(--accent-new); outline-offset: 3px; }

/* ---------- SpokenLine ---------- */
/* The speaker's words. Always the largest thing on the screen. */

.ds-said__prior {
  font-family: var(--font-display);
  font-size: var(--said-prior);
  color: var(--text-faint);
  margin-bottom: var(--s-4);
}
.ds-said__line {
  font-family: var(--font-display);
  font-size: var(--said-lg);
  line-height: var(--lh-said);
  font-weight: var(--weight-said);
  max-width: var(--said-measure);
  color: var(--text-said);
  text-wrap: pretty;
}
.ds-said--md .ds-said__line { font-size: var(--said-md); }
.ds-said--sm .ds-said__line { font-size: var(--said-sm); }
.ds-said--trailed .ds-said__line { color: var(--text-trailed); }
.ds-said__prior:empty { display: none; }

/* Helvetica needs the tracking pulled in where Newsreader does not. */
[data-theme="night"] .ds-said__line { letter-spacing: -.015em; }

/* ---------- ThreadNote ---------- */
/* Notes are never cards: no background, no border, no shadow, no radius. */

.ds-note {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  border-radius: var(--r-note);
  cursor: default;
}
button.ds-note { cursor: pointer; }
.ds-note:focus-visible { outline: 1px solid var(--accent-new); outline-offset: 4px; }

.ds-note__text {
  display: block;
  font-family: var(--font-display);
  font-size: var(--note-sm);
  line-height: var(--lh-note);
  text-wrap: pretty;
}

/* waiting — the default. Deeper in the stack fades a step further. */
.ds-note[data-state="waiting"] .ds-note__text { color: var(--text-quiet); }
.ds-note[data-state="waiting"][data-deep="true"] .ds-note__text { color: var(--text-faint); }

/* answered — the only glyph in the system */
.ds-note[data-state="answered"] {
  display: flex;
  gap: 10px;
  opacity: var(--note-op, .6);
}
.ds-note[data-state="answered"] .ds-note__text {
  color: var(--text-trailed);
  text-decoration: line-through;
  text-decoration-color: var(--strike);
}
.ds-note__check {
  font-size: 13px;
  line-height: 1.5;
  color: var(--accent-done);
  flex: 0 0 auto;
}
.ds-note:not([data-state="answered"]) .ds-note__check { display: none; }

/* new — the one 2px rule in the system */
.ds-note[data-state="new"] {
  border-left: 2px solid var(--accent-new);
  padding-left: 14px;
  animation: ds-note-in var(--dur-fade) var(--ease-calm);
}
.ds-note[data-state="new"] .ds-note__text {
  font-size: var(--note-lg);
  color: var(--text-said);
}
.ds-note__badge {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--accent-new);
  margin-bottom: 10px;
}
.ds-note:not([data-state="new"]) .ds-note__badge { display: none; }

/* ---------- ThreadRail ---------- */

.ds-rail {
  width: var(--rail-w);
  flex: 0 0 auto;
  box-sizing: border-box;
  background: var(--surface-margin);
  display: flex;
  flex-direction: column;
  padding: var(--s-6);
}
.ds-rail__label {
  font-family: var(--font-mono);
  font-size: var(--label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
}
.ds-rail[data-filled="true"] .ds-rail__label { color: var(--text-trailed); }

.ds-rail__empty {
  flex: 1;
  display: flex;
  align-items: flex-end;
  font-family: var(--font-display);
  font-size: var(--note-md);
  line-height: 1.6;
  color: var(--text-quiet);
  font-style: italic;
}
.ds-rail__list {
  flex: 1;
  position: relative;
  margin-top: var(--s-5);
  overflow: hidden;
}
/* Notes stack up from the floor, newest last — the rail fills the way a page does. */
.ds-rail__stack {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 20px;
}
/* The only soft edge in the system. */
.ds-rail__scrim {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 64px;
  background: linear-gradient(var(--surface-margin), transparent);
  pointer-events: none;
}
.ds-rail__hint {
  font-family: var(--font-mono);
  font-size: var(--label);
  line-height: var(--lh-meta);
  color: var(--text-quiet);
  margin-top: var(--s-5);
}
.ds-rail[data-filled="true"] .ds-rail__empty,
.ds-rail[data-filled="false"] .ds-rail__list { display: none; }

/* ---------- ThreadSheet (the rail, on a phone) ---------- */

.ds-sheet {
  background: var(--surface-margin);
  padding: var(--s-5) var(--screen-pad-x-sm) 42px;
}
.ds-sheet__grab {
  width: 34px;
  height: 3px;
  border-radius: 2px;
  background: var(--rule);
  margin: 0 auto var(--s-5);
}
.ds-sheet__prev { margin-bottom: var(--s-4); }
.ds-sheet__actions {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-top: var(--s-6);
}
.ds-sheet__actions .ds-btn--primary { flex: 1; text-align: center; }
.ds-sheet__empty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
}
.ds-sheet__emptyLabel {
  font-family: var(--font-mono);
  font-size: var(--label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
}
.ds-sheet[data-filled="true"] .ds-sheet__empty,
.ds-sheet[data-filled="false"] .ds-sheet__full { display: none; }

/* ---------- Room (the layout the UI kit composes) ---------- */
/*
 * The spoken line sits on the FLOOR of the room — bottom-left, not centred.
 * That is the one layout decision the whole system rests on: the screen reads
 * as a room with a floor, and the margin is beside it rather than above it.
 */

.ds-room {
  background: var(--surface-page);
  color: var(--text-said);
  font-family: var(--font-display);
  display: flex;
  min-height: 100svh;
}
.ds-room__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.ds-room__status { padding: var(--s-6) var(--s-7); }
.ds-room__floor {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 var(--screen-pad-x) var(--s-9);
}
.ds-room__foot {
  padding: var(--s-8) var(--screen-pad-x);
  display: flex;
  align-items: center;
  gap: var(--s-4);
}
.ds-room__aside { display: flex; flex: 0 0 auto; }
.ds-room .ds-sheet { display: none; }

/* Phone: the rail becomes a sheet under the spoken line. The spoken line does
   not move to accommodate it. */
@media (max-width: 860px) {
  .ds-room { flex-direction: column; }
  .ds-room__status { padding: var(--s-7) var(--screen-pad-x-sm) 0; }
  .ds-room__floor { padding: 0 var(--screen-pad-x-sm) var(--s-7); }
  .ds-room__foot { padding: var(--s-7) var(--screen-pad-x-sm); }
  .ds-room .ds-said__line { font-size: var(--said-md); }
  .ds-room .ds-rail { display: none; }
  .ds-room .ds-sheet { display: block; }
  .ds-room__aside { display: block; }
}
