@layer modules {

    /* Routes container — width constraints */
    .routes {
        --routes-item-padding-inline: 0;

        margin: 0 auto;
        max-inline-size: min(80ch, 100%);
    }

    /* Routes — group picker list */
    .routes__asset-list {
        list-style: none;
        margin: 0;
        padding: 0;
        padding-inline-start: var(--routes-item-padding-inline);
    }

    /* Execution report — grid layout for response rows */
    .execution-report__row {
        display: grid;
        grid-template-columns: auto 1fr auto;
        align-items: center;
        gap: 0 1ch;
        padding-inline: var(--space-half);
        padding-block: 0.4em;

        &>.separator--horizontal {
            width: 100%;
        }
    }

    .execution-report__response--alert {
        background-color: oklch(var(--lch-red-lightest) / 0.3);
    }

    /* Execution report — notes and files */
    .execution-report__note {
        grid-column: 1 / -1;
        width: fit-content;
        margin: 0.4em 0 0;
        padding: 0.3em 0.75em;
        display: flex;
        align-items: center;
        gap: 0.5ch;
        background-color: var(--color-highlight);
        border-radius: 0.3em;
    }

    .execution-report__files {
        grid-column: 1 / -1;
        display: flex;
        flex-wrap: wrap;
        gap: 0.5em;
        padding-block-start: 0.25em;
    }

    .execution-report__file-img {
        display: block;
        max-width: 8rem;
        max-height: 6rem;
        border-radius: var(--radius, 4px);
        object-fit: cover;
        cursor: zoom-in;
    }

    /* Execution report — multi-check subchecks */
    .execution-report__subchecks {
        grid-column: 1 / -1;
        display: flex;
        flex-direction: column;
    }

    .execution-report__subcheck {
        display: flex;
        align-items: center;
        gap: 0.5ch;
        padding-inline-start: 0.5em;
    }

    .execution-report__subcheck--fail {
        color: oklch(var(--lch-red-dark));
        font-weight: 500;
    }

    /* Route editor — turbo-frame layout (measurement-point select row) */
    .route-edit__item-row > turbo-frame {
        display: contents;
    }

    /* Route editor — group card
     *
     * Each checklist group is a card: breadcrumb header on top, stack of
     * item cards beneath. Borders and shadows kept subtle to stay in the
     * industrial/utilitarian aesthetic. */
    .route-edit__group {
        --group-border: var(--color-ink-lighter);

        display: flex;
        flex-direction: column;
        gap: var(--space-half, 0.6em);
        padding: var(--space-half, 0.6em);
        background: var(--color-canvas);
        border: 1px solid var(--group-border);
        border-radius: 0.5em;
        box-shadow: 0 1px 2px oklch(0% 0 0 / 0.03);
    }

    .route-edit__group-head {
        display: flex;
        align-items: center;
        gap: 0.5ch;
        min-inline-size: 0;
    }

    .route-edit__group-title {
        flex: 1 1 auto;
        min-inline-size: 0;
        margin: 0;
        font-size: 1em;
        line-height: 1.2;
        overflow: hidden;

        /* Last crumb (the asset/zone name) in bold — this is the current segment */
        & .breadcrumb__item--current {
            font-weight: 700;
        }

        /* Let the breadcrumb wrap on very narrow containers rather than
           clipping the asset name. */
        flex-wrap: wrap;
    }

    .route-edit__group-actions {
        display: flex;
        gap: 0.25ch;
        flex-shrink: 0;
    }

    /* Stack of item cards inside a group. */
    .route-edit__item-list {
        display: flex;
        flex-direction: column;
        gap: 0.4em;
    }

    /* Item card — drag handle on the left edge + row of controls + optional photo gallery. */
    .route-edit__item {
        display: grid;
        grid-template-columns: auto 1fr;
        gap: 0 0.25em;
        padding: 0.5em 0.6em;
        padding-inline-start: 0;
        background: color-mix(in srgb, var(--color-ink-lightest) 40%, var(--color-canvas));
        border: 1px solid var(--color-ink-lighter);
        border-radius: 0.35em;
    }

    /* Drag handle sits in its own narrow column, spanning both rows. */
    .route-edit__item > .drag-handle {
        grid-row: 1 / -1;
        align-self: stretch;
        display: flex;
        align-items: center;
        padding: 0.25em 0.3em;
        border-inline-end: 1px solid var(--color-ink-lighter);
        margin-inline-end: 0.25em;
    }

    .route-edit__item-row {
        display: flex;
        align-items: center;
        gap: 0.5ch;
        min-inline-size: 0;
    }

    .route-edit__item-row > input[name="item_label"],
    .route-edit__item-row > turbo-frame > select[name="measurement_point"] {
        flex: 1 1 auto;
        min-inline-size: 0;
    }

    /* Photo gallery under the item row. Inherits .attachments base styling
       from measurement_form.css; this just tightens the thumbnail size and
       hides the gallery when empty via the [hidden] attribute.
       Grid column 2 so it sits next to the drag handle, not under it. */
    .route-edit__photos {
        --attachment-height: 5.5rem;
        grid-column: 2;
        margin: 0;
    }

    /* Empty-state upload placeholder inside the photos strip. */
    .attachment--upload {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 0.25rem;
        block-size: var(--attachment-height, 5.5rem);
        aspect-ratio: 1;
        border: 2px dashed var(--color-ink-lighter);
        border-radius: var(--radius-s, 6px);
        cursor: pointer;

        &:hover {
            border-color: var(--color-link);
            color: var(--color-link);
        }
    }

    /* Upload button (camera) — count badge stacks top-right like
       attachment__download. */
    .route-edit__upload-btn {
        position: relative;
    }

    .route-edit__upload-count {
        position: absolute;
        inset-block-start: -0.35em;
        inset-inline-end: -0.35em;
        min-inline-size: 1.4em;
        padding: 0 0.3em;
        background: var(--color-link);
        color: var(--color-canvas);
        border: 2px solid var(--color-canvas);
        border-radius: 999px;
        font-size: 0.65em;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
        line-height: 1.4;
        text-align: center;
    }

    /* Delete badge on photo thumbnails — mirrors .attachment__download
       geometry but in destructive red. Clicking triggers
       route-editor#deletePhoto. */
    .attachment__delete {
        --size: 1.5em;

        align-items: center;
        appearance: none;
        background-color: var(--color-negative);
        block-size: var(--size);
        border: 2px solid var(--color-canvas);
        border-radius: 50%;
        color: var(--color-canvas);
        cursor: pointer;
        display: flex;
        inline-size: var(--size);
        inset-block-end: -0.3em;
        inset-inline-end: -0.3em;
        justify-content: center;
        padding: 0;
        position: absolute;
        z-index: 2;

        .icon {
            font-size: 0.5em;
        }

        @media (any-hover: hover) {
            &:hover {
                background-color: oklch(var(--lch-red-dark));
            }
        }
    }

    /* Route editor — item row reflow on narrow containers.
     *
     * The row packs label + type + optional camera + move + remove.
     * The drag handle is outside the row (in its own grid column), so
     * the row only needs to worry about its own controls. On narrow
     * viewports the row wraps onto two lines:
     *
     * Narrow layout:
     *   row 1: [label — full width]
     *   row 2: [type select — grows] [camera?] [move] [remove]
     */
    [data-route-editor-target="itemList"] {
        container-type: inline-size;
        container-name: route-item-list;
    }

    @container route-item-list (max-width: 55ch) {
        .route-edit__item-row {
            flex-wrap: wrap;
        }

        /* Label input OR measurement-point select (inside display:contents
           turbo-frame) takes the full row width,
           pushing the action cluster onto row 2. */
        .route-edit__item-row > input[name="item_label"],
        .route-edit__item-row > turbo-frame > select[name="measurement_point"] {
            flex: 1 1 100%;
            min-inline-size: 0;
        }

        /* Type select grows to fill the action row. */
        .route-edit__item-row > select[name="item_type"] {
            flex: 1 1 auto;
            min-inline-size: 0;
        }
    }

    /* Route editor — drag-and-drop affordances */
    .drag-handle {
        display: inline-flex;
        cursor: grab;
        padding: 0.25em;
    }

    .drag-handle:active {
        cursor: grabbing;
    }

    .sortable-ghost {
        opacity: 0.3;
    }

    .sortable-chosen {
        box-shadow: 0 2px 8px oklch(0% 0 0 / 0.15);
    }

    [data-route-editor-target="itemList"]:empty {
        min-block-size: 2em;
        border: 1px dashed var(--color-ink-lighter);
        border-radius: 0.5em;
    }

    /* Non-conformity stamp on asset detail card (mirrors .card__closed pattern) */
    .card__nc-stamp {
        --stamp-color: oklch(var(--lch-red-medium) / 0.65);

        align-items: center;
        background-color: color-mix(in srgb, var(--card-bg-color) 90%, transparent);
        border-radius: 0.2em;
        border: 0.5ch solid var(--stamp-color);
        color: var(--color-ink-dark);
        display: flex;
        flex-direction: column;
        font-weight: bold;
        inset: auto 1ch 1ch auto;
        justify-content: center;
        max-inline-size: 25ch;
        min-inline-size: 16ch;
        padding: 1ch;
        position: absolute;
        rotate: -3deg;
        text-decoration: none;
        transform-origin: top right;
    }

    .card__nc-stamp-title {
        color: var(--stamp-color);
        font-size: 1.3em;
        font-weight: 900;
        text-align: center;
        text-transform: uppercase;
    }

    .card__nc-stamp-date {
        font-family: var(--font-data);
        letter-spacing: 0.02em;
        text-transform: uppercase;
    }

    .card__nc-stamp-by {
        border-block-end: 1px dashed currentcolor;
    }

    /* Non-conformity panel in comments section (mirrors comment-by-system look) */
    .nc-panel {
        display: flex;
        margin-inline: auto;
        max-inline-size: var(--comment-max, 70ch);

        &::before {
            content: "";
            display: flex;
            inline-size: calc(var(--comment-padding-inline, 2ch) * 0.9);
            flex-shrink: 0;
        }
    }

    .nc-panel__content {
        --stripe-color: color-mix(in srgb, var(--color-negative) 10%, var(--color-canvas));

        background-color: var(--color-ink-lightest);
        background-image: repeating-linear-gradient(45deg in srgb,
                var(--color-canvas) 0 1px,
                var(--stripe-color) 1px 10px);
        border-radius: 0.2em;
        flex-grow: 1;
        padding: var(--block-space-half, 0.75em) var(--comment-padding-inline, 2ch);
        text-align: start;
    }

    /* Non-conformity row in asset panel */
    .asset-nc-row {
        padding-block: 0.5em;

        &:not(:last-child) {
            border-block-end: 1px solid var(--color-ink-lighter);
        }
    }

    /* Resolved state in execution report */
    .execution-report__response--resolved {
        opacity: 0.5;

        & .badge {
            background-color: var(--color-positive);
        }
    }

    /* Resolution form in resolve turbo-frame */
    .resolve-form {
        display: flex;
        flex-direction: column;
        gap: var(--space-half);
        padding: var(--space-half);
        background: var(--color-highlight);
        border-radius: 0.5em;
        margin-block-start: 0.25em;
    }

    .resolve-form__buttons {
        display: flex;
        gap: 0.5ch;
        justify-content: flex-end;
    }

    /* Resolution timeline entry - green accent */
    .comment-by-system--resolution {
        --card-color: var(--color-positive);
    }

    /* Execution UI
    /* ------------------------------------------------------------------------ */

    /* Execution cards — state grammar via data-state:
       pending: grey,  anchored left (untouched)
       pass:    green, anchored left
       fail:    red,   anchored right  (+ reveals severity)
       Measurement cards defer state to the saved measurement's status. */

    .execution__card-stack {
        display: flex;
        flex-direction: column;
        gap: var(--space, 1em);
        padding-block: var(--space-half);
    }

    .execution__card {
        --card-accent: var(--color-ink-lighter);
        --card-bg: var(--color-canvas);
        --card-shadow: 0 1px 2px oklch(0% 0 0 / 0.04),
                       0 2px 8px oklch(0% 0 0 / 0.03);

        display: flex;
        flex-direction: column;
        gap: var(--space-half, 0.75em);
        padding: var(--space, 1em);
        background: var(--card-bg);
        border: 1px solid var(--card-accent);
        border-radius: 0.5em;
        box-shadow: var(--card-shadow);
        transition: margin-inline 0.3s ease, border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
    }

    .execution__card[data-state="pending"] {
        --card-bg: color-mix(in srgb, var(--color-ink-lightest) 50%, var(--color-canvas));
    }

    .execution__card[data-state="pass"] {
        --card-accent: var(--color-positive);
        --card-bg: color-mix(in srgb, var(--color-positive) 7%, var(--color-canvas));
    }

    .execution__card[data-state="fail"] {
        --card-accent: var(--color-negative);
        --card-bg: color-mix(in srgb, var(--color-negative) 7%, var(--color-canvas));
    }

    /* Fail cards recolor by severity: minor = yellow, major stays red.
       The :has() selector targets card-level severity only (not the per-check
       severity inside multi_check rows, which live under [data-check-index]). */
    .execution__card[data-state="fail"]:has(> .execution__severity [data-role="severity"][data-severity="minor"]) {
        --card-accent: oklch(var(--lch-yellow-dark));
        --card-bg: color-mix(in srgb, oklch(var(--lch-yellow-medium)) 10%, var(--color-canvas));
    }

    /* Multi-check cards in fail state: if every failed check is minor, use
       yellow; any major check keeps the card red. */
    .execution__card[data-state="fail"]:not(:has([data-check-state="fail"] [data-severity="major"])):has([data-check-state="fail"] [data-severity="minor"]) {
        --card-accent: oklch(var(--lch-yellow-dark));
        --card-bg: color-mix(in srgb, oklch(var(--lch-yellow-medium)) 10%, var(--color-canvas));
    }

    /* Wide screens: cards are fixed 50% width and slide between left/right to
       convey state. On narrow screens the card fills width and state is
       conveyed by color alone. */
    @media (min-width: 100ch) {
        .execution__card {
            inline-size: 50%;
            margin-inline-end: auto;
        }
        .execution__card[data-state="fail"] {
            margin-inline-start: auto;
            margin-inline-end: 0;
        }
    }

    /* Card head — titles on the left, toggle or kind indicator on the right */
    .execution__card-head {
        display: flex;
        align-items: center;
        gap: 1ch;
    }

    .execution__card-titles {
        flex: 1;
        min-inline-size: 0;
        display: flex;
        flex-direction: column;
        gap: 0.1em;
    }

    .execution__card-title {
        font-weight: 600;
        margin: 0;
        font-size: 1em;
        line-height: 1.2;
    }

    .execution__card-breadcrumb {
        margin: 0;
        justify-content: center;
        margin-block-end: 0.4em;
    }

    .execution__card-subtitle {
        color: var(--color-ink-medium);
        font-size: var(--text-x-small, 0.78em);
    }

    .execution__card-kind {
        color: var(--color-ink-medium);
        flex-shrink: 0;
    }

    /* Hey-style pill toggle (Fail | Pass) */
    .execution__toggle {
        --toggle-h: 1.9em;
        --toggle-w: 6ch;

        position: relative;
        display: inline-grid;
        grid-template-columns: 1fr 1fr;
        align-items: stretch;
        inline-size: calc(var(--toggle-w) * 2);
        block-size: var(--toggle-h);
        background: var(--color-ink-lightest);
        border: 1px solid var(--color-ink-lighter);
        border-radius: calc(var(--toggle-h) / 2);
        flex-shrink: 0;
        padding: 2px;
    }

    .execution__toggle--sm {
        --toggle-h: 1.6em;
        --toggle-w: 5ch;
    }

    .execution__toggle-seg {
        appearance: none;
        background: transparent;
        border: none;
        color: var(--color-ink-medium);
        font: inherit;
        font-size: var(--text-x-small, 0.78em);
        font-weight: 600;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        cursor: pointer;
        padding: 0;
        position: relative;
        z-index: 1;
        border-radius: calc(var(--toggle-h) / 2);
        transition: color 0.15s ease;
    }

    .execution__toggle-thumb {
        position: absolute;
        inset: 2px;
        inline-size: calc(50% - 2px);
        border-radius: calc(var(--toggle-h) / 2);
        background: transparent;
        opacity: 0;
        transform: translateX(0);
        transition: transform 0.2s ease, background-color 0.2s ease, opacity 0.2s ease;
        z-index: 0;
    }

    /* Thumb + segment coloring driven by ancestor state.
       Card-level state colors the card-head toggle; check-row state colors the
       inline toggle inside that row. */
    .execution__card[data-state="pass"] .execution__card-head > .execution__toggle > .execution__toggle-thumb,
    [data-check-state="pass"] > .execution__toggle > .execution__toggle-thumb {
        opacity: 1;
        background: var(--color-positive);
        transform: translateX(calc(100% + 2px));
    }

    .execution__card[data-state="fail"] .execution__card-head > .execution__toggle > .execution__toggle-thumb,
    [data-check-state="fail"] > .execution__toggle > .execution__toggle-thumb {
        opacity: 1;
        background: var(--color-negative);
        transform: translateX(0);
    }

    .execution__card[data-state="pass"] .execution__card-head > .execution__toggle .execution__toggle-seg--pass,
    [data-check-state="pass"] > .execution__toggle .execution__toggle-seg--pass {
        color: var(--color-canvas);
    }

    .execution__card[data-state="fail"] .execution__card-head > .execution__toggle .execution__toggle-seg--fail,
    [data-check-state="fail"] > .execution__toggle .execution__toggle-seg--fail {
        color: var(--color-canvas);
    }

    /* Severity pill — independent of pass/fail; thumb colored per level
       (yellow=minor, red=major). Driven by its own data-severity attr. */
    .execution__toggle--severity {
        --toggle-w: 9ch;
    }

    .execution__toggle--severity.execution__toggle--sm {
        --toggle-w: 7ch;
    }

    .execution__toggle--severity[data-severity="minor"] > .execution__toggle-thumb {
        opacity: 1;
        background: oklch(var(--lch-yellow-medium));
        transform: translateX(0);
    }

    .execution__toggle--severity[data-severity="major"] > .execution__toggle-thumb {
        opacity: 1;
        background: var(--color-negative);
        transform: translateX(calc(100% + 2px));
    }

    .execution__toggle--severity[data-severity="minor"] .execution__toggle-seg--minor {
        color: var(--color-canvas);
    }

    .execution__toggle--severity[data-severity="major"] .execution__toggle-seg--major {
        color: var(--color-canvas);
    }

    /* Card body — shared container for variant-specific content */
    .execution__card-body {
        display: flex;
        flex-direction: column;
        gap: 0.5em;
    }

    .execution__card-body--frame {
        padding-block-start: 0.25em;
    }

    .execution__value-field {
        position: relative;
        display: flex;
    }

    .execution__value-input {
        inline-size: 100%;
        font-variant-numeric: tabular-nums;
        font-size: 1.1em;
    }

    .execution__value-field--has-unit .execution__value-input {
        padding-inline-end: 5ch;
    }

    .execution__value-unit {
        position: absolute;
        inset-inline-end: 0.75ch;
        inset-block: 0;
        display: inline-flex;
        align-items: center;
        color: var(--color-ink-medium);
        font-size: 0.9em;
        pointer-events: none;
        font-variant-numeric: tabular-nums;
    }

    .execution__frame-loading {
        padding-block: 0.5em;
    }

    /* Severity — hidden until the card is in fail state.
       Using a base display:none + state-based override (not the [hidden]
       attribute) because the HTML [hidden] attr beats @layer rules. */
    .execution__severity {
        display: none;
        flex-direction: column;
        gap: 0.25em;
    }

    .execution__severity--inline {
        flex-direction: row;
        align-items: center;
        gap: 0.5ch;
    }

    .execution__card[data-state="fail"] > .execution__severity {
        display: flex;
    }

    [data-check-state="fail"] > .execution__severity {
        display: flex;
    }

    /* Multi-check sub-rows */
    .execution__checks {
        display: flex;
        flex-direction: column;
        gap: 0.35em;
        list-style: none;
        margin: 0;
        padding: 0;
    }

    .execution__check-row {
        display: grid;
        grid-template-columns: 1fr auto;
        align-items: center;
        gap: 0.25em 1ch;
        padding: 0.4em 0.5em;
        border-radius: 0.35em;
        border: 1px solid var(--color-ink-lighter);
        background: var(--color-canvas);
        transition: border-color 0.2s ease, background-color 0.2s ease;
    }

    .execution__check-row[data-check-state="pass"] {
        border-color: var(--color-positive);
        background: color-mix(in srgb, var(--color-positive) 6%, var(--color-canvas));
    }

    .execution__check-row[data-check-state="fail"] {
        border-color: var(--color-negative);
        background: color-mix(in srgb, var(--color-negative) 6%, var(--color-canvas));
    }

    .execution__check-label {
        font-size: var(--text-small, 0.9em);
    }

    .execution__check-row > .execution__severity {
        grid-column: 1 / -1;
        margin-block-start: 0.1em;
    }

    /* Card footer — photo upload + rich-text note.
       Uses the same building blocks as the measurement form so every card,
       regardless of item_type, shares the same note/photo affordances. */
    .execution__card-foot {
        display: flex;
        flex-direction: column;
        gap: var(--space-half, 0.75em);
        margin-block-start: auto;
        padding-block-start: var(--space-half, 0.75em);
        border-block-start: 1px dashed var(--card-accent);
    }

    .execution__note {
        margin: 0;
    }

    /* Measurement form when embedded inline inside an execution card —
       tighter gaps, no oversized page margins, subtle auto-save hint. */
    .execution__card .measurement-form,
    .measurement-form--inline {
        gap: var(--space-half, 0.75em);
    }

    .execution__card .measurement-form__upload-btn {
        min-block-size: 3em;
        font-size: var(--text-small, 0.9em);
    }

    /* Saved measurement partial — compact embedded card that mirrors the
       measurement detail view's layout (numbered .card__board, status
       badge, .card__meta readouts, notes, thermogram gallery) while
       sitting inside the route-execution wizard card. The `.card` base
       already supplies the --card-color chrome; these rules just tighten
       spacing so the embedded card doesn't feel cavernous and wire up the
       actions footer.

       The outer <turbo-frame> gets display:contents from base.css, so
       .measurement-saved__card IS the visible container. */
    .measurement-saved__card {
        --card-padding-block: var(--space-half, 0.6em);
        --card-padding-inline: 1ch;
        gap: 0.5em;
        box-shadow: none;
        border: 1px solid color-mix(in srgb, var(--card-color) 28%, transparent);
    }

    .execution__card .measurement-saved__card {
        /* Inside the execution wizard card, drop to a borderless inset so
           the accent comes purely from --card-color on the board tag. */
        border: 0;
        background: transparent;
    }

    .measurement-saved__body {
        display: flex;
        flex-direction: column;
        gap: 0.6em;
    }

    .measurement-saved__body > .card__meta {
        gap: 0.5ch 1.25ch;
    }

    .measurement-saved__attachments {
        --attachment-size: 4.5em;
        gap: 0.4em;
    }

    /* Empty grid is kept in the DOM purely as an append-target for the
       inline uploader; collapse it so it doesn't leave a visual gap
       above the "Add another thermograph" button. */
    .measurement-saved__attachments--empty:empty {
        display: none;
    }

    /* Inline thermograph upload-row on the saved measurement — uses the
       same .measurement-form__upload-btn chrome as the capture form, just
       tightened for the compact saved-card context. */
    .measurement-saved__upload-row .measurement-form__upload-btn {
        min-block-size: 2.8em;
        padding-block: 0.5em;
        padding-inline: 1em;
        font-size: var(--text-small, 0.9em);
    }

    .measurement-saved__upload-row [data-controller*="thermogram-upload"].is-uploading {
        opacity: 0.55;
        pointer-events: none;
    }

    .measurement-saved__actions {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.25ch;
        margin-block-start: 0.25em;
        padding-block-start: 0.4em;
        border-block-start: 1px dashed color-mix(in srgb, var(--card-color) 20%, var(--color-ink-lighter));
    }

    .measurement-saved__detail-link {
        margin-inline-start: auto;
    }

    /* Bare comment wrap (no avatar, compact Trix) — applied to every note
       inside a route execution, on both measurement and non-measurement
       cards, so the Trix editor + toolbar render identically everywhere. */
    .measurement-form__comments-wrap--bare {
        --comment-padding-inline: 0;

        & .comment {
            padding: 0;
            gap: 0;
        }

        & .django-prose-editor-container {
            inline-size: 100%;
        }

        & trix-editor {
            min-block-size: 3.1em;
            padding: 0.4em 0.6em;
            border-radius: 0.35em;
            border: 1px solid var(--color-ink-lighter);
            background: var(--color-canvas);
            font-size: var(--text-small, 1em);
        }

        & trix-toolbar {
            margin-block-end: 0.25em;
        }
    }

    .execution__wizard-nav {
        position: static;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--space-half, 0.75em);
        padding-inline: var(--space-half, 0.75em);
        padding-block: calc(0.45rem + 0.7dvh);
        margin-block-end: var(--space-half, 0.75em);
        margin-inline: var(--space-half, 0.75em);
        background: var(--color-canvas);
        border-radius: 0.5em 0.5em 0 0;
    }

    .execution__wizard-btn {
        --btn-size: 2.75rem;
        transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease,
                    transform 0.2s ease;
    }

    /* Primary state — set on the Next button when the current card has been
       answered (pass_fail / numerical / multi_check / measurement saved).
       Visual cue that tapping Next will commit the response. */
    .execution__wizard-btn--primary {
        --btn-background: var(--color-link);
        --btn-color: var(--color-ink-inverted);
        --btn-border-color: var(--color-canvas);
        --focus-ring-color: var(--color-link);
        transform: scale(1.05);
    }

    .execution__wizard-btn--primary:disabled {
        transform: none;
    }

    .execution__cancel-zone {
        display: flex;
        justify-content: center;
        margin-block-start: var(--space-double, 2em);
        padding-block-end: var(--space-double, 2em);
    }

    .execution__cancel-trigger {
        max-inline-size: 32ch;
    }

    /* Mobile wizard mode: one item per "page". Drop the group panel chrome
       so the current card isn't boxed inside a redundant frame — the group
       heading stays above the card as context, but without background and
       padding. Desktop (min-width: 640px) keeps the grouped panel layout.
     *
     * Sizing model: the group fills the dynamic viewport minus:
     *   - native top inset (reserved by the collapsed header on native, 0 on web)
     *   - native bottom inset (reserved for the floating tab bar on native, 0 on web)
     *   - web-side chrome above the group (header + padding + wizard nav + heading),
     *     estimated at 13rem as a stable fallback. The controller refines this
     *     into an exact pixel value via --execution-wizard-item-min-height,
     *     which honours both insets so the card never slips under the tab bar.
     */
    .execution--wizard .execution__group {
        background: transparent;
        border: 0;
        box-shadow: none;
        padding: 0;
        margin-block-end: 0;
        min-block-size: var(
            --execution-wizard-item-min-height,
            calc(
                100dvh
                - 13rem
                - var(--custom-safe-inset-top, 0px)
                - var(--custom-safe-inset-bottom, 0px)
            )
        );
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    .execution--wizard .execution__card-stack {
        padding-block: 0;
        flex: 1;
        display: flex;
        align-items: stretch;
        min-block-size: 0;
        overflow: hidden;
    }

    /* Stretch the one visible item to fill the stack width on mobile. */
    @media (max-width: 99.99ch) {
        .execution--wizard .execution__card[data-state] {
            inline-size: 100%;
            block-size: 100%;
            min-block-size: 100%;
            flex: 1;
            margin-inline: 0;
            overflow-y: auto;
            overscroll-behavior: contain;
        }

        .measurement-form__comments-wrap--bare {
            & trix-editor {
                min-block-size: 5em;
                font-size: 1.15em;
                padding: 0.75em 0.95em;
            }
        }

        /* A thumb-reach of empty space between the card and the destructive
           action — enough that cancel requires a deliberate pull past the
           fold, not so much that it turns into an archaeology expedition. */
        .execution--wizard .execution__cancel-zone {
            margin-block-start: 25dvh;
        }
    }

    @media (min-width: 640px) {
        .execution__wizard-nav {
            display: none;
        }
    }

    /* ------------------------------------------------------------------------ */
    /* Read-only execution detail                                                */
    /* ------------------------------------------------------------------------ */

    /* Indicator pill — static counterpart to `.execution__toggle`. Renders the
       captured pass/fail/value outcome in the same visual register as the
       capture flow so a completed run reads as "the same card, resolved." */
    .execution__indicator {
        display: inline-flex;
        align-items: center;
        gap: 0.4ch;
        padding-block: 0.3em;
        padding-inline: 0.9em;
        border-radius: 999em;
        font-size: var(--text-x-small, 0.78em);
        font-weight: 600;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        line-height: 1;
        white-space: nowrap;
        background: var(--color-ink-lightest);
        color: var(--color-ink-medium);
        border: 1px solid transparent;
    }

    .execution__indicator--sm {
        padding-block: 0.2em;
        padding-inline: 0.7em;
        font-size: 0.7em;
    }

    .execution__indicator--pass {
        background: var(--color-positive);
        color: var(--color-canvas);
    }

    .execution__indicator--fail {
        background: var(--color-negative);
        color: var(--color-canvas);
    }

    /* Severity-specific pills — used for the standalone severity stamp and
       for per-row severity inside multi-check. Colour + explicit label so the
       two are never confused. */
    .execution__indicator--major {
        background: var(--color-negative);
        color: var(--color-canvas);
    }

    .execution__indicator--minor {
        background: oklch(var(--lch-yellow-medium));
        color: var(--color-canvas);
    }

    /* Severity pills carry an "SEVERITY:" shape via a leading dot, so they
       read visually distinct from a plain pass/fail badge even at a glance. */
    .execution__indicator--severity {
        padding-inline-start: 1em;
        position: relative;
    }

    .execution__indicator--severity::before {
        content: "";
        position: absolute;
        inset-inline-start: 0.45em;
        inset-block-start: 50%;
        inline-size: 0.45em;
        block-size: 0.45em;
        border-radius: 50%;
        background: currentColor;
        opacity: 0.9;
        transform: translateY(-50%);
    }

    .execution__indicator--value {
        font-family: var(--font-data, inherit);
        font-variant-numeric: tabular-nums;
        text-transform: none;
        letter-spacing: 0;
        padding-inline: 1em;
    }

    .execution__indicator--value strong {
        font-weight: 700;
        font-size: 1.05em;
    }

    .execution__indicator-unit {
        opacity: 0.85;
        font-weight: 500;
    }

    /* Readonly cards inherit the capture-flow's left/right anchoring so pass
       reads as "left, accepted" and fail as "right, flagged" — keeps the same
       spatial grammar between capture and report. */

    /* Minor-severity recolour, driven by a plain attribute on the card instead
       of the capture-flow's nested severity toggle. */
    .execution__card--readonly[data-state="fail"][data-severity="minor"] {
        --card-accent: oklch(var(--lch-yellow-dark));
        --card-bg: color-mix(in srgb, oklch(var(--lch-yellow-medium)) 10%, var(--color-canvas));
    }

    /* Severity stamp row — a distinct, labelled pill below the header so
       minor vs major is unmistakable (redundant coding per MIL-STD-1472H:
       colour + text). */
    .execution__severity-readout {
        display: flex;
        align-items: center;
        gap: 0.5ch;
        font-size: var(--text-x-small, 0.78em);
        color: var(--color-ink-medium);
    }

    /* Card photo strip — response attachments rendered as a horizontal row of
       thumbnails, lightbox-enabled via the parent section's controller. */
    .execution__card-photos {
        display: flex;
        flex-wrap: wrap;
        gap: 0.4em;
    }

    .execution__card-photo {
        display: block;
        inline-size: 4.5em;
        /* Height follows the image's natural aspect ratio — no fixed
           block-size, no letterboxing. Thermography hotspot overlays and
           burned-in temperature markers stay pixel-true because the tile
           is exactly the shape of the image it holds. */
        block-size: auto;
        border-radius: 0.35em;
        overflow: hidden;
        background: var(--color-ink-lightest);
    }

    .execution__card-photo img {
        inline-size: 100%;
        block-size: auto;
        display: block;
    }

    /* Note readout — the Trix editor's on-page twin. Same padding, border
       radius, and typography as the editable version inside an execution
       card, minus the toolbar and input chrome, so a saved note reads as
       "the note the inspector typed, preserved." */
    .execution__note-readout {
        display: block;
        padding: 0.55em 0.75em;
        border-radius: 0.35em;
        border: 1px solid var(--color-ink-lighter);
        background: var(--color-canvas);
        color: var(--color-ink);
        font-size: var(--text-small, 0.9em);
        line-height: 1.45;
    }

    .execution__note-body {
        min-inline-size: 0;
    }

    .execution__note-body :where(p, ul, ol, blockquote) {
        margin-block: 0.3em;
    }

    .execution__note-body :where(p:first-child, ul:first-child, ol:first-child) {
        margin-block-start: 0;
    }

    .execution__note-body :where(p:last-child, ul:last-child, ol:last-child) {
        margin-block-end: 0;
    }

    .execution__resolve-frame {
        display: block;
    }
}
