/* slip.css — owned by new-ux lane 09; see docs/APP.md "The split stylesheets". */

/* The decision card and the slip body (spec 09 B6; class prefix ds-).
 * Tokens only: colours via var(--c-*), sizes via var(--fs-*), shadows
 * via var(--sh-*).  The surface chrome (position, z-order, the bottom
 * sheet) is lane 06's surfaces.css; this sheet styles bodies alone. */

/* ---- the card ---------------------------------------------------- */

/* dc.html :99 (the Home card): 2px accent top, radius 8, the quiet
 * 0 1px 3px shadow, and the comfortable density's box — `cardPad`
 * 18px 20px with `cardGap` 10px (:963-964, :898 `density =
 * 'comfortable'`).  The detail panel's own 12px gap (:346) belongs to
 * that panel, so it rides `.td-pending .ds-card` in detail.css rather
 * than this base rule; both bodies are pinned in
 * tests/test_app_publish_gate_ui.py. */
.ds-card {
    background: var(--c-sand-card);
    border: 1px solid var(--c-sand-rule);
    border-top: 2px solid var(--c-accent);
    border-radius: var(--radius);
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    box-shadow: var(--sh-slip);
}

/* dc.html :100 — one 12px row in --c-ink-muted with .02em tracking:
 * the source (marks + provider join) at the left, the when at the
 * right.  The mockup's head holds exactly two children, so it splits
 * them with `justify-content: space-between`; ours holds up to four
 * (marks, source, when, deadline), where space-between would spread a
 * head that has no when at all — the synthesised fallback card, whose
 * `paused_at` and `decided_at` are both null (`_approvalFallbackDecision`,
 * app_ctrl_detail.js :1430-1469) — so the split is the auto margin below. */
.ds-card-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    letter-spacing: 0.02em;
    color: var(--c-ink-muted);
}

.ds-marks {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* dc.html :103 — the when rides the right edge in the head's own
 * colour.  It keeps --c-ink-muted rather than the decoration tier
 * --c-ink-faint, which is 2.38:1 on the sand card at 12px (CONTRACTS
 * §9 "Contrast sweep"); the fidelity audit (2026-09-11) row 22 drops
 * that override.  Exactly one auto margin must survive, so a deadline
 * that follows a when joins it as a pair instead of splitting the gap. */
.ds-when,
.ds-deadline {
    margin-left: auto;
}

.ds-when + .ds-deadline {
    margin-left: 0;
}

/* dc.html :104 — the card title is the text face (adobe-caslon-pro),
 * 20px, line-height 1.25. */
.ds-title {
    margin: 0;
    font-family: var(--font-text);
    font-size: var(--fs-title);
    font-weight: 400;
    line-height: 1.25;
    color: var(--c-ink);
    text-wrap: pretty;
}

/* dc.html :105 — the card's question is the UI face at 14.5px/1.5 in
 * soft ink.  (No sheet outside this one styles `.ds-question`; the
 * comment that sent the Home override to home.css named a rule that was
 * never written, so every card asked in 18px Caslon — fidelity audit
 * (2026-09-11) row 24.) */
.ds-question {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-14-5);
    line-height: 1.5;
    color: var(--c-ink-soft);
    text-wrap: pretty;
}

/* dc.html :348 — the one exception: task detail's "Needs your decision"
 * panel asks in the text face at 18px/1.4 in full ink (fidelity audit
 * row 16, whose fix names this `.td-pending` scope). */
.td-pending .ds-question {
    font-family: var(--font-text);
    font-size: var(--fs-18);
    line-height: 1.4;
    color: var(--c-ink);
}

/* ---- options and the free-text channel --------------------------- */

.ds-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/* dc.html :351-352, :742-743 — 13.5px/500 controls, 8px 13px, radius 6:
 * the primary is filled accent, the rest transparent on the strong rule
 * with a gold hover. */
.ds-option,
.ds-other-submit,
.ds-keep,
.ds-change {
    font-family: var(--font-ui);
    font-size: var(--fs-13-5);
    font-weight: 500;
    border: 1px solid var(--c-rule-strong);
    border-radius: var(--r-6);
    background: transparent;
    color: var(--c-ink);
    padding: 8px 13px;
    cursor: pointer;
}

/* dc.html :110 (the Home decision card) and :743 (the slip) write the
   outline option's hover as TWO declarations — a `border-color` AND a
   `background` — so the hover warms the GROUND as well as the border.
   The border takes `--c-gold-hover`, the rung the slip's free-text field
   already focuses to; the ground takes `--c-paper-warm`, the parchment
   the mockup names there (the hexes live in style.css's palette
   registry, never here).  Those two mockup lines are its only
   `style-hover` attributes carrying both properties, and one rule serves
   both of them, because `ds-option` is on every option button on either
   host (app_ctrl_decisions.js :386).  Border-only left a hovered option
   computing a transparent background in Chromium where the mockup warms
   it (fidelity audit 2026-09-11, review rounds 6 and 7 — R6-V1-3,
   V-R7-3); pinned by test_the_options_hover_warms_the_mockups_ground.
   The mockup draws this control a THIRD time, in the task-detail panel
   (:352), and warms only its border there; one rule serves all three
   hosts, so the app follows the two sites that warm.  The pin derives
   that split from dc.html rather than restating it.
   The filled option keeps its accent ground because
   `.ds-option-primary:hover` below is the LATER rule at the same
   specificity.
   Review round 8, V-R8-1 and V-R8-2: this hover is the OPTION buttons'
   and nobody else's.  Round 7 wrote it as a four-selector group, so the
   parchment ground leaked onto three controls the mockup hovers
   differently -- the slip's submit and the made decision's pair, each
   given its own rule below. */
.ds-option:hover {
    border-color: var(--c-gold-hover);
    background: var(--c-paper-warm);
}

.ds-option-primary {
    background: var(--c-accent);
    border-color: var(--c-accent);
    color: var(--c-sand-card);
}

.ds-option-primary:hover {
    background: var(--c-accent-hover);
    border-color: var(--c-accent-hover);
}

/* dc.html :747 -- the slip's "Do this" submit hovers to the ACCENT on
   its border and its label alike (`border-color` and `color`, both the
   accent's own hex; it lives in style.css's palette registry, never
   here) and takes no ground: the submit is the affirmative end of the
   free-text channel, not one more option to browse.
   `:not(.ds-option-primary)` holds its change-mode twin out -- "Re-run
   with this change" carries both classes (app_ctrl_decisions.js :432)
   and is a FILLED accent button, whose label this rule would repaint
   accent-on-accent, being the more specific rule and
   `.ds-option-primary:hover` declaring no colour at all.  Measured in
   Chromium with the `:not()` dropped, that button's hovered label comes
   out at 1.18:1 against its own hovered ground, i.e. gone.  Measured
   with the rule as written, the submit hovers its border and label to
   the accent over a transparent ground, the option pair still warms
   border and ground, and the filled option keeps its accent ground.
   Review round 8, V-R8-1. */
.ds-other-submit:not(.ds-option-primary):hover {
    border-color: var(--c-accent);
    color: var(--c-accent);
}

/* dc.html :416 (Change) and :417 (Keep as preference), and their twins
   in the Covered list at :442-443: the made decision's controls hover
   their TEXT to the accent and change nothing else.  The mockup draws
   them as bare 12.5px links with no frame; the app gives them the
   control group's button face above, so the border stays at rest and
   only the label answers the pointer -- the hover the mockup draws, with
   nothing invented for a frame it never drew.  Review round 8, V-R8-2. */
.ds-keep:hover,
.ds-change:hover {
    color: var(--c-accent);
}

.ds-option:disabled,
.ds-other-submit:disabled,
.ds-keep:disabled,
.ds-change:disabled {
    opacity: 0.55;
    cursor: default;
}

.ds-other {
    display: flex;
    flex: 1 1 100%;
    gap: 8px;
    margin: 0;
}

/* dc.html :746 — 14px, transparent ground, radius 6, gold focus rule. */
.ds-other-input {
    /* min-width: 0 lets either input shrink to the line it is on: the
       phone row reserves the launcher's column out of its content box,
       and an input's automatic minimum is its ~20ch size suggestion --
       235px at 320px, 53px past the 182px left inside the reserved
       column, i.e. under the disc. */
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-ui);
    color: var(--c-ink);
    background: transparent;
    border: 1px solid var(--c-rule-strong);
    border-radius: var(--r-6);
    padding: 8px 10px;
}

/* The mockup focuses this field with `outline:0` and the burnished hover
   gold on the border (dc.html :746) — --c-gold-hover, the minted tint,
   not the decorative --c-gold.  That border change alone is a 2.0-2.3:1
   indicator against the rest border, so the ring `outline:0` takes away
   comes back as the app's one --focus-ring, the way every other
   well-less field carries it (.hb-composer:focus-within, home.css
   :89-92).  Review round 4, R4-C1. */
.ds-other-input:focus {
    outline: 0;
    border-color: var(--c-gold-hover);
    box-shadow: var(--focus-ring);
}

/* width: 0 collapses the "Or tell me" input's size suggestion, which is
   what the form's min-content is built from: at the intrinsic ~20ch
   that min-content (input + gap + "Do this", one nowrap line) was
   301px, wider than a 320px phone's card, and the reserved launcher
   column (the 720px block) tipped a 400px phone over the same edge.
   min-width alone cannot do it -- the suggestion, not the minimum,
   feeds a nowrap container's min-content.  flex-grow still fills the
   row.  Scoped to .ds-other because the other call site -- the
   change-mode row's "What should it do instead?" input (a 500
   character instruction, app_ctrl_decisions.js) -- is a direct child of
   a wrapping .ds-actions: it needs its intrinsic basis to stay wider
   than the space left beside its label and so wrap onto its own line at
   the row's content width (262px at a 400px phone).  Collapsing its
   basis squeezed it onto the label's line at 105px, 25px at 320px. */
.ds-other .ds-other-input {
    width: 0;
}

.ds-other-input[aria-invalid="true"] {
    border-color: var(--c-status-failed);
}

.ds-other-label {
    display: block;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-ink-muted);
}

.ds-change-note {
    margin: 0;
    flex: 1 1 100%;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-gold);
}

/* dc.html :349 (and :106 on Home) — the Details / Talk it through pair
 * sits ABOVE the options: 13.5px/500 muted text on the strong hairline,
 * gap 14, hover accent; the bubble glyph rides inside the button. */
.ds-foot {
    display: flex;
    gap: 14px;
    align-items: center;
}

/* These two are NOT members of the control-group rule above: the pair is a
 * hairline text link, and every property that rule set for them — border,
 * border-radius, background, colour, padding — it then overrode here, so
 * the arm was dead (review round 6, R6-C3).  The rule is self-contained
 * instead: the UA button reset (`border`, `border-radius`, `background`,
 * `font-family`, `cursor`, which no base `button` rule supplies) and the
 * mockup's own treatment, in one place. */
.ds-details,
.ds-discuss {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-ui);
    border: 0;
    border-bottom: 1px solid var(--c-rule-strong);
    border-radius: 0;
    background: none;
    padding: 0 2px;
    color: var(--c-ink-muted);
    font-size: var(--fs-13-5);
    font-weight: 500;
    cursor: pointer;
}

.ds-details:hover,
.ds-discuss:hover {
    color: var(--c-accent);
    border-color: var(--c-accent);
}

/* ---- the slip body ----------------------------------------------- */

.ds-slip-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-ink-muted);
    padding-bottom: 8px;
    border-bottom: 1px solid var(--c-sand-rule);
}

.ds-h {
    margin: 14px 0 6px;
    font-family: var(--font-ui);
    font-size: var(--fs-micro);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--c-ink-muted);
}

.ds-scroll {
    overflow-x: auto;
}

/* dc.html :728-731 — an unruled table: 11px tracked uppercase faint
 * headers, numeric columns right-aligned in tabular figures, the first
 * column 15px text face, the values 13.5px soft ink, the Gap accent. */
.ds-evidence {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-ui);
    font-size: var(--fs-13-5);
    color: var(--c-ink-soft);
}

.ds-evidence th {
    text-align: left;
    font-size: var(--fs-micro);
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--c-ink-faint);
    border-bottom: 0;
    padding: 3px 14px 3px 0;
    vertical-align: baseline;
}

.ds-evidence td {
    color: var(--c-ink-soft);
    border-bottom: 0;
    padding: 3px 14px 3px 0;
    vertical-align: baseline;
}

.ds-evidence th:last-child,
.ds-evidence td:last-child {
    padding-right: 0;
}

.ds-evidence th:not(:first-child),
.ds-evidence td:not(:first-child) {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.ds-evidence td:first-child {
    font-family: var(--font-text);
    font-size: var(--fs-body);
    color: var(--c-ink);
}

.ds-evidence td.ds-gap {
    font-weight: 500;
    color: var(--c-accent);
}

.ds-reasoning {
    margin: 0;
    font-family: var(--font-text);
    font-size: var(--fs-15-5);
    line-height: 1.5;
    color: var(--c-ink-soft);
}

/* dc.html :738 — the slip's discuss control is an outlined pill: 13px
 * soft ink, 6px 11px 6px 9px, gold hover rule.  (The card foot's
 * `.ds-discuss` above is the hairline text link; this override is
 * scoped to lane 06's slip surface and to a gate card's inlined body.) */
.fs-slip .ds-discuss,
[data-decision-expanded] .ds-discuss {
    align-self: flex-start;
    margin-top: 4px;
    border: 1px solid var(--c-sand-rule);
    border-radius: var(--radius-pill);
    padding: 6px 11px 6px 9px;
    font-size: var(--fs-13);
    font-weight: 400;
    color: var(--c-ink-soft);
    gap: 6px;
}

/* dc.html :738 hovers Discuss's border to the mockup's hover rung,
   `--c-gold-hover`, and its text to the accent. */
.fs-slip .ds-discuss:hover,
[data-decision-expanded] .ds-discuss:hover {
    border-color: var(--c-gold-hover);
    color: var(--c-accent);
}

/* dc.html :740 — the action block opens on a 14px-padded hairline. */
.fs-slip .ds-actions,
[data-decision-expanded] .ds-actions {
    padding-top: 14px;
    border-top: 1px solid var(--c-sand-rule);
}

/* dc.html :749 — 13px muted, hover accent. */
.ds-open-task:hover {
    color: var(--c-accent);
}

.ds-basis {
    margin: 10px 0 0;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-gold);
}

.ds-chosen {
    margin: 0;
    font-family: var(--font-text);
    font-size: var(--fs-base);
    color: var(--c-ink);
}

.ds-made-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}

.ds-kept {
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-status-complete);
}

.ds-note {
    flex: 1 1 100%;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-ink-muted);
}

.ds-note-summary {
    cursor: pointer;
}

.ds-note-label {
    display: block;
    margin: 6px 0 4px;
}

.ds-note-text {
    width: 100%;
    font-family: var(--font-ui);
    font-size: var(--fs-base);
    color: var(--c-ink);
    background: var(--c-sand-card);
    border: 1px solid var(--c-rule-strong);
    border-radius: 4px;
    padding: 8px 10px;
}

.ds-preview,
.ds-budget {
    margin-top: 10px;
}

.ds-budget-loading {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-ink-faint);
}

.ds-open-task {
    display: inline-block;
    margin-top: 10px;
    font-family: var(--font-ui);
    font-size: var(--fs-13);
    color: var(--c-ink-muted);
    text-decoration: none;
    border-bottom: none;
}

/* --c-ink-muted, not faint: this is 12px running text ("No steps planned
 * yet.", "No decisions made yet.") and --c-ink-faint is the decoration
 * tier — 2.38:1 on the sand card, below the AA floor (CONTRACTS §9
 * "Contrast sweep"; the axe color-contrast rule flagged it at 12px). */
.td-empty {
    margin: 8px 0 0;
    font-family: var(--font-ui);
    font-size: var(--fs-meta);
    color: var(--c-ink-muted);
}

/* ---- phone (§7.8; the slip is lane 06's bottom sheet — this sheet
 * only styles the body: the sticky action row and the touch sizes) -- */

@media (max-width: 720px) {
    /* Scoped to the sheet.  An inline card — Home's deck, task
     * detail's pending panel, an expanded gate's change-mode row —
     * is page flow, not a scrolling body: pinning its action row to
     * the viewport floor lifts that opaque row over the card's own
     * title and question, the fidelity audit's phone blockers
     * (home.md P3, and the task-detail phone shot).  The desktop
     * separator above serves the expanded mount too; sticky does not,
     * because only the sheet scrolls under its actions. */
    .fs-slip .ds-actions {
        position: sticky;
        bottom: 0;
        background: var(--c-sand-card);
        border-top: 1px solid var(--c-sand-rule);
        padding: 10px 0;
        /* The Support launcher's column.  The product owner decided
           (2026-09-12), answering the fidelity audit (2026-09-11) D2,
           that the launcher stays on every screen (R29) and is lifted
           above this row rather than removed.  A row is as tall as its
           wrapped controls (the seeded first decision -- three options
           + the "Or tell me" form -- measures 237px at 400x860, 269px
           at 320x860), so no constant lift can clear every line: the
           part of the disc's column that falls inside this row is
           reserved here, every control's right edge stops --s-3 short
           of the disc, and style.css's lift clears the last control
           line (44px + this 10px bottom padding = 54px).
           Only 37px of the 56px disc falls inside the row: the disc's
           right offset is the same var(--s-4) as the page's side
           inset, so those two cancel and the row's border box still
           ends 19px further in (the card's 18px padding + its 1px
           border, above) -- measured 37px at 320 and at 400 alike, so
           re-measure if the disc's offset, the card's padding or the
           page's inset move.  Reserving the whole 56px left a 19px
           dead gutter inside the card at every scroll position and
           wrapped a second option onto a second line (44/60/60/44
           control heights at 400x860, against 44/44/60/44 here).
           The reservation is unconditional because a stuck row is not
           the only one the disc covers: scanning 400x860 in 40px steps,
           four of the five scroll positions where the disc is over this
           row have it in ordinary flow, not stuck. */
        padding-right: calc(37px + var(--s-3));
    }

    .ds-option,
    .ds-other-submit,
    .ds-other-input,
    .ds-keep,
    .ds-change,
    .ds-discuss {
        min-height: 44px;
    }

    .ds-evidence {
        min-width: 480px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ds-card,
    .ds-option,
    .ds-option-primary:hover {
        transition: none;
    }
}
