/* Storyteller — main conversation surface (V2.4 Invisible Conversation) */

/*
 * Only when active. An always-on display:flex here outranked .screen{display:none}
 * and left #screen-app in document flow under other screens, doubling page height
 * and revealing a document scrollbar beside utility scrollers.
 */
#screen-app.is-active {
    padding: var(--st-page-pad-y) var(--st-page-pad-x);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    /* Definite viewport height so the stage flex child can consume remainder */
    height: 100vh;
    height: 100dvh;
    max-height: 100vh;
    max-height: 100dvh;
    box-sizing: border-box;
    overflow: hidden;
    /* Never keep the shared .screen enter fade — fill-mode transform
     * promotes a compositor layer that shimmers idle question text. */
    animation: none;
    transform: none;
}

#screen-app.is-active > .brand-bar {
    flex: 0 0 auto;
}

/*
 * flex-basis must be 0% (not auto). With basis:auto the grid sizes to its
 * content, row 1's 1fr collapses, and justify-content:center on
 * .app-question-area has no free space — the question sticks under the header.
 */
#screen-app.is-active > .app-layout.voice-stage {
    flex: 1 1 0%;
    min-height: 0;
    width: 100%;
    max-width: var(--st-measure);
    align-self: center;
}

.app-layout {
    width: 100%;
    max-width: var(--st-measure);
}

.app-resume {
    width: 100%;
    max-width: 560px;
    margin: 0 auto 28px;
    text-align: center;
    animation: st-fade-in var(--st-duration-slow) var(--st-ease) both;
}

.app-resume[hidden] {
    display: none;
}

/*
 * Resume greeting shares grid row 1 with the prompt band.
 * Mic stays on grid row 2 — do not collapse or re-order tracks.
 */
.voice-stage > .app-resume:not([hidden]) {
    justify-content: flex-start;
    align-items: center;
    width: min(560px, 100%);
    margin: clamp(6vh, 11vh, 15vh) auto 0;
    padding: 0;
}

.voice-stage:has(> .app-question-area:not([hidden]) .app-question:not(:empty)) > .app-resume {
    display: none;
}

.app-resume-greeting {
    margin: 0 0 12px;
    font-size: clamp(1.75rem, 4vw, 2.25rem);
    font-weight: 400;
    letter-spacing: -0.04em;
    color: var(--st-ink);
}

.app-resume-continuity {
    display: none;
}

/*
 * Row 4 — type-instead in the lower flex track, pinned to the track end
 * so the composer stays near the bottom without pulling the mic down.
 */
.app-say {
    grid-row: 4;
    grid-column: 1;
    width: 100%;
    max-width: 420px;
    margin: 0 auto;
    text-align: left;
    justify-self: center;
    align-self: end;
    min-height: 0;
    max-height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    position: relative;
    z-index: 5;
    overflow-x: visible;
    overflow-y: visible;
    box-sizing: border-box;
}

.app-say-label {
    display: block;
    margin: 0 0 8px;
    font-size: 13px;
    color: var(--st-faint, #9a9a9a);
}

.app-say-row {
    display: flex;
    gap: 8px;
    align-items: flex-end;
}

.app-say-input {
    flex: 1;
    min-width: 0;
    height: 44px;
    min-height: 44px;
    max-height: 168px;
    padding: 10px 14px;
    border: 1px solid #ddd;
    border-radius: 12px;
    font: inherit;
    font-size: 16px;
    background: #fff;
    color: var(--st-ink, #111);
    line-height: 1.4;
    resize: none;
    overflow-x: hidden;
    overflow-y: auto;
    white-space: pre-wrap;
    box-sizing: border-box;
}

.app-say-go {
    appearance: none;
    border: none;
    border-radius: 12px;
    padding: 0 14px;
    min-height: 44px;
    background: #111;
    color: #fff;
    font: inherit;
    font-size: 14px;
    cursor: pointer;
    flex-shrink: 0;
}

.app-say-input:disabled,
.app-say-go:disabled {
    opacity: 0.55;
    cursor: default;
}

.voice-stage.is-processing > .app-say,
.voice-stage.is-thinking > .app-say {
    pointer-events: none;
}

/*
 * Upper conversation band (grid row 1): fill the space above the mic and
 * vertically centre short/medium editorial copy inside it. Long copy
 * scrolls within the band — mic (row 2) and composer (row 4) stay fixed.
 * A small proportional padding-block-start biases optical centre slightly
 * lower (text centres read high) without a fixed screenshot margin-top.
 */
#screen-app.is-active .voice-stage > .app-question-area,
#screen-app.is-active .voice-stage > .app-processing {
    grid-row: 1;
    grid-column: 1;
    align-self: stretch;
    justify-self: center;
    width: min(680px, 100%);
    min-height: 0;
    max-height: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: safe center;
    justify-content: center;
    align-items: center;
    overscroll-behavior: contain;
    margin: 0;
    /* ~half a line of optical bias toward the mic; scales with the band */
    padding: min(4.5vh, 2.75rem) 0 0;
    box-sizing: border-box;
    /* No transform fade on the question band — causes idle shimmer. */
    animation: none;
    /*
     * Idle flicker root: overflow:auto + justify-content:center in a
     * fractional 1fr track makes the scrollbar/scroll-layer toggle and
     * recentre the question every frame. Stay hidden unless JS marks
     * the band as actually overflowing.
     */
    overflow-x: hidden;
    overflow-y: hidden;
    overflow-anchor: none;
}

#screen-app.is-active .voice-stage > .app-question-area.is-scrollable,
#screen-app.is-active .voice-stage > .app-processing.is-scrollable {
    overflow-y: auto;
    justify-content: flex-start;
    padding-top: 0;
}

/*
 * display:flex above outranks the [hidden] attribute (same bug class as
 * utility screens). Keep the static processing markup out of the upper band
 * until explicitly shown — otherwise "Thank you." / reflection stack under
 * loading phrases and ordinary questions.
 */
#screen-app.is-active .voice-stage > .app-processing[hidden],
#screen-app.is-active .voice-stage > .copy-processing[hidden] {
    display: none;
}

#screen-app.is-active .voice-stage:not(.is-first-chapter-offer) > .app-question-area > .app-question {
    flex: 0 1 auto;
    margin-top: 0;
    margin-bottom: 0;
    max-width: 560px;
    width: 100%;
    text-align: center;
    /* Same reading weight as manuscript/prose — never medium/bold. */
    font-weight: 400;
    /* Opacity transition only while a deliberate question swap is in progress
     * (inline style). A standing transition re-paints the idle surface. */
    transition: none;
}

#screen-app.is-active
    .voice-stage:not(.is-first-chapter-offer)
    > .app-question-area
    > .app-question[style*="opacity"] {
    transition: opacity 160ms var(--st-ease, ease);
}

/* Processing copy: centre the block as a unit (may have lead + reflection). */
#screen-app.is-active .voice-stage > .app-processing {
    justify-content: safe center;
    justify-content: center;
}

#screen-app.is-active .voice-stage.is-first-chapter-offer > .app-question-area {
    justify-content: safe center;
    justify-content: center;
    gap: 28px;
}

.voice-stage > .app-question-area {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    /* Enter once via screen activation — do not leave a transform layer
     * on the overflow:auto question band (idle compositor flicker). */
    animation: none;
}

.voice-stage > .app-question {
    max-width: 560px;
}

.voice-stage.is-first-chapter-offer > .app-question-area {
    flex-direction: column;
    align-items: center;
    gap: 28px;
}

.voice-stage.is-first-chapter-offer .app-question {
    text-align: center;
    font-size: clamp(1.25rem, 2.8vw, 1.7rem);
    font-weight: 400;
    line-height: 1.4;
}

.app-first-chapter-continue {
    appearance: none;
    border: 0;
    background: var(--st-text);
    color: #fff;
    font: inherit;
    font-size: 1rem;
    padding: 12px 28px;
    border-radius: 999px;
    cursor: pointer;
}

.app-first-chapter-continue[hidden] {
    display: none;
}

.voice-stage.is-first-chapter-offer > .app-mic,
.voice-stage.is-first-chapter-offer > .app-say {
    display: none;
}

/* Upper-band layout shared by manuscript welcome and editorial loading.
 * pre-wrap is welcome/soft-ask only — never for long manuscript prose. */
.voice-stage.is-manuscript-welcome > .app-resume,
.voice-stage.is-editorial-loading > .app-resume {
    display: none !important;
}

/*
 * Loading status uses the same centred upper band as ordinary questions.
 * Do not left-align or shrink the band — short phrases looked left/high.
 */
#screen-app.is-active .voice-stage.is-editorial-loading > .app-question-area {
    justify-content: safe center;
    justify-content: center;
    align-items: center;
    width: min(680px, 100%);
    max-width: none;
    margin: 0;
    padding: min(4.5vh, 2.75rem) 0 0;
}

#screen-app.is-active .voice-stage.is-editorial-loading .app-question {
    max-width: 560px;
    width: 100%;
    margin: 0 auto;
    text-align: center;
    font-size: clamp(1.15rem, 2.6vw, 1.45rem);
    font-weight: 400;
    line-height: 1.55;
    letter-spacing: -0.03em;
    color: var(--st-ink);
}

.voice-stage.is-manuscript-welcome > .app-question-area {
    justify-content: safe center;
    justify-content: center;
    align-items: center;
    margin: 0 auto;
    max-width: 560px;
    width: 100%;
}

.voice-stage.is-manuscript-welcome .app-question {
    max-width: 560px;
    margin-top: 0;
    margin-bottom: 0;
    margin-left: auto;
    margin-right: auto;
    text-align: left;
    font-size: clamp(1.15rem, 2.6vw, 1.45rem);
    font-weight: 400;
    line-height: 1.55;
    letter-spacing: -0.03em;
    color: var(--st-ink);
    white-space: pre-wrap;
}

.voice-stage > .app-processing {
    animation: st-fade-in var(--st-duration-slow) var(--st-ease) both;
}

.voice-stage > .app-status-area {
    transition: opacity var(--st-duration) var(--st-ease);
}

/*
 * Continuous conversational editorial response.
 * Panel grows with content above mic/status/composer. Short copy stays
 * vertically centered in the spare band; long copy extends the page so
 * the document scrolls — no nested response scrollbar.
 *
 * Horizontal: panel / mic / status / composer share the same full-width
 * conversation column (.app-layout / --st-measure). The mic button is
 * centered in that column — never against a narrower text measure.
 */
.continuous-response-panel {
    display: none;
}

.continuous-response-panel[hidden] {
    display: none !important;
}

/*
 * Continuous responses can exceed the viewport. Let #screen-app grow with
 * content so the document scrolls instead of nesting a panel scroller.
 * Content must start at the top (not vertically centered) so long readings
 * are never clipped above the microphone/composer.
 */
#screen-app.is-active:has(> .voice-stage.is-continuous-response),
#screen-app.is-active:has(> .app-layout.voice-stage.is-continuous-response) {
    height: auto;
    max-height: none;
    min-height: 100vh;
    min-height: 100dvh;
    overflow-x: hidden;
    overflow-y: auto;
}

#screen-app.is-active:has(> .voice-stage.is-continuous-response) > .voice-stage,
#screen-app.is-active:has(> .app-layout.voice-stage.is-continuous-response) > .voice-stage {
    flex: 1 1 auto;
    min-height: calc(100vh - var(--st-page-pad-y) * 2 - 3.5rem);
    min-height: calc(100dvh - var(--st-page-pad-y) * 2 - 3.5rem);
    overflow: visible;
}

.voice-stage.is-continuous-response {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    grid-template-rows: none;
    grid-template-columns: none;
    width: 100%;
    flex: 1 1 auto;
    min-height: 0;
}

.voice-stage.is-continuous-response > .continuous-response-panel {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    /* Grow with content; never center long text (centers clip under overflow). */
    flex: 0 0 auto;
    justify-content: flex-start;
    grid-row: auto;
    grid-column: auto;
    align-self: stretch;
    width: 100%;
    max-width: none;
    min-height: 0;
    max-height: none;
    overflow-x: hidden;
    overflow-y: visible;
    margin: 0;
    padding: 12px 0 16px;
    text-align: left;
    box-sizing: border-box;
}

.voice-stage.is-continuous-response > .app-resume,
.voice-stage.is-continuous-response > .app-processing,
.voice-stage.is-continuous-response > .app-question-area {
    display: none !important;
}

.voice-stage.is-continuous-response > .voice-recorder-anchor {
    grid-row: auto;
    grid-column: auto;
    align-self: stretch;
    justify-self: auto;
    flex: 0 0 var(--voice-mic-cluster);
    width: 100%;
    max-width: none;
    margin: 8px 0 0;
    /* Button stays centered on the shared conversation column axis */
    display: flex;
    flex-direction: column;
    align-items: center;
}

.voice-stage.is-continuous-response > .status-area,
.voice-stage.is-continuous-response > .app-status-area {
    grid-row: auto;
    grid-column: auto;
    align-self: stretch;
    flex: 0 0 var(--voice-status-band);
    width: 100%;
    max-width: none;
    margin: 0;
    padding: calc(var(--voice-mic-ring-bleed) + var(--voice-status-gap)) 12px 0;
    overflow-x: hidden;
    overflow-y: auto;
    text-align: center;
    box-sizing: border-box;
}

.voice-stage.is-continuous-response > .app-say {
    grid-row: auto;
    grid-column: auto;
    flex: 0 0 auto;
    /* Same centered composer width as the normal mic screen */
    width: 100%;
    max-width: 420px;
    align-self: center;
    justify-self: auto;
    max-height: none;
    margin: 8px auto 0;
}

.continuous-response-title {
    margin: 0 0 28px;
    font-size: var(--st-size-title, 1.75rem);
    font-weight: 400;
    letter-spacing: -0.02em;
    line-height: 1.2;
    color: var(--st-text, var(--st-ink));
}

.continuous-response-body {
    margin: 0;
}

.continuous-response-body .prologue-paragraph,
.continuous-response-paragraph {
    font-size: var(--st-size-body-lg, 1.125rem);
    line-height: 1.75;
    color: var(--st-text, var(--st-ink));
    font-weight: 400;
    margin: 0;
}

.continuous-response-body .prologue-paragraph + .prologue-paragraph,
.continuous-response-paragraph + .continuous-response-paragraph {
    margin-top: 20px;
}

.continuous-response-followup {
    margin: 28px 0 0;
    font-size: clamp(1.15rem, 2.6vw, 1.45rem);
    line-height: 1.55;
    letter-spacing: -0.03em;
    color: var(--st-ink);
    font-weight: 400;
}

.continuous-response-followup[hidden] {
    display: none !important;
}

.continuous-response-approval {
    margin-top: 18px;
}

.continuous-response-approval[hidden] {
    display: none !important;
}

.continuous-response-approval-btn {
    appearance: none;
    border: 1px solid var(--st-border, #cfcfcf);
    background: var(--st-bg, #fff);
    color: var(--st-ink, #1a1a1a);
    font-family: var(--st-font-sans, inherit);
    font-size: 15px;
    line-height: 1.3;
    padding: 10px 16px;
    border-radius: 8px;
    cursor: pointer;
}

.continuous-response-approval-btn:hover {
    border-color: var(--st-ink, #1a1a1a);
}

.continuous-response-approval-btn:disabled {
    opacity: 0.55;
    cursor: default;
}

@media (max-width: 768px) {
    .voice-stage.is-continuous-response > .continuous-response-panel {
        width: 100%;
        padding: 12px 0;
    }

    .continuous-response-title {
        margin-bottom: 20px;
    }

    .continuous-response-body .prologue-paragraph,
    .continuous-response-paragraph {
        font-size: 18px;
    }

    .continuous-response-body .prologue-paragraph + .prologue-paragraph,
    .continuous-response-paragraph + .continuous-response-paragraph {
        margin-top: 16px;
    }

    .continuous-response-followup {
        margin-top: 22px;
        font-size: 1.15rem;
    }
}

/*
 * Desktop editorial conversation workspace (≥1024).
 *
 * Align with Read Manuscript: broad desktop workspace canvas, controlled
 * reading measure for questions/responses, useful writing width for the
 * composer, calm mic size. Mic button sized directly (not --voice-mic-size
 * on #screen-app) so the cluster track stays stable while idle.
 * Scoped to #screen-app; Welcome / Help / mobile unchanged.
 */
@media (min-width: 768px) {
    /*
     * Idle flicker: any lasting animation/transition/compositor promotion on
     * the conversation shell shimmered the question + stage. Kill enter
     * animation entirely after paint intent; freeze idle mic chrome (shadow
     * transitions + soft blur shadows repaint continuously on some GPUs).
     * Only intentional listening/processing mic motion may animate.
     * Threshold 768px so large tablets match desktop stillness.
     */
    #screen-app.is-active,
    #screen-app.is-active .voice-stage,
    #screen-app.is-active .app-layout {
        animation: none !important;
        transition: none !important;
        transform: none !important;
        filter: none !important;
        backdrop-filter: none !important;
        will-change: auto !important;
    }

    #screen-app.is-active .voice-stage > .app-question-area,
    #screen-app.is-active .voice-stage > .app-processing,
    #screen-app.is-active .voice-stage > .app-question-area .app-question,
    #screen-app.is-active .brand-bar,
    #screen-app.is-active .app-say,
    #screen-app.is-active .app-say-input,
    #screen-app.is-active .app-status-area,
    #screen-app.is-active .voice-recorder-anchor,
    #screen-app.is-active .voice-waveform,
    #screen-app.is-active .voice-recorder-timer {
        animation: none !important;
        transform: none !important;
        filter: none !important;
        backdrop-filter: none !important;
        transition: none !important;
        will-change: auto !important;
    }

    #screen-app.is-active
        .voice-stage:not(.is-recording):not(.is-processing)
        .btn-mic:not(.is-listening),
    #screen-app.is-active
        .voice-stage:not(.is-recording):not(.is-processing)
        .voice-recorder-anchor
        .btn-mic:not(.is-listening) {
        animation: none !important;
        transition: none !important;
        /* Soft blur shadows shimmer on some GPUs — use a hard idle lift. */
        box-shadow: 0 1px 0 rgba(17, 17, 17, 0.06) !important;
        filter: none !important;
        transform: none !important;
        will-change: auto !important;
    }

    #screen-app.is-active
        .voice-stage:not(.is-recording):not(.is-processing)
        .btn-mic:not(.is-listening):hover {
        box-shadow: 0 1px 0 rgba(17, 17, 17, 0.06) !important;
        transform: none !important;
    }

    #screen-app.is-active
        .voice-stage:not(.is-recording):not(.is-processing)
        .btn-mic:not(.is-listening)::before,
    #screen-app.is-active
        .voice-stage:not(.is-recording):not(.is-processing)
        .btn-mic:not(.is-listening)::after {
        animation: none !important;
        opacity: 0 !important;
        transition: none !important;
        content: none !important;
        filter: none !important;
        box-shadow: none !important;
    }

    #screen-app.is-active
        .voice-stage:not(.is-recording)
        .voice-waveform,
    #screen-app.is-active
        .voice-stage:not(.is-recording)
        .voice-recorder-timer {
        transition: none !important;
        animation: none !important;
    }

    #screen-app.is-active > .app-layout.voice-stage {
        max-width: var(--st-desktop-workspace);
    }

    #screen-app.is-active .voice-stage > .app-question-area,
    #screen-app.is-active .voice-stage > .app-processing,
    #screen-app.is-active .voice-stage > .copy-processing,
    #screen-app.is-active .voice-stage > .status-area,
    #screen-app.is-active .voice-stage > .app-status-area,
    #screen-app.is-active .voice-stage.is-continuous-response > .continuous-response-panel {
        width: 100%;
    }

    #screen-app.is-active
        .voice-stage:not(.is-first-chapter-offer)
        > .app-question-area
        > .app-question,
    #screen-app.is-active .voice-stage > .app-question,
    #screen-app.is-active .voice-stage.is-editorial-loading .app-question,
    #screen-app.is-active .voice-stage.is-manuscript-welcome .app-question,
    #screen-app.is-active .voice-stage.is-continuous-response .continuous-response-title,
    #screen-app.is-active .voice-stage.is-continuous-response .continuous-response-body,
    #screen-app.is-active .voice-stage.is-continuous-response .continuous-response-followup,
    #screen-app.is-active .voice-stage.is-continuous-response .continuous-response-approval {
        max-width: var(--st-desktop-canvas);
        width: 100%;
        margin-left: auto;
        margin-right: auto;
    }

    #screen-app.is-active .app-say,
    #screen-app.is-active .voice-stage.is-continuous-response > .app-say {
        max-width: var(--st-measure-reader);
        width: 100%;
    }

    #screen-app.is-active .voice-stage.is-writing-desk > .app-say,
    #screen-app.is-active
        .voice-stage.is-writing-desk.is-continuous-response
        > .app-say {
        width: 100%;
        max-width: none;
    }

    #screen-app.is-active .app-say-input {
        min-height: 40px;
        max-height: 40px;
        padding: 8px 14px;
        border-radius: 8px;
        border-color: #e4e4e4;
        font-size: 16px;
        line-height: 1.35;
        letter-spacing: -0.01em;
    }

    #screen-app.is-active .app-say-go {
        min-height: 40px;
        border-radius: 8px;
        padding: 0 16px;
        align-self: flex-end;
    }

    #screen-app.is-active .voice-recorder-anchor .btn-mic {
        width: 152px;
        height: 152px;
    }
}

@media (min-width: 1200px) {
    #screen-app.is-active > .app-layout.voice-stage {
        max-width: var(--st-desktop-workspace);
    }

    #screen-app.is-active .app-say,
    #screen-app.is-active .voice-stage.is-continuous-response > .app-say {
        max-width: var(--st-measure-reader);
    }

    #screen-app.is-active .voice-stage.is-writing-desk > .app-say,
    #screen-app.is-active
        .voice-stage.is-writing-desk.is-continuous-response
        > .app-say {
        width: 100%;
        max-width: none;
    }

    #screen-app.is-active .voice-recorder-anchor .btn-mic {
        width: 154px;
        height: 154px;
    }
}

@media (min-width: 1440px) {
    #screen-app.is-active > .app-layout.voice-stage {
        max-width: var(--st-desktop-workspace);
    }

    #screen-app.is-active .app-say,
    #screen-app.is-active .voice-stage.is-continuous-response > .app-say {
        max-width: var(--st-measure-reader);
    }

    #screen-app.is-active .voice-stage.is-writing-desk > .app-say,
    #screen-app.is-active
        .voice-stage.is-writing-desk.is-continuous-response
        > .app-say {
        width: 100%;
        max-width: none;
    }

    #screen-app.is-active .voice-recorder-anchor .btn-mic {
        width: 156px;
        height: 156px;
    }
}

/*
 * Writing Desk V1 — Word Count.
 * Replaces the former large-screen .is-typewriter sheet. Phone/mobile
 * composer is unchanged (class may still be set below the desk viewport).
 */
.writing-desk-bar[hidden] {
    display: none !important;
}

#screen-app.is-active:has(> .voice-stage.is-writing-desk) {
    height: 100vh;
    height: 100dvh;
    max-height: 100vh;
    max-height: 100dvh;
    overflow: hidden;
}

#screen-app.is-active:has(> .voice-stage.is-writing-desk) > .brand-bar {
    padding-bottom: 12px;
}

#screen-app.is-active > .app-layout.voice-stage.is-writing-desk {
    max-width: none;
    width: 100%;
    align-self: stretch;
    padding-bottom: 8px;
    justify-items: stretch;
    grid-template-columns:
        minmax(0, 1fr)
        min(900px, 100%)
        minmax(0, 1fr);
    grid-template-rows:
        auto
        minmax(0, 1fr)
        auto;
}

#screen-app.is-active .voice-stage.is-writing-desk > .voice-recorder-anchor,
#screen-app.is-active .voice-stage.is-writing-desk > .app-status-area,
#screen-app.is-active .voice-stage.is-writing-desk > .status-area,
#screen-app.is-active .voice-stage.is-writing-desk > .app-processing,
#screen-app.is-active .voice-stage.is-writing-desk > .app-resume,
#screen-app.is-active .voice-stage.is-writing-desk .app-say-label,
#screen-app.is-active .voice-stage.is-writing-desk .app-say-go,
#screen-app.is-active .voice-stage.is-writing-desk .app-say-focus {
    display: none !important;
}

#screen-app.is-active .voice-stage.is-writing-desk > .app-question-area,
#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    > .continuous-response-panel,
#screen-app.is-active .voice-stage.is-writing-desk > .app-say,
#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    > .app-say {
    grid-column: 2;
    width: 100% !important;
    max-width: none !important;
    margin-left: 0;
    margin-right: 0;
    justify-self: stretch;
    box-sizing: border-box;
    padding-left: 0;
    padding-right: 0;
}

#screen-app.is-active .voice-stage.is-writing-desk > .app-question-area {
    grid-row: 1;
    height: auto;
    max-height: none;
    justify-content: flex-start;
    align-items: stretch;
    padding-top: 80px;
    padding-bottom: 0;
    overflow: hidden;
}

#screen-app.is-active
    .voice-stage.is-writing-desk:not(.is-first-chapter-offer)
    > .app-question-area
    > .app-question {
    max-width: none !important;
    width: 100% !important;
    text-align: left;
    font-family: var(--st-font-sans);
    font-size: 1.0625rem;
    font-weight: 400;
    line-height: 1.5;
    letter-spacing: -0.02em;
    color: var(--st-ink);
}

#screen-app.is-active
    .voice-stage.is-writing-desk.has-writing:not(.is-first-chapter-offer)
    > .app-question-area
    > .app-question {
    font-size: 0.9375rem;
    line-height: 1.45;
    color: #8a8a8a;
}

#screen-app.is-active .voice-stage.is-writing-desk.is-continuous-response {
    display: grid;
    justify-items: stretch;
    grid-template-columns:
        minmax(0, 1fr)
        min(900px, 100%)
        minmax(0, 1fr);
    grid-template-rows:
        auto
        minmax(0, 1fr)
        auto;
}

#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    > .continuous-response-panel {
    grid-row: 1;
    flex: 0 0 auto;
    justify-content: flex-start;
    padding-top: 80px;
    padding-bottom: 0;
}

#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    .continuous-response-title,
#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    .continuous-response-body,
#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    .continuous-response-approval {
    display: none !important;
}

#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    .continuous-response-followup {
    margin: 0;
    max-width: none;
    text-align: left;
    font-family: var(--st-font-sans);
    font-size: 1.0625rem;
    line-height: 1.5;
    color: var(--st-ink);
}

#screen-app.is-active
    .voice-stage.is-writing-desk.has-writing.is-continuous-response
    .continuous-response-followup {
    font-size: 0.9375rem;
    color: #8a8a8a;
}

#screen-app.is-active .voice-stage.is-writing-desk > .app-say,
#screen-app.is-active
    .voice-stage.is-writing-desk.is-continuous-response
    > .app-say {
    grid-row: 2;
    height: 100%;
    min-height: 0;
    max-height: none;
    padding-top: 40px;
    padding-bottom: 20px;
    align-self: stretch;
    justify-content: flex-start;
    overflow: hidden;
}

#screen-app.is-active .voice-stage.is-writing-desk .app-say-row {
    flex: 1 1 auto;
    align-items: stretch;
    min-height: 0;
    height: 100%;
    gap: 0;
}

#screen-app.is-active .voice-stage.is-writing-desk .app-say-input,
#screen-app.is-active .voice-stage.is-writing-desk .app-say-input:focus,
#screen-app.is-active .voice-stage.is-writing-desk .app-say-input:focus-visible {
    flex: 1 1 auto;
    width: 100% !important;
    max-width: none !important;
    min-width: 0;
    height: 100% !important;
    min-height: 0 !important;
    max-height: none !important;
    padding: 0 0 48px;
    border: 0 !important;
    border-radius: 0;
    background: transparent;
    box-shadow: none !important;
    outline: none !important;
    font-family: var(--st-font-serif);
    font-size: 20px;
    font-weight: 400;
    line-height: var(--st-line-reader);
    letter-spacing: 0;
    color: var(--st-ink-soft, #1a1a1a);
    caret-color: var(--st-ink-soft, #1a1a1a);
    overflow-x: hidden;
    overflow-y: auto;
}

#screen-app.is-active .voice-stage.is-writing-desk > .writing-desk-bar {
    grid-row: 3;
    grid-column: 1 / -1;
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    margin: 0;
    padding: 4px 2px 2px;
    box-sizing: border-box;
}

.writing-desk-count {
    margin: 0;
    font-size: 12px;
    line-height: 1;
    color: #b5b5b5;
    letter-spacing: 0.01em;
}

.writing-desk-done {
    appearance: none;
    border: 0;
    background: none;
    padding: 8px 2px;
    font: inherit;
    font-size: 13px;
    line-height: 1;
    color: #8a8a8a;
    cursor: pointer;
}

.writing-desk-done:disabled {
    opacity: 0.45;
    cursor: default;
}

.app-say-focus {
    appearance: none;
    align-self: flex-start;
    margin: 8px 0 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 13px;
    line-height: 1;
    letter-spacing: 0.01em;
    color: #8a8a8a;
    cursor: pointer;
}

.app-say-focus:disabled {
    opacity: 0.45;
    cursor: default;
}

.app-say-focus[hidden] {
    display: none !important;
}

@media (max-width: 767px), (max-height: 559px) {
    .app-say-focus {
        display: none !important;
    }
}

/*
 * iPhone / narrow phones — Continue / start conversation STRUCTURE.
 *
 * Not a textarea-height bug. The desktop 4-row grid keeps a fixed mic
 * cluster (~meter band + button) and status band that starve the question
 * track once Safari chrome shortens the visual viewport. The question then
 * clips into the mic/composer stack (higher z-index) and cannot scroll
 * fully clear of the bottom chrome.
 *
 * Phone-only flex column (Writing Desk / continuous response / ≥768 untouched):
 *   question scrolls in remaining space
 *   mic sits below the question in normal flow
 *   status sizes to content
 *   composer is content-sized at the bottom — never overlaps the question
 * Idle invisible meter/waveform space collapses so the mic can sit closer
 * under the question without changing button chrome.
 */
@media (max-width: 767px) {
    #screen-app.is-active:not(:has(> .voice-stage.is-writing-desk)):not(
            :has(> .voice-stage.is-continuous-response)
        ) {
        height: 100vh;
        height: 100dvh;
        height: 100svh;
        max-height: 100vh;
        max-height: 100dvh;
        max-height: 100svh;
        /* Bottom clearance lives on .app-say (browser/OS chrome); keep
         * the screen bottom pad neutral so the stage is not lifted. */
        padding-bottom: 0;
        box-sizing: border-box;
        overflow: hidden;
    }

    #screen-app.is-active
        > .app-layout.voice-stage:not(.is-writing-desk):not(.is-continuous-response) {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: flex-start;
        grid-template-rows: none;
        grid-template-columns: none;
        padding-bottom: 0;
        min-height: 0;
        overflow: hidden;
        gap: 0;
    }

    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .app-question-area,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .app-processing,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .app-resume {
        flex: 1 1 auto;
        grid-row: auto;
        grid-column: auto;
        align-self: stretch;
        width: 100%;
        min-height: 0;
        max-height: none;
        height: auto;
        margin: 0;
        /* Comfortable air above the mic; question scrolls fully in this band. */
        padding: 8px 0 20px;
        box-sizing: border-box;
        overflow-x: hidden;
        overflow-y: hidden;
        justify-content: safe center;
        justify-content: center;
    }

    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .app-question-area.is-scrollable,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .app-processing.is-scrollable {
        overflow-y: auto;
        justify-content: flex-start;
        padding-top: 8px;
    }

    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .voice-recorder-anchor {
        flex: 0 0 auto;
        grid-row: auto;
        grid-column: auto;
        align-self: center;
        height: auto;
        min-height: 0;
        max-height: none;
        margin: 0 0 8px;
    }

    /* Idle: collapse opacity-0 meter/timer so they do not reserve 101px. */
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response):not(
            .is-recording
        )
        .voice-recorder-timer,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response):not(
            .is-recording
        )
        .voice-waveform {
        height: 0;
        margin: 0;
        overflow: hidden;
        opacity: 0;
        pointer-events: none;
    }

    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .app-status-area,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .status-area {
        flex: 0 0 auto;
        grid-row: auto;
        grid-column: auto;
        align-self: stretch;
        width: 100%;
        height: auto;
        min-height: 0;
        max-height: none;
        padding: 8px 12px 4px;
        box-sizing: border-box;
    }

    /*
     * Composer: normal-flow bottom chrome, content-sized. Never position
     * fixed/absolute over the question. Narrow-phone bottom clearance —
     * env(safe-area-inset-bottom) when the OS reports it, plus a minimum
     * that still clears typical mobile browser toolbars when inset is 0.
     * Responsive max-width only; no UA / device sniffing.
     */
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk):not(.is-continuous-response)
        > .app-say {
        flex: 0 0 auto;
        grid-row: auto;
        grid-column: auto;
        align-self: stretch;
        width: 100%;
        max-width: 100%;
        margin: 8px auto 0;
        min-height: 0;
        max-height: none;
        overflow: visible;
        position: relative;
        z-index: 5;
        /* Fallback when constant/env are unsupported */
        padding-bottom: 56px;
        /* Older WebKit */
        padding-bottom: max(
            56px,
            calc(constant(safe-area-inset-bottom, 0px) + 16px)
        );
        /* Modern: inset when present, else keep the toolbar floor */
        padding-bottom: max(
            56px,
            calc(env(safe-area-inset-bottom, 0px) + 16px)
        );
        box-sizing: border-box;
    }
}

/*
 * Narrow phones: Continue question — restored pre-typography size with
 * the frozen visually regular weight.
 *
 * From git before tonight's weight work (40b548a): nested .app-question
 * inherited body metrics — font-size 16px, line-height normal. The
 * 24px/20px rules never matched (.voice-stage > .app-question). Keep
 * font-weight 300 (current correct optical regular). Shared stack only.
 * Desktop / iPad / Writing Desk untouched.
 */
@media (max-width: 767px) {
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk)
        > .app-question-area
        > .app-question,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk).is-editorial-loading
        .app-question,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk).is-manuscript-welcome
        .app-question,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk).is-first-chapter-offer
        .app-question {
        font-family: var(--st-font-sans);
        font-size: 16px;
        font-weight: 300;
        line-height: normal;
    }
}

/*
 * iPhone / narrow phones: idle type-instead must stay one compact row.
 *
 * Real iPhone Safari root cause (not a deploy miss):
 * 1) Base .app-say-input leaves appearance:auto (default textarea).
 * 2) VoiceRecorderUI.autosizeTypeInstead sets height:auto then writes an
 *    inline pixel height from scrollHeight. On WebKit that empty-field
 *    scrollHeight is ~two line-boxes, and the form-control intrinsic size
 *    does not honor max-height:40 the way Chromium does — so the used
 *    height stays ~two rows even though this media query wins the cascade.
 * Fix: kill WebKit textarea appearance, pin idle box-sizing heights, clear
 * fixed height on focus so autosize may grow, blur returns to one row.
 * Writing Desk / desktop / iPad unchanged.
 */
@media (max-width: 767px) {
    #screen-app.is-active .voice-stage:not(.is-writing-desk) .app-say-input {
        -webkit-appearance: none;
        appearance: none;
        box-sizing: border-box;
        height: 40px;
        min-height: 40px;
        max-height: 40px;
        padding: 8px 14px;
        line-height: 1.35;
        overflow-x: hidden;
        overflow-y: auto;
    }

    #screen-app.is-active .voice-stage:not(.is-writing-desk) .app-say-go {
        min-height: 40px;
    }

    #screen-app.is-active .voice-stage:not(.is-writing-desk) .app-say-input:focus,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk)
        .app-say-input:focus-visible {
        height: auto;
        min-height: 40px;
        max-height: 168px;
    }
}

/*
 * Desk-capable viewports: compact one-line composer until the author
 * clicks in. Focus is an explicit second step — never auto-enter.
 */
@media (min-width: 768px) and (min-height: 560px) {
    #screen-app.is-active .voice-stage:not(.is-writing-desk) > .app-say {
        overflow: visible;
    }

    #screen-app.is-active .voice-stage:not(.is-writing-desk) .app-say-input {
        min-height: 40px;
        max-height: 40px;
        padding: 8px 14px;
        font-size: 16px;
        line-height: 1.35;
    }

    #screen-app.is-active .voice-stage:not(.is-writing-desk) .app-say-input:focus,
    #screen-app.is-active
        .voice-stage:not(.is-writing-desk)
        .app-say-input:focus-visible {
        outline: none;
        border-color: #d0d0d0;
        box-shadow: 0 0 0 1px rgba(17, 17, 17, 0.16);
    }

    #screen-app.is-active .voice-stage:not(.is-writing-desk) .app-say-go {
        min-height: 40px;
        align-self: flex-end;
    }

    #screen-app.is-active
        .voice-stage:not(.is-writing-desk)
        .app-say.is-composer-open
        .app-say-input {
        min-height: 5.75rem;
        max-height: 320px;
        transition: min-height 180ms ease, height 180ms ease !important;
    }
}

@media (min-width: 768px) and (max-width: 1023px) and (orientation: portrait) {
    #screen-app.is-active:has(> .voice-stage.is-writing-desk) {
        padding-left: 24px;
        padding-right: 24px;
    }

    #screen-app.is-active .voice-stage.is-writing-desk > .app-question-area,
    #screen-app.is-active
        .voice-stage.is-writing-desk.is-continuous-response
        > .continuous-response-panel {
        padding-top: 56px;
        padding-left: 0;
        padding-right: 0;
    }

    #screen-app.is-active .voice-stage.is-writing-desk > .app-say,
    #screen-app.is-active
        .voice-stage.is-writing-desk.is-continuous-response
        > .app-say {
        padding-top: 32px;
        padding-bottom: 16px;
        padding-left: 0;
        padding-right: 0;
    }
}

@media (min-width: 768px) and (orientation: landscape) and (max-height: 850px) {
    #screen-app.is-active .voice-stage.is-writing-desk > .app-question-area,
    #screen-app.is-active
        .voice-stage.is-writing-desk.is-continuous-response
        > .continuous-response-panel {
        padding-top: 56px;
    }
}

@media (min-width: 1024px) {
    #screen-app.is-active .voice-stage.is-writing-desk > .app-say,
    #screen-app.is-active
        .voice-stage.is-writing-desk.is-continuous-response
        > .app-say {
        width: 100%;
        max-width: none;
        padding-top: 48px;
        padding-bottom: 24px;
        padding-left: 0;
        padding-right: 0;
    }
}
