/* ============================================================================
   pulse-robo.css -- the robo pillar's visual system
   ----------------------------------------------------------------------------
   Targets p-* ONLY. Never bl-*.
   Per ROBO_SURFACE_DECISIONS.md section 5: bl-* is behaviour, JS binds it, and
   styling it turns a behaviour rename into a visual regression. Elements carry
   both classes; this sheet sees only the presentation half.

   Enumerated data-* values ARE styled (closed sets, specified in the contract).
   data-code, data-setting, data-step-id are addressing only and never styled.

   Load AFTER pulse-design-tokens.css. Every colour here dereferences a token;
   no hex, no rgb, per the bridge rule.
   ========================================================================= */

/* --- the two values this sheet adds, and why they are not in the token file --
   --pulse-hatch  is a wash used only by the "not a result" treatment. It is a
                  composition (a colour at an alpha inside a repeating gradient)
                  rather than a palette value, so it belongs to the component.
   --pulse-focus  is the focus ring. Named here because the token file has no
                  interaction layer; move it there if one is added, and delete
                  this block rather than keeping both.
   Everything else in this sheet dereferences pulse-design-tokens.css. If you
   find a hex or an oklch() below this comment, it is a bug. */
:root {
  /* Hover. Dereferenced, not a new literal: the raised-surface value already
     exists, and a second hex here would drift from it the first time either
     changes. Lives in this sheet rather than the token file for the same reason
     as --pulse-hatch and --pulse-focus -- it is an interaction state this
     pillar introduced, and the token file should gain it deliberately rather
     than by accident. */
  --pulse-hover: var(--pulse-well);
  /* NOTE, because it has now happened three times in this sheet: an undefined
     custom property is dropped at parse time, so the intent vanishes with no
     error and no visual clue beyond the thing simply not happening.
     --pulse-hover was missing, then --pulse-line-strong, then the value I
     dereferenced it to. The token file has exactly two line values --
     --pulse-line and --pulse-line-soft -- and nothing "strong". Before writing
     a rule that uses a --pulse-* name, confirm it exists here or in
     pulse-design-tokens.css. */
  --pulse-hatch: oklch(0.32 0.055 75 / 0.20);
  --pulse-focus: var(--pulse-teal-edge);
}

/* --- surface ------------------------------------------------------------- */

/* --- NO CONTAINER IN THIS SHEET SETS font-family -----------------------------
   A class that declares only size and colour inherits its family from whatever
   it lands in -- so it renders one way in one panel and another way in the
   next, which is the per-context drift a shared visual system exists to remove.

   .p-basis hit exactly that: mono inside .p-split, sans inside .p-panel, for
   the same semantic element. An earlier draft patched .p-split-note's family
   instead of the container, which is the tell -- patching one child of a
   family-setting container means the next child will need patching too.

   So: every class that needs a family declares it. Containers never do.
   -------------------------------------------------------------------------- */

/* --- NOTHING IN THIS SHEET REDEFINES A TOKEN-FILE CLASS ---------------------
   pulse-design-tokens.css owns a full component layer. These are ITS classes;
   use them, do not restate them here:

     p-kicker  p-panel  p-note  p-chip  p-stat__*  p-row  p-table__head
     p-table__row  p-num  p-well  p-btn  p-h1  p-h2  p-h3  p-lead  p-body
     p-dense  p-wordmark

   An earlier draft of this sheet redefined eight of them. Because a partial
   redefinition sets only type and colour, the token file's BOX cascaded
   through -- so p-note's note-card border and padding turned two inline
   captions into floating panels. That is this sheet's own contract broken
   inside the sheet that declares it.

   For inline metadata beside a value, use the token file's .p-dense. It is
   already 12.5px / --pulse-ink-2 / text-wrap:pretty, which is exactly what a
   caption needs -- so there is nothing to add.

   Collision check before adding any p-* rule below:
     for (const ss of document.styleSheets)
       for (const r of ss.cssRules) r.selectorText
   -------------------------------------------------------------------------- */

.p-page {
  background: var(--pulse-bg);
  color: var(--pulse-ink);
  font-family: var(--pulse-sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* --- the spine ----------------------------------------------------------- */
/* Five steps, always five, equal columns. A grid rather than flex-basis:
   five-across is structural, so it cannot break when a label lengthens. */

/* CD139: six columns, not five. The spine carries the six V126 operator steps
   (Audience / Script / Calling / Schedule / Rehearse / Ready); at five it wrapped
   the sixth onto its own row. */
.p-spine {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--pulse-s2);
}

.p-spine-step {
  /* display is declared here rather than inherited from the element: the
     rule previously worked only because robo's steps are <button>. Used on
     a <label> it stayed inline and the steps overlapped -- a component
     class must not depend on the tag it is used on. */
  display: flex;
  flex-direction: column;
  min-width: 0;
  text-align: left;
  font: inherit;
  color: inherit;                 /* button reset -- font:inherit does not carry colour */
  cursor: pointer;
  background: var(--pulse-well);
  border: 1px solid var(--pulse-line);
  border-top: 3px solid var(--pulse-line-soft);
  border-radius: var(--pulse-r-inner);
  padding: 10px 12px;
}
.p-spine-step:hover { filter: brightness(1.15); }

.p-spine-step[data-state="done"]    { border-top-color: var(--pulse-teal-edge); }
.p-spine-step[data-state="current"] {
  background: var(--pulse-teal-fill);
  border-color: var(--pulse-teal-edge);
  border-top-color: var(--pulse-teal);
}
.p-spine-step[data-state="next"]    { color: var(--pulse-ink-3); }

.p-spine-index { font-family: var(--pulse-mono); font-size: 9px; color: var(--pulse-ink-3); }
.p-spine-name  { font-size: 12.5px; font-weight: 600; white-space: nowrap;
                 overflow: hidden; text-overflow: ellipsis; }
.p-spine-state { font-family: var(--pulse-mono); font-size: 8.5px; letter-spacing: 0.07em;
                 color: var(--pulse-ink-3); margin-top: 5px; }
.p-spine-step[data-state="current"] .p-spine-state { color: var(--pulse-teal); }

/* --- the detour banner --------------------------------------------------- */
/* Top AND bottom. Both positions are load-bearing on a long form. */

.p-detour {
  background: var(--pulse-blue-fill);
  border: 1px solid var(--pulse-blue-edge);
  border-left: 3px solid var(--pulse-blue);
  border-radius: var(--pulse-r-inner);
  padding: 12px 14px;
}
.p-detour-reason { font-size: 13px; color: var(--pulse-blue); text-wrap: pretty; }

/* --- blocker rows -------------------------------------------------------- */

.p-blockers { display: flex; flex-direction: column; gap: var(--pulse-s2); list-style: none;
              margin: 0; padding: 0; }

.p-blocker-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) auto;
  gap: var(--pulse-s3);
  align-items: center;
  background: var(--pulse-well);
  border: 1px solid var(--pulse-line);
  border-left: 3px solid var(--pulse-line-soft);
  border-radius: var(--pulse-r-inner);
  padding: 12px 14px;
}

/* level -- a closed set, so it styles */
.p-blocker-row[data-level="block"] { border-left-color: var(--pulse-red); }
.p-blocker-row[data-level="warn"]  { border-left-color: var(--pulse-amber); }
.p-blocker-row[data-level="pass"]  { border-left-color: var(--pulse-teal); }

/* na and unproven are NOT pass. Hatched: not a result. */
.p-blocker-row[data-level="na"],
.p-blocker-row[data-level="unproven"] {
  border-left-color: var(--pulse-amber-edge);
  background-image: repeating-linear-gradient(135deg,
    var(--pulse-hatch) 0 6px, transparent 6px 13px);
}

.p-blocker-what { font-size: 13.5px; color: var(--pulse-ink); text-wrap: pretty; }
.p-blocker-say  { font-size: 12.5px; color: var(--pulse-ink-2); min-width: 0; text-wrap: pretty; }

/* the code stays visible and small -- it is what gets read down the phone */
.p-blocker-code {
  font-family: var(--pulse-mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  color: var(--pulse-ink-3);
  margin-top: 5px;
}

/* owner -- closed set */
.p-blocker-owner { font-family: var(--pulse-mono); font-size: 9px; letter-spacing: 0.08em; }
[data-owner="you"]     .p-blocker-owner, .p-blocker-owner[data-owner="you"]     { color: var(--pulse-teal); }
[data-owner="us"]      .p-blocker-owner, .p-blocker-owner[data-owner="us"]      { color: var(--pulse-violet); }
[data-owner="client"]  .p-blocker-owner, .p-blocker-owner[data-owner="client"]  { color: var(--pulse-blue); }
[data-owner="carrier"] .p-blocker-owner, .p-blocker-owner[data-owner="carrier"] { color: var(--pulse-ink-3); }

/* freshness -- an age never renders without its budget */
.p-blocker-age { font-family: var(--pulse-mono); font-size: 9px; color: var(--pulse-ink-3); }
.p-blocker-age[data-stale="true"] { color: var(--pulse-amber); }

/* reach -- decides whether a fix control renders at all */
.p-blocker-row[data-reach="no_surface"]    .p-btn,
.p-blocker-row[data-reach="wrong_surface"] .p-btn { display: none; }
.p-blocker-row[data-reach="trackable"]     .p-btn { display: none; }

.p-blocker-noreach { font-family: var(--pulse-mono); font-size: 9px; letter-spacing: 0.08em;
                     color: var(--pulse-ink-3); }

/* the na summary line must not read as a pass */
.p-na-summary {
  font-size: 12px;
  color: var(--pulse-ink-2);
  border-left: 2px solid var(--pulse-amber-edge);
  padding-left: 10px;
  background-image: repeating-linear-gradient(135deg,
    var(--pulse-hatch) 0 6px, transparent 6px 13px);
}

/* --- verdict ------------------------------------------------------------- */

.p-verdict { display: flex; align-items: baseline; gap: var(--pulse-s3); flex-wrap: wrap; }
.p-verdict-word { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
.p-verdict[data-verdict="blocked"] .p-verdict-word { color: var(--pulse-chip-red-ink); }
.p-verdict[data-verdict="ready"]   .p-verdict-word { color: var(--pulse-teal); }
.p-verdict[data-verdict="warn"]    .p-verdict-word { color: var(--pulse-amber); }

/* --- control outcomes ---------------------------------------------------- */
/* Adjacent to its control, never a centred modal -- that position belongs to a
   PRE-action confirmation, and two opposite meanings in one place is the
   catalogued defect. */

.p-outcome {
  font-size: 12.5px;
  border-radius: var(--pulse-r-inner);
  padding: 0;
}
.p-outcome[data-outcome="idle"] { display: none; }

.p-outcome[data-outcome="pending"] {
  padding: 9px 12px;
  background: var(--pulse-well);
  border: 1px solid var(--pulse-line);
  color: var(--pulse-ink-2);
}
.p-outcome[data-outcome="acted"] {
  padding: 9px 12px;
  background: var(--pulse-teal-fill);
  border: 1px solid var(--pulse-teal-edge);
  color: var(--pulse-chip-teal-ink);
}
.p-outcome[data-outcome="refused"],
.p-outcome[data-outcome="unavailable"] {
  padding: 11px 13px;
  background: var(--pulse-red-fill);
  border: 1px solid var(--pulse-red-edge);
  color: var(--pulse-chip-red-ink);
}
/* unknown is neither success nor failure and must not borrow either colour */
.p-outcome[data-outcome="unknown"] {
  padding: 11px 13px;
  background: var(--pulse-amber-fill);
  border: 1px solid var(--pulse-amber-edge);
  color: var(--pulse-chip-amber-ink);
  background-image: repeating-linear-gradient(135deg,
    var(--pulse-hatch) 0 6px, transparent 6px 13px);
}

/* a bound always accompanies a pending indicator -- when one exists */
.p-outcome-bound { font-family: var(--pulse-mono); font-size: 10px; color: var(--pulse-ink-3); }

/* --- the six-field refusal ----------------------------------------------- */
/* specific_cause is never behind a disclosure that defaults closed. */

.p-refusal { display: flex; flex-direction: column; gap: 7px; }
.p-refusal-cause { font-size: 13px; color: var(--pulse-ink); text-wrap: pretty; }
.p-refusal-class { font-family: var(--pulse-mono); font-size: 9.5px; letter-spacing: 0.06em;
                   color: var(--pulse-ink-3); }
.p-refusal-meta  { display: flex; flex-wrap: wrap; gap: var(--pulse-s3);
                   border-top: 1px solid var(--pulse-line); padding-top: 8px; }
.p-refusal-k { font-family: var(--pulse-mono); font-size: 8.5px; letter-spacing: 0.09em;
               color: var(--pulse-ink-3); }
.p-refusal-v { font-size: 12px; color: var(--pulse-ink-2); }
/* effect is the field that matters -- what was and was not done to the work */
.p-refusal-effect { font-size: 12.5px; color: var(--pulse-ink); font-weight: 500; }

/* --- consequences -------------------------------------------------------- */
/* A DIFFERENT COMPONENT from help, not the same one with a flag. If they
   differed by a boolean somebody would eventually tag a fee warning as help. */

.p-consequence {
  background: var(--pulse-red-fill);
  border: 1px solid var(--pulse-red-edge);
  border-radius: var(--pulse-r-inner);
  padding: 13px 15px;
}
.p-consequence-kicker { font-family: var(--pulse-mono); font-size: 9px; letter-spacing: 0.10em;
                        color: var(--pulse-chip-red-ink); }
.p-consequence-text { font-size: 13px; color: var(--pulse-chip-red-ink); margin-top: 7px;
                      text-wrap: pretty; }

/* --- explanation: absent when off, never collapsed ---------------------- */

.p-help { display: none; }
[data-explain="on"] .p-help {
  display: block;
  font-size: 12px;
  color: var(--pulse-blue);
  border-left: 2px solid var(--pulse-blue-edge);
  padding-left: 10px;
}

/* --- forms --------------------------------------------------------------- */
/* One column. A two-column form has no reading order, so it cannot express
   "this before that". */

.p-form  { display: flex; flex-direction: column; gap: var(--pulse-s4); max-width: 620px; }
.p-field { display: flex; flex-direction: column; gap: 6px; }

.p-label { font-size: 12.5px; font-weight: 500; color: var(--pulse-ink); }
.p-field[data-required="true"] .p-label::after {
  content: " *"; color: var(--pulse-amber);
}

.p-input, .p-select, .p-textarea {
  font-family: var(--pulse-sans);
  font-size: 13.5px;
  color: var(--pulse-ink);
  background: var(--pulse-well);
  border: 1px solid var(--pulse-line);
  border-radius: var(--pulse-r-inner);
  padding: 9px 11px;
  width: 100%;
  box-sizing: border-box;
}
.p-input:focus, .p-select:focus, .p-textarea:focus {
  outline: 2px solid var(--pulse-focus);
  outline-offset: 1px;
  border-color: var(--pulse-focus);
}
.p-field[data-state="error"] .p-input,
.p-field[data-state="error"] .p-select,
.p-field[data-state="error"] .p-textarea { border-color: var(--pulse-red-edge); }

.p-field-error { font-size: 12px; color: var(--pulse-chip-red-ink); text-wrap: pretty; }
.p-field-help  { font-size: 12px; color: var(--pulse-ink-3); text-wrap: pretty; }

.p-form-actions { display: flex; flex-direction: column; gap: var(--pulse-s2);
                  align-items: flex-start; }

/* --- the financial cell -------------------------------------------------- */
/* Distinguished, not decorated. An operator editing it must know the class of
   thing they are editing. */

.p-cell--financial {
  border-left: 2px solid var(--pulse-violet);
  background: var(--pulse-violet-fill);
}
.p-cell--financial[data-value-state="unclassified"] {
  color: var(--pulse-chip-amber-ink);
  font-style: italic;
}

/* --- tables at volume ---------------------------------------------------- */

/* The volume table's own header: it carries data-count-basis, which the token
   file's .p-table__head has no concept of. Different name, no collision. */
.p-table-header { display: flex; align-items: baseline; gap: var(--pulse-s3); flex-wrap: wrap;
                  padding-bottom: 10px; border-bottom: 1px solid var(--pulse-line); }
.p-count { font-size: 14px; color: var(--pulse-ink); font-variant-numeric: tabular-nums; }
.p-table-header[data-count-basis="estimated"] .p-count { color: var(--pulse-ink-2); }
.p-table-header[data-count-basis="unknown"]   .p-count { color: var(--pulse-chip-amber-ink); }

.p-th  { font-family: var(--pulse-mono); font-size: 8.5px; letter-spacing: 0.09em;
         text-transform: uppercase; color: var(--pulse-ink-3); text-align: left; }
.p-cell { font-size: 13px; color: var(--pulse-ink); min-width: 0; }

.p-sort { cursor: pointer; }
.p-sort[data-sort-cost="unavailable"] { cursor: default; color: var(--pulse-ink-3); }
.p-sort[data-sort-cost="slow"]::after { content: " (slow)"; font-size: 8px; }

.p-pager { display: flex; align-items: center; gap: var(--pulse-s3); padding-top: 12px; }

/* --- stages (data tab) --------------------------------------------------- */

.p-stage { border: 1px solid var(--pulse-line); border-radius: var(--pulse-r-inner);
           background: var(--pulse-well); padding: 13px 15px; }
.p-stage[data-stage-state="current"] { border-color: var(--pulse-teal-edge);
                                       background: var(--pulse-teal-fill); }
.p-stage[data-stage-state="next"]    { color: var(--pulse-ink-3); }
.p-stage[data-stage-state="blocked"] { border-left: 3px solid var(--pulse-amber-edge); }
.p-stage-result { font-size: 12.5px; color: var(--pulse-ink-2); }

/* --- empty states -------------------------------------------------------- */

.p-empty { padding: 28px 22px; text-align: center; }
.p-empty-head { font-size: 15px; font-weight: 600; color: var(--pulse-ink); }
.p-empty-body { font-size: 12.5px; color: var(--pulse-ink-2); margin-top: 8px; text-wrap: pretty; }
.p-empty[data-empty-reason="load_failed"]  .p-empty-head { color: var(--pulse-chip-red-ink); }
.p-empty[data-empty-reason="all_rejected"] .p-empty-head { color: var(--pulse-chip-amber-ink); }

/* --- the funnel (data tab) ----------------------------------------------- */

.p-funnel { display: flex; flex-direction: column; gap: 6px; font-size: 12px; }
.p-funnel-row { display: grid; grid-template-columns: 92px minmax(0,1fr) auto; gap: var(--pulse-s3);
                align-items: baseline; }
.p-funnel-n { font-family: var(--pulse-mono); text-align: right;
              font-variant-numeric: tabular-nums; color: var(--pulse-ink); }
.p-funnel-why { font-family: var(--pulse-sans); font-size: 12px; color: var(--pulse-ink-2); }
.p-funnel-row[data-attributable="you"] .p-funnel-why { color: var(--pulse-chip-amber-ink); }
.p-funnel-total { border-top: 1px solid var(--pulse-line); padding-top: 7px; font-weight: 600; }

/* ============================================================================
   RUN SCREEN. robo_run only. Names checked against pulse-design-tokens.css --
   no collisions. See ROBO_RUN_SPEC.md.
   ========================================================================= */

/* worker liveness -- renders even when healthy, because its absence is the one
   condition under which every other number keeps looking fine */
.p-worker { border-radius: var(--pulse-r-inner); padding: 11px 14px;
            display: flex; align-items: baseline; gap: var(--pulse-s3); flex-wrap: wrap; }
.p-worker[data-worker="alive"] { background: var(--pulse-well);
  border: 1px solid var(--pulse-line-soft); color: var(--pulse-ink-2); font-size: 12.5px; }
.p-worker[data-worker="dead"]  { background: var(--pulse-red-fill);
  border: 1px solid var(--pulse-red-edge); color: var(--pulse-chip-red-ink); }
.p-worker-head { font-size: 15px; font-weight: 600; }
.p-worker[data-worker="alive"] .p-worker-head { font-size: 12.5px; font-weight: 400; }

/* the four outcome counts */
.p-outcomes { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
              gap: var(--pulse-s3); }
.p-outcome-count { background: var(--pulse-well); border: 1px solid var(--pulse-line-soft);
                   border-radius: var(--pulse-r-inner); padding: 12px 14px; }
.p-outcome-n { font-size: var(--pulse-t-stat); font-weight: 600;
               letter-spacing: var(--pulse-track-stat); font-variant-numeric: tabular-nums; }
.p-outcome-k { font-family: var(--pulse-mono); font-size: 9px;
               letter-spacing: var(--pulse-track-kicker); color: var(--pulse-ink-3); }
.p-outcome-how { font-size: 11.5px; color: var(--pulse-ink-3); margin-top: 4px; text-wrap: pretty; }

/* unknown is not a failure and does not borrow the failure colour. Hatched,
   because it is a verdict the detector could not reach. */
.p-outcome-count[data-outcome-kind="unknown"] {
  border-color: var(--pulse-amber-edge);
  background-image: repeating-linear-gradient(135deg,
    var(--pulse-hatch) 0 6px, transparent 6px 13px);
}
.p-outcome-count[data-outcome-kind="unknown"] .p-outcome-n { color: var(--pulse-chip-amber-ink); }

/* the basis clause travels with every machine figure -- mode AND rule */
.p-basis { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-3);
            text-wrap: pretty; }
.p-basis--inflated { color: var(--pulse-chip-amber-ink); }

/* a figure spanning a boundary splits rather than averaging */
/* No font-family on the container -- see the rule above. .p-split-n carries the
   mono the figures want; everything else keeps its own. */
.p-split { display: grid; grid-template-columns: auto auto minmax(0,1fr); gap: var(--pulse-s3);
           font-size: 12px; align-items: baseline; }
.p-split-n { font-family: var(--pulse-mono); font-variant-numeric: tabular-nums;
             color: var(--pulse-ink); }
.p-split-of { font-family: var(--pulse-mono); color: var(--pulse-ink-2); }
.p-split-note { font-family: var(--pulse-sans); font-size: 11.5px;
                color: var(--pulse-chip-amber-ink); }

/* rate: set and observed, both always */
.p-rate { display: flex; align-items: baseline; gap: var(--pulse-s5); flex-wrap: wrap; }
.p-rate-n { font-size: var(--pulse-t-stat); font-weight: 600;
            letter-spacing: var(--pulse-track-stat); font-variant-numeric: tabular-nums; }
.p-rate[data-rate-known="false"] .p-rate-n { color: var(--pulse-chip-amber-ink); }
.p-rate-source { font-size: 11.5px; color: var(--pulse-ink-3); }

/* goal -- the basis is named, never implied */
.p-goal-bar { height: 6px; border-radius: 3px; background: var(--pulse-line);
              overflow: hidden; margin-top: var(--pulse-s2); }
.p-goal-fill { height: 100%; background: var(--pulse-teal); }
.p-goal[data-below-floor="true"] .p-goal-bar { display: none; }

/* run controls. Pace is an operating adjustment; pause and stop suspend work.
   Three adjacent equal buttons is how an operator stops a run they meant to
   slow, so stop is separated and takes the danger treatment. */
.p-run-controls { display: flex; align-items: center; gap: var(--pulse-s3); flex-wrap: wrap; }
.p-run-controls .p-run-sep { flex: 1 1 var(--pulse-s6); min-width: var(--pulse-s6); }

/* A fee-bearing FIELD. The volume table has .p-cell--financial for a table
   cell; this is the form equivalent. Distinguished, not decorated -- an
   operator must know the class of thing they are editing. */
.p-field--financial { border-left: 2px solid var(--pulse-violet);
                      padding-left: var(--pulse-s3); }

/* the repeater's step. p-step is not in the token file -- checked. */
.p-step { padding: 13px 15px; }
.p-repeater { margin: 0; padding: 0; }

/* ============================================================================
   OVERVIEW / FILES / SETTINGS. See ROBO_REMAINING_TABS_SPEC.md.
   Every class here declares its own font-family -- no container sets one.
   ========================================================================= */

/* identity strip -- read-only, all nine fields, every time */
.p-strip { background: var(--pulse-panel); border: 1px solid var(--pulse-line);
           border-radius: var(--pulse-r-panel); padding: var(--pulse-s4) var(--pulse-s5); }
.p-strip-num { font-family: var(--pulse-mono); font-size: 11px;
               letter-spacing: 0.06em; color: var(--pulse-ink-3); }
.p-strip-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
                 gap: var(--pulse-s4); margin-top: var(--pulse-s4);
                 padding-top: var(--pulse-s4); border-top: 1px solid var(--pulse-line-soft); }
.p-strip-fact { min-width: 0; }
.p-strip-v { font-family: var(--pulse-sans); font-size: 15px; font-weight: 500;
             color: var(--pulse-ink); margin-top: 3px; text-wrap: pretty; }
/* an absent value is stated, never blank -- a clientless robo project is the
   common case, so an empty cell would read as missing data */
.p-strip-v--absent { color: var(--pulse-ink-3); font-weight: 400; }

/* files -- "used by" carries two different absences */
.p-cell--absent  { font-family: var(--pulse-sans); color: var(--pulse-chip-amber-ink); }
.p-cell--unknown { font-family: var(--pulse-sans); color: var(--pulse-ink-3);
                   background-image: repeating-linear-gradient(135deg,
                     var(--pulse-hatch) 0 6px, transparent 6px 13px); }

/* empty states. Three kinds, and "loaded and all rejected" must not look like
   "nothing loaded" -- they demand opposite actions. */
.p-empty { background: var(--pulse-well); border: 1px solid var(--pulse-line-soft);
           border-radius: var(--pulse-r-panel); padding: var(--pulse-s5);
           display: flex; flex-direction: column; gap: var(--pulse-s2);
           align-items: flex-start; }
.p-empty-head { font-family: var(--pulse-sans); font-size: 15px; font-weight: 600;
                color: var(--pulse-ink); }
.p-empty-body { font-family: var(--pulse-sans); font-size: 12.5px;
                color: var(--pulse-ink-2); text-wrap: pretty; }
.p-empty--rejected { border-color: var(--pulse-red-edge); background: var(--pulse-red-fill); }
.p-empty--rejected .p-empty-head { color: var(--pulse-chip-red-ink); }
.p-empty--unknown { border-color: var(--pulse-amber-edge);
                    background-image: repeating-linear-gradient(135deg,
                      var(--pulse-hatch) 0 6px, transparent 6px 13px); }

/* settings -- permanent and reversible never share a section */
.p-fieldset { border: 0; padding: 0; margin: 0 0 var(--pulse-s5); }
.p-legend { font-family: var(--pulse-mono); font-size: 9px;
            letter-spacing: var(--pulse-track-kicker); color: var(--pulse-ink-3);
            padding: 0 0 var(--pulse-s3); }
.p-fieldset[data-kind="permanent"] { border-left: 2px solid var(--pulse-red-edge);
                                     padding-left: var(--pulse-s4); }
.p-fieldset[data-kind="permanent"] .p-legend { color: var(--pulse-chip-red-ink); }

/* A panel whose direct children are sections rather than one flow. Use it
   wherever a .p-kicker sits as a SIBLING of a block child -- a form, a table, a
   div. Without it the kicker touches whatever follows, because .p-panel has
   padding and no gap, and relying on the next element's own padding-top is how
   #roboCallerId's heading merged into its first field label.
   Does not redefine .p-panel; adds to it. */
.p-panel--stack { display: flex; flex-direction: column; gap: var(--pulse-s3); }

/* ============================================================================
   NAV DESTINATIONS. See ROBO_NAV_PAGES_SPEC.md. Every class declares its own
   font-family; no container sets one.
   ========================================================================= */

/* NEEDS YOU -- exception-first. An empty top is a reading, so the cleared
   state renders a sentence rather than nothing at all. */
.p-needs { background: var(--pulse-panel); border: 1px solid var(--pulse-line);
           border-radius: var(--pulse-r-panel); padding: var(--pulse-s4) var(--pulse-s5);
           display: flex; flex-direction: column; gap: var(--pulse-s2); }
.p-needs[data-count="0"] { border-color: var(--pulse-line-soft); background: var(--pulse-well); }
.p-needs-clear { font-family: var(--pulse-sans); font-size: 13px; color: var(--pulse-ink-2); }
.p-need-row { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.6fr) 104px;
              gap: var(--pulse-s3); align-items: baseline; text-decoration: none;
              padding: var(--pulse-s3) 0; border-top: 1px solid var(--pulse-line-soft); }
.p-need-row:hover { background: var(--pulse-hover); }
.p-need-row:hover .p-need-what { text-decoration: underline;
                                 text-decoration-thickness: 1px;
                                 text-underline-offset: 2px; }
.p-need-what { font-family: var(--pulse-sans); font-size: 13.5px; font-weight: 500;
               color: var(--pulse-ink); }
.p-need-say  { font-family: var(--pulse-sans); font-size: 12.5px; color: var(--pulse-ink-2);
               text-wrap: pretty; }
.p-need-owner { font-family: var(--pulse-mono); font-size: 9px;
                letter-spacing: var(--pulse-track-kicker); text-align: right; }
.p-need-owner[data-owner="you"]     { color: var(--pulse-teal); }
.p-need-owner[data-owner="us"]      { color: var(--pulse-violet); }
.p-need-owner[data-owner="carrier"] { color: var(--pulse-ink-3); }

/* DIALLING NOW -- rate with its source inside, never a headroom percentage */
.p-run-row { display: grid; grid-template-columns: minmax(0,1.2fr) minmax(0,1fr) minmax(0,1.1fr);
             gap: var(--pulse-s4); align-items: baseline; padding: var(--pulse-s3) 0;
             border-top: 1px solid var(--pulse-line-soft); }
.p-run-name { font-family: var(--pulse-sans); font-size: 14px; font-weight: 500;
              color: var(--pulse-ink); }
.p-run-nums, .p-run-rate { display: flex; align-items: baseline; gap: var(--pulse-s2);
                           flex-wrap: wrap; }
.p-run-n { font-family: var(--pulse-mono); font-size: 18px; font-variant-numeric: tabular-nums;
           color: var(--pulse-ink); }
.p-run-n--flagged { color: var(--pulse-chip-amber-ink); }
.p-dense--flagged { color: var(--pulse-chip-amber-ink); }

/* PROJECTS -- the Needs count is deduped rows, not failing checks */
.p-cell-sub { font-family: var(--pulse-mono); font-size: 9.5px; color: var(--pulse-ink-3);
              margin-top: 2px; }
.p-needs-count { font-family: var(--pulse-mono); font-size: 12px; font-weight: 500;
                 padding: 2px 8px; border-radius: 999px;
                 background: var(--pulse-amber-fill); color: var(--pulse-chip-amber-ink);
                 border: 1px solid var(--pulse-amber-edge); }

/* THE REGISTER -- one preflight, two readings. The note is on the page so a
   reviewer can see WHICH register a rendering belongs to. */
.p-register-note { display: flex; align-items: baseline; gap: var(--pulse-s3);
                   flex-wrap: wrap; padding: var(--pulse-s3) var(--pulse-s4);
                   border-radius: var(--pulse-r-inner); background: var(--pulse-well);
                   border: 1px solid var(--pulse-line-soft); }
.p-register-note[data-register="client"] { border-color: var(--pulse-blue-edge);
                                           background: var(--pulse-blue-fill); }

/* HELD -- a client sees the count and not the detail. Quiet, because it is
   deliberately not actionable by them. */
.p-blocker-row[data-level="held"] { border-left-color: var(--pulse-line); }
.p-blocker-row[data-level="held"] .p-blocker-what { color: var(--pulse-ink-2); }
.p-blocker-owner[data-owner="carrier"] { color: var(--pulse-ink-3); }

/* ============================================================================
   CLIENT DELIVERABLES. See CLIENT_DELIVERABLES_SPEC.md. Every class declares
   its own font-family; no container sets one.
   ========================================================================= */

.p-lede { font-family: var(--pulse-sans); font-size: 14px; color: var(--pulse-ink-2);
          margin: var(--pulse-s2) 0 0; text-wrap: pretty; }

/* THE LIST AS STACKED BOXES. A seven-column table with three controls crammed
   into the last cell reads as a grid to scan -- but this page is a set of
   things to take, not data to compare. One box per project, three zones:
   what it is, what it did, what you can have.

   The columns' order is preserved as reading order rather than as columns. */
.p-deliv-bar { display: flex; align-items: center; gap: var(--pulse-s4);
               flex-wrap: wrap; }
/* Three pills, one control, no sort row. Active and Complete on by default;
   Billed off. The pill is the only boxed thing in the bar -- an earlier draft
   had a row of grey sort buttons offering the ordering the page always wants,
   which is furniture with an affordance on it. */
.p-deliv-pills { display: flex; align-items: center; gap: var(--pulse-s2); flex-wrap: wrap; }
.p-pill { font-family: var(--pulse-sans); font-size: 12.5px; padding: 6px 14px;
          border-radius: 999px; cursor: pointer;
          background: transparent; border: 1px solid var(--pulse-line);
          color: var(--pulse-ink-3); }
.p-pill:hover { border-color: var(--pulse-teal-edge); color: var(--pulse-ink-2); }
.p-pill[aria-pressed="true"] { background: var(--pulse-teal-fill);
                               border-color: var(--pulse-teal-edge);
                               color: var(--pulse-chip-teal-ink); }





.p-deliv-list { list-style: none; margin: 0; padding: 0;
                display: flex; flex-direction: column; gap: var(--pulse-s3);
                container-type: inline-size; container-name: deliv; }

/* Two rows. Identity spans the card; detail sits underneath in three columns.
   An earlier draft had all four zones on one row, and every fix moved the
   shortfall somewhere else -- first the date wrapped, then the status pill,
   then the project name. A name competing with controls for width will always
   lose to the next longer name. */
.p-deliv-item { background: var(--pulse-panel); border: 1px solid var(--pulse-line);
                border-radius: var(--pulse-r-panel); padding: var(--pulse-s4) var(--pulse-s5);
                display: grid; column-gap: var(--pulse-s5); row-gap: var(--pulse-s3);
                grid-template-columns: minmax(0, 1fr) max-content auto;
                align-items: center; }
.p-deliv-item:hover { border-color: var(--pulse-teal-edge); background: var(--pulse-hover); }

.p-deliv-ids { min-width: 0; }
/* Row 1: the name and its state, across the whole card. */
.p-deliv-head { grid-column: 1 / -1; display: flex; align-items: baseline;
                gap: var(--pulse-s3); flex-wrap: wrap; }
.p-deliv-state { display: flex; align-items: baseline; gap: var(--pulse-s2);
                 flex-wrap: wrap; flex: none; }
.p-deliv-name { font-family: var(--pulse-sans); font-size: 15.5px; font-weight: 600;
                letter-spacing: -0.015em; color: var(--pulse-ink); text-wrap: pretty;
                min-width: 0; }

/* Status sits on the NAME line as a pill, not in the mono ID line. It was
   legible there and read as metadata -- the person who asked for it scanned
   past it, which is the only test that counts. Invoiced follows it, because
   the two are both state and belong together. */
.p-deliv-pill { font-family: var(--pulse-mono); font-size: 9.5px; font-weight: 500;
                letter-spacing: 0.07em; text-transform: uppercase; white-space: nowrap;
                padding: 3px 9px; border-radius: 999px; flex: none;
                background: var(--pulse-well); border: 1px solid var(--pulse-line);
                color: var(--pulse-ink-2); }
.p-deliv-pill[data-status="active"]   { background: var(--pulse-teal-fill);
                                        border-color: var(--pulse-teal-edge);
                                        color: var(--pulse-chip-teal-ink); }
.p-deliv-pill[data-status="invoiced"]   { background: var(--pulse-violet-fill);
                                        border-color: var(--pulse-violet);
                                        color: var(--pulse-violet); }
.p-deliv-ids { display: flex; align-items: baseline; gap: var(--pulse-s2);
               flex-wrap: wrap; margin-top: 4px;
               font-family: var(--pulse-mono); font-size: 10px; color: var(--pulse-ink-3); }
.p-deliv-sep { color: var(--pulse-ink-3); }

.p-deliv-figures { display: grid; grid-template-columns: repeat(3, max-content);
                   column-gap: var(--pulse-s5); align-items: baseline;
                   justify-content: start; min-width: 0; }
.p-deliv-fig { min-width: 0; }
/* nowrap belongs here, not on the column: a figure is a single value and
   breaking one across lines makes the same field render differently card to
   card depending on whether the day has one digit or two. */
.p-deliv-fig-v { font-family: var(--pulse-sans); font-size: 14px; font-weight: 500;
                 color: var(--pulse-ink); margin-top: 3px; white-space: nowrap; }
.p-deliv-fig-v--num { font-family: var(--pulse-mono); font-variant-numeric: tabular-nums; }

/* One box per card -- View. The downloads are links, not grey boxes: three
   boxed controls per row made the card a toolbar, and the file affordance
   comes from the extension tag rather than from a border. */
.p-deliv-actions { display: flex; align-items: center; gap: var(--pulse-s4);
                   flex-wrap: wrap; justify-content: flex-end; }
.p-dl { display: inline-flex; align-items: center; gap: var(--pulse-s2);
        font-family: var(--pulse-sans); font-size: 12.5px; text-decoration: none;
        color: var(--pulse-ink-2); white-space: nowrap; }
.p-dl:hover { color: var(--pulse-ink); }
.p-dl:hover .p-dl-ext { border-color: var(--pulse-teal-edge);
                        color: var(--pulse-chip-teal-ink); }
.p-dl-ext { font-family: var(--pulse-mono); font-size: 8.5px; letter-spacing: 0.08em;
            padding: 2px 5px; border-radius: 3px; border: 1px solid var(--pulse-line);
            color: var(--pulse-ink-3); }

/* NARROW. The box already is the narrow layout -- it only needs to stop being
   three columns, which is a grid change rather than a different component.
   That is the argument for boxes at every width: one layout, not two. */
/* Keyed on the LIST's width, not the viewport's. The card is constrained by
   its container, and a shell rail makes those two numbers differ by 268px --
   at a 1000px viewport behind a rail this list is ~700px wide, where the old
   viewport query had not fired and the figures were already overflowing. */
/* Behind a rail the list is ~608px. ids and figures still fit side by side --
   only the controls need their own row, so the card is three rows rather than
   four and stays 30% shorter than a full stack. */
@container deliv (max-width: 760px) {
  .p-deliv-item { grid-template-columns: minmax(0, 1fr) max-content; }
  .p-deliv-actions { grid-column: 1 / -1; justify-content: flex-start;
                     padding-top: var(--pulse-s2);
                     border-top: 1px solid var(--pulse-line-soft); }
}
/* Only here does everything stack. */
@container deliv (max-width: 440px) {
  .p-deliv-item { grid-template-columns: minmax(0, 1fr); align-items: stretch; }
  .p-deliv-actions { justify-content: stretch; }
  .p-deliv-actions .p-btn { flex: 1 1 auto; justify-content: center; }
}
/* Engines without container queries: the same break on viewport, which is
   correct with no rail and conservative with one. */
@supports not (container-type: inline-size) {
  @media (max-width: 1040px) {
    .p-deliv-item { grid-template-columns: minmax(0, 1fr) max-content; }
    .p-deliv-actions { grid-column: 1 / -1; justify-content: flex-start;
                       padding-top: var(--pulse-s2);
                       border-top: 1px solid var(--pulse-line-soft); }
  }
}

/* ============================================================================
   MOVING AGENTS BETWEEN LIVE CAMPAIGNS. See AGENT_REALLOCATION_SPEC.md.
   ========================================================================= */

/* Status counts, each stating its move class -- the only question the screen
   asks is whether an agent can be moved. */
.p-status-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
                gap: var(--pulse-s2); }
.p-status-cell { background: var(--pulse-well); border: 1px solid var(--pulse-line-soft);
                 border-left: 3px solid var(--pulse-line); border-radius: var(--pulse-r-inner);
                 padding: 10px 12px; }
.p-status-cell[data-move="now"]  { border-left-color: var(--pulse-teal); }
.p-status-cell[data-move="wrap"] { border-left-color: var(--pulse-blue); }
.p-status-cell[data-move="no"]   { border-left-color: var(--pulse-line); }
.p-status-n { font-family: var(--pulse-mono); font-size: 19px;
              font-variant-numeric: tabular-nums; color: var(--pulse-ink); margin-top: 3px; }
.p-status-move { font-family: var(--pulse-sans); font-size: 11px; margin-top: 2px; }
.p-status-cell[data-move="now"]  .p-status-move { color: var(--pulse-chip-teal-ink); }
.p-status-cell[data-move="wrap"] .p-status-move { color: var(--pulse-blue); }
.p-status-cell[data-move="no"]   .p-status-move { color: var(--pulse-ink-3); }

.p-select-bar { display: flex; align-items: center; gap: var(--pulse-s2); flex-wrap: wrap; }

/* THE GRID. Status squares rather than photographs: 3,842 faces is the wrong
   information at this density and a real page-load cost for a figure the
   manager cannot act on. Identity lives on hover and in the selection list. */
.p-agent-grid { display: grid; grid-template-columns: repeat(auto-fill, 14px);
                gap: 3px; justify-content: space-between; }
.p-cell { width: 14px; height: 14px; padding: 0; border-radius: 3px; cursor: pointer;
          border: 1px solid transparent; }
.p-cell[data-status="available"] { background: var(--pulse-teal); }
.p-cell[data-status="wrap"]      { background: oklch(0.62 0.09 172); }
.p-cell[data-status="oncall"]    { background: var(--pulse-blue); }
.p-cell[data-status="break"]     { background: oklch(0.42 0.03 210); }
.p-cell[data-status="training"]  { background: var(--pulse-violet); }
.p-cell[data-status="offline"]   { background: oklch(0.30 0.014 215);
                                   border-color: var(--pulse-line); }
/* cannot-move cells are hatched: not a severity, a different kind of thing */
.p-cell[data-move="no"] { background-image: repeating-linear-gradient(135deg,
  oklch(0.55 0.01 215 / 0.55) 0 2px, transparent 2px 4px); }
.p-cell[aria-pressed="true"] { outline: 2px solid var(--pulse-ink);
                               outline-offset: 1px; }
.p-cell:hover { filter: brightness(1.35); }

.p-legend { display: flex; flex-wrap: wrap; gap: var(--pulse-s4); }
.p-legend-item { display: inline-flex; align-items: center; gap: var(--pulse-s2);
                 font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-2); }
.p-legend-sw { width: 11px; height: 11px; border-radius: 3px; flex: none; }
.p-legend-sw[data-status="available"] { background: var(--pulse-teal); }
.p-legend-sw[data-status="oncall"]    { background: var(--pulse-blue); }
.p-legend-sw[data-status="wrap"]      { background: oklch(0.62 0.09 172); }
.p-legend-sw[data-status="offline"]   { background: oklch(0.30 0.014 215);
  background-image: repeating-linear-gradient(135deg,
    oklch(0.55 0.01 215 / 0.55) 0 2px, transparent 2px 4px); }

/* The split, stated BEFORE confirming -- selecting a mix of move classes and
   seeing one number is how a manager believes 208 moved when 96 did. */
.p-split-classes { display: flex; flex-direction: column; gap: var(--pulse-s2); }
.p-split-class { display: flex; align-items: baseline; gap: var(--pulse-s3);
                 padding: 9px 12px; border-radius: var(--pulse-r-inner);
                 background: var(--pulse-well); border: 1px solid var(--pulse-line-soft);
                 border-left: 3px solid var(--pulse-line);
                 font-family: var(--pulse-sans); font-size: 12.5px; color: var(--pulse-ink-2); }
.p-split-class[data-move="now"]  { border-left-color: var(--pulse-teal); }
.p-split-class[data-move="wrap"] { border-left-color: var(--pulse-blue); }
.p-split-class-n { font-family: var(--pulse-mono); font-size: 17px;
                   font-variant-numeric: tabular-nums; color: var(--pulse-ink); }

/* BOTH campaigns. A move is a transfer, and a screen showing only the
   destination is reassuring while the source breaches. */
.p-transfer { display: grid; gap: var(--pulse-s2); }
.p-transfer-side { padding: 11px 13px; border-radius: var(--pulse-r-inner);
                   background: var(--pulse-well); border: 1px solid var(--pulse-line-soft); }
.p-transfer-side[data-side="from"] { border-left: 3px solid var(--pulse-amber-edge); }
.p-transfer-side[data-side="to"]   { border-left: 3px solid var(--pulse-teal); }
.p-transfer-name { font-family: var(--pulse-sans); font-size: 13.5px; font-weight: 600;
                   color: var(--pulse-ink); margin-top: 3px; }
.p-transfer-count { font-family: var(--pulse-mono); font-size: 12.5px;
                    font-variant-numeric: tabular-nums; color: var(--pulse-ink-2);
                    margin-top: 4px; }
.p-transfer-arrow { color: var(--pulse-ink-3); }

/* WHY MOVE THEM -- the first axis. Status says whether an agent CAN move;
   this says whether they SHOULD, and an agent stranded on a finished campaign
   is invisible in a status grid because they look exactly like a busy one. */
.p-reason-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
                gap: var(--pulse-s2); }
.p-reason { display: grid; gap: 3px; text-align: left; cursor: pointer;
            padding: 11px 13px; border-radius: var(--pulse-r-inner);
            background: var(--pulse-well); border: 1px solid var(--pulse-line);
            border-left: 3px solid var(--pulse-line); color: inherit; font: inherit; }
.p-reason:hover { background: var(--pulse-hover); }
.p-reason[aria-pressed="true"] { border-color: var(--pulse-teal-edge);
                                 border-left-color: var(--pulse-teal);
                                 background: var(--pulse-teal-fill); }
.p-reason[data-reason="working"] { border-left-color: var(--pulse-amber-edge); }
.p-reason-n { font-family: var(--pulse-mono); font-size: 21px;
              font-variant-numeric: tabular-nums; color: var(--pulse-ink); }
.p-reason-k { font-family: var(--pulse-mono); font-size: 9px;
              letter-spacing: var(--pulse-track-kicker); color: var(--pulse-ink-3); }
.p-reason[aria-pressed="true"] .p-reason-k { color: var(--pulse-chip-teal-ink); }
.p-reason-why { font-family: var(--pulse-sans); font-size: 11.5px;
                color: var(--pulse-ink-2); text-wrap: pretty; }

/* BANDS. The sort has to be visible in the grid, not asserted in a label --
   an earlier draft shuffled the cells and claimed "sorted stranded first". */
.p-bands { display: flex; flex-direction: column; gap: var(--pulse-s4); }
.p-band { border-left: 3px solid var(--pulse-line); padding-left: var(--pulse-s3); }
.p-band[data-reason="stranded"]   { border-left-color: var(--pulse-teal); }
.p-band[data-reason="idle"]       { border-left-color: oklch(0.62 0.09 172); }
.p-band[data-reason="unassigned"] { border-left-color: var(--pulse-blue); }
.p-band[data-reason="working"]    { border-left-color: var(--pulse-amber-edge); }
.p-band-head { display: flex; align-items: baseline; gap: var(--pulse-s3);
               flex-wrap: wrap; padding-bottom: var(--pulse-s2); }
.p-band-label { font-family: var(--pulse-mono); font-size: 9.5px;
                letter-spacing: var(--pulse-track-kicker); color: var(--pulse-ink-2); }
.p-band-n { font-family: var(--pulse-mono); font-size: 14px;
            font-variant-numeric: tabular-nums; color: var(--pulse-ink); }
.p-band-why { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-3); }
.p-band-head .p-chip--sm { margin-left: auto; font-size: 11px; padding: 4px 10px; }
.p-band-more { font-family: var(--pulse-sans); font-size: 11px; color: var(--pulse-ink-3);
               margin-top: var(--pulse-s2); }

/* ============================================================================
   PRESENTATION TWINS THAT HAD NO RULES. Used in the markup, defined nowhere --
   and an undefined CLASS is worse than an undefined custom property: the
   property is dropped with a parse warning, the class just styles nothing.

   Cause of the p-deliv-card* set: when the deliverables list was rebuilt from a
   table to cards, the replacement dropped the tail of that block and took these
   with it. A twin that survives its markup is invisible until something looks.
   ========================================================================= */

/* mono utility -- codes, ids, figures inside prose */
.p-mono { font-family: var(--pulse-mono); font-variant-numeric: tabular-nums; }

/* table head strip: the count and its search, above a table or a list */
.p-table-head { display: flex; align-items: flex-end; justify-content: space-between;
                gap: var(--pulse-s4); flex-wrap: wrap; }
.p-table-count { font-family: var(--pulse-sans); font-size: 13px; font-weight: 500;
                 color: var(--pulse-ink); margin-top: 3px; }
/* an estimated count says so -- per VOLUME_TABLE_SPEC, a count whose basis is
   not stated is a count somebody will quote */
.p-table-count[data-count-basis="estimate"]::after { content: " · estimated";
  font-family: var(--pulse-mono); font-size: 9px;
  letter-spacing: var(--pulse-track-kicker); color: var(--pulse-chip-amber-ink); }

.p-search { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.p-search-label { font-family: var(--pulse-mono); font-size: 8.5px;
                  letter-spacing: var(--pulse-track-kicker); color: var(--pulse-ink-3); }

/* the identity strip's left column */
.p-strip-id { min-width: 0; }

/* detour banner -- the contract's own component */
.p-detour-kicker { font-family: var(--pulse-mono); font-size: 9px;
                   letter-spacing: var(--pulse-track-kicker);
                   color: var(--pulse-blue); flex: none; }
.p-detour-why { font-family: var(--pulse-sans); font-size: 12.5px;
                color: var(--pulse-ink); min-width: 0; text-wrap: pretty; }
/* the foot copy is the same contract, repeated at the bottom of a long page */
.p-detour--foot { margin-top: var(--pulse-s5); }

/* the project tab's two download cards */
.p-deliv-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
                gap: var(--pulse-s4); }
.p-deliv-card { background: var(--pulse-well); border: 1px solid var(--pulse-line-soft);
                border-radius: var(--pulse-r-inner); padding: var(--pulse-s4);
                display: flex; flex-direction: column; gap: var(--pulse-s2);
                align-items: flex-start; }
.p-deliv-card-head { font-family: var(--pulse-sans); font-size: 15px; font-weight: 600;
                     color: var(--pulse-ink); }
.p-deliv-card-what { font-family: var(--pulse-sans); font-size: 12.5px;
                     color: var(--pulse-ink-2); text-wrap: pretty; }
.p-deliv-card-note { font-family: var(--pulse-sans); font-size: 11.5px;
                     color: var(--pulse-ink-3); text-wrap: pretty;
                     padding-top: var(--pulse-s2);
                     border-top: 1px solid var(--pulse-line-soft); }

/* THE DESTINATION BOARD. Ranked by need rather than listed, and every card
   states how many of the selection it can take -- the count is a function of
   the DESTINATION, not of the agent, and a single-destination panel cannot
   express that. */
.p-dest-board { display: flex; flex-direction: column; gap: var(--pulse-s2); }
.p-dest { display: grid; gap: 4px; text-align: left; font: inherit; color: inherit;
          cursor: pointer; padding: 11px 13px; border-radius: var(--pulse-r-inner);
          background: var(--pulse-well); border: 1px solid var(--pulse-line);
          border-left: 3px solid var(--pulse-line); }
.p-dest:hover { background: var(--pulse-hover); }
.p-dest[aria-pressed="true"] { border-color: var(--pulse-teal-edge);
                               border-left-color: var(--pulse-teal);
                               background: var(--pulse-teal-fill); }
.p-dest[data-need="short"] { border-left-color: var(--pulse-amber-edge); }
.p-dest[data-need="full"]  { border-left-color: var(--pulse-line); opacity: .72; }
.p-dest[data-takes="0"]    { cursor: not-allowed; }
.p-dest-head { display: flex; align-items: baseline; gap: var(--pulse-s2); flex-wrap: wrap; }
.p-dest-name { font-family: var(--pulse-sans); font-size: 13.5px; font-weight: 600;
               color: var(--pulse-ink); }
/* the honest headline: how many of the selection THIS destination can take */
.p-dest-takes { margin-left: auto; font-family: var(--pulse-mono); font-size: 9px;
                letter-spacing: var(--pulse-track-kicker); white-space: nowrap; }
.p-dest-takes[data-takes="all"]  { color: var(--pulse-chip-teal-ink); }
.p-dest-takes[data-takes="some"] { color: var(--pulse-chip-amber-ink); }
.p-dest-takes[data-takes="none"] { color: var(--pulse-ink-3); }
.p-dest-client { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-3); }
.p-dest-bar { height: 5px; border-radius: 3px; background: var(--pulse-line);
              overflow: hidden; margin-top: 2px; }
.p-dest-fill { height: 100%; background: var(--pulse-teal); }
.p-dest[data-need="short"] .p-dest-fill { background: var(--pulse-amber-edge); }
.p-dest[data-need="full"] .p-dest-fill { background: var(--pulse-ink-3); }
.p-dest-nums { display: flex; align-items: baseline; gap: var(--pulse-s3); flex-wrap: wrap;
               font-size: 11.5px; color: var(--pulse-ink-2); }
.p-dest-why[data-need="short"] { color: var(--pulse-chip-amber-ink); }
.p-dest-why[data-need="full"]  { color: var(--pulse-ink-3); }
.p-dest-note { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-2);
               text-wrap: pretty; }

/* WHEN. Three timings, chosen not inferred. */
.p-when { display: flex; flex-direction: column; gap: var(--pulse-s2); }
.p-when-opt { display: grid; gap: 2px; text-align: left; font: inherit; color: inherit;
              cursor: pointer; padding: 10px 12px; border-radius: var(--pulse-r-inner);
              background: var(--pulse-well); border: 1px solid var(--pulse-line); }
.p-when-opt:hover { background: var(--pulse-hover); }
.p-when-opt[aria-pressed="true"] { border-color: var(--pulse-teal-edge);
                                   background: var(--pulse-teal-fill); }
.p-when-label { font-family: var(--pulse-sans); font-size: 13px; font-weight: 600;
                color: var(--pulse-ink); }
.p-when-why { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-2);
              text-wrap: pretty; }

/* STAGED MOVES. Editable until they fire, and each states whether it still
   works -- a plan that silently became unexecutable looks identical to a fine
   one, which is the absence rule applied to intent rather than to data. */
/* min-width:0 is load-bearing: as a flex item this floors at max-content
   without it, and the three-column grid inside never sees a constrained width.
   Its own container, because .p-stage-row is not inside .p-blockers. */
.p-staged { display: flex; flex-direction: column; gap: var(--pulse-s2);
            min-width: 0; container-type: inline-size; container-name: staged; }
.p-stage-row { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.3fr) auto;
               gap: var(--pulse-s4); align-items: start;
               padding: 12px 14px; border-radius: var(--pulse-r-inner);
               background: var(--pulse-well); border: 1px solid var(--pulse-line);
               border-left: 3px solid var(--pulse-teal); }
.p-stage-row[data-validity="drifted"] { border-left-color: var(--pulse-amber-edge);
  background-image: repeating-linear-gradient(135deg,
    var(--pulse-hatch) 0 6px, transparent 6px 13px); }
.p-stage-row[data-validity="invalid"] { border-left-color: var(--pulse-red-edge);
                                        background: var(--pulse-red-fill); }
.p-stage-what { font-family: var(--pulse-sans); font-size: 13.5px; font-weight: 600;
                color: var(--pulse-ink); }
.p-stage-when { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-3);
                margin-top: 3px; }
.p-stage-state { display: grid; gap: 4px; min-width: 0; }
.p-stage-badge { font-family: var(--pulse-mono); font-size: 9px; justify-self: start;
                 letter-spacing: var(--pulse-track-kicker); padding: 3px 8px;
                 border-radius: 999px; border: 1px solid var(--pulse-line); }
.p-stage-badge[data-validity="valid"]   { color: var(--pulse-chip-teal-ink);
  border-color: var(--pulse-teal-edge); background: var(--pulse-teal-fill); }
.p-stage-badge[data-validity="drifted"] { color: var(--pulse-chip-amber-ink);
  border-color: var(--pulse-amber-edge); background: var(--pulse-amber-fill); }
.p-stage-badge[data-validity="invalid"] { color: var(--pulse-chip-red-ink);
  border-color: var(--pulse-red-edge); background: var(--pulse-red-fill); }
.p-stage-acts { display: flex; gap: var(--pulse-s2); flex-wrap: wrap; justify-content: flex-end; }

/* Keyed on .p-staged, which IS the ancestor -- an earlier attempt used
   @container blockers, a container .p-stage-row does not sit inside, so the
   rule could never match. Placed after the base declaration for the same
   source-order reason as the block below. */
@container staged (max-width: 520px) {
  .p-stage-row { grid-template-columns: minmax(0, 1fr); row-gap: var(--pulse-s2); }
  .p-stage-acts { justify-content: flex-start; }
}
@supports not (container-type: inline-size) {
  @media (max-width: 760px) { .p-stage-row { grid-template-columns: minmax(0, 1fr); } }
}

/* ============================================================================
   THE SIX NAV ROUTES. See robo-nav-routes.html.
   ========================================================================= */

/* launch_center rows: identity, state, then the blockers inline */
.p-lc-row { display: grid; grid-template-columns: minmax(0,1fr) 120px;
            gap: var(--pulse-s3) var(--pulse-s4); align-items: start;
            padding: 14px 16px; border-radius: var(--pulse-r-inner);
            background: var(--pulse-well); border: 1px solid var(--pulse-line);
            border-left: 3px solid var(--pulse-line); }
.p-lc-row[data-state="blocked"] { border-left-color: var(--pulse-red-edge); }
.p-lc-row[data-state="ready"]   { border-left-color: var(--pulse-teal); }
.p-lc-row > .p-blockers, .p-lc-row > .p-dense { grid-column: 1 / -1; }
.p-lc-id { min-width: 0; }
.p-lc-name { font-family: var(--pulse-sans); font-size: 14px; font-weight: 600;
             color: var(--pulse-ink); }
.p-lc-name:hover { color: var(--pulse-chip-teal-ink); text-decoration: underline; }
.p-lc-state { justify-self: end; font-family: var(--pulse-mono); font-size: 9.5px;
              letter-spacing: var(--pulse-track-kicker); padding: 4px 9px;
              border-radius: 999px; white-space: nowrap; }
.p-lc-state[data-state="blocked"] { color: var(--pulse-chip-red-ink);
  background: var(--pulse-red-fill); border: 1px solid var(--pulse-red-edge); }
.p-lc-state[data-state="ready"] { color: var(--pulse-chip-teal-ink);
  background: var(--pulse-teal-fill); border: 1px solid var(--pulse-teal-edge); }

/* help_center list */
.p-help-list { list-style: none; margin: 0; padding: 0;
               display: flex; flex-direction: column; gap: 1px;
               background: var(--pulse-line); border: 1px solid var(--pulse-line);
               border-radius: var(--pulse-r-inner); overflow: hidden; }
.p-help-item { display: grid; gap: 3px; padding: 13px 15px; background: var(--pulse-panel); }
.p-help-item:hover { background: var(--pulse-hover); }
.p-help-what { font-family: var(--pulse-sans); font-size: 13.5px; font-weight: 500;
               color: var(--pulse-ink); }
.p-help-item:hover .p-help-what { text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 2px; }
.p-help-why { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-3);
              text-wrap: pretty; }

/* State chip. Used wherever a row states a verdict inline: an AMD basis, a
   completion class, a check result. VOID is a distinct state from WARN --
   hatched, because the figure has not become wrong, its basis has moved. */
.p-chip-state { font-family: var(--pulse-mono); font-size: 9px;
                letter-spacing: var(--pulse-track-kicker); padding: 3px 8px;
                border-radius: 999px; white-space: nowrap;
                border: 1px solid var(--pulse-line); color: var(--pulse-ink-3); }
.p-chip-state[data-state="pass"] { color: var(--pulse-chip-teal-ink);
  border-color: var(--pulse-teal-edge); background: var(--pulse-teal-fill); }
.p-chip-state[data-state="warn"] { color: var(--pulse-chip-amber-ink);
  border-color: var(--pulse-amber-edge); background: var(--pulse-amber-fill); }
.p-chip-state[data-state="void"] { color: var(--pulse-chip-amber-ink);
  border-color: var(--pulse-amber-edge); background: var(--pulse-amber-fill);
  background-image: repeating-linear-gradient(135deg,
    var(--pulse-hatch) 0 5px, transparent 5px 11px); }
.p-chip-state[data-state="na"] { color: var(--pulse-ink-3);
  border-style: dashed; background: transparent; }

/* A preserved panel: production content this markup did not specify, kept and
   restyled rather than replaced. Marked so it is visible in a review that the
   panel is inherited -- see COVERAGE_DECLARATION.md. */
.p-panel[data-coverage="preserved"] { border-style: dashed; }

/* ============================================================================
   SEMANTIC TABLE. A real <table class="bl-table p-table"> with thead/tbody,
   used by robo-nav-routes, robo-tabs and robo-nav-pages.

   Distinct from .p-table__head / .p-table__row above, which is a GRID for the
   volume table -- that one exists because a virtualised body must align to a
   fixed header. This one is for small tabular data where the element carries
   the meaning.

   Written late because bundle 107's audit false-positived: the guard regex
   /\.p-table(?![a-z0-9-])/ matched .p-table__head, since '_' was absent from
   the character class. The block was skipped and the sweep reported clean.
   ========================================================================= */
.p-table { width: 100%; border-collapse: collapse;
           font-family: var(--pulse-sans); font-size: 13px; }
.p-table thead th { text-align: left; padding: 10px 14px; font-weight: 400;
  font-family: var(--pulse-mono); font-size: 8.5px;
  letter-spacing: var(--pulse-track-kicker); color: var(--pulse-ink-3);
  background: oklch(0.22 0.016 212); white-space: nowrap; }
.p-table thead th:first-child { border-top-left-radius: var(--pulse-r-inner); }
.p-table thead th:last-child  { border-top-right-radius: var(--pulse-r-inner); }
.p-table td { padding: 12px 14px; vertical-align: top; color: var(--pulse-ink);
              border-top: 1px solid var(--pulse-line-soft); }
.p-table tbody tr:hover { background: var(--pulse-hover); }
.p-table th.p-num, .p-table td.p-num { text-align: right;
              font-variant-numeric: tabular-nums; font-family: var(--pulse-mono); }
.p-table a { color: var(--pulse-ink); font-weight: 500; }
.p-table a:hover { color: var(--pulse-chip-teal-ink);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.p-table .p-dense { margin-top: 3px; }

/* ============================================================================
   TEXT PILLAR. See TEXT_PILLAR_SPEC.md.
   ========================================================================= */

/* Segment cost, at the field. The encoding flip is loud because a character
   count alone does not explain why one emoji tripled the bill. */
.p-segcost { display: flex; flex-wrap: wrap; gap: var(--pulse-s4); margin-top: var(--pulse-s2);
             padding: 9px 12px; border-radius: var(--pulse-r-inner);
             background: var(--pulse-well); border: 1px solid var(--pulse-line-soft); }
.p-segcost-part { display: flex; align-items: baseline; gap: 6px;
                  font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-3); }
.p-segcost-n { font-family: var(--pulse-mono); font-size: 13px;
               font-variant-numeric: tabular-nums; color: var(--pulse-ink); }
.p-segcost[data-encoding="ucs2"] { border-color: var(--pulse-amber-edge);
                                   background: var(--pulse-amber-fill); }
.p-segcost-part[data-flip="true"] .p-segcost-n { color: var(--pulse-chip-amber-ink); }
.p-segcost-why { font-size: 11px; color: var(--pulse-chip-amber-ink); }

/* Three modes. Radio semantics, because they are exclusive and a checkbox row
   would imply otherwise. */
.p-modes { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
           gap: var(--pulse-s2); }
.p-mode { display: grid; gap: 4px; text-align: left; cursor: pointer; font: inherit;
          color: inherit; padding: 13px 15px; border-radius: var(--pulse-r-inner);
          background: var(--pulse-well); border: 1px solid var(--pulse-line);
          border-left: 3px solid var(--pulse-line); }
.p-mode:hover { background: var(--pulse-hover); }
.p-mode[aria-checked="true"] { border-color: var(--pulse-teal-edge);
  border-left-color: var(--pulse-teal); background: var(--pulse-teal-fill); }
.p-mode-name { font-family: var(--pulse-sans); font-size: 14px; font-weight: 600;
               color: var(--pulse-ink); }
.p-mode-why { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-2);
              text-wrap: pretty; }

/* A rule that sits OUTSIDE a control, because it is not that control's option. */
.p-always { display: flex; align-items: flex-start; gap: var(--pulse-s3);
            padding: 11px 14px; border-radius: var(--pulse-r-inner);
            background: var(--pulse-teal-fill); border: 1px solid var(--pulse-teal-edge);
            font-family: var(--pulse-sans); font-size: 12.5px; color: var(--pulse-ink);
            text-wrap: pretty; }
.p-always-mark { color: var(--pulse-chip-teal-ink); flex: none; }

/* A repeater row whose content is ONE line: text, rate, goto. A modifier
   rather than a change to .p-step, because robo-forms' rows hold stacked block
   children (a kicker and a field) and need the default flow.

   Without this .p-step computes display:list-item, .p-goto computes inline,
   and its margin-left:auto is inert -- which rendered "[1] Yes -> Q2" as one
   run and buried the routing decision mid-sentence. A response is exactly
   three things and the goto is the one that makes a branching script
   scannable. */
.p-step--row { display: flex; align-items: baseline; gap: var(--pulse-s3);
               flex-wrap: wrap; }

.p-goto { margin-left: auto; font-family: var(--pulse-mono); font-size: 11px;
          color: var(--pulse-ink-3); }
/* the fallback's goto is the longest and most consequential string here */
.p-step[data-fallback="true"] .p-goto { color: var(--pulse-chip-amber-ink); }
.p-step[data-fallback="true"] { border-style: dashed; }

/* Inbound arriving after its project ended. Neither an orphan nor a live row. */
.p-inbound-row { display: grid; gap: 5px; padding: 13px 15px;
                 border-radius: var(--pulse-r-inner); background: var(--pulse-well);
                 border: 1px solid var(--pulse-line);
                 border-left: 3px solid var(--pulse-line-soft); }
.p-inbound-msg { font-family: var(--pulse-sans); font-size: 14.5px; color: var(--pulse-ink); }
.p-inbound-meta { font-family: var(--pulse-mono); font-size: 10px;
                  letter-spacing: var(--pulse-track-kicker); color: var(--pulse-ink-3); }
.p-inbound-rule { font-family: var(--pulse-sans); font-size: 11.5px; color: var(--pulse-ink-2);
                  margin-top: 3px; text-wrap: pretty; }

/* ============================================================================
   NARROW BLOCKER ROWS. Must sit at the END of this sheet: the override and
   .p-blocker-row's base grid-template-columns have equal specificity, so
   source order decides -- an earlier attempt placed this above the base rule
   and it silently lost.

   Blocker rows are a fixed three-column grid authored for Build & Launch's
   ~800px content column. In a 340px aside every track resolves below its
   content width at once and the row stacks its text INSIDE the columns: 195px
   tall with a four-line headline. Keyed on the list's own width rather than the
   viewport, for the same reason as .p-deliv-list.
   ========================================================================= */
.p-blockers { container-type: inline-size; container-name: blockers; }

@container blockers (max-width: 520px) {
  .p-blocker-row { grid-template-columns: minmax(0, 1fr); row-gap: var(--pulse-s2); }
  .p-blocker-row > div:last-child { text-align: left !important; }
}
@supports not (container-type: inline-size) {
  @media (max-width: 720px) {
    .p-blocker-row { grid-template-columns: minmax(0, 1fr); row-gap: var(--pulse-s2); }
  }
}

/* A spine step may wrap its own radio (the no-JS selection mechanism). The
   input is the control; the label is the presentation, so the native circle
   is removed without removing the input. */
.p-spine-step input[type="radio"] { position: absolute; opacity: 0;
                                    width: 1px; height: 1px; pointer-events: none; }

/* A REFERENCE spine. The pillar handoff pages render every step's pane at
   once, so their strip names the sequence rather than switching it -- and
   must not present as a control it is not. No pointer, no hover lift, and
   the current step is marked THIS PAGE rather than YOU ARE HERE, which
   would be false on a page showing step 1 at the top.

   The robo workspace spine keeps its interactive treatment. */
.p-spine-step--ref { cursor: default; }
.p-spine-step--ref:hover { filter: none; }
.v-spine--ref .p-spine-state:empty { display: none; }

/* ---------------------------------------------------------------
   PRESERVED FROM HF10. This selector exists in production and not in
   the design package, so adopting the package sheet wholesale would
   delete a working rule. COVERAGE_DECLARATION.md: additive by
   default -- where the package does not speak, production wins.
   --------------------------------------------------------------- */
.p-worker[data-worker="unknown"] { background: var(--pulse-amber-fill);
  border: 1px solid var(--pulse-amber-edge); color: var(--pulse-chip-amber-ink); }


/* ============================================================================
   RULING C3. The hand-ported V126 concepts and the hand-built spine treatment
   that used to sit here are REMOVED. pulse-v126.css now ships as the canonical
   Robo workspace sheet, route-scoped to the automation tab, so porting a subset
   of it into this sheet would be a second copy of the same rules with nothing
   comparing them -- and the partial port is what produced a half-converged page.

   What stays below is layout this sheet legitimately owns: the workspace is one
   column once the legacy build rail is retired.
   ========================================================================= */
/* CD139: with the legacy build rail retired, the workspace is one column. The
   base .bl-workspace grid in build-launch.css is 232px + 1fr, which would strand
   the content in the rail's empty column. */
.bl-workspace--norail { grid-template-columns: minmax(0, 1fr); }
