/**
 * A recording in the body of an entry.
 *
 * 📐 core/attachments/spoken.py · templates/core/includes/_spoken_block.html
 *    docs/admin/design_system.md ("the card goes on the item; the name goes on
 *    the ground") · docs/features/media-capture.md F3, F16, D4
 *
 * ⛔ **THE SELECTORS ARE UNSCOPED, AND THAT IS DELIBERATE — DO NOT "FIX" THEM
 * INTO `.trix-content .spoken`.** `components/attachments.css` writes every
 * photo rule twice, once under `trix-editor` and once under `.trix-content`,
 * and the stated reason is "so the composer and the reading view agree". But
 * measured in the browser: **`.trix-content` is a class on the `<trix-editor>`
 * element itself** (`entry_form.html`), and the reading view is
 * `.entry-content.prose` (`entry_detail.html`). So the `.trix-content` half of
 * every one of those pairs applies in the COMPOSER, a second time — and reaches
 * the reader never.
 *
 * Written that way here first, `Listen` rendered as a browser-default
 * `2px outset` grey button on the entry page. The block carries its own class
 * and exists in exactly two places, so scoping it buys nothing and costs a trap.
 *
 * ⚠️ The `trix-editor`-prefixed rules at the bottom are the real exception:
 * they describe the block being a selectable object, which is only true while
 * editing.
 *
 * ⛔ **NO BOX AROUND HER WORDS.** The transcript is her writing, so it is set on
 * the fourth surface — *nothing* — like every other paragraph she wrote. The
 * previous `.voice-note` rule put a `--surface` fill and a border around it,
 * which said "machine output" about the most personal thing on the page, and
 * contradicted the header of the very template that drew it. The one provenance
 * signal is the receipt line, and one is enough.
 *
 * ⛔ **NO FILE SIZE.** Duration is the human fact. See the template header for
 * the twelve products that agree.
 */

/* ── The block ───────────────────────────────────────────────────────────── */
/* `1em`, the paragraph rhythm from main.css, not a --space-* step: a recording
   sits in the flow of her writing and should breathe like a paragraph, and a
   third rhythm in an entry that already has two reads as a seam. */
.spoken {
    display: block;
    margin-block: 1em;
}

/* ── The receipt: a mark, a length, and the way to hear it ───────────────── */
/* The meta rung of the type ladder. `tabular-nums` so a timer does not shuffle
   its own digits when several recordings sit in one entry. */
.spoken__receipt {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    min-height: 44px;
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* ⚠️ `.marks__glyph` is reused rather than re-derived: it carries the 24→16
   downscale compensation (`stroke-width: 2.25`), and a stroke thins when scaled
   while a fill does not. Re-deriving it is how the two drift. */

/* ── Listen: revealed, not resident ──────────────────────────────────────── */
/* The control-hierarchy's "a choice we are asking her to make" rung: readable
   rather than shouted, underlined so it is unmistakably a control, and 44px of
   target because it sits inside a scrolling editor on a phone. */
.spoken__listen {
    min-height: 44px;
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    color: var(--text-color);
    text-decoration: underline;
    text-underline-offset: 0.2em;
    cursor: pointer;
}

.spoken__listen:hover {
    color: var(--primary);
}

.spoken__listen:focus-visible {
    outline: var(--border-width-md) solid var(--primary);
    outline-offset: var(--space-2xs);
    border-radius: var(--border-radius-sm);
}

/* ⛔ **`:not([hidden])`, NOT A BARE `display: block`.** The `hidden` attribute
 * works by a UA rule of `display: none`, which ANY author `display` declaration
 * outranks — so the plain version showed the player on load, which is precisely
 * the thing `Listen` exists to prevent, and it looked like the button was
 * broken rather than the stylesheet. */
.spoken__player:not([hidden]) {
    display: block;
    width: 100%;
    margin-top: var(--space-xs);
}

/* ── Her words ───────────────────────────────────────────────────────────── */
/* ⛔ Deliberately declares almost nothing. Inside `.entry-content` the transcript
   simply IS prose and inherits the measure, the leading and the ink; inside the
   editor it inherits the editor's paragraph type. Re-declaring either here is
   how her spoken words would start looking different from her typed ones. */
.spoken__words > p:last-child {
    margin-bottom: 0;
}

/* ── The lines that are not her words ────────────────────────────────────── */
/* Waiting, failed, nothing-was-said, and the recording being gone. Quiet: only
   one of them is something she can act on. */
.spoken__state,
.spoken__gone {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--text-base-sm);
    line-height: 1.5;
    color: var(--text-secondary);
}

.spoken__gone {
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.spoken__state--failed {
    color: var(--error-text);
}

/* ⚠️ The pulsing dot is `.analysis-pending-dot` from main.css, reused verbatim
   and NOT re-declared here — it is the same "Pensio is working on this" signal
   the emotions wait uses ten centimetres away on the same page, and it already
   carries its own `prefers-reduced-motion` guard. Two animations for one idea
   would read as two different kinds of waiting. */

/* ── Inside the editor, the block is one object ──────────────────────────── */
/* Trix marks the figure `contenteditable="false"`, so the caret cannot enter it
   and a click selects the whole thing. Saying so visually is what makes
   "select it, then delete it" discoverable. */
trix-editor .attachment--voice {
    display: block;
    cursor: default;
}

trix-editor .attachment--voice[data-trix-mutable] .spoken {
    outline: var(--border-width-md) solid var(--primary);
    outline-offset: var(--space-xs);
    border-radius: var(--border-radius-sm);
}

/* ── Asking again, when the words did not come ───────────────────────────── */
/* ⛔ **A FAILURE NEEDS A VERB.** The failed line was true, kind, and a dead
   end. This is the same "a choice we are asking her to make" rung as `Listen`
   — readable rather than shouted, underlined so it is unmistakably a control —
   and it sits inline after the sentence rather than below it, because it is
   the second half of that sentence rather than a separate offer. */
.spoken__again {
    min-height: 44px;
    margin-left: var(--space-2xs);
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--font-body);
    font-size: inherit;
    color: var(--text-color);
    text-decoration: underline;
    text-underline-offset: 0.2em;
    cursor: pointer;
}

.spoken__again:hover {
    color: var(--primary);
}

.spoken__again:focus-visible {
    outline: var(--border-width-md) solid var(--primary);
    outline-offset: var(--space-2xs);
    border-radius: var(--border-radius-sm);
}

/* ⚠️ Disabled the moment it is pressed — asking twice is two paid calls for one
   answer — so it has to still read as a control that did something, not as one
   that broke. */
.spoken__again[disabled] {
    color: var(--text-muted);
    cursor: default;
    text-decoration: none;
}

/* ⛔ **NO PULSING DOT ON A RAIL THAT IS NOT WAITING.** The stalled sentence
   sits where the "Pensio is reading this" line does, and the dot beside it
   would say work is under way when there is none. */
.analysis-pending-text--stalled {
    color: var(--text-secondary);
}

/* ── Fixing what it heard ────────────────────────────────────────────────── */
/* ⭐ The same "a choice we are asking her to make" rung as `Listen` and `Try
   again` — readable rather than shouted, underlined so it is unmistakably a
   control. It sits under her words rather than beside them: correcting is
   something she does to the paragraph, not a property of the receipt line. */
.spoken__fix-line {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin: var(--space-2xs) 0 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.spoken__fix {
    min-height: 44px;
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    color: var(--text-color);
    text-decoration: underline;
    text-underline-offset: 0.2em;
    cursor: pointer;
}

.spoken__fix:hover {
    color: var(--primary);
}

.spoken__fix:focus-visible {
    outline: var(--border-width-md) solid var(--primary);
    outline-offset: var(--space-2xs);
    border-radius: var(--border-radius-sm);
}

/* ⛔ **THE BOX SHE TYPES IN IS THE ONE PLACE A CONTAINER IS RIGHT.** Everywhere
   else her spoken words are set as prose with nothing around them — that is the
   grammar's fourth surface and the 2026-09-21 decision. A textarea is a control,
   not her words, and a control with no edges is a control nobody can find.
   ⚠️ It inherits the prose type so the words do not JUMP when she starts
   editing them: the same measure, the same leading, the same ink.
   ⭐ **AND THE SAME ROOM AS THE COMPOSER** (2026-10-11): `--writing-min-height`
   is the composer's own height, so correcting what she said is never a smaller
   space than writing it. `field-sizing` lets a long recording grow the box
   rather than scroll inside it, as the composer grows. */
.spoken__editor {
    width: 100%;
    min-height: var(--writing-min-height);
    field-sizing: content;
    margin-top: var(--space-2xs);
    padding: var(--space-sm);
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    color: var(--text-color);
    background: var(--surface);
    border: var(--border-width) solid var(--border-color);
    border-radius: var(--border-radius-sm);
    resize: vertical;
}

.spoken__editor:focus-visible {
    outline: var(--border-width-md) solid var(--primary);
    outline-offset: var(--space-2xs);
}

.spoken__editor-actions {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-top: var(--space-xs);
}

.spoken__fix-problem {
    margin: var(--space-2xs) 0 0;
    font-size: var(--text-xs);
    color: var(--error-text);
}
