/* static/css/reading-tree.css — the v1 riff-tree reading styles.
 *
 * Third of the seven stylesheets split out of the former single
 * ``gallae.css`` (tasks/FILE_SPLIT_TASKS.md Phase 1). It styles the ARIA
 * ``role="tree"`` riff structure, the riff-vs-comment distinction, the
 * inline compose form, and the keyboard-help modal. (The v2 card navigator
 * that superseded the v1 tree lives separately in ``reading-v2.css``.) MUST
 * load after ``base.css`` for the shared type + container primitives.
 */

/* ---------------------------------------------------------------------
 * Riff tree (Task 5.4)
 * ------------------------------------------------------------------ */

/* The tree is a plain <ul> with ARIA roles. We strip list bullets and
 * default padding so the indentation is fully under our control —
 * children groups carry the visible left rule that makes parentage
 * legible at a glance. */
.contribution-tree,
.contribution-children {
    list-style: none;
    padding: 0;
    margin: 0;
}

.contribution {
    padding: 0.5rem 0;
}

/* Task U.5 — Body-side indentation.
 *
 * Pre-U.5 the indentation lived on ``.contribution-children``:
 * ``margin-left: 0.5rem; padding-left: 1rem; border-left: 2px
 * solid`` per nested level. That accumulated visually (deep riffs
 * shifted right by N * 1.5rem) AND shrank the meta-panel column at
 * each level because the ``.contribution`` per-row grid was nested
 * inside the shrinking container.
 *
 * Post-U.5 the depth-based step-right comes from the nested
 * ``<ul class="contribution-children">`` carrying ``padding-left:
 * 1rem`` (see the Task 5.4 block below) — each nest level shifts
 * the child ``<li>``'s leading edge (and the body's left border on
 * it) right by 1rem.
 *
 * The body's own ``padding-inline-start`` is intentionally a
 * **constant** 0.75rem at every depth so the gap between the left
 * accent line and the leading edge of the text reads the same at a
 * top-level riff as at a depth-5 nested one.
 *
 * The border on the body's leading edge keeps a single 2px
 * parentage line at every depth so the tree structure stays
 * legible without the per-level line accumulation. */
.contribution-body {
    padding-inline-start: 0.75rem;
    border-inline-start: 2px solid var(--border-tree);
}

/* Active-riff highlight (thread-view UI refresh).
 *
 * The pre-refresh focus ring was a 2px outline on
 * ``[role="treeitem"]:focus-visible``. It was reachable for
 * screen-reader users via the roving tabindex pattern but did
 * not read as a deliberate "this is the row I'm on" cue for a
 * sighted keyboard-first user — the dotted browser ring blends
 * into the card background at most zoom levels.
 *
 * Post-refresh: a left-edge accent + tinted background that
 * matches the mockup's coloured-bar-on-active-row treatment.
 * The selector covers two cases:
 *
 *   1. ``[role="treeitem"]:focus`` — fires whenever the
 *      treeitem has DOM focus. ``keynav.js`` calls ``.focus()``
 *      on every arrow / hjkl movement, so this is the load-
 *      bearing rule on a normal keyboard navigation.
 *   2. ``[role="treeitem"][tabindex="0"]`` (no focus pseudo) —
 *      Safari sometimes drops ``:focus`` after a programmatic
 *      ``.focus({preventScroll:true})`` when the element
 *      scrolls. ``keynav.js`` keeps roving tabindex in sync so
 *      the active row always has ``tabindex="0"`` — we use
 *      that as the always-true marker. The browser draws the
 *      accent for the active row even when ``:focus`` itself
 *      is briefly lost.
 *
 * We attach to ``[role="treeitem"]`` rather than to a class so
 * a future template change that swaps the class can't
 * accidentally remove the highlight — the role is the load-
 * bearing contract.
 *
 * ``outline: none`` on the highlighted state suppresses the
 * default browser focus ring so the page doesn't get a doubled
 * box (the left-edge accent + the dotted outline). We keep a
 * fallback ``:focus-visible`` selector that re-adds a thin
 * outline for users who tab in via the tree's outer
 * ``tabindex`` entry — there's no left-edge accent until they
 * walk onto a real treeitem, and a totally unstyled focus on
 * the outer ``<ul>`` would feel broken. */
[role="treeitem"]:focus,
[role="treeitem"][tabindex="0"] {
    outline: none;
    box-shadow: inset 3px 0 0 var(--accent);
    border-radius: 2px;
}

[role="tree"]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

/* ---------------------------------------------------------------------
 * Riff vs comment styling (Task 5.7)
 * ------------------------------------------------------------------ */

/* The contribution-kind class is stamped on the treeitem ``<li>`` by
 * _contribution.html (``contribution-{{ contribution.kind }}``).
 * Comments get a lighter background and slightly tighter typography
 * so the social affordance reads at a glance — riffs are extensions,
 * comments are kudos. The visual differentiation is intentionally
 * mild: both are first-class contributions, just different in
 * register. */
.contribution-comment .contribution-content {
    background: var(--surface-comment);
    padding: 0.5rem 0.75rem;
    border-radius: 4px;
    font-size: 0.95em;
    color: var(--text-comment);
}

.contribution-comment .contribution-kind-badge {
    color: var(--text-muted);
}

/* Riffs don't get a background — the default surrounding chrome is
 * enough. We declare the riff styles explicitly so a future "make
 * comments lighter still" tweak can adjust the contrast without
 * having to invent a riff-specific class first. */
.contribution-riff .contribution-content {
    /* Inherit page background; no special treatment beyond the
     * tree's structural indent. */
    background: transparent;
}

/* Visually-hidden pattern for fieldset legends and other content
 * that should be available to screen readers but not visible.
 * Ships here because the compose form's kind fieldset uses it. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------------
 * Compose form (Tasks 5.5 + 5.7)
 * ------------------------------------------------------------------ */

/* The compose-area starts empty; it grows when HTMX swaps the form
 * (or the post-submit "pending" partial) into it. We give it a top
 * margin only when it has content so an empty area doesn't push
 * surrounding content around. */
.compose-area:not(:empty) {
    margin-top: 1rem;
}

/* Refactor (riff-modal-out-of-body, step 1): the compose-area is now a
 * direct child of the page/card grids (``.post-detail-layout`` for the
 * post, ``.contribution`` for a riff) instead of living inside the body
 * ``<article>``. That makes it a grid ITEM, so two things need stating:
 *
 * 1. Empty → out of flow. By default the area is empty (no composer
 *    open); an empty grid item would still claim a cell and add a
 *    row-gap, shifting the layout. ``:empty { display: none }`` removes
 *    it until HTMX swaps a form in, keeping the no-composer page
 *    pixel-identical to before the move. (HTMX still targets it by id
 *    and fills it; once non-empty it reappears.)
 * 2. Full-width placement. When it does open it should span both grid
 *    columns (body + meta), not get squeezed into the body track. */
.post-detail-layout > .compose-area:empty,
.contribution > .compose-area:empty {
    display: none;
}
.post-detail-layout > .compose-area,
.contribution > .compose-area {
    grid-column: 1 / -1;
}

.compose-form {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1rem;
    border: 1px solid var(--border-subtle);
    border-radius: 4px;
    background: var(--surface-raised);
}

.compose-form textarea {
    width: 100%;
    font-family: inherit;
    font-size: 1rem;
    padding: 0.5rem;
    border: 1px solid var(--border);
    border-radius: 3px;
}

.compose-actions {
    display: flex;
    gap: 0.5rem;
}

/* Kind toggle (Task 5.7) — two side-by-side radio "cards". Bigger
 * tap targets than a default radio + label, with a visual selected
 * state so the user can see their choice without staring at the
 * radio dot. We use `:has()` to style the wrapping label based on
 * the contained input's checked state; `:has` shipped in all major
 * browsers in 2023 and the project's deployment story doesn't
 * include legacy browser support. */
.compose-kind {
    display: flex;
    gap: 0.5rem;
    border: 0;
    padding: 0;
    margin: 0;
}

.compose-kind-option {
    flex: 1;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    cursor: pointer;
    background: var(--surface-raised);
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}

.compose-kind-option:has(input:checked) {
    border-color: var(--accent);
    background: var(--accent-tint);
}

.compose-kind-option input {
    /* Keep the input itself clickable for keyboard / a11y but
     * suppress the native circle — the parent label's border and
     * background carry the selected state. */
    margin: 0 0.4em 0 0;
}

.compose-kind-label {
    font-weight: 600;
}

.compose-kind-blurb {
    color: var(--text-muted-2);
}

/* Validation errors. ``role="alert"`` is on the markup so screen
 * readers announce them; the styling here just makes them visually
 * distinct from the form body. */
.form-errors {
    list-style: none;
    padding: 0.5rem 0.75rem;
    margin: 0;
    background: var(--error-bg);
    border-left: 3px solid var(--danger);
    color: var(--error-text);
}

/* Post-submit "pending" status partial. Same visual weight as the
 * compose form so the swap doesn't feel jarring. */
.compose-pending {
    padding: 1rem;
    border: 1px solid var(--border-pending);
    border-radius: 4px;
    background: var(--surface-pending);
}

/* Profile-colour picker (templates/accounts/_color_picker.html). Scoped to
 * the isolated partial so the whole control — native <input type="color"> for
 * now — can be restyled or swapped from one place. The signup ("optional")
 * variant adds the checkbox toggle; the edit variant is just the swatch. */
.color-picker {
    margin: 0.75rem 0;
}
.color-picker-toggle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
}
.color-picker-control {
    margin-top: 0.5rem;
}
/* Give the native colour well a usable, consistent size — browsers default it
 * to a tiny box. The well's chrome still varies per-OS (that's the trade-off
 * of the native control), but the footprint at least stays predictable.
 *
 * The swatch rests on a split surround instead of the input's default uniform
 * grey: the native control's padding is painted with a hard-stop gradient —
 * dark-theme page background on the left half, light-theme on the right — so
 * the chosen colour previews against both themes at once. The two halves are
 * literals (not `var(--bg)`, which is a single themed value) and intentionally
 * mirror the dark/light `--bg` definitions at :root above; keep them in sync if
 * those page backgrounds change. The swatch itself is centred on top via the
 * per-engine pseudo-elements below. */
.color-picker-control input[type="color"],
.color-picker input[type="color"] {
    width: 3.5rem;
    height: 2rem;
    padding: 6px;
    border: 1px solid var(--text-faintest);
    border-radius: 4px;
    background: linear-gradient(to right, #141110 0 50%, #e2d6bd 50% 100%);
    cursor: pointer;
    vertical-align: middle;
}
/* Drop the engines' default wrapper inset so the gradient surround is an even
 * band around the swatch, and give the swatch a faint frame so it reads as a
 * distinct chip sitting on the split background. */
.color-picker input[type="color"]::-webkit-color-swatch-wrapper {
    padding: 0;
}
.color-picker input[type="color"]::-webkit-color-swatch {
    border: 1px solid rgba(0, 0, 0, 0.25);
    border-radius: 2px;
}
.color-picker input[type="color"]::-moz-color-swatch {
    border: 1px solid rgba(0, 0, 0, 0.25);
    border-radius: 2px;
}

.compose-pending-headline {
    margin: 0 0 0.5em;
    font-weight: 600;
}

/* ---------------------------------------------------------------------
 * Keyboard-help modal (Task 5.4)
 * ------------------------------------------------------------------ */

.keynav-help-modal {
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 1.5rem;
    max-width: 28rem;
    background: var(--surface-raised);
    color: inherit;
}

.keynav-help-modal::backdrop {
    /* Translucent backdrop dims the page behind the modal so the
     * dialog reads as the foreground task. */
    background: rgba(0, 0, 0, 0.4);
}

.keynav-help-title {
    margin-top: 0;
}

.keynav-help-list {
    list-style: none;
    padding: 0;
    margin: 0 0 1rem;
}

.keynav-help-list li {
    margin: 0.4em 0;
}

.keynav-help-actions {
    margin: 0;
    text-align: right;
}

/* The reading-page modal's "Down goes to the child" note
 * (works/_keynav_help.html, RV.8.1). Set apart from the key list as a
 * quieter, smaller aside so it reads as an explanation of the one
 * surprising binding rather than another shortcut row. */
.keynav-help-note {
    margin: 0 0 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border-faint);
    font-size: 0.9em;
    color: var(--text-muted);
}

/* ``<kbd>`` is used in the help modal to render literal key labels.
 * The styling here is general so any future use of the element
 * elsewhere in the site picks it up. */
kbd {
    display: inline-block;
    padding: 0.1em 0.4em;
    background: var(--surface-code);
    border: 1px solid var(--border);
    border-radius: 3px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.9em;
}

