﻿@import url('tokens.css');

/* ============================================================================
   Process page (ADR 0031 Template B — the heaviest page). The selection-driven detail panels
   (Model/Channels/Unit/Procedure/Recipe/Evaluation/Occurrence/Report/Label + folder overviews)
   and the unit run control. The tree pane needs nothing of its own: it is one shared TreeView
   over the three roots. Prefixed as-* ; tokens only. The header each panel opens with is the
   shared one (ui-panel-head*, shared.css).
   ============================================================================ */

/* ---- Pills (neutral by default; semantic variants tint) ---- */
.as-pill {
    display: inline-flex; align-items: center;
    padding: var(--space-1) var(--space-4); border-radius: var(--radius-pill);
    background: var(--color-surface-alt); color: var(--color-text-secondary);
    border: 1px solid var(--color-stroke);
    font-size: var(--font-size-eyebrow); font-weight: var(--font-weight-semibold);
}
.as-pill-success { background: var(--color-success-bg); color: var(--color-success); border-color: var(--color-success); }
.as-pill-caution { background: var(--color-caution-bg); color: var(--color-caution); border-color: var(--color-caution); }
.as-pill-critical { background: var(--color-critical-bg); color: var(--color-critical); border-color: var(--color-critical); }

/* ---- List and the row picked in it (the shared .ui-collection, shared.css) ----
   Recipes, Evaluations and Actions open their selection through the one layout the whole app uses,
   laid on the well beside the panel's cards rather than inside one: the hairline between its columns
   is the only rule it needs, and a card around it would draw a second. What is this page's is only
   how it sits among those cards; the field stack inside the column is the shared .ui-inspector,
   because every list of the app opens its selection into the same shape (the split model screens
   open theirs into the shared settings column, .ui-split-settings, which holds the same stack).

   The units on the model's own page are the exception, and deliberately: that list is carried by a
   card, because the two verbs over it stand in that card's head, and a head has to be the head of
   something. It needs nothing of its own here, since the head's own note already spaces the list
   under it and the card stack spaces the card among its neighbours. */
.ui-card + .ui-collection, .ui-collection + .ui-card { margin-top: var(--space-4); }

/* ---- Card internals ---- */
.as-card-title { font-size: var(--font-size-card-title); font-weight: var(--font-weight-semibold); color: var(--color-text); display: block; margin-bottom: var(--space-3); }
.as-card-head-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); }
.as-card-head-row .as-card-title { margin-bottom: 0; }
.as-mt { margin-top: var(--space-4); }

/* The Ch# field a repeated number was put back into: the row the note under the grid is talking
   about, marked in the same caution ink so the eye goes from the sentence to the field. */
.as-channel-number-refused .ui-input { border-color: var(--color-caution); }

/* ---- Channels screen: the drawing the colour and the group are picked against ----
   The chart a unit will put on screen, posed, standing in the settings column right under the two
   fields that decide it. It is framed like the unit's own chart card (the same hairline, radius and
   surface as .unit-overview-chart) and shorter, because a column is not a card: enough height to
   tell the bands and the inks apart, never enough to push the fields off the column. The size
   container is what lets the chart's own type scale to the box it was given rather than to the
   window. It is a sibling of the field stack rather than a field in it, because the picture belongs
   to the model and the stack is rebuilt for every row picked. */
.as-channel-chart-preview {
    container-type: size;
    display: flex;
    flex-direction: column;
    height: 220px;
    margin-top: var(--space-2);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: var(--color-surface);
}

/* The one line that is about the picked channel rather than about the drawing: where it lands on
   the picture above, or why the picture leaves it out. */
.as-channel-chart-note { margin-top: var(--space-2); }

/* ---- The heads of the two halves of a model screen ----
   The two heads dress alike: the per-unit one (UnitsSectionHead) and the definition one
   (DefinitionSectionHead) open with the same title line, and each of them may end in commands — the
   way to where the units are declared, the "+" that grows the table under it, and whatever else
   works that table, down to what ends a row of it. A head with nothing there sits exactly where it
   always did, because the line's own height is the title's. */
.as-section-head-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
}
.as-section-head-commands {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.as-units-head-title,
.as-definition-head-title { margin-bottom: 0; }
.as-definition-head-note { margin-top: var(--space-1); margin-bottom: var(--space-4); }

/* Inside an area's head band the pair keeps the band's rhythm: the band rules itself off and
   spaces the body below, so the note's standalone air would double it. */
.ui-stack-area-head .as-definition-head-note { margin-bottom: 0; }

/* The same head worn inside the units card on the model's page: there it announces one card among
   three rather than half a screen, so the title takes the size its neighbours' titles have. Nothing
   else about the head changes, which is the point of reusing it. */
.as-units-card .as-definition-head-title { font-size: var(--font-size-card-title); }

/* One unit's cards, keyed to the unit so picking another opens it fresh: the stack is what the
   .ui-card rules already draw, and the wrapper only has to not swallow the air between them. */
.as-unit-cards { display: block; min-width: 0; }

/* A unit still short of sources or of a queue reads in the caution ink and nothing else changes:
   the list is a reading, not an alarm. Every units list wears it the same way. */
.as-units-missing { color: var(--color-caution); }

/* A unit that has left the model's default is the exception on its screen, so it is the one that is
   marked: the same weight the app gives a name, against siblings that read as ordinary text. It is
   not a warning, because differing is a decision and not a fault. */
.as-unit-detached {
    color: var(--color-text);
    font-weight: var(--font-weight-semibold);
}

/* ---- Form fields (label-above, wrapped) ---- */
.as-wrap-fields { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-bottom: var(--space-3); }
.as-field-grow { flex: 1 1 320px; }
.as-field-bottom { justify-content: flex-end; }

/* ---- Model structure tiles ---- */
.as-tiles { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-4); }
.as-tile {
    width: 150px; display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2);
    padding: var(--space-4); border: 1px solid var(--color-stroke); border-radius: var(--radius-lg);
    background: var(--color-surface); cursor: pointer; text-align: left; color: inherit;
}
.as-tile:hover { background: var(--color-overlay-hover); border-color: var(--color-accent); }
.as-tile-icon { width: 32px; height: 32px; border-radius: var(--radius-md); background: var(--color-surface-alt); color: var(--color-text-secondary); display: flex; align-items: center; justify-content: center; }
.as-tile-count { font-size: var(--font-size-readout); font-weight: var(--font-weight-semibold); color: var(--color-text); }
.as-tile-name { font-size: var(--font-size-description); color: var(--color-text-secondary); }
/* A row that is one thing rather than a list of them (a unit's two areas, the model's interlock)
   is named rather than counted, so the tile's own label takes the count's place. */
.as-tile-label { font-size: var(--font-size-body); font-weight: var(--font-weight-semibold); color: var(--color-text); }

/* ---- Folder overview cards ---- */
.as-overview { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.as-overview-card {
    width: 280px; display: flex; align-items: center; gap: var(--space-3);
    padding: var(--space-4); border: 1px solid var(--color-stroke); border-radius: var(--radius-lg);
    background: var(--color-surface); cursor: pointer;
}
.as-overview-card:hover { background: var(--color-overlay-hover); border-color: var(--color-accent); }
/* The face of the card is the button that opens it, filling the row so the whole card answers a
   click, taking the app's one focus ring on Tab and leaving the row's verb beside it. It carries
   none of the browser's own button dressing: the card around it is the drawing. */
.as-overview-open {
    flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--space-3);
    padding: 0; border: 0; background: none; color: inherit; text-align: left; cursor: pointer;
}
.as-overview-icon { flex: 0 0 auto; width: 36px; height: 36px; border-radius: var(--radius-lg); background: var(--color-surface-alt); color: var(--color-text-secondary); display: flex; align-items: center; justify-content: center; }
.as-overview-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--font-weight-semibold); color: var(--color-text); }
.as-overview-empty { padding: var(--space-5) 0; }
/* A unit card stacks its name over the live status line, so the batch trigger is not blind. */
.as-overview-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.as-overview-body .as-overview-name { flex: 0 0 auto; }
.as-overview-status { font-size: var(--font-size-eyebrow); color: var(--color-text-secondary); }
.as-overview-status-running { color: var(--color-success); }
.as-overview-status-caution { color: var(--color-caution); }
.as-overview-status-critical { color: var(--color-critical); }

/* ---- Summary card ---- */
.as-summary-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) 0; }
.as-summary-label { color: var(--color-text-secondary); }
.as-summary-value { font-weight: var(--font-weight-semibold); color: var(--color-text); }

/* ---- Occurrence/report checklist ---- */
.as-checklist { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-2); }

/* ---- Action selection: a checklist whose rows also say what each choice emits ---- */
.as-action-choices {
    display: flex; flex-direction: column; margin-top: var(--space-2);
    overflow: hidden; border: 1px solid var(--color-stroke); border-radius: var(--radius-md);
}
.as-action-choice {
    display: flex; flex-direction: column; gap: var(--space-1);
    padding: var(--space-3); border-bottom: 1px solid var(--color-stroke-subtle);
}
.as-action-choice:last-child { border-bottom: 0; }
.as-action-choice.is-review { box-shadow: inset 3px 0 0 var(--color-caution); }
.as-action-choice-head { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.as-action-choice-head .as-pill { flex: 0 0 auto; margin-left: auto; }
.as-action-choice-emission {
    color: var(--color-text-secondary); font-size: var(--font-size-description);
}
.as-action-choice-notes {
    margin: 0; padding-left: var(--space-5);
    color: var(--color-caution); font-size: var(--font-size-small);
}

/* ---- Empty state ---- */
/* Empty state uses the shared .ui-empty-state. */

/* ---- Unit run-control bar ---- */
.as-runbar { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

/* ---- Cycle progress (status line over a thin bar) ---- */
.as-cycle { flex: 0 1 460px; min-width: 0; }
.as-cycle-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); }
.as-cycle-status { font-size: var(--font-size-description); color: var(--color-text); }
.as-cycle-bar { width: 100%; height: 7px; }

/* ---- Inline transient prompts (metadata / end-note) ---- */
.as-prompt { margin-bottom: var(--space-4); }
.as-meta-list { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-2); }
.as-meta-row { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: var(--space-3); align-items: center; }
.as-meta-label { color: var(--color-text-secondary); }
.as-coord { margin-top: var(--space-4); }
.as-coord-title { font-weight: var(--font-weight-semibold); margin-bottom: var(--space-2); color: var(--color-text); }
.as-coord-cand { margin-top: var(--space-3); }
.as-coord-meta { margin: var(--space-2) 0 0 var(--space-7); }
.as-coord-meta .as-meta-row { grid-template-columns: 156px minmax(0, 1fr); }
.as-prompt-actions { display: flex; gap: var(--space-3); margin-top: var(--space-5); }

/* ---- Live unit charts (one per plot group, stacked) ---- */
.as-unit-charts { display: flex; flex-direction: column; gap: var(--space-4); margin-top: var(--space-3); }
.as-unit-chart { height: 260px; }
.as-chart-idle {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-3);
    height: 180px; margin-top: var(--space-3);
    border: 1px solid var(--color-stroke); border-radius: var(--radius-lg);
    color: var(--color-text-disabled); font-size: var(--font-size-description);
}

/* ---- Run-comment add row ---- */
.as-comment-add { display: flex; gap: var(--space-3); align-items: center; margin: var(--space-3) 0 var(--space-4); }
.as-comment-add .ui-input { flex: 1 1 auto; }

/* ---- Recipe profile preview (inline ChartView) ---- */
.as-recipe-chart {
    height: 320px; border: 1px solid var(--color-stroke); border-radius: var(--radius-lg);
    overflow: hidden; background: var(--color-surface); margin-top: var(--space-2);
}

/* ---- Occurrence condition editor ---- */
.as-condition-editor { margin-top: var(--space-2); }
.as-hint-tertiary { color: var(--color-text-disabled); margin-top: var(--space-3); }

/* ---- Sequential metadata: composition + operational counter ledger ----
   The whole editor stands in the settings column of the Metadata screen, flush with the first row,
   which is why it opens with no margin of its own; every block below sets its own rhythm. */
/* What a Sequential field adds under the fields every metadata field has, in the same column. */
.as-sequence-editor { min-width: 0; }
.ui-inspector + .as-sequence-editor { margin-top: var(--space-5); }
.as-sequence-preview {
    display: flex; flex-direction: column; gap: var(--space-2);
    padding: var(--space-5); margin-top: var(--space-4);
    border: 1px solid var(--color-stroke); border-radius: var(--radius-lg);
    background: var(--color-surface-alt);
}
.as-sequence-preview-value {
    color: var(--color-accent-text); font-family: var(--font-mono);
    font-size: var(--font-size-readout); font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.as-sequence-preview-note { color: var(--color-text-disabled); font-size: var(--font-size-eyebrow); }
.as-sequence-config {
    display: flex; align-items: flex-end; flex-wrap: wrap;
    gap: var(--space-4); margin-top: var(--space-5);
}
.as-sequence-pad { min-height: 32px; display: flex; align-items: center; }
.as-sequence-section-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: var(--space-4); margin-top: var(--space-6);
}
.as-sequence-section-head .as-card-title { margin-bottom: var(--space-1); }
.as-sequence-add-part { display: flex; align-items: center; gap: var(--space-2); }
.as-sequence-parts {
    margin-top: var(--space-3); border: 1px solid var(--color-stroke);
    border-radius: var(--radius-lg); overflow: hidden; background: var(--color-surface);
}
/* The two middle tracks give way before the row does: the list lives in a column, not across the
   panel, so its width is whatever the layout leaves it. */
.as-sequence-part {
    display: grid; grid-template-columns: 28px minmax(0, 152px) minmax(0, 1fr) auto;
    align-items: center; gap: var(--space-3); min-height: 44px;
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--color-stroke-subtle);
}
.as-sequence-part-kind { min-width: 0; }
.as-sequence-part:last-child { border-bottom: 0; }
.as-sequence-part.counter { background: var(--color-surface-alt); }
.as-sequence-part-index {
    color: var(--color-text-disabled); font-size: var(--font-size-eyebrow);
    font-variant-numeric: tabular-nums; text-align: center;
}
.as-sequence-counter-label {
    display: inline-flex; align-items: center; min-height: 28px;
    color: var(--color-accent-text); font-size: var(--font-size-small);
    font-weight: var(--font-weight-semibold);
}
.as-sequence-part-settings { min-width: 0; }
.as-sequence-part-help { color: var(--color-text-secondary); font-size: var(--font-size-description); }
.as-sequence-part-actions { display: flex; align-items: center; gap: var(--space-1); }
.as-sequence-model-state { margin-top: var(--space-5); }

.as-sequence-code-field { margin-top: var(--space-4); }
.as-counter-state-list {
    margin-top: var(--space-4); border-top: 1px solid var(--color-stroke-subtle);
}
/* Every track may give way: the ledger stands full width on a unit or procedure page and in the
   settings column of the Metadata screen, and the same row has to read in both. */
.as-counter-state-row {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 120px) minmax(0, 148px) minmax(0, auto);
    align-items: center; gap: var(--space-4); min-height: 60px;
    padding: var(--space-3) 0; border-bottom: 1px solid var(--color-stroke-subtle);
}
.as-counter-state-identity,
.as-counter-state-reading,
.as-counter-state-next { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.as-counter-state-name {
    color: var(--color-text); font-size: var(--font-size-small);
    font-weight: var(--font-weight-semibold); overflow: hidden; text-overflow: ellipsis;
}
.as-counter-state-context { color: var(--color-text-secondary); font-size: var(--font-size-description); }
.as-counter-state-value {
    color: var(--color-text); font-family: var(--font-mono);
    font-size: var(--font-size-body); font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
}
.as-counter-next-input { width: 132px; max-width: 100%; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.as-counter-state-note { min-height: 16px; }
.as-counter-repeat { color: var(--color-caution); font-size: var(--font-size-eyebrow); font-weight: var(--font-weight-semibold); }
.as-counter-state-help { margin-top: var(--space-3); }

@media (max-width: 760px) {
    .as-sequence-section-head { flex-direction: column; }
    .as-sequence-add-part { width: 100%; }
    .as-sequence-part { grid-template-columns: 24px minmax(120px, 1fr) auto; }
    .as-sequence-part-settings { grid-column: 2 / -1; }
    .as-sequence-part-actions { grid-column: 3; grid-row: 1; }
    .as-counter-state-row { grid-template-columns: minmax(0, 1fr) 120px 148px; }
    .as-counter-state-note { grid-column: 1 / -1; }
}

@media (max-width: 520px) {
    .as-sequence-add-part { align-items: stretch; flex-direction: column; }
    .as-counter-state-row { grid-template-columns: minmax(0, 1fr) 132px; }
    .as-counter-state-next { grid-column: 2; grid-row: 1 / span 2; }
    .as-counter-state-reading { grid-column: 1; }
}

/* ---- Bindings grid: shared-writers cell ---- */
.as-shared-cell { color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- Finalization grid (temporal): cap width 560px ---- */
.as-finalization-wide { max-width: 560px; }

/* ---- The report layout: the drawing IS the configuration (ADR 0024 §7) ----
   One page-shaped surface: the header band, then one card per section in the order the PDF writes
   them. Each card carries the switch that includes it and the pair that moves it, so turning a
   section on and placing it are gestures on the drawing itself and never on a separate list. A
   section that is off stays legible and reads as out of the document, because the operator has to
   see what he can put back. */
.as-report-page { border: 1px solid var(--color-stroke); border-radius: var(--radius-lg); overflow: hidden; background: var(--color-surface); margin-top: var(--space-2); }

.as-report-head {
    display: flex; flex-direction: column; align-items: stretch; gap: var(--space-3);
    padding: var(--space-5); border-bottom: 1px solid var(--color-stroke-subtle);
}

/* A band of the page: what stands on it, in the order it is printed across the sheet. The logo
   takes its own end of the band, so moving it from one side to the other moves it here too. */
.as-report-band { display: flex; align-items: flex-start; gap: var(--space-4); }
.as-report-headings { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1); }

.as-report-logo {
    flex: 0 0 auto;
    width: 70px; height: 26px; border-radius: var(--radius-sm);
    border: 1px solid var(--color-stroke); background: var(--color-surface-alt);
    display: flex; align-items: center; justify-content: center; overflow: hidden;
    font-size: var(--font-size-micro); color: var(--color-text-disabled);
}
.as-report-logo img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* Nothing resolves, so the PDF would print no logo: the plate says that instead of standing in
   for a picture the page will not carry. */
.as-report-logo.is-empty { border-style: dashed; background: transparent; }

.as-report-title { font-size: var(--font-size-card-title); font-weight: var(--font-weight-bold); color: var(--color-text); }
.as-report-headertext { font-size: var(--font-size-small); color: var(--color-text-secondary); }

/* The questions a band's own furniture asks, under the band they act on. */
.as-report-options { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-4); }
.as-report-logo-hint { flex-basis: 100%; }

.as-report-section {
    display: flex; align-items: flex-start; gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-stroke-subtle);
}
.as-report-section:last-child { border-bottom: 0; }
.as-report-section-body { display: flex; flex-direction: column; gap: var(--space-2); flex: 1; min-width: 0; }
.as-report-section-name { font-size: var(--font-size-small); font-weight: var(--font-weight-semibold); color: var(--color-text); }
.as-report-section-what { font-size: var(--font-size-description); color: var(--color-text-secondary); }
.as-report-section-option { margin-top: var(--space-1); }

/* Out of the document: the row keeps its place in the list but not on the page. */
.as-report-section.off { background: var(--color-surface-alt); }
.as-report-section.off .as-report-section-what { color: var(--color-text-disabled); }

/* The block every report leads with, and the mark saying it is not the operator's to arrange. */
.as-report-section-fixed { background: var(--color-surface-alt); }
.as-report-always {
    font-size: var(--font-size-micro); color: var(--color-text-disabled);
    text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap;
}

/* Two fields of the same option standing side by side (the chart's window and its length). */
.as-report-inline-fields { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-4); }

/* Where the body stops: the switches that close the document, and under them the close itself, at
   the place on the page it will occupy. */
.as-report-close {
    display: flex; flex-direction: column; gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-stroke-subtle);
}
.as-report-rules { display: flex; gap: var(--space-6); }
.as-report-rule {
    flex: 1; min-width: 0; padding-top: var(--space-5);
    border-top: 1px solid var(--color-stroke);
    font-size: var(--font-size-micro); color: var(--color-text-secondary);
}
.as-report-end {
    text-align: center; padding-top: var(--space-2);
    border-top: 1px solid var(--color-stroke);
    font-size: var(--font-size-micro); font-weight: var(--font-weight-semibold);
    color: var(--color-text-secondary);
}

/* The page footer: the note the layout carries about itself, typed where it prints, then the line
   the app always writes and the page count beside it. */
.as-report-foot {
    display: flex; flex-direction: column; gap: var(--space-3);
    padding: var(--space-4) var(--space-5); background: var(--color-surface-alt);
}
.as-report-footline { align-items: center; }
.as-report-generated { flex: 1; min-width: 0; font-size: var(--font-size-micro); color: var(--color-text-disabled); }
.as-report-pages { font-size: var(--font-size-micro); color: var(--color-text-disabled); }

/* The sample prompt: what the sample would be filled with. */
.as-report-sample-source { display: flex; align-items: baseline; gap: var(--space-3); margin-top: var(--space-4); }

/* ---- A view of the model: the arrangement IS the drawing (ADR 0024 §9) ----
   One surface shaped like the page a unit operates through: a card per row, in the order the view
   draws them, each carrying the card itself posed with sample readings plus the switch that includes
   it and the pair that moves it. So turning a card on and placing it are gestures on the surface
   being configured, never on a separate list of names mapped back onto it. A card that is off stays
   legible and reads as out of the view, because the operator has to see what he can put back. */
.as-view-page {
    border: 1px solid var(--color-stroke); border-radius: var(--radius-lg);
    overflow: hidden; background: var(--color-surface); margin-top: var(--space-2);
}

/* The mark the view is drawn with, picked on the view's own page. The library is thousands of marks
   long, so the field is a button carrying the mark that is in force and the grid unfolds under the
   card: a grid is far taller than a field, and this station is operated with a finger. */
.as-icon-trigger {
    min-height: 32px; min-width: 56px;
    justify-content: center;
    padding: var(--space-2) var(--space-4);
}

.as-icon-trigger .ui-glyph { color: var(--color-text); }

.as-icon-trigger-name {
    min-width: 0; max-width: 140px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Open, the button is the way back out of the grid under it, so it says so. */
.as-icon-trigger[aria-expanded="true"] { border-color: var(--color-accent); }

.as-icon-search { max-width: 200px; margin-bottom: var(--space-2); }

.as-icon-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(36px, 1fr));
    gap: var(--space-1);
    max-height: 180px; overflow-y: auto;
    padding: var(--space-2);
    border: 1px solid var(--color-stroke); border-radius: var(--radius-md);
    background: var(--color-surface);
}

.as-icon-cell {
    display: flex; align-items: center; justify-content: center;
    aspect-ratio: 1;
    background: transparent; color: var(--color-text);
    border: 1px solid transparent; border-radius: var(--radius-sm);
    cursor: pointer;
}

.as-icon-cell:hover { background: var(--color-overlay-hover); }
.as-icon-cell.sel { border-color: var(--color-accent); background: var(--color-overlay-hover); }
.as-icon-cell .ui-glyph { color: inherit; }

.as-view-card {
    display: flex; align-items: flex-start; gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-stroke-subtle);
}
.as-view-card:last-child { border-bottom: 0; }
.as-view-card-body { display: flex; flex-direction: column; gap: var(--space-2); flex: 1; min-width: 0; }
.as-view-card-name { font-size: var(--font-size-small); font-weight: var(--font-weight-semibold); color: var(--color-text); }
.as-view-card-what { font-size: var(--font-size-description); color: var(--color-text-secondary); }
.as-view-card-option { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-1); }

/* Out of the view: the row keeps its place in the arrangement but not on the surface. */
.as-view-card.off { background: var(--color-surface-alt); }
.as-view-card.off .as-view-card-what { color: var(--color-text-disabled); }
.as-view-card.off .as-view-preview { opacity: 0.4; }

/* The safety context every view carries, and the mark saying it is not the operator's to arrange. */
.as-view-card-fixed { background: var(--color-surface-alt); }
.as-view-always {
    font-size: var(--font-size-micro); color: var(--color-text-disabled);
    text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap;
}

/* The preview: the card itself, drawn with sample readings, so a row is recognized by what it puts
   on the surface rather than read from its name. Nothing here is a second drawing — these are the
   very components a unit's surface mounts — and nothing here is a control: the row is inert, and the
   switch beside it is the gesture. */
.as-view-preview { margin-top: var(--space-1); min-width: 0; }

/* A screen card draws the room it takes, at the height chosen on it, with the screen inside it. The
   thumbnail carries the screen's own proportions on a folder stage; here the box states the height,
   so the drawing takes the box (a definite width and height leave the authored ratio nothing to
   decide) and the row shows the room the page will give it. */
.as-view-preview-screen { overflow: hidden; border-radius: var(--radius-md); }
.as-view-preview-screen > .dnav-thumb-shape { height: 100%; }

/* ---- A screen of the model, mounted inside the Process page (ADR 0024 §6/§9) ----
   The stage itself is the shared canvas host (.dnav-canvas-host, dashboard.css) — the very element
   the Home page and the dashboard editor draw into, positioned for the runtime grid and stretching
   along its parent's flex line. That is the whole scaling mechanism: the grid's rows are fractions
   of the stage, so a screen fills the area it is given instead of standing at a height computed for
   it, and the panel, the editor over it and the Home page all draw the definition the same way.
   The detail card is what has to be told: its body scrolls a column of cards, which gives a child
   nothing to fill. While a screen IS the panel, it becomes that flex line — one item, taking the
   height the card has left rather than the height of its content. A screen drawn as a card of a
   view does not ask for that: it stands at the height the view chose, inside a body that goes on
   scrolling, so it carries no fill mark.
   Added here: only how the stage is seated on this page (the hairline and the card's radius). */
.ui-md-detail-body:has(.as-screen-fill) { display: flex; flex-direction: column; }

.as-screen-stage {
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-lg);
}

/* ---- A unit's view: the fixed cards, in the order the model arranges them (ADR 0024 §9) ----
   Eight cards read as ONE family, so what they share is written here once and each card's own rules
   below say only what is that card's alone: the head every card opens with, the single label voice
   every name inside them is said in, two number tiers and no third, the frame a live runtime view is
   seated in, and the rhythm between blocks. Reviewing a card by itself is what produced eight
   drawings; this block is the answer to that. It dresses the inert preview in the model's view panel
   at the same time, because that preview IS these components and never a second drawing of them.

   One slot per card so the stack spaces itself, whichever cards the arrangement carries and
   whichever of them have something to draw. */
.unit-overview-slot + .unit-overview-slot { margin-top: var(--space-4); }

/* The line above the first card: a standing statement about the surface, not a card of it. */
.unit-view-notice { margin-bottom: var(--space-4); text-wrap: pretty; }

/* ---- The head (ViewCardHead) ----
   The card's name, optionally what it holds, and on the trailing side the one thing that qualifies
   the whole card right now. It wraps rather than squeezes, so a narrow column drops the trailing
   part under the name instead of crushing both. */
.unit-view-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    flex-wrap: wrap; gap: var(--space-2) var(--space-4);
    margin-bottom: var(--space-4);
}
.unit-view-head-name { min-width: 0; }
.unit-view-head .as-card-title { margin-bottom: 0; }
.unit-view-head .field-description { margin-top: var(--space-1); text-wrap: pretty; }
.unit-view-head-aside { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-3); }

/* A state stated on a head: the dot the whole app states a state with, and the word beside it. */
.unit-view-state {
    display: inline-flex; align-items: center; gap: var(--space-2);
    font-size: var(--font-size-small); color: var(--color-text-secondary); white-space: nowrap;
}

/* The scope a card's numbers are counted over: a segmented track, the picked segment raised out of
   the well onto the card's own surface. It is a scope and not a command, which is exactly what the
   segmented shape says and what two ordinary keys did not. */
.unit-view-scope {
    display: inline-flex; flex-wrap: wrap; gap: var(--space-1);
    padding: var(--space-1); border-radius: var(--radius-md);
    background: var(--color-surface-alt);
}
.unit-view-scope-seg {
    flex: 1 1 auto;
    font-family: var(--font-sans); font-size: var(--font-size-description);
    color: var(--color-text-secondary); background: transparent;
    border: none; border-radius: var(--radius-sm);
    padding: var(--space-2) var(--space-4); white-space: nowrap; cursor: pointer;
    transition: transform var(--dur-press) var(--ease-out);
}
.unit-view-scope-seg:hover { background: var(--color-overlay-hover); }
.unit-view-scope-seg:active { transform: scale(0.97); }
.unit-view-scope-seg.is-selected {
    background: var(--color-surface); color: var(--color-text);
    font-weight: var(--font-weight-semibold); box-shadow: var(--shadow-card);
}

/* One label voice inside these cards (the app's own .input-label) and one gap under it: the stack
   the label stands in owns that gap, so the label never adds a second one of its own. */
.unit-view-card .input-label { margin-bottom: 0; }

/* ---- The two number tiers ----
   A reading taken from a metre away is the readout; every figure that supports one is the body size
   in the same ink. One weight and one ruler in both, so a count, a percentage and a duration line up
   down the card and nothing jumps a size for no reason. */
.unit-view-readouts {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: var(--space-4) var(--space-6);
}
.unit-view-readout { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.unit-view-readout-value {
    font-size: var(--font-size-readout); font-weight: var(--font-weight-semibold);
    color: var(--color-text); font-variant-numeric: tabular-nums;
    line-height: 1.15; overflow-wrap: anywhere;
}
.unit-view-figure {
    font-size: var(--font-size-body); font-weight: var(--font-weight-semibold);
    color: var(--color-text); font-variant-numeric: tabular-nums;
}

/* A block inside a card: its name in the label voice over the rows it names, and one hairline
   between it and what came before. A card holding a single block never draws one. */
.unit-view-group {
    display: block; margin-top: var(--space-5);
    padding-top: var(--space-4); border-top: 1px solid var(--color-stroke-subtle);
}
.unit-view-group > .input-label { margin-bottom: var(--space-3); }

/* Nothing to draw is said in the app's one empty voice, at the height of a block inside a card
   rather than the height of an empty page. */
.unit-view-empty { min-height: 92px; padding: var(--space-6) var(--space-4); }

/* A line the card adds under its body: why a command was refused, what a state rules out. Two of
   them read as one paragraph rather than two notices. */
.unit-view-note { margin-top: var(--space-4); text-wrap: pretty; }
.unit-view-note + .unit-view-note { margin-top: var(--space-2); }

/* ---- The stage a live runtime view is seated in ----
   The chart, the comment timeline and the occurrence list are runtime views rather than markup these
   cards write, so all three are given the same box: the card's own surface behind one hairline, a
   corner tighter than the card's so the two read as nested, and no second frame drawn by the view
   inside it. */
.unit-view-stage {
    border: 1px solid var(--color-stroke); border-radius: var(--radius-md);
    background: var(--color-surface); overflow: hidden;
}

/* The run card: the staged pick and the lifecycle keys on one line, wrapping before either is
   squeezed. The keys are what a finger lands on all day, so they are given a target a finger can
   take without aiming. */
.unit-run {
    display: flex; align-items: flex-end; flex-wrap: wrap;
    gap: var(--space-4) var(--space-6);
}
.unit-run-lifecycle { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.unit-run-lifecycle .ui-btn {
    min-height: 40px; padding-inline: var(--space-6); justify-content: center;
}

/* Metadata: a labelled entry per metadata field the staged procedure prompts. */
.unit-staging {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: var(--space-4) var(--space-5);
}

/* A sequential field is a prediction and not an entry, so it stands where its entry would, in the
   mono the counter composes it in and in the quieter ink of something not yet reserved. */
.unit-staging-preview {
    display: flex; align-items: center; padding: var(--space-3) 0;
    font-family: var(--font-mono); font-size: var(--font-size-body);
    color: var(--color-text-secondary);
}

/* The three cards that host a runtime view give it the box the canvas cell used to: those views write
   their geometry against their container, so a host that is not a size container leaves them
   resolving against the page. Height is this surface's to state, since there is no grid cell here to
   take it from.

   And the type is this surface's too. On the canvas a component's words scale with the cell the
   operator drew, which is why the family resolves its size from the container's height; a card is not
   a cell the operator sized, so the same rule would print a heading at 48px just because the card is
   tall. The family reads its size from one variable, so the host answers it with the page's own body
   size and the view reads as app text among app cards. */
.unit-overview-feed,
.unit-overview-chart {
    container-type: size;
    display: flex;
    flex-direction: column;
}

/* Written at the element that declares the variable, because a declaration on the element itself wins
   over the same variable inherited from its host. */
.unit-overview-feed .cmp-command { --cmp-type: var(--font-size-body); }

.unit-overview-feed { height: 220px; overflow: auto; }
.unit-overview-chart { height: 320px; }

/* Both feeds write a line about themselves with the live state in it, and the card is headed with
   exactly that line: inside the box it would be the same sentence twice, so it is left out there.
   The list's own frame gives way to the card's for the same reason, one box around one thing. */
.unit-overview-feed .cmp-command > div:first-child,
.unit-overview-feed .occ-header { display: none; }
.unit-overview-feed .cmp-occurrences { border: 0; background: transparent; }

/* A screen of the model, drawn as a card of a view: the box is exactly the height the view
   declared, and the screen scales to fill it (the stage host stretches on this flex line). The page
   scrolls; the card never does. The stage takes the family's inner corner, like every other box a
   card of this family seats something in. */
.unit-view-screen {
    display: flex; flex-direction: column; min-height: 0;
}
.unit-view-screen .as-screen-stage { border-radius: var(--radius-md); }

/* Single commands: one labelled group per ad-hoc command (snapshot / evaluate / apply), its
   controls on a line that wraps instead of a label column that never gives way. */
.unit-quick-actions { display: flex; flex-direction: column; gap: var(--space-5); }
.unit-quick-line { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); }
.unit-quick-line .ui-select { flex: 0 1 auto; min-width: 8rem; max-width: 15rem; }

/* ---- Productivity: what the unit is doing, then what it produced ----
   The three summary readouts are the family's readout band, the very grid the run state card is read
   in, so two cards of one surface answer in the same shape and the same size. Under it the ledger is
   a ledger (name, figure, rate) and the tally under that is the readout's shape one tier down, so the
   eye descends from the answer to its parts instead of choosing between four number sizes. */
.unit-productivity-output {
    display: flex; flex-wrap: wrap; align-items: baseline;
    gap: var(--space-2) var(--space-4);
    padding: var(--space-3) 0; border-bottom: 1px solid var(--color-stroke-subtle);
    font-variant-numeric: tabular-nums;
}
.unit-productivity-output:last-child { border-bottom: 0; padding-bottom: 0; }
.unit-productivity-output-name {
    flex: 1 1 140px; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--color-text); font-weight: var(--font-weight-medium);
}
.unit-productivity-output-quantity {
    flex: 0 0 auto; display: flex; align-items: baseline;
    gap: var(--space-2); white-space: nowrap;
}
.unit-productivity-output-quantity span,
.unit-productivity-output-rate {
    color: var(--color-text-secondary); font-size: var(--font-size-description);
}
/* Pushed to the trailing edge on a wide row, and onto the next line under the figure it belongs to
   when the row runs out of width. */
.unit-productivity-output-rate { flex: 0 0 auto; margin-left: auto; white-space: nowrap; }

.unit-productivity-outcomes {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: var(--space-4) var(--space-5);
}
.unit-productivity-outcome { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.unit-productivity-outcome.is-ok .unit-view-figure { color: var(--color-success); }
.unit-productivity-outcome.is-nok .unit-view-figure,
.unit-productivity-outcome.is-failed .unit-view-figure { color: var(--color-critical); }

/* The per-Procedure breakdown, behind the app's own disclosure: the same reading, split by what
   produced it, so it belongs under a fold rather than beside the answer. */
.unit-productivity-details { margin-top: var(--space-5); }
.unit-productivity-table-wrap { overflow-x: auto; margin-top: var(--space-3); }
.unit-productivity-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.unit-productivity-table th,
.unit-productivity-table td {
    padding: var(--space-3); text-align: right;
    border-bottom: 1px solid var(--color-stroke-subtle); white-space: nowrap;
}
.unit-productivity-table th {
    color: var(--color-text-secondary); font-size: var(--font-size-description);
    font-weight: var(--font-weight-semibold);
}
.unit-productivity-table tbody tr:last-child td { border-bottom: 0; }
.unit-productivity-table th:first-child,
.unit-productivity-table td:first-child { text-align: left; }
.unit-productivity-unit-note { color: var(--color-text-disabled); font-size: var(--font-size-description); }

/* Unit Settings: one editable quantity ledger, with source compatibility visible in place. */
.unit-productivity-config-default {
    display: flex; flex-direction: column; gap: var(--space-1);
    padding: var(--space-4) 0; color: var(--color-text-secondary);
}
.unit-productivity-config-default strong { color: var(--color-text); }
.unit-productivity-config-list { display: flex; flex-direction: column; margin-top: var(--space-3); }
.unit-productivity-config-item { padding: var(--space-4) 0; border-top: 1px solid var(--color-stroke-subtle); }
.unit-productivity-config-head { display: flex; align-items: center; gap: var(--space-3); }
.unit-productivity-config-name { flex: 1 1 260px; }
.unit-productivity-source-list {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-2) var(--space-5); margin-top: var(--space-3);
}

/* The cards of a view need no breakpoint of their own: every one of them reflows on its own width,
   which is the only measure that is true here — the column they stand in is a fraction of the window
   and a query on the window would fire at the wrong moment. What is left is the Unit Settings
   ledger, which does stand across the panel. */
@media (max-width: 980px) {
    .unit-productivity-source-list { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
    .unit-productivity-config-head { flex-wrap: wrap; }
}

/* ---- Global external-label template library ----
   The transparent file input covers its button label, so the ring has to come from the wrapper:
   the label never takes focus and the input that does is invisible. */
.as-file-import { position: relative; overflow: hidden; cursor: pointer; }
.as-file-import:focus-within { outline: var(--focus-ring-width) solid var(--color-accent); outline-offset: var(--focus-ring-offset); }
.as-file-import-input {
    position: absolute; inset: 0; width: 100%; height: 100%;
    opacity: 0; cursor: pointer;
}
.as-file-import:has(.as-file-import-input:disabled) { cursor: default; opacity: .55; }
.as-file-import:has(.as-file-import-input:disabled) .as-file-import-input { cursor: default; }

/* The command text reads as a listing: monospace comes from the field, the smaller step and the
   tab width keep a wide ZPL line legible in the panel column. */
.as-label-template-commands { font-size: var(--font-size-small); line-height: 1.5; tab-size: 4; }

/* Empty states use the shared .ui-empty-state; only the measure is this panel's. The opaque-commands
   state stands where the editor would, so it holds that field's height instead of letting the card
   collapse; the marker card's states are a single line and sit tight. */
.as-label-template-opaque { min-height: 260px; }
.as-label-template-empty { padding: var(--space-6) var(--space-4); }

.as-label-template-markers {
    display: flex; flex-wrap: wrap; gap: var(--space-2);
    margin-top: var(--space-4);
}
.as-label-template-marker {
    display: inline-flex; align-items: center; min-height: 28px;
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--color-stroke); border-radius: var(--radius-md);
    background: var(--color-surface-alt); color: var(--color-accent-text);
    font-family: var(--font-mono); font-size: var(--font-size-small);
}
.as-label-template-help > summary {
    cursor: pointer; color: var(--color-text);
    font-weight: var(--font-weight-semibold);
}
.as-label-template-help[open] > summary { margin-bottom: var(--space-3); }
.as-label-template-help ol {
    margin: 0 0 var(--space-3); padding-left: var(--space-6);
    color: var(--color-text-secondary);
}
.as-label-template-help li + li { margin-top: var(--space-2); }
.as-label-template-help code { font-family: var(--font-mono); color: var(--color-accent-text); }

.as-label-template-values {
    display: flex; flex-direction: column; gap: var(--space-3);
    margin-top: var(--space-5); padding-top: var(--space-4);
    border-top: 1px solid var(--color-stroke-subtle);
}
.as-label-template-value-row {
    display: grid; grid-template-columns: minmax(120px, 180px) minmax(0, 1fr);
    align-items: center; gap: var(--space-3);
}
.as-label-template-value-row .input-label {
    margin: 0; overflow: hidden; text-overflow: ellipsis;
    color: var(--color-text-secondary); font-family: var(--font-mono);
}
.as-label-template-value-input { width: 100%; }
.as-label-template-test-controls {
    display: flex; align-items: flex-end; gap: var(--space-3);
    margin-top: var(--space-5);
}
.as-label-template-queue-field { flex: 1 1 260px; min-width: 0; }
.as-label-template-queue-field .ui-select { width: 100%; }

@media (max-width: 620px) {
    .as-label-template-test-controls { align-items: stretch; flex-direction: column; }
    .as-label-template-value-row { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* ---- Procedure page: the staged run composition, and the label action picked in the column ----
   The Procedure detail is where a run is written, so the two shapes that are its own are the
   composition (one row per thing a run does, each row carrying the mark of the library it reaches
   for) and the marker bindings the label column opens. Everything else it wears is shared: the
   cards, the .ui-collection laid beside them, the .ui-inspector field stack inside the column and
   the .ui-grid rows in the list. */
.as-run-stages { display: flex; flex-direction: column; }
.as-stage {
    display: grid; grid-template-columns: 34px minmax(0, 1fr);
    gap: var(--space-4); padding: var(--space-4) 0;
    border-top: 1px solid var(--color-stroke-subtle);
}
.as-stage:first-child { border-top: 0; padding-top: var(--space-1); }
.as-stage:last-child { padding-bottom: 0; }

/* The library's own mark. A stage with nothing chosen keeps its place and is drawn as an outline,
   so the composition shows what a run does NOT do as plainly as what it does. */
.as-stage-mark {
    display: inline-flex; align-items: center; justify-content: center;
    align-self: start; width: 34px; height: 34px;
    border: 1px solid var(--color-stroke); border-radius: var(--radius-md);
    background: var(--color-surface-alt); color: var(--color-text-secondary);
}
.as-stage.is-unset .as-stage-mark {
    border-style: dashed; background: transparent; color: var(--color-text-disabled);
}
.as-stage-body { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.as-stage-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-1) var(--space-4); }
.as-stage-title { color: var(--color-text); font-weight: var(--font-weight-semibold); }
.as-stage-result { color: var(--color-text-secondary); font-size: var(--font-size-small); }
.as-stage.is-unset .as-stage-result { color: var(--color-text-disabled); }
.as-stage-fields {
    display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-3) var(--space-4);
}
.as-stage-fields .ui-field-stack { max-width: 300px; }
.as-stage-fields .field-description { max-width: 300px; }
.as-stage-detail { min-width: 0; }

/* The referenced recipe's own preview, at the height a consequence is read at rather than the one
   the Recipe page gives the same drawing when it is the subject of the screen. */
.as-stage-chart {
    height: 200px; overflow: hidden; border: 1px solid var(--color-stroke);
    border-radius: var(--radius-lg); background: var(--color-surface);
}

/* ---- Label actions: what the picked action opens in the column ---- */
.as-marker-verdicts { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); }
.as-marker-list {
    overflow: hidden; border: 1px solid var(--color-stroke); border-radius: var(--radius-md);
}
.as-marker-row {
    display: flex; flex-direction: column; gap: var(--space-2);
    padding: var(--space-3); border-bottom: 1px solid var(--color-stroke-subtle);
}
.as-marker-row:last-child { border-bottom: 0; }
.as-marker-row.is-review { box-shadow: inset 3px 0 0 var(--color-caution); }
.as-marker-head { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.as-marker-head code {
    min-width: 0; color: var(--color-accent-text); font-family: var(--font-mono);
    font-weight: var(--font-weight-semibold); overflow-wrap: anywhere;
}
.as-marker-head .as-pill { flex: 0 0 auto; margin-left: auto; }
.as-marker-fields {
    display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); min-width: 0;
}
.as-marker-source { flex: 1 1 190px; min-width: 0; }
.as-marker-narrow { flex: 0 1 120px; min-width: 0; }
.as-marker-fields .ui-select,
.as-marker-fields .ui-input { width: 100%; }
.as-marker-repair { align-self: flex-end; white-space: nowrap; }
.as-marker-note { color: var(--color-caution); font-size: var(--font-size-small); }
.as-marker-preserved {
    display: flex; flex-direction: column; gap: var(--space-1);
    padding: var(--space-4); border: 1px dashed var(--color-stroke);
    border-radius: var(--radius-md); color: var(--color-text-secondary);
}
.as-marker-preserved strong { color: var(--color-text); }
.as-marker-preserved-list {
    display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2);
}
.as-marker-preserved code,
.as-marker-stale-row code {
    color: var(--color-accent-text); font-family: var(--font-mono); overflow-wrap: anywhere;
}
.as-marker-stale {
    display: flex; flex-direction: column; gap: var(--space-2);
    margin-top: var(--space-4); padding-top: var(--space-4);
    border-top: 1px solid var(--color-stroke-subtle);
}
.as-marker-stale-head {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
}
.as-marker-stale-head strong { color: var(--color-text); }
.as-marker-stale-row {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    align-items: center; gap: var(--space-1) var(--space-3); padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-stroke-subtle); border-radius: var(--radius-md);
    color: var(--color-text-secondary); font-size: var(--font-size-small);
}
.as-marker-stale-row > span { grid-column: 1; }
.as-marker-stale-row > .ui-icon-btn { grid-column: 2; grid-row: 1 / span 2; }

@media (max-width: 760px) {
    .as-stage { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
    .as-stage-mark { display: none; }
    .as-stage-fields .ui-field-stack,
    .as-stage-fields .field-description { max-width: none; }
}

/* ---- Unit interlock: the preparation fold ----
   While the model's External stop switch is off, the unit's Interlock card folds its
   signal-and-polarity pair into this collapsed disclosure: nothing reads as in force, and opening
   it is how an operator prepares before the model arms. */
.as-interlock-prep { margin-top: var(--space-3); }
.as-interlock-prep-body { padding: var(--space-2) 0 var(--space-1); }

/* ---- Unit automation (Process → Unit → Settings → Automation) ----
   One PLC-facing interface per Unit: the enable switch stands on the card itself, with five
   native-<details> sections under it. Section headers reuse the shared .ui-disclosure chevron;
   content reuses the summary/pill/field vocabulary. Colour stays reserved for the live-diagnosis
   semantics. */
.as-automation-enable { display: flex; margin: var(--space-2) 0 var(--space-3); }
.as-automation-section { border-top: 1px solid var(--color-stroke-subtle); }
.as-automation-section > summary {
    padding: var(--space-4) 0;
    font-size: var(--font-size-card-title);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text);
}
.as-automation-body { padding-bottom: var(--space-5); }

.as-automation-fields { display: flex; flex-direction: column; gap: var(--space-4); }
.as-automation-required {
    margin-left: var(--space-2); color: var(--color-caution);
    font-size: var(--font-size-eyebrow); font-weight: var(--font-weight-semibold);
    text-transform: uppercase; letter-spacing: 0.06em;
}

/* Numeric selector: code → Procedure rows, with an add row hairline-split from the list. */
.as-automation-code-list { display: flex; flex-direction: column; gap: var(--space-3); }
.as-automation-code-row {
    display: grid; grid-template-columns: 110px minmax(0, 1fr) auto;
    align-items: center; gap: var(--space-3);
}
.as-automation-code-add { padding-top: var(--space-3); border-top: 1px solid var(--color-stroke-subtle); }

/* Metadata: one group per relevant Procedure. */
.as-automation-meta-group {
    margin-top: var(--space-4); padding-top: var(--space-4);
    border-top: 1px solid var(--color-stroke-subtle);
}
.as-automation-meta-group:first-of-type { margin-top: 0; padding-top: 0; border-top: 0; }
.as-automation-meta-head { margin-bottom: var(--space-3); font-weight: var(--font-weight-semibold); color: var(--color-text); }

/* Public 0–7 command-result contract. */
.as-automation-result-list {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-1) var(--space-5); margin: var(--space-2) 0 var(--space-2); padding: 0;
    list-style: none;
}
.as-automation-result-list li {
    color: var(--color-text-secondary); font-size: var(--font-size-small);
    font-variant-numeric: tabular-nums;
}

/* Live diagnosis: key/value rows reuse .as-summary-*, then per-source lines. */
.as-automation-diag-block {
    margin-top: var(--space-5); padding-top: var(--space-4);
    border-top: 1px solid var(--color-stroke-subtle);
}
.as-automation-diag-line {
    display: grid; grid-template-columns: 96px minmax(0, 1fr) auto auto;
    align-items: center; gap: var(--space-3); padding: var(--space-2) 0;
    font-size: var(--font-size-small);
}
.as-automation-diag-name { font-weight: var(--font-weight-semibold); color: var(--color-text); }
.as-automation-diag-detail {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    color: var(--color-text-secondary); font-variant-numeric: tabular-nums;
}
.as-automation-diag-reason {
    padding: 0 0 var(--space-2); color: var(--color-caution); font-size: var(--font-size-eyebrow);
}

@media (max-width: 640px) {
    .as-automation-code-row { grid-template-columns: 90px minmax(0, 1fr) auto; }
    .as-automation-result-list { grid-template-columns: 1fr; }
    .as-automation-diag-line { grid-template-columns: minmax(0, 1fr) auto; }
    .as-automation-diag-detail { grid-column: 1 / -1; white-space: normal; }
}

/* ---- Evaluation: the rule drawn, and the result each criterion declares ----
   The screen that decides what passes is about a rule and never about a run, so what it adds to the
   shared list + column is a picture of that rule (the preview standing over the picked criterion's
   own fields) and the fold that turns the criteria into one verdict. */

/* The preview stands in the inspector because it is the picked criterion's, not the evaluation's;
   shorter than the recipe's profile for the same reason, since it shares a column with the fields
   that draw it. */
.as-criterion-preview {
    height: 220px; margin-bottom: var(--space-4);
    border: 1px solid var(--color-stroke); border-radius: var(--radius-lg);
    overflow: hidden; background: var(--color-surface);
}

/* The fold: one verdict per line, its pill first, so the three read as the ordered rule they are. */
.as-verdict-fold { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-3); }
.as-verdict-rule {
    display: flex; align-items: center; gap: var(--space-3);
    color: var(--color-text-secondary); font-size: var(--font-size-description);
}
.as-verdict-rule .as-pill { flex: 0 0 auto; min-width: 104px; justify-content: center; }

/* What one criterion contributes: in its own row, and again beside the field that decides it. A
   criterion nothing could be judged from is tinted, because it is the one state the operator has to
   fix before a run rather than a choice he made. */
.as-criterion-result {
    color: var(--color-text); font-size: var(--font-size-description);
    font-weight: var(--font-weight-semibold);
}
.as-criterion-unjudged { color: var(--color-caution); }

