/*
 * Stetworth /app — the Preferences screen (#/preferences), the
 * text-first page cut to the new-ux mockup (digest 571-601) by lane
 * 07: every rule is `pf-` prefixed and tokens-only.  Created empty and
 * linked by lane 06; this lane only fills it.
 */
/*
 * Load order is load-bearing: the /app shell links every split sheet
 * BEFORE style.css.  That keeps both source-order contracts intact —
 * a rule kept behind in style.css still beats its shared group there
 * by file order, and the responsive tail at the end of style.css
 * still overrides this sheet's base rules at equal specificity.
 * This sheet declares no design-token block of its own; its media
 * only media block is the phone (max-width: 720px) block the split-sheet
 * amendment allows (docs/APP.md#the-split-stylesheets); the page's
 * entrance is the shell's `main.fade-in`, whose reduced-motion guard
 * lives in style.css.
 */

/* ============================================================
 * The page IS the two-column grid (mockup 571 — minmax(0,1.6fr)
 * minmax(280px,1fr), gap 40px, top-aligned so the aside can stick,
 * entering with the mockup's `rise` — the shell's `main.fade-in`
 * carries that 10px rise, so .pf-page itself does not animate).  The left column (572) holds
 * the header AND the list, so the sticky aside's top sits level with
 * the h1 as the mockup draws it; DOM order is the mockup's — left
 * column, then aside (592) — and the phone block reorders visually.
 * Ids and data hooks are the contract (CONTRACTS.md §7.3); these
 * classes are styling only.
 * ============================================================ */

.pf-page {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(280px, 1fr);
    gap: 40px;
    align-items: start;
}

/* The left column (mockup 572): header, then the list, 22px apart. */
.pf-left {
    display: flex;
    flex-direction: column;
    gap: 22px;
    min-width: 0;
}

.pf-head {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* The page h1 (mockup 574: 40px display serif — the scale's
 * --fs-hero rung exactly). */
.pf-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 400;
    font-size: var(--fs-hero);
    line-height: 1.1;
    color: var(--c-ink);
}

/* The intro line (mockup 575: 17px text serif — --fs-lede). */
.pf-intro {
    margin: 0;
    font-family: var(--font-text);
    font-size: var(--fs-lede);
    line-height: 1.5;
    color: var(--c-ink-soft);
    max-width: 620px;
}

.pf-list-col {
    min-width: 0;
}

/* ============================================================
 * The list (mockup 577-590): one card holding the rows, each row a
 * 3-column grid — glyph, sentence, controls (mockup 579).
 * ============================================================ */

.pf-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    background: var(--c-sand-card);
    border: 1px solid var(--c-sand-rule);
    border-radius: var(--radius);
    overflow: hidden;
}

.pf-row {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr) auto;
    gap: 14px;
    align-items: baseline;
    padding: 14px 20px;
    border-bottom: 1px solid var(--c-soft);
}

/* Body + controls share a wrapper so the phone block below can wrap
 * the controls under the sentence (spec 07 :128).  On desktop it is
 * `display: contents`: its children are the grid items, so the row
 * is still the mockup's 3-column grid. */
.pf-main {
    display: contents;
}

/* The leading mark (mockup 580): an 18px moss circle carrying a light
 * ✓ — --c-status-complete is the mockup's moss (style.css :165).  The glyph is a
 * mark, not text (§7.7); the mockup's 9px is the shared sheet's --fs-9
 * rung, minted for this badge by the fidelity audit (2026-09-11).
 * `top: 3px` drops the badge to the sentence's x-height as the mockup does. */
.pf-glyph {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--c-status-complete);
    color: var(--c-sand-card);
    font-size: var(--fs-9);
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: relative;
    top: 3px;
}

.pf-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

/* The sentence (mockup 581: 16px text serif — --fs-base). */
.pf-text {
    margin: 0;
    font-family: var(--font-text);
    font-size: var(--fs-base);
    line-height: 1.4;
    color: var(--c-ink);
    overflow-wrap: break-word;
}

/* The "from task #N" provenance line. */
.pf-source {
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-ink-muted);
}

/* The "why" disclosure: the summary is a quiet toggle, the note
 * inside is secondary prose. */
.pf-why {
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-ink-muted);
}

.pf-why summary {
    cursor: pointer;
}

.pf-rationale {
    margin: 4px 0 0;
    font-family: var(--font-text);
    font-size: var(--fs-body);
    line-height: 1.45;
    color: var(--c-ink-soft);
    overflow-wrap: break-word;
}

/* The row controls (mockup 584-585): quiet text buttons, always
 * visible — no hover reveal, so touch devices can reach them. */
.pf-controls {
    display: flex;
    gap: 10px;
    white-space: nowrap;
}

.pf-btn {
    border: 0;
    background: transparent;
    padding: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-12-5);
    color: var(--c-ink-muted);
    cursor: pointer;
}

.pf-btn:hover {
    color: var(--c-accent);
}

.pf-btn:disabled {
    opacity: 0.6;
    cursor: default;
}

.pf-btn-danger:hover {
    color: var(--c-status-failed);
}

/* Cancel darkens to ink on hover (mockup 585), not to the accent. */
.pf-btn-cancel:hover {
    color: var(--c-ink);
}

.pf-btn-save {
    color: var(--c-accent);
    font-weight: 500;
}

/* The inline editor (mockup 582): the input takes the sentence's
 * cell, with the optional rationale textarea under it; Save/Cancel
 * are `.pf-controls` in the row's third cell (583-585). */
.pf-editor {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}

.pf-edit-input,
.pf-rationale-input {
    width: 100%;
    box-sizing: border-box;
    font-family: var(--font-ui);
    font-size: var(--fs-body);
    color: var(--c-ink);
    background: var(--c-sand-page);
    border: 1px solid var(--c-rule-strong);
    border-radius: var(--r-6);
    padding: 7px 10px;
    outline: 0;
}

.pf-edit-input:focus,
.pf-rationale-input:focus,
.pf-textarea:focus {
    box-shadow: var(--focus-ring);
}

.pf-rationale-input {
    resize: vertical;
}

/* The empty state (mockup 589). */
.pf-empty {
    padding: 28px 20px;
    font-family: var(--font-ui);
    font-size: var(--fs-14-5);
    color: var(--c-ink-muted);
    text-align: center;
}

/* ============================================================
 * The sticky aside (mockup 592-599): the add form's card, gold top
 * spine, sticky at 24px on desktop.
 * ============================================================ */

.pf-aside {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 18px 20px;
    background: var(--c-sand-card);
    border: 1px solid var(--c-sand-rule);
    border-top: 2px solid var(--c-gold);
    border-radius: var(--radius);
    position: sticky;
    top: 24px;
}

/* The aside heading (mockup 593: 22px display serif — --fs-22). */
.pf-aside-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 400;
    font-size: var(--fs-22);
    color: var(--c-ink);
}

.pf-form {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* The textarea's accessible name (spec 07 :114) — visually hidden,
 * since the mockup (593-595) puts the textarea straight under the h2. */
.pf-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* The add textarea (mockup 595: 15.5px text serif on the page
 * ground — --fs-15-5). */
.pf-textarea {
    font-family: var(--font-text);
    font-size: var(--fs-15-5);
    line-height: 1.45;
    color: var(--c-ink);
    background: var(--c-sand-page);
    border: 1px solid var(--c-rule-strong);
    border-radius: var(--r-6);
    padding: 10px 12px;
    outline: 0;
    resize: vertical;
}

/* The inline error line ships hidden and is written with textContent
 * only (`_showFormError`). */
.pf-error {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-status-failed);
}

/* The submit control (mockup 596: filled accent with a 1px accent
 * border, 13.5px — --fs-13-5). */
.pf-submit {
    border: 1px solid var(--c-accent);
    background: var(--c-accent);
    color: var(--c-sand-card);
    font-family: var(--font-ui);
    font-size: var(--fs-13-5);
    font-weight: 500;
    padding: 8px 13px;
    border-radius: var(--r-6);
    cursor: pointer;
    align-self: flex-start;
}

.pf-submit:hover {
    background: var(--c-accent-hover);
}

.pf-submit:disabled {
    opacity: 0.6;
    cursor: default;
}

/* The helper line (mockup 598; --c-ink-muted rather than the
 * mockup's faint ink, which sits below the text floor). */
.pf-helper {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-12-5);
    line-height: 1.45;
    color: var(--c-ink-muted);
}

/* The confirm dialog's body (rendered into the shared AppSurface
 * dialog): one sentence, then the accept/cancel pair. */
.pf-confirm-body {
    margin: 0 0 12px;
    font-family: var(--font-ui);
    font-size: var(--fs-body);
    line-height: 1.5;
    color: var(--c-ink-soft);
}

.pf-confirm-actions {
    display: flex;
    gap: 12px;
}

/* ============================================================
 * Phone (< 720px) — §7.8 and the Screen 3 phone rules: one column
 * with the aside first (it loses the stick and keeps its DOM-order
 * lead — `order: -1` pins that even against a re-ordered grid), a
 * full-width textarea and a >= 44px full-width Save; the rows keep
 * the glyph column and flex-wrap the controls under the sentence
 * below 360px.  No extra breakpoint (CONTRACTS R33 allows split
 * sheets only the 720px and reduced-motion preludes): the wrap point
 * is the body's flex-basis — at a 360px viewport the row's body +
 * controls box is 252px (page 16px, card 1px and row 20px each side,
 * then the 20px glyph column and its 14px gap), the Edit/Remove pair
 * is 72px and the gap 14px, so a 166px basis keeps one line at 360
 * and wraps the controls under the sentence from 359 down.
 * ============================================================ */

@media (max-width: 720px) {
    /* §7.8 (touch targets >= 44px): the "why" disclosure summary
     * keeps its list-item display (so the marker stays) and pads to a
     * 44px tap area. */
    .pf-why summary {
        box-sizing: border-box;
        min-height: 44px;
        padding: 12px 0;
    }

    .pf-page {
        grid-template-columns: 1fr;
        gap: 24px;
    }

    /* The left column dissolves so its header, the aside and the list
     * are the grid's items: header first, then the add form (spec 07
     * :128 — adding is the primary action on a phone), then the list. */
    .pf-left {
        display: contents;
    }

    .pf-head {
        order: -2;
    }

    .pf-aside {
        position: static;
        order: -1;
    }

    .pf-textarea {
        width: 100%;
        box-sizing: border-box;
    }

    .pf-submit {
        align-self: stretch;
        width: 100%;
        min-height: 44px;
    }

    .pf-row {
        grid-template-columns: 20px minmax(0, 1fr);
    }

    .pf-main {
        display: flex;
        flex-wrap: wrap;
        gap: 14px;
        align-items: baseline;
        min-width: 0;
    }

    .pf-body {
        flex: 1 1 166px;
    }

    .pf-controls {
        flex: 0 0 auto;
    }

    .pf-btn {
        min-height: 44px;
    }

    /* An editing row is glyph / editor / controls in a two-column
     * grid: Save/Cancel drop under the input, not under the glyph. */
    .pf-row-editing .pf-controls {
        grid-column: 2;
    }
}
