/* Pre-Permit tracker skin (PDS-388 redesign — "o rastreio").
   DELIBERATELY OUTSIDE THE DESIGN SYSTEM, approved by the owner: the screen
   trades the steel/blueprint form voice for a parcel-tracking voice — a spine
   of steps, green as the colour of progress and action (amber back to waiting,
   red to blocking). If the model is ever re-skinned to steel/blueprint, only
   this file moves — the decision is the skeleton, not the palette.

   CORNERS: A SCALE, NOT A SETTING (owner, 07/aug — asked for sharp, then
   "empobreceu um pouco a UI, qual seria o meio termo?"). The first pass had 7
   to 14px, which read soft; zero read raw, because with no radius at all every
   box is the same slab and a button stops looking pressable. The middle ground
   is a THREE-STEP SCALE where the corner is proportional to the box, so the
   radius itself becomes hierarchy:
     --trk-r-s  (3px)  controls and stamps — buttons, fields, chips, the status
                       word, the checkbox
     --trk-r    (5px)  containers — cards, message cards, rows, notes, the fee
                       table, rail rows
     --trk-r-lg (8px)  the two big surfaces — the popup dialog and the section
                       frame itself
   Nothing goes back to a pill: the status word stays a stamp, which is what a
   register uses. ROUND SURVIVES ONLY AS A MARK — the spine nubs, the timeline
   nubs, the state dots, the composer numerals and the "?" badge: those are
   glyphs, not containers, and a square dot is not a dot. When adding a rule
   here, pick the step by the size of the box; never hardcode a radius. */

/* NO DISPLAY SERIF (owner, 07/aug: "parece algo mais jornalístico ao invés de
   sóbrio"). The Palatino/Iowan face was the voice of the serif situation
   sentence, cut the same day; on titles alone it read editorial. Titles are the
   same sans as everything else, separated by weight and tracking — a register
   is sober, and its hierarchy is size and ink, not another typeface. */

/* Scoped under .process-tracker so nothing leaks into the rest of the app. Dark mode is
   the app's `.dark` CLASS strategy (specs/design-system-patterns/09), never
   prefers-color-scheme: the same custom properties are re-declared under
   `.dark .process-tracker`, so every component rule below is written once. */

.process-tracker {
  --trk-bg: #f7f4ee;
  --trk-panel: #fffdf9;
  --trk-ink: #26231c;
  --trk-sub: #6b665a;
  --trk-faint: #a09a8c;
  --trk-line: #e6e1d5;
  --trk-line-soft: #efebe0;
  /* ⚠️ OS TONS `-soft` SÃO TRANSPARÊNCIA DA PRÓPRIA COR, NÃO UM HEX FIXO, e a
     razão é medida: quando o cartão do overview recuou para `--trk-line-soft`,
     três marcas pintadas com esses tokens foram para 1,00 : 1 contra o fundo —
     a cor de preenchimento delas virou exatamente a cor do cartão. Eles tinham
     sido desenhados contra o papel e só existiam lá.
     Como `color-mix`, a marca se compõe sobre QUALQUER fundo e chega no mesmo
     lugar relativo: o trilho do meter mede 1,17 no papel e 1,16 no recuo, contra
     1,15 e 1,02 antes.
     ⚠️ E CADA ALFA FOI RESOLVIDO PARA REPRODUZIR O HEX ANTIGO SOBRE O PAPEL
     (#e5f0ea, #f9efdd, #f9e7e4, #e4e8f0, #f3e9f4), então nenhuma das ~30 telas
     que já usavam esses tokens muda de aparência — só passam a se adaptar.
     Por isso também não há definição no bloco escuro: a cor-mãe já troca lá, e
     a porcentagem vale nos dois temas. */
  --trk-green: #1e6b50;
  --trk-green-soft: color-mix(in srgb, var(--trk-green) 11%, transparent);
  /* A METADE AÇÃO DO QUE ERA VERDE (07/ago/2026). Um token só servia os dois
     papéis — o botão que se clica e o nub que reporta um fato — e agora o matiz
     separa: NAVY É O QUE SE CLICA OU RECEBE FOCO, verde é onde a coisa está.
     Ao acrescentar uma regra aqui, a pergunta é essa, e não qual fica melhor. */
  --trk-navy: #2d3d5f;
  --trk-navy-soft: color-mix(in srgb, var(--trk-navy) 13%, transparent);
  --trk-amber: #915809;
  --trk-amber-soft: color-mix(in srgb, var(--trk-amber) 9%, transparent);
  --trk-red: #b3362b;
  --trk-red-soft: color-mix(in srgb, var(--trk-red) 8%, transparent);
  /* THE HAND (PDS-424). The sixth origin of the application form is the only
     one that is a person rather than a record, and it needed a colour no other
     state on this skin already owns: green is "the system holds it", navy is
     the triage, amber is both the registries and every warning, red is a
     failure. Plum is the one hue left that reads as deliberate at 2px. */
  --trk-plum: #7a4b7d;
  --trk-plum-soft: color-mix(in srgb, var(--trk-plum) 10%, transparent);
  --trk-act-ink: #ffffff;
  --trk-shadow: 0 1px 2px rgba(60, 50, 30, .05), 0 12px 32px -18px rgba(60, 50, 30, .25);
  --trk-sans: -apple-system, 'Segoe UI', system-ui, Roboto, sans-serif;
  --trk-mono: ui-monospace, 'SF Mono', Consolas, monospace;
  --trk-r-s: 3px;
  --trk-r: 5px;
  --trk-r-lg: 8px;

  background: var(--trk-bg);
  color: var(--trk-ink);
  font-family: var(--trk-sans);
  border-color: var(--trk-line);
  border-radius: var(--trk-r-lg);
}

/* THE SKIN WITHOUT ITS GROUND (owner, 21/ago/2026: "no slab"). On a <section>
   or a dialog the ground above is the surface itself — that is the object. On a
   PAGE container it is a slab of --trk-bg laid over `.process-canvas`, and at
   the top of the page the two are three hex points apart (#f7f4ee against a
   gradient that starts #f9f6f0): invisible where it starts, so its 8px corners
   read as a rendering artefact, and visible only further down where the
   gradient has darkened and nothing explains the edge. Three alternatives went
   to the owner (drop the slab / commit to it as a sheet / weld the pipeline to
   the tabs strip) and the drop won: a surface that carries no meaning is one
   the page is better without, and the cards already say what a surface means.
   Type, tokens and border colour stay — this only gives up the ground. */
.process-tracker.trk-page {
  background: none;
  border-radius: 0;
}

.dark .process-tracker {
  --trk-bg: #161511;
  --trk-panel: #1f1d18;
  --trk-ink: #efeadf;
  --trk-sub: #a8a294;
  --trk-faint: #6e6a5e;
  --trk-line: #343026;
  --trk-line-soft: #2a271f;
  --trk-green: #5cb890;
  --trk-navy: #9aa8c6;
  --trk-amber: #e0a352;
  --trk-red: #e0705f;
  --trk-plum: #c79ad0;
  --trk-act-ink: #10201a;
  --trk-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 14px 34px -18px rgba(0, 0, 0, .6);
}

/* PDS: lets a page OUTSIDE the tracker (Estimate, restyled to this skin —
   owner request, 18/ago/2026) pick up the tracker's exact typefaces by
   wrapping its content in `.process-tracker`, without rewriting every
   font-mono/font-sans occurrence already in that markup: Tailwind's
   font-mono/font-sans utilities read `--font-mono`/`--font-sans`, so
   redeclaring those two tokens here re-resolves every existing occurrence
   in scope. Colors are NOT done this way — steel-400/steel-500 play
   different semantic roles depending on which one is the `dark:` side in a
   given pair, so a blanket token override would silently swap meaning in
   half the cases; those are replaced per occurrence instead. */
.process-tracker {
  --font-sans: var(--trk-sans);
  --font-mono: var(--trk-mono);
}

/* WELDED TO THE CHROME BAND (12/ago/2026). On the four viewport-locked
   workspaces the process header is a surface that sits directly ON this section
   — same panel, same line, same 8px corner — so the two read as one object. The
   section squares its TOP corners and lets its own top border be the seam; the
   band drops its bottom border so the seam is one hairline and not two. Two
   classes deep on purpose: it has to beat `.process-tracker`'s own radius no
   matter which stylesheet the bundler emits last. */
.process-tracker.trk-welded {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

/* ---- shared surfaces & borders ---- */
.process-tracker .trk-surface { background: var(--trk-panel); }
.process-tracker .trk-chrome { background: var(--trk-bg); }
.process-tracker .trk-border { border-color: var(--trk-line); }
.process-tracker .trk-border-soft { border-color: var(--trk-line-soft); }
.process-tracker .trk-ink { color: var(--trk-ink); }
.process-tracker .trk-sub { color: var(--trk-sub); }
.process-tracker .trk-faint { color: var(--trk-faint); }
.process-tracker .trk-green { color: var(--trk-green); }
.process-tracker .trk-amber { color: var(--trk-amber); }
.process-tracker .trk-red { color: var(--trk-red); }
.process-tracker .trk-mono { font-family: var(--trk-mono); }

/* mono uppercase micro-heading (category rails, drawer headings, footers) */
.process-tracker .trk-kicker {
  font-family: var(--trk-mono);
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--trk-faint);
}

/* ---- situation header ----
   THE NAME IS THE HEADLINE (owner, 07/aug: "esse tipo de título não agrega
   muito, só consome espaço e tira a atenção dos elementos que são variáveis de
   verdade"). The serif line used to restate in prose what the spine already
   says step by step — and it did it in the biggest type on the pane, above a
   13px muted name. Inverted: the document name (the one thing that changes on
   every rail click) takes the display face, the status word keeps its pill,
   and the situation is read where it is actually operated — in the steps. */
.process-tracker .trk-doc-name {
  font-size: clamp(14.5px, .35vw + 12px, 16px);
  line-height: 1.3;
  font-weight: 650;
  letter-spacing: -.012em;
  text-wrap: balance;
  color: var(--trk-ink);
  margin: 0;
}
/* THE STATUS STAMP LEFT THIS FILE (PDS-416). `.trk-word` and its four tones were
   the app's SECOND spelling of one look, and the owner kept this one: "os badges
   do pre-permit estão mais modernos… vamos obsoletar o antigo e manter apenas o
   novo estilo globalmente". It now lives unscoped as `.badge` in
   application.css, with the same values — the tracker's tokens were the app's
   warm tokens under different names, so nothing here changed colour. The
   `.trk-blocked / .trk-waiting / .trk-ours` container selectors went with it:
   nothing in the app had written those classes for a long time.

   Anything in this file that is NOT a badge stayed: `.trk-kicker` is a section
   eyebrow with no fill, and `.trk-nowtag` is a marker on a spine node. */

/* ---- spine ---- */
.process-tracker .trk-spine { list-style: none; margin: 0; padding: 18px 20px 8px; }
.process-tracker .trk-spine > li { position: relative; padding: 0 0 22px 36px; }
.process-tracker .trk-spine > li::before {
  content: "";
  position: absolute;
  left: 9px;
  top: 24px;
  bottom: 2px;
  width: 2px;
  background: var(--trk-line);
  border-radius: 2px;
}
.process-tracker .trk-spine > li:last-child::before { display: none; }
.process-tracker .trk-spine > li.trk-n-done::before { background: var(--trk-green); opacity: .45; }

.process-tracker .trk-nub {
  position: absolute;
  left: 0;
  top: 1px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: grid;
  place-items: center;
}
/* the done check is DRAWN (rotated border L), never a unicode glyph — same
   rule as the required-work boxes: platform font coverage is not UI. */
.process-tracker li.trk-n-done .trk-nub { background: var(--trk-green); }
.process-tracker li.trk-n-done .trk-nub::after {
  content: "";
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}
.dark .process-tracker li.trk-n-done .trk-nub::after { border-color: #10201a; }
.process-tracker li.trk-n-now .trk-nub, .process-tracker li.trk-n-hold .trk-nub { border: 2.5px solid var(--trk-green); background: var(--trk-panel); }
.process-tracker li.trk-n-now .trk-nub::after, .process-tracker li.trk-n-hold .trk-nub::after {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--trk-green);
}
.process-tracker li.trk-n-hold .trk-nub { border-color: var(--trk-amber); }
.process-tracker li.trk-n-hold .trk-nub::after { background: var(--trk-amber); }
.process-tracker li.trk-n-next .trk-nub { width: 12px; height: 12px; left: 4px; top: 5px; border: 2px solid var(--trk-faint); background: var(--trk-panel); }
.process-tracker li.trk-n-ghost .trk-nub { width: 12px; height: 12px; left: 4px; top: 5px; border: 2px dashed var(--trk-faint); background: var(--trk-panel); }

.process-tracker .trk-node-t { font-size: 14.5px; font-weight: 650; color: var(--trk-ink); line-height: 1.4; }
.process-tracker li.trk-n-next .trk-node-t { color: var(--trk-sub); font-weight: 550; }
.process-tracker li.trk-n-ghost .trk-node-t { color: var(--trk-faint); font-weight: 550; }
.process-tracker .trk-node-d { margin: 4px 0 0; font-size: 13px; line-height: 1.6; color: var(--trk-sub); max-width: 60ch; }
.process-tracker li.trk-n-ghost .trk-node-d { color: var(--trk-faint); }
.process-tracker .trk-node-d b { color: var(--trk-ink); font-weight: 600; }
/* what somebody typed beside the triage option (PDS-413) — set off by a rule
   rather than by quotation marks, so the words stay the operator's own and the
   attribution reads as a caption instead of part of the sentence. */
.process-tracker .trk-quote {
  padding-left: 9px;
  border-left: 2px solid var(--trk-line);
  color: var(--trk-ink);
}
.process-tracker .trk-nowtag {
  display: inline-block;
  margin-left: 8px;
  font-family: var(--trk-mono);
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--trk-green);
}
.process-tracker li.trk-n-hold .trk-nowtag { color: var(--trk-amber); }
/* the one tag that names something already delivered — filled, so it is found
   from across the screen instead of read line by line (PDS-388 S3c). The `li`
   selector is repeated to outrank the .trk-n-hold colour above. */
.process-tracker .trk-nowtag-reply,
.process-tracker li.trk-n-hold .trk-nowtag-reply {
  color: var(--trk-navy);
  background: var(--trk-navy-soft);
  padding: 1.5px 5px;
  border-radius: 2px;
}

/* the action card mounted inside the current node */
.process-tracker .trk-node-card {
  margin-top: 12px;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
  background: var(--trk-bg);
  max-width: 560px;
  overflow: hidden;
}
.process-tracker .trk-node-card-body { padding: 13px 14px; display: grid; gap: 10px; }
/* the owed step when it also carries the wait clock (PDS-414): action on the
   left, figure on the right. A `flex` utility on `.trk-node-card-body` would
   lose to the `display: grid` above — same specificity, and this file loads
   after Tailwind — so the variant is a class here rather than a fight there. */
.process-tracker .trk-node-card-split { max-width: 640px; }
.process-tracker .trk-node-card-split .trk-node-card-body {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 14px 22px;
}
.process-tracker .trk-node-card-split .trk-node-card-main { flex: 1 1 240px; min-width: 0; }
.process-tracker .trk-node-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-top: 1px solid var(--trk-line-soft);
}
.process-tracker .trk-hint { font-size: 11.5px; line-height: 1.5; color: var(--trk-faint); margin: 0; }

/* ---- forms, tracker voice ---- */
.process-tracker .trk-label {
  display: block;
  margin-bottom: 5px;
  font-family: var(--trk-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--trk-sub);
}
.process-tracker .trk-input {
  width: 100%;
  padding: 8px 10px;
  font-size: 13px;
  font-family: var(--trk-sans);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  background: var(--trk-panel);
  color: var(--trk-ink);
}
.process-tracker .trk-input::placeholder { color: var(--trk-faint); }
.process-tracker .trk-input:focus { outline: 2px solid var(--trk-navy); outline-offset: 1px; border-color: var(--trk-navy); }
.process-tracker .trk-file {
  width: 100%;
  font-size: 12.5px;
  color: var(--trk-sub);
}
.process-tracker .trk-file::file-selector-button {
  margin-right: 10px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  font-family: var(--trk-sans);
  color: var(--trk-sub);
  background: var(--trk-panel);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  cursor: pointer;
}
.process-tracker .trk-file::file-selector-button:hover { border-color: var(--trk-faint); }
.process-tracker .trk-check { accent-color: var(--trk-navy); }

/* ONE geometry for every work button (owner, 06/aug — "todos esses botões
   devem ser o mesmo"): only the fill differs. Solid green changes state
   (submits inside popups); outline green opens a view (every popup button on
   the spine). Same padding, same type, 1px border on both so the boxes match
   to the pixel. */
.process-tracker .trk-act {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 15px;
  font-size: 13px;
  font-weight: 650;
  font-family: var(--trk-sans);
  color: var(--trk-act-ink);
  background: var(--trk-navy);
  border: 1px solid var(--trk-navy);
  border-radius: var(--trk-r-s);
  cursor: pointer;
  width: fit-content;
}
.process-tracker .trk-act:hover { filter: brightness(1.07); }
.process-tracker .trk-act-soft {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 15px;
  font-size: 13px;
  font-weight: 650;
  font-family: var(--trk-sans);
  color: var(--trk-navy);
  background: none;
  border: 1px solid var(--trk-navy);
  border-radius: var(--trk-r-s);
  cursor: pointer;
  width: fit-content;
  opacity: .9;
}
.process-tracker .trk-act-soft:hover { opacity: 1; background: var(--trk-navy-soft); }
/* ⚠️ A DISABLED WORK BUTTON HAS TO LOOK DISABLED (PDS-419). There was no rule
   here, so a locked question rendered `disabled` in the same navy as a live
   control: identical to the pixel, and the only way to find out was to click it
   and have nothing happen. Dashed border and faint ink, because the box has to
   stay in the layout — a locked question still shows WHERE the act would be. */
.process-tracker .trk-act-soft:disabled,
.process-tracker .trk-act:disabled,
.process-tracker .trk-act-ghost:disabled {
  color: var(--trk-faint);
  background: none;
  border: 1px dashed var(--trk-line);
  cursor: not-allowed;
  opacity: 1;
}
.process-tracker .trk-act-soft:disabled:hover,
.process-tracker .trk-act:disabled:hover,
.process-tracker .trk-act-ghost:disabled:hover {
  color: var(--trk-faint);
  background: none;
  border-color: var(--trk-line);
  filter: none;
}
/* THE THIRD WEIGHT, AND IT KEEPS THE GEOMETRY (owner, 07/aug: "esse botão pode
   ser melhorado"). "Correct" next to "Confirm" was a bare underlined link — the
   underline read as a hyperlink dropped into a cluster of controls, and the two
   boxes did not line up because one had no box. The rule is one geometry for
   every work button; what carries hierarchy is the INK, not the shape. So the
   secondary act keeps the same padding, type and radius, and gives up its fill
   and its border until you point at it. */
.process-tracker .trk-act-ghost {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 15px;
  font-size: 13px;
  font-weight: 650;
  font-family: var(--trk-sans);
  color: var(--trk-sub);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--trk-r-s);
  cursor: pointer;
  width: fit-content;
}
.process-tracker .trk-act-ghost:hover { color: var(--trk-navy); border-color: var(--trk-navy); background: var(--trk-navy-soft); }

/* `.trk-rowacts` LIVED HERE (10/ago) AND WAS REMOVED BY THE BLOCK 0 TICK
   (12/ago). It was a grid of two FIXED 96px slots, and the empty slot was the
   point: `Confirm` exists on the minority of rows, so a flex cluster let the
   second act slide left and the column arrived with a different edge on almost
   every row. The grid fixed the ragged edge and paid 192px of every row for it,
   half of them empty — which is the cost the owner refused on 12/ago ("eu
   disaprovo esses botões lado a lado").

   The replacement is not another button geometry: agreeing stopped being a
   button at all. See `.trk-bz-tick` at the bottom of this file. */
.process-tracker .trk-act-danger {
  display: inline-flex;
  align-items: center;
  padding: 7px 13px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--trk-red);
  background: none;
  border: 1px solid var(--trk-red);
  border-radius: var(--trk-r-s);
  cursor: pointer;
  width: fit-content;
}
.process-tracker .trk-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--trk-navy);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.process-tracker .trk-link:hover { color: var(--trk-ink); }

/* left-accent note (catalog note, applies-when, error) */
.process-tracker .trk-note {
  padding: 9px 12px;
  border-left: 3px solid var(--trk-line);
  border-radius: 0 var(--trk-r) var(--trk-r) 0;
  background: var(--trk-line-soft);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--trk-sub);
}
.process-tracker .trk-note-red { border-left-color: var(--trk-red); background: var(--trk-red-soft); color: var(--trk-red); }
.process-tracker .trk-note-amber { border-left-color: var(--trk-amber); background: var(--trk-amber-soft); color: var(--trk-amber); }

/* ---- the work popup (rastreio v2) ----
   The spine is a skeleton; the work opens here, sized to its content. The
   dialog lives INSIDE the workspace frame, so every turbo_stream repaint
   destroys it — success closes it for free, failure re-opens via the
   pre-permit-popup controller's `open` value. Nothing else in the app styles
   bare <dialog> (only dialog.modal-dialog, class-qualified), so this rules out
   every UA default itself. */
.process-tracker .trk-work { margin-top: 10px; }
.process-tracker dialog.trk-pop {
  border: none;
  padding: 0;
  margin: auto;
  width: min(680px, 94vw);
  max-height: 88vh;
  background: var(--trk-panel);
  color: var(--trk-ink);
  font-family: var(--trk-sans);
  border-radius: var(--trk-r-lg);
  box-shadow: var(--trk-shadow);
  flex-direction: column;
}
.process-tracker dialog.trk-pop[open] { display: flex; }
.process-tracker dialog.trk-pop::backdrop { background: rgba(28, 24, 16, .45); }
.dark .process-tracker dialog.trk-pop::backdrop { background: rgba(0, 0, 0, .6); }
@media (prefers-reduced-motion: no-preference) {
  .process-tracker dialog.trk-pop[open] { animation: trk-pop-in .16s ease-out; }
}
@keyframes trk-pop-in {
  from { transform: translateY(8px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

.process-tracker .trk-pop-head {
  flex-shrink: 0;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--trk-line-soft);
}
.process-tracker .trk-pop-title { font-size: 15.5px; font-weight: 650; letter-spacing: -.012em; color: var(--trk-ink); }
.process-tracker .trk-pop-sub { margin: 2px 0 0; font-size: 12px; line-height: 1.5; color: var(--trk-sub); overflow-wrap: anywhere; }
.process-tracker .trk-pop-x {
  margin-left: auto;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  background: none;
  color: var(--trk-sub);
  cursor: pointer;
  flex-shrink: 0;
}
.process-tracker .trk-pop-x:hover { color: var(--trk-ink); border-color: var(--trk-faint); }
/* ── THE QUESTION IS THE HEADLINE (PDS-419) ────────────────────────────────
   The owner: "a principal coisa nesse modal é a pergunta, que tem que estar
   muito clara e visível. E ela está simplesmente em linha minúscula, na miúda."

   ⚠️ THIS IS THE SAME INVERSION HE CORRECTED IN THE TRACKER THIS MORNING, and
   the rule was already written into `.trk-doc-name` above: WHAT VARIES IS THE
   HEADLINE. The work popup put a label identical on all 24 questions at 14.5px
   bold and the question — the only thing that changes, and the entire reason
   the popup opens — at 11.5px grey. The generic label is gone; the section
   headings inside say what it said, where the work is.

   The eyebrow carries the code and the axis: both are short, both are useful
   for scanning, and neither competes with the sentence under it. */
.process-tracker .trk-pop-code {
  display: block;
  font-family: var(--trk-mono);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--trk-faint);
}
.process-tracker .trk-pop-q {
  margin: 3px 0 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.32;
  letter-spacing: -.015em;
  color: var(--trk-ink);
  text-wrap: balance;
}

/* One stacked section of the work popup. The heading is a kicker because it
   labels a region and carries no state — the same rule that keeps kickers out
   of the badge vocabulary. The rule between sections is what the tab strip used
   to do: say where one ends and the next begins. */
.process-tracker .trk-sect { display: grid; gap: 8px; }
.process-tracker .trk-sect + .trk-sect { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--trk-line-soft); }

.process-tracker .trk-pop-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 18px;
  display: grid;
  gap: 14px;
  align-content: start;
}
.process-tracker .trk-pop-foot {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  padding: 11px 18px;
  border-top: 1px solid var(--trk-line-soft);
  background: var(--trk-bg);
}

/* ---- the email popup's FOUR ZONES (owner-approved reorganization, 06/aug:
   one voice and one line per zone; only the conversation may grow) ---- */

/* zone 1 — WHO: serif name + the one pill (ball possession); contact subline;
   one mono meta line (kind · count · waiting since) */
.process-tracker .trk-mail-meta {
  font-family: var(--trk-mono);
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--trk-faint);
}

/* zone 2 — THE CLOCK: expected return in ONE line, state left, control right.
   The single home of the promise (the first-send field died with it). */
.process-tracker .trk-expect {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  padding: 8px 18px;
  border-bottom: 1px solid var(--trk-line-soft);
  background: var(--trk-bg);
}
.process-tracker .trk-expect .trk-expect-v { font-size: 12px; }
.process-tracker .trk-expect .trk-expect-ctrl { margin-left: auto; display: flex; align-items: center; gap: 7px; }
.process-tracker .trk-expect .trk-expect-ctrl .trk-input { width: auto; padding: 4px 8px; font-size: 12px; }
.process-tracker .trk-expect .trk-expect-ctrl button {
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 650;
  font-family: var(--trk-sans);
  color: var(--trk-navy);
  background: none;
  border: 1px solid var(--trk-navy);
  border-radius: var(--trk-r-s);
  cursor: pointer;
}

/* zone 3 — THE CONVERSATION, the protagonist: a mini-spine in the tracker's
   own language. No left-accent stripe (owner, 06/aug).

   THE NUB CARRIES STATE, NOT DIRECTION (owner, 07/aug — the first cut had a
   filled green nub for everything that left here, and green read as finished on
   the exact message still waiting for an answer):
     · amber ring + dot  — sent and UNANSWERED, the transitory state; the same
                           mark a waiting step wears on the spine
     · neutral solid     — sent and answered later: history, no colour owed
     · green solid check — something ARRIVED; the only event that advanced the
                           document, and the palette's only "done"
     · dashed grey       — internal (a reopen)
   Direction stays in the words (REQUEST SENT · to … / DOCUMENT RECEIVED · from
   …), so the colour is free to say what the words cannot. */
.process-tracker .trk-tl { position: relative; display: grid; gap: 12px; padding-left: 26px; }
.process-tracker .trk-tl::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 10px;
  bottom: 10px;
  width: 2px;
  background: var(--trk-line);
  border-radius: 2px;
}
.process-tracker .trk-tl-item { position: relative; }
.process-tracker .trk-tl-nub { position: absolute; left: -26px; top: 8px; width: 14px; height: 14px; border-radius: 50%; box-sizing: border-box; }
.process-tracker .trk-tl-nub::after { content: ""; display: block; }
/* sent, still unanswered — open ring, amber dot inside */
.process-tracker .trk-tl-item.trk-tl-wait .trk-tl-nub {
  border: 2.5px solid var(--trk-amber);
  background: var(--trk-panel);
  display: grid;
  place-items: center;
}
.process-tracker .trk-tl-item.trk-tl-wait .trk-tl-nub::after {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--trk-amber);
}
/* sent and answered later — history: solid, quiet, no colour owed */
.process-tracker .trk-tl-item.trk-tl-out .trk-tl-nub { background: var(--trk-faint); }
/* arrived — the one event that advanced the document; check DRAWN, never a glyph */
.process-tracker .trk-tl-item.trk-tl-in .trk-tl-nub { background: var(--trk-green); display: grid; place-items: center; }
.process-tracker .trk-tl-item.trk-tl-in .trk-tl-nub::after {
  width: 3.5px;
  height: 6.5px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}
.dark .process-tracker .trk-tl-item.trk-tl-in .trk-tl-nub::after { border-color: #10201a; }
.process-tracker .trk-tl-item.trk-tl-int .trk-tl-nub { border: 2px dashed var(--trk-faint); background: var(--trk-panel); }
/* captured by e-mail and NOT decided yet — navy ring, the same mark the
   Architectural exchange gives a pending reply. Deliberately not green: nothing
   is on file until somebody confirms this is the file. */
.process-tracker .trk-tl-item.trk-tl-pend .trk-tl-nub { border: 2.5px solid var(--trk-navy); background: var(--trk-panel); }
/* the wash alone was too quiet to find in a long conversation (owner, 20/ago:
   "melhoremos a visibilidade"), so the card also carries the navy edge — the
   same weight the rail's filled marker and the spine's filled tag carry. */
.process-tracker .trk-tl-item.trk-tl-pend .trk-mail-msg {
  background: var(--trk-amber-soft);
  border-color: var(--trk-amber);
  border-left: 3px solid var(--trk-navy);
}
.process-tracker .trk-tl-item.trk-tl-pend .trk-mail-kind { color: var(--trk-navy); }
.process-tracker .trk-mail-msg {
  border: 1px solid var(--trk-line-soft);
  border-radius: var(--trk-r);
  background: var(--trk-bg);
  padding: 10px 13px;
  display: grid;
  gap: 6px;
}
.process-tracker .trk-mail-msg .trk-mail-kind {
  font-family: var(--trk-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--trk-sub);
}
.process-tracker .trk-tl-item.trk-tl-wait .trk-mail-kind { color: var(--trk-amber); }
.process-tracker .trk-tl-item.trk-tl-in .trk-mail-kind { color: var(--trk-green); }
.process-tracker .trk-mail-body { font-size: 12.5px; line-height: 1.55; color: var(--trk-ink); }
.process-tracker .trk-mail-body b { font-weight: 650; }
.process-tracker .trk-file-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--trk-sub);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  padding: 3px 10px;
  background: var(--trk-panel);
}
.process-tracker .trk-file-chip:hover { border-color: var(--trk-navy); color: var(--trk-navy); }
.process-tracker .trk-file-chip .trk-file-sz { font-weight: 400; color: var(--trk-faint); flex-shrink: 0; }

/* zone 4 — THE COMPOSER's hairline rows (e-mail client voice): label inside
   the row, no boxes; the body is the dominant, frameless field. */
.process-tracker .trk-crow {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--trk-line-soft);
}
.process-tracker .trk-crow .trk-crow-lab {
  width: 66px;
  flex-shrink: 0;
  font-family: var(--trk-mono);
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--trk-faint);
}
/* the editable stretch reads as a FIELD (owner, 07/aug: "não dá pra perceber
   que isso é um campo de texto"): a soft well — line-soft ground, 6px corners
   — much lighter than the old boxed inputs but unmistakably writable. */
.process-tracker .trk-crow select,
.process-tracker .trk-crow input {
  flex: 1;
  min-width: 0;
  border: none;
  background: var(--trk-line-soft);
  border-radius: var(--trk-r-s);
  padding: 5px 9px;
  font-size: 13px;
  font-family: var(--trk-sans);
  color: var(--trk-ink);
}
.process-tracker .trk-crow select:focus-visible,
.process-tracker .trk-crow input:focus-visible { outline: 2px solid var(--trk-navy); outline-offset: 1px; }
.process-tracker .trk-cfree {
  width: 100%;
  box-sizing: border-box;
  border: none;
  background: none;
  resize: vertical;
  padding: 12px 0 8px;
  min-height: 88px;
  font-size: 13.5px;
  line-height: 1.6;
  font-family: var(--trk-sans);
  color: var(--trk-ink);
}
.process-tracker .trk-cfree::placeholder { color: var(--trk-faint); }
.process-tracker .trk-cfree:focus-visible { outline: none; }

/* the attach CHIP (dock variant of the drawn control): rides the same
   pre-permit-attach controller, filename lands inside the chip */
.process-tracker .trk-attach-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  padding: 6px 13px;
  font-size: 12px;
  font-weight: 650;
  color: var(--trk-navy);
  border: 1.5px dashed var(--trk-line);
  border-radius: var(--trk-r-s);
  background: var(--trk-panel);
  cursor: pointer;
}
.process-tracker .trk-attach-chip:hover { border-color: var(--trk-navy); }
.process-tracker .trk-attach-chip input[type="file"] { position: absolute; left: 8px; bottom: 2px; width: 1px; height: 1px; opacity: 0; }
.process-tracker .trk-attach-chip .trk-attach-name { margin-left: 0; min-width: 0; overflow-wrap: anywhere; text-align: left; font-size: 11.5px; font-style: italic; color: var(--trk-faint); }
.process-tracker .trk-attach-chip.has-file { border-style: solid; border-color: var(--trk-navy); }
.process-tracker .trk-attach-chip.has-file .trk-attach-name { font-style: normal; font-weight: 600; color: var(--trk-ink); }

/* the docked composer and its numbered step tabs: 1 chase, 2 register what
   arrived. The numeral is DRAWN (a bordered circle), same rule as every mark
   in this skin — platform glyph coverage is not UI. */
.process-tracker .trk-composer { flex-shrink: 0; border-top: 1px solid var(--trk-line-soft); background: var(--trk-bg); }
.process-tracker .trk-ctabs { display: flex; gap: 2px; padding: 6px 18px 0; border-bottom: 1px solid var(--trk-line-soft); }
.process-tracker .trk-ctab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--trk-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--trk-sub);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 7px 10px 8px;
  margin-bottom: -1px;
  cursor: pointer;
}
.process-tracker .trk-ctab:hover { color: var(--trk-ink); }
.process-tracker .trk-ctab.on { color: var(--trk-navy); border-bottom-color: var(--trk-navy); }
.process-tracker .trk-ctab-num {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  border: 1.5px solid var(--trk-faint);
  color: var(--trk-sub);
  background: var(--trk-panel);
}
.process-tracker .trk-ctab.on .trk-ctab-num { background: var(--trk-navy); border-color: var(--trk-navy); color: var(--trk-act-ink); }
.process-tracker .trk-cbody { padding: 12px 18px 14px; display: grid; gap: 10px; }
.process-tracker .trk-cpane { padding: 4px 18px 0; }
.process-tracker .trk-cdock { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 10px 18px 14px; }
/* the hidden ATTRIBUTE always wins inside the tracker — a display utility
   (flex/grid/contents) on the same element would otherwise override the UA's
   [hidden] rule and un-hide the inactive composer step */
.process-tracker [hidden] { display: none !important; }
.process-tracker .trk-cfoot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }

/* the drawn attach control: dashed row, filename in place, solid once chosen.
   The input is 1px-and-transparent, never display:none — a required file field
   the browser cannot focus blocks submission silently. */
.process-tracker .trk-attach {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 13px;
  border: 1.5px dashed var(--trk-line);
  border-radius: var(--trk-r);
  background: var(--trk-panel);
  cursor: pointer;
}
.process-tracker .trk-attach:hover { border-color: var(--trk-navy); background: var(--trk-navy-soft); }
.process-tracker .trk-attach input[type="file"] { position: absolute; left: 8px; bottom: 4px; width: 1px; height: 1px; opacity: 0; }
.process-tracker .trk-attach-cta { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 650; color: var(--trk-navy); white-space: nowrap; }
.process-tracker .trk-attach-name { margin-left: auto; min-width: 0; overflow-wrap: anywhere; text-align: right; font-size: 11.5px; font-style: italic; color: var(--trk-faint); }
.process-tracker .trk-attach.has-file { border-style: solid; border-color: var(--trk-navy); background: var(--trk-panel); }
.process-tracker .trk-attach.has-file .trk-attach-name { font-style: normal; font-weight: 600; color: var(--trk-ink); }

/* list rows inside popups (owner, 06/aug: rows, never chips — full text, the
   whole list scrolls, nothing behind a "+15") */
.process-tracker .trk-rows { border: 1px solid var(--trk-line); border-radius: var(--trk-r); overflow: hidden; background: var(--trk-panel); }

/* ONE COMMENT (owner: low visibility, wants more contrast/highlight). Its own
   card and not a `trk-row` divider — a chat needs each message to read as a
   distinct utterance sitting on the panel, not a line in a list. Author name
   at full ink contrast, not the faint caption weight the row pattern uses. */
.process-tracker .trk-comment {
  padding: 8px 12px;
  background: var(--trk-bg);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
}
.process-tracker .trk-comment-meta {
  font-family: var(--trk-mono);
  font-size: 10.5px;
  font-weight: 700;
  color: var(--trk-sub);
}
.process-tracker .trk-comment-meta b { color: var(--trk-ink); }
.process-tracker .trk-comment-body { margin-top: 3px; font-size: 13px; line-height: 1.45; color: var(--trk-ink); }
.process-tracker .trk-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 13px;
  border-top: 1px solid var(--trk-line-soft);
  text-align: left;
}
.process-tracker .trk-row:first-child { border-top: none; }
.process-tracker .trk-row:hover { background: var(--trk-bg); }
.process-tracker .trk-row-body { flex: 1; min-width: 0; }
.process-tracker .trk-row-t { display: block; font-size: 13px; font-weight: 600; color: var(--trk-ink); line-height: 1.35; }
.process-tracker .trk-row-d { display: block; margin-top: 1px; font-size: 11.5px; line-height: 1.45; color: var(--trk-sub); }
/* a row that is also a CHOICE (PDS-414): the triage options, the companies and
   the three information statuses are lists where one entry is selected, and the
   chip row they replaced could not carry the consequence line that makes the
   choice legible. `align-items: flex-start` so a two-line option keeps its radio
   on the first line. */
.process-tracker label.trk-row, .process-tracker a.trk-row { align-items: flex-start; cursor: pointer; text-decoration: none; }
.process-tracker .trk-row-on { background: var(--trk-green-soft); }
.process-tracker .trk-row-on:hover { background: var(--trk-green-soft); }
.process-tracker .trk-row-on .trk-row-t { color: var(--trk-green); }

/* ---- the question header and the answer box (PDS-419) ----
   TWO HEADLINES, ONE AT A TIME. Unanswered, the question is the panel's subject
   and takes the display size; answered, it demotes to a label and the ANSWER
   takes it. The owner: "uma vez que foi respondida, ela deixa de ser o principal
   componente e a resposta se torna o destaque." Same inversion `.trk-doc-name`
   made on the tracker — what varies is what gets the body. */
.process-tracker .trk-q-head {
  margin: 4px 0 0;
  font-size: 17px;
  line-height: 1.3;
  font-weight: 700;
  letter-spacing: -.013em;
  text-wrap: balance;
  color: var(--trk-ink);
}
.process-tracker .trk-q-label { min-width: 0; font-size: 12.5px; line-height: 1.4; color: var(--trk-sub); }

/* THE BOX IS DRAWN ONLY WHEN IT HAS A FACT (see `answer_box?`). It is not a
   frame for the header — it is the answer's own region, which is why the
   provenance and the wait live inside it and not around it. */
.process-tracker .trk-ansbox {
  margin-top: 10px;
  padding: 9px 13px 11px;
  background: var(--trk-bg);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
}
/* Locked: the box does not sit empty waiting, it says what it is waiting ON —
   which is the one thing the deleted amber banner knew that nothing else did. */
.process-tracker .trk-ansbox-locked { background: var(--trk-amber-soft); border-color: var(--trk-amber); }
.process-tracker .trk-ansbox-locked .trk-kicker { color: var(--trk-amber); opacity: .8; }
/* And the same for the status the box is carrying (owner, 07/ago) — green
   confirmed, amber searching, red blocked. The tones are the badge's, so the
   fill and the badge on top of it can never say different things; the border
   stays at full strength, which is what the locked box already established.
   No status means no tint: absence is not a fourth colour. */
.process-tracker .trk-ansbox-green { background: var(--trk-green-soft); border-color: var(--trk-green); }
.process-tracker .trk-ansbox-amber { background: var(--trk-amber-soft); border-color: var(--trk-amber); }
.process-tracker .trk-ansbox-red   { background: var(--trk-red-soft);   border-color: var(--trk-red); }
/* ⚠️ THE BADGE KEEPS ITS FILL ON A TINTED GROUND (owner, 07/ago: "informações
   desse estado desapareceram com o background verde"). `badge-green` fills with
   #e5f0ea and `--trk-green-soft` IS #e5f0ea — the same hex, so the chip
   dissolved into the box and the state was left as bare coloured text. A badge
   without a fill is not a badge.
   The chip takes the panel's own ground: it reads as an object again, and the
   state still speaks twice — in the badge's ink and in the wash around it.
   The two faint labels get one step darker for the same reason: `--trk-faint`
   over a tint is 2.4:1, and these are the words that say WHICH fact each cell
   is. */
.process-tracker .trk-ansbox-green .badge,
.process-tracker .trk-ansbox-amber .badge,
.process-tracker .trk-ansbox-red .badge,
.process-tracker .trk-ansbox-locked .badge { background: var(--trk-panel); }
.process-tracker .trk-ansbox-green .trk-kicker,
.process-tracker .trk-ansbox-amber .trk-kicker,
.process-tracker .trk-ansbox-red .trk-kicker,
.process-tracker .trk-ansbox-green .trk-ansbox-meta,
.process-tracker .trk-ansbox-amber .trk-ansbox-meta,
.process-tracker .trk-ansbox-red .trk-ansbox-meta { color: var(--trk-sub); }
/* and the date inside it keeps a step of its own, or the whole line flattens */
.process-tracker .trk-ansbox-green .trk-ansbox-meta b,
.process-tracker .trk-ansbox-amber .trk-ansbox-meta b,
.process-tracker .trk-ansbox-red .trk-ansbox-meta b { color: var(--trk-ink); }
.process-tracker .trk-ansbox-v {
  margin-top: 2px;
  font-size: 21px;
  line-height: 1.25;
  font-weight: 650;
  letter-spacing: -.015em;
  text-wrap: balance;
  color: var(--trk-ink);
}
.process-tracker .trk-ansbox-waiting { font-size: 17px; color: var(--trk-amber); }
.process-tracker .trk-waiting-link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.process-tracker .trk-waiting-link:hover { color: var(--trk-ink); }
.process-tracker .trk-ansbox-cells {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid var(--trk-line-soft);
}
.process-tracker .trk-ansbox-cell { margin-top: 2px; font-size: 12.5px; font-weight: 600; color: var(--trk-ink); }
.process-tracker .trk-ansbox-meta { margin-top: 8px; font-size: 11.5px; line-height: 1.5; color: var(--trk-faint); }
.process-tracker .trk-ansbox-meta b { color: var(--trk-sub); font-weight: 600; }

/* the reference "?" — a circle in the situation header; everything the drawer
   used to fold opens in its popup, off the working surface */
.process-tracker .trk-ref-btn {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--trk-line);
  background: var(--trk-panel);
  color: var(--trk-sub);
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}
.process-tracker .trk-ref-btn:hover { border-color: var(--trk-navy); color: var(--trk-navy); background: var(--trk-navy-soft); }

/* one reference section inside the "?" popup (the old drawer's h4/p voice,
   scoped so it never bleeds into the email popup's paragraphs) */
.process-tracker .trk-refsec { display: grid; gap: 6px; }
.process-tracker .trk-refsec h4 {
  margin: 0;
  font-family: var(--trk-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--trk-faint);
}
.process-tracker .trk-refsec p { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--trk-sub); max-width: 64ch; }
.process-tracker .trk-refsec p b { color: var(--trk-ink); }

/* fee table, per-part */
.process-tracker .trk-fee { border: 1px solid var(--trk-line); border-radius: var(--trk-r); overflow: hidden; max-width: 520px; background: var(--trk-panel); }
.process-tracker .trk-fee-row { display: flex; align-items: baseline; gap: 10px; padding: 8px 13px; border-top: 1px solid var(--trk-line-soft); font-size: 13px; }
.process-tracker .trk-fee-row:first-child { border-top: none; }
.process-tracker .trk-fee-row .trk-fee-n { flex: 1; min-width: 0; color: var(--trk-ink); }
.process-tracker .trk-fee-row .trk-fee-n small { color: var(--trk-faint); font-family: var(--trk-mono); font-size: 10.5px; margin-left: 6px; }
.process-tracker .trk-fee-row .trk-fee-a { font-family: var(--trk-mono); font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px; text-align: right; }
.process-tracker .trk-fee-row .trk-fee-a.trk-fee-na { font-weight: 400; font-style: italic; color: var(--trk-faint); font-size: 12px; }
.process-tracker .trk-fee-foot { padding: 8px 13px; border-top: 1px solid var(--trk-line); background: var(--trk-bg); font-size: 11.5px; line-height: 1.55; color: var(--trk-sub); }

/* reference chips (also activated / also affects / chain) */
.process-tracker .trk-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  color: var(--trk-sub);
  max-width: 100%;
}
.process-tracker .trk-chip:hover { border-color: var(--trk-faint); color: var(--trk-ink); }
.process-tracker .trk-chip-on { border-color: var(--trk-green); color: var(--trk-green); }

/* facts list (recorded filing, sent request, thread status) */
.process-tracker .trk-facts { display: grid; }
.process-tracker .trk-fact { display: flex; align-items: baseline; gap: 10px; padding: 6px 0; border-top: 1px solid var(--trk-line-soft); }
.process-tracker .trk-fact:first-child { border-top: none; }
.process-tracker .trk-fact dt { width: 110px; flex-shrink: 0; font-family: var(--trk-mono); font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--trk-faint); }
.process-tracker .trk-fact dd { min-width: 0; flex: 1; overflow-wrap: break-word; font-size: 12.5px; font-weight: 500; color: var(--trk-ink); }

/* ---- provenance footer ---- */
.process-tracker .trk-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  padding: 10px 20px;
  border-top: 1px solid var(--trk-line-soft);
  background: var(--trk-bg);
  font-size: 11.5px;
  color: var(--trk-faint);
}
.process-tracker .trk-foot b { color: var(--trk-sub); font-weight: 600; }
.process-tracker .trk-foot .trk-flag { margin-left: auto; font-family: var(--trk-mono); font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; }
.process-tracker .trk-foot .trk-flag-op { color: var(--trk-green); }

/* ---- rail ---- */
/* ── THE SEGMENT BAR ────────────────────────────────────────────────────────
   The Pre-permit rail filters on one axis — is this work, was nobody asked, or
   was it checked and cleared — and it says so ONCE, here, instead of repeating
   the answer as a collapsed line inside every category (which is how the rail
   came to print "checked — not required" three times in a row, one of them a
   category heading).

   IT IS A CONTROL, SO THE ACTIVE ONE IS A CARD AND THE REST ARE INK. Same move
   `.trk-rail-row.trk-sel` makes eight rules down: the panel ground plus the
   shadow is what "you are here" looks like on this skin, and it is the only
   place a raised surface is spent. Hover takes navy, because navy is what you
   click (07/ago) — the counts underneath report a fact and stay `--trk-sub`.

   The count is the LARGER of the two lines on purpose. The word is a label the
   operator learns once; the number is what they came to read, and it is the
   thing the collapsed groups existed to protect. */
.process-tracker .trk-seg {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
  padding: 8px 8px 5px;
  border-bottom: 1px solid var(--trk-line-soft);
}
.process-tracker .trk-seg button {
  flex: 1;
  min-width: 0;
  padding: 5px 4px;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--trk-r);
  cursor: pointer;
  font-family: var(--trk-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  line-height: 1.35;
  color: var(--trk-faint);
}
.process-tracker .trk-seg button > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.process-tracker .trk-seg button .ct { font-size: 11px; color: var(--trk-sub); font-variant-numeric: tabular-nums; }
/* The qualifier of a triage fraction ("1 not applicable"). It gets a LINE and
   not a tooltip, which is the rule stated where `Fraction` is defined: a
   tooltip is not a place to keep a fact this screen exists to state. Rendered
   only when there is a closed question, so most leads see two lines. */
.process-tracker .trk-seg button .cav { font-size: 8.5px; font-weight: 400; letter-spacing: .02em; text-transform: none; color: var(--trk-faint); }
.process-tracker .trk-seg button:hover { color: var(--trk-navy); background: var(--trk-navy-soft); }
.process-tracker .trk-seg button:hover .ct { color: var(--trk-navy); }
.process-tracker .trk-seg button[aria-pressed="true"] {
  background: var(--trk-panel);
  border-color: var(--trk-line);
  box-shadow: var(--trk-shadow);
  color: var(--trk-ink);
}
.process-tracker .trk-seg button[aria-pressed="true"] .ct { color: var(--trk-ink); }

.process-tracker .trk-rail-cat { display: flex; align-items: baseline; gap: 7px; padding: 12px 10px 5px; }
.process-tracker .trk-rail-open { font-family: var(--trk-mono); font-size: 10px; font-weight: 700; color: var(--trk-red); flex-shrink: 0; }
.process-tracker .trk-rail-ask { font-family: var(--trk-mono); font-size: 10px; color: var(--trk-faint); flex-shrink: 0; }
.process-tracker .trk-rail-ct { margin-left: auto; font-family: var(--trk-mono); font-size: 10px; color: var(--trk-faint); flex-shrink: 0; }
.process-tracker .trk-rail-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--trk-r);
  font-size: 12.5px;
  color: var(--trk-sub);
}
.process-tracker .trk-rail-row:hover { background: var(--trk-panel); }
.process-tracker .trk-rail-row.trk-sel { background: var(--trk-panel); box-shadow: var(--trk-shadow); color: var(--trk-ink); font-weight: 650; }
/* ── THE DISCLOSURE LINE (PDS-418) ─────────────────────────────────────────
   Stands in a section for the rows that were taken out of the queue: locked
   questions on the Triage side, documents nobody was asked about on the
   Pre-permit side. It carries the COUNT, because the count is the fact that
   keeps hiding from becoming erasing — and it only renders when there is
   something behind it.

   It is a control, so it takes the navy of action on hover (07/ago: what you
   click or focus is navy, what reports a fact is green) — but at rest it is as
   quiet as a kicker, because it is not work either. */
.process-tracker .trk-disclose {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  padding: 5px 10px;
  margin-top: 1px;
  background: none;
  border: 0;
  border-radius: var(--trk-r);
  cursor: pointer;
  font-family: var(--trk-mono);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--trk-faint);
  text-align: left;
}
.process-tracker .trk-disclose:hover { color: var(--trk-navy); background: var(--trk-navy-soft); }
/* The chevron is DRAWN, like every other mark in this skin — platform glyph
   coverage is not UI. */
.process-tracker .trk-chev {
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  margin-left: 2px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
}
.process-tracker .trk-chev-open { transform: rotate(45deg); }
/* The revealed rows keep a rule down their left so they read as a group that
   was opened, not as rows that always lived there. */
.process-tracker .trk-revealed { margin-left: 10px; padding-left: 6px; border-left: 2px solid var(--trk-line-soft); }

.process-tracker .trk-mk { flex-shrink: 0; font-family: var(--trk-mono); font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--trk-faint); }
.process-tracker .trk-mk-warn { color: var(--trk-amber); }
/* the reply in hand — the rail's only filled marker, because it is the only one
   that names work already delivered and sitting on this desk (PDS-388 S3c) */
.process-tracker .trk-mk-reply {
  color: var(--trk-navy);
  background: var(--trk-navy-soft);
  padding: 1px 4px;
  border-radius: 2px;
}
/* THE SECOND LEVEL, WHICH ONLY THE TRIAGE RAIL HAS (PDS-417): an axis is split
   into the jurisdiction's own phases, so a phase sits between the category
   heading and the rows. Lighter than `.trk-rail-cat` and indented, because it
   subdivides rather than opens — and it keeps its own fraction on the right for
   the reason the axis header does: the axis total is the sum of these, and the
   phase is where the operator goes looking for the missing one. */
.process-tracker .trk-rail-sub {
  display: flex;
  align-items: baseline;
  gap: 7px;
  padding: 7px 10px 3px 18px;
  font-size: 11px;
  color: var(--trk-faint);
}
.process-tracker .trk-rail-sub .trk-rail-ct { font-size: 9.5px; }

.process-tracker .trk-rail-sum {
  flex-shrink: 0;
  margin: 10px;
  padding: 10px 13px;
  background: var(--trk-panel);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
}

/* rail state dots — same six states the helper names, tracker palette */
.process-tracker .trk-d { flex-shrink: 0; width: 7px; height: 7px; border-radius: 50%; }
.process-tracker .trk-d-on { background: var(--trk-green); }
.process-tracker .trk-d-wait { background: var(--trk-amber); }
.process-tracker .trk-d-block { background: var(--trk-red); }
.process-tracker .trk-d-off { background: var(--trk-line); }
/* `trk-d-unstated` LIVED HERE (PDS-418) AND WAS REMOVED BY PDS-420. It drew the
   answered question whose status nobody had declared — hollow green, because the
   answer was there and the fill is what `confirmed` earns. The state lasted one
   day: an answered question now derives `confirmed`, so the dot it needed is
   `trk-d-on`. */
.process-tracker .trk-d-ask { background: transparent; border: 1.5px solid var(--trk-faint); }
.process-tracker .trk-d-hold { background: transparent; border: 1.5px solid var(--trk-amber); }
.process-tracker .trk-d-na { background: var(--trk-line-soft); }

/* ---- misc ---- */
.process-tracker .trk-addr { font-size: 15px; font-weight: 650; color: var(--trk-ink); letter-spacing: -.012em; }
/* pre-WRAP, never pre + overflow-x (owner, 06/aug): the form's own line must
   read verbatim but no container of this panel may scroll horizontally. */
.process-tracker .trk-verbatim {
  font-family: var(--trk-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--trk-sub);
  white-space: pre-wrap;
  overflow-wrap: break-word;
  padding: 8px 12px;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
  background: var(--trk-panel);
}

/* CHECKBOX MARKS ARE DRAWN, NEVER GLYPHS (owner, 06/aug): U+2610/U+2611 render
   as tofu on Chrome/Linux — the UI never depends on unicode coverage. The
   check inside the ticked box is a rotated border L, same trick as any CSS
   checkmark, in the tracker's own green. */
.process-tracker .trk-box {
  position: relative;
  display: inline-block;
  width: 13px;
  height: 13px;
  border: 1.5px solid var(--trk-faint);
  border-radius: var(--trk-r-s);
  vertical-align: -1px;
  flex-shrink: 0;
}
.process-tracker .trk-box-on { background: var(--trk-green); border-color: var(--trk-green); }
.process-tracker .trk-box-on::after {
  content: "";
  position: absolute;
  left: 3px;
  top: 0.5px;
  width: 4px;
  height: 7px;
  border: solid #fff;
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
.dark .process-tracker .trk-box-on::after { border-color: #10201a; }
.process-tracker .trk-box-undecided { border-color: var(--trk-amber); border-style: dashed; }

/* the presentation of "☐" inside the verbatim line — the YAML keeps the form's
   own characters, the view swaps them for a drawn square. */
.process-tracker .trk-vbox {
  display: inline-block;
  width: .8em;
  height: .8em;
  border: 1.2px solid currentColor;
  border-radius: var(--trk-r-s);
  margin: 0 .3em 0 .15em;
  vertical-align: -.06em;
  opacity: .75;
}
/* ── THE WAIT CLOCK (PDS-414) ──────────────────────────────────────────────
   How long the current step has been owed, and — when a window exists — how
   that figure reads against it. The one emphatic number on the panel, because
   it is the only one that moves on its own.

   THE BAR IS NOT DECORATION AND IT IS NOT ALWAYS THERE. A bar needs two ends:
   it renders only when PrePermit::WaitClock reports a window. On `:open` and
   `:blocked` there is none, and drawing one would invent a deadline this app
   never recorded — which is also why the figure goes NEUTRAL on `:open`
   instead of amber. Nothing is late when nothing was promised; the missing
   promise is the finding.

   The three inks come from `Clock#tone`, never from the template. */
.process-tracker .trk-clock { width: 190px; flex: 0 0 auto; }
/* INSIDE THE ANSWER BOX THE FIGURE SHRINKS (PDS-419). At 38px it was the largest
   thing on the panel, so promoting the answer to 21px still lost the comparison —
   and the wait is not a peer of the answer, it is a CONSEQUENCE of this answer's
   status being open. Reversible in one line: drop `small: true` at the call site
   and the clock goes back to full size beside the box. */
.process-tracker .trk-clock-sm { width: 150px; }
.process-tracker .trk-clock-sm .trk-clock-n b { font-size: 19px; letter-spacing: -.02em; }
.process-tracker .trk-clock-sm .trk-clock-n span { font-size: 10px; }
.process-tracker .trk-clock-sm .trk-clock-bar { margin-top: 8px; }
.process-tracker .trk-clock-sm .trk-clock-verdict { margin-top: 7px; }
.process-tracker .trk-clock-n { display: flex; align-items: baseline; gap: 7px; color: var(--trk-amber); }
.process-tracker .trk-clock-n b {
  font-size: 38px;
  line-height: .92;
  font-weight: 700;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}
.process-tracker .trk-clock-n span {
  font-size: 11px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .08em;
}
.process-tracker .trk-clock-red .trk-clock-n { color: var(--trk-red); }
.process-tracker .trk-clock-neutral .trk-clock-n { color: var(--trk-sub); }

/* ⚠️ THE SEGMENTS ARE <rect>s, NOT FLEX CHILDREN. The proportion has to come
   from the data, and this app's CSP has no `unsafe-inline` in `style_src`, so
   `style="flex: 10"` is discarded by the browser with no error — the first
   version of this bar rendered two zero-width segments. `width`/`x` on a rect
   are presentation attributes and survive; only the FILL comes from here. */
.process-tracker .trk-clock-bar {
  height: 5px;
  margin-top: 11px;
  border-radius: var(--trk-r-s);
  overflow: hidden;
  background: var(--trk-line-soft);
}
.process-tracker .trk-clock-bar svg { display: block; width: 100%; height: 100%; }
.process-tracker .trk-clock-bar .trk-clock-used { fill: var(--trk-amber); }
.process-tracker .trk-clock-bar .trk-clock-over { fill: var(--trk-red); }

.process-tracker .trk-clock-scale {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
  font-size: 10.5px;
  color: var(--trk-faint);
  font-variant-numeric: tabular-nums;
}
.process-tracker .trk-clock-verdict { margin-top: 9px; font-size: 11.5px; line-height: 1.45; color: var(--trk-sub); }
.process-tracker .trk-clock-verdict b { font-weight: 700; color: var(--trk-amber); }
.process-tracker .trk-clock-red .trk-clock-verdict b { color: var(--trk-red); }
.process-tracker .trk-clock-neutral .trk-clock-verdict b { color: var(--trk-sub); }

/* The same figure in the rail, one glyph wide. It is what makes the column
   scannable for what is ROTTING without opening anything — a question sitting
   with the county for 41 days used to render exactly like one answered this
   morning. */
.process-tracker .trk-days {
  flex: 0 0 auto;
  margin-left: 8px;
  font-family: var(--trk-mono);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  color: var(--trk-amber);
}
.process-tracker .trk-days-red { color: var(--trk-red); font-weight: 700; }
.process-tracker .trk-days-neutral { color: var(--trk-faint); }

/* ── BLOCK 0 (PDS-415) ─────────────────────────────────────────────────────
   A FRACTION, NOT A CLOCK. These lines are not out with anybody — no "since
   when", nothing to be late against — so the gate states how many of three are
   agreed and never how long. The pips are the same three, at a glance: solid
   green agreed, amber has a value nobody confirmed yet, empty has neither. */
.process-tracker .trk-bz-tally { display: inline-flex; align-items: baseline; gap: 6px; color: var(--trk-amber); }
.process-tracker .trk-bz-tally b {
  font-size: 30px;
  line-height: .9;
  font-weight: 700;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.process-tracker .trk-bz-tally span {
  font-size: 11px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .08em;
}
.process-tracker .trk-bz-tally-done { color: var(--trk-green); }
.process-tracker .trk-bz-pips { display: inline-flex; gap: 4px; }
.process-tracker .trk-bz-pips i { display: block; width: 22px; height: 5px; border-radius: var(--trk-r-s); background: var(--trk-line); }
.process-tracker .trk-bz-pips i.on { background: var(--trk-green); }
.process-tracker .trk-bz-pips i.now { background: var(--trk-amber); }

/* THE VALUE IS THE POINT OF THE LINE, so it is the biggest thing in it — and it
   appears ONCE. The old panel printed it as text and again as the placeholder
   inside the "Correct" box, with the editable copy louder than the fact. */
.process-tracker .trk-bz-value { margin-top: 3px; font-size: 14.5px; font-weight: 650; letter-spacing: -.01em; color: var(--trk-ink); }
.process-tracker .trk-bz-value-empty { color: var(--trk-faint); font-weight: 600; }
.process-tracker .trk-bz-caveat { font-size: 12px; font-weight: 600; color: var(--trk-amber); }

/* ── THE MARK IS THE ACT (dono, 12/ago) ─────────────────────────────────────
   Block 0 used to end every row in `.trk-rowacts` — two fixed 96px slots, so
   192px reserved on every line with one of them empty on most of them, a solid
   navy `Confirm` beside a borderless ghost that reads as disabled, and the same
   pair of decisions repeated four times down the panel. The owner cut it: "eu
   disaprovo esses botões lado a lado".

   THE STATE DOT AND THE CONFIRM BUTTON WERE ONE FACT SAID TWICE. The amber nub
   said "this line has a value nobody has agreed with"; the button beside it said
   "agree with it". They collapse into ONE object — a box you tick — and the act
   that happens nine times out of ten becomes the smallest gesture on the panel
   instead of its loudest control. The column of buttons is gone; the exception
   (`Correct` / `Change`) arrives with the cursor. This is a REGISTER, and a
   register is filled in by marking.

   ⚠️ THE SLOT IS ALWAYS 19px AND ALWAYS THERE, whatever fills it — otherwise
   the ragged left edge `.trk-rowacts` was built to fix comes back on the other
   side of the row. Six things can fill it, and the helper
   `triage_block_zero_tick` is the one place that decides which:
     router   the state dot, centred — the router never asks to be confirmed
              (03/ago), so a box would invite a click that does nothing
     ask      dashed empty box — a line with no value yet cannot be agreed with,
              and dashed is already this file's word for "the act would be here"
     confirm  live empty box → PATCH confirm_block_zero_item
     undo     live ticked box → PATCH unconfirm_block_zero_item
     vouched  ticked box, STATIC — a value a person typed is vouched for by
              whoever typed it, and the way back from that is `Correct`, never a
              tick that would leave their words on screen with nobody behind them
     pending  empty box, static — the read-only viewer

   ⚠️ GREEN IS THE MARK, NAVY IS THE CLICK, and this control is both, so the two
   tokens split by ROLE rather than by state: the resting mark is green because
   it reports where the line is, and hover/focus paints the CHROME navy because
   that is what says the box takes a click. A ticked box keeps its green under
   the cursor and gains a navy ring — repainting a state on hover would have the
   colour report the pointer instead of the fact. */
.process-tracker .trk-bz-slot {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 19px;
  height: 19px;
  margin-top: 1px;
}
.process-tracker .trk-bz-tick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 19px;
  height: 19px;
  padding: 0;
  background: none;
  border: 1.5px solid var(--trk-faint);
  border-radius: var(--trk-r-s);
  color: var(--trk-green);
}
.process-tracker button.trk-bz-tick { cursor: pointer; }
/* the check is drawn, not typed: a glyph would come out of whatever font the
   OS resolves at 19px, and this box is the same on every machine. */
.process-tracker .trk-bz-tick::after {
  content: "";
  width: 5px;
  height: 9px;
  margin-top: -2px;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
  .process-tracker .trk-bz-tick { transition: border-color .12s ease, background-color .12s ease, box-shadow .12s ease; }
  .process-tracker .trk-bz-tick::after { transition: opacity .12s ease; }
}
/* HOVER PREVIEWS THE MARK IT WOULD LEAVE — the ghost check is what tells a
   first-time reader that this box is the confirmation, without a label. */
.process-tracker button.trk-bz-tick:hover,
.process-tracker button.trk-bz-tick:focus-visible {
  border-color: var(--trk-navy);
  background: var(--trk-navy-soft);
  color: var(--trk-navy);
}
.process-tracker button.trk-bz-tick:hover::after,
.process-tracker button.trk-bz-tick:focus-visible::after { opacity: .5; }
/* ⚠️ KEEPS `--trk-faint`, NOT `--trk-line`. The disabled-button rule further up
   uses the line colour, but this box is the successor of `.trk-d-ask` — the
   hollow dot — and that one is drawn in faint for a reason: at `--trk-line` the
   dark theme puts #343026 on a #1f1d18 panel and the state disappears. Only the
   dash changes. */
.process-tracker .trk-bz-tick-ask { border-style: dashed; }
.process-tracker .trk-bz-tick-on {
  border-color: var(--trk-green);
  background: var(--trk-green);
  color: var(--trk-act-ink);
}
.process-tracker .trk-bz-tick-on::after { opacity: 1; }
.process-tracker button.trk-bz-tick-on:hover,
.process-tracker button.trk-bz-tick-on:focus-visible {
  border-color: var(--trk-green);
  background: var(--trk-green);
  color: var(--trk-act-ink);
  box-shadow: 0 0 0 2px var(--trk-navy-soft);
}
.process-tracker button.trk-bz-tick-on:hover::after,
.process-tracker button.trk-bz-tick-on:focus-visible::after { opacity: 1; }
.process-tracker .trk-bz-tick:focus-visible { outline: 2px solid var(--trk-navy); outline-offset: 2px; }

/* ⚠️ THE EXCEPTION ARRIVES WITH THE CURSOR, AND `opacity` IS WHY IT IS STILL
   REACHABLE. `display: none` would take `Correct` out of the tab order, so the
   keyboard would lose the act the mouse gets on hover; at zero opacity the
   button stays in the document, and `:focus-within` on the row brings it up the
   moment somebody tabs into it. A pointerless device never had a hover to wait
   for, so there it is simply always on.

   The one act that does NOT hide is the line that is a real question: it is the
   only thing on this panel that is asking for something, and hiding it would
   hide the panel's only pending work. It renders without `-quiet`. */
.process-tracker .trk-bz-acts { flex-shrink: 0; padding-top: 1px; }
.process-tracker .trk-bz-acts-quiet { opacity: 0; }
.process-tracker .trk-row:hover .trk-bz-acts-quiet,
.process-tracker .trk-row:focus-within .trk-bz-acts-quiet { opacity: 1; }
@media (hover: none) {
  .process-tracker .trk-bz-acts-quiet { opacity: 1; }
}
@media (prefers-reduced-motion: no-preference) {
  .process-tracker .trk-bz-acts-quiet { transition: opacity .12s ease; }
}

/* the Router mark. `.trk-kicker` is typography only — no border, no padding —
   so the chip is drawn here rather than by adding a border-color to a rule that
   has no border to colour. It earns the ink because it is the one line that
   decides which catalog, portal and library the whole workspace loads. */
.process-tracker .trk-kicker-green {
  color: var(--trk-green);
  background: var(--trk-green-soft);
  border: 1px solid var(--trk-green);
  border-radius: var(--trk-r-s);
  padding: 1px 5px;
}

.process-tracker :focus-visible { outline: 2px solid var(--trk-navy); outline-offset: 2px; }

/* ── THE ARCHITECTURAL WORKSPACE CONVERSATION, BY REVISIONS ────────────────
   The review loop of a plan is not a thread of messages, it is a sequence of
   REVISIONS: Rev A goes out, comes back marked up, Rev B is stored, and so on.
   So the list is FLAT and chronological — no grouping, no collapsing — and the
   revisions are the anchors: `.trk-ev-rev` is the only row that gets a solid,
   oversized nub and full ink, and its chip is right-aligned, so the arc
   Rev A / Rev B / Rev C reads straight down the column without opening a thing.
   Sends and replies live between the anchors and stay subordinate.

   Same construction as `.trk-tl` above (hairline on the container, nubs
   absolutely positioned over it), but a row here is a GRID, not a card: one
   line tall when it carries no body, because a review loop is long and a stack
   of boxes would bury the three revisions inside it. */
.process-tracker .trk-ev-list { position: relative; padding-left: 26px; }
/* inset top and bottom so the line starts and stops AT the first and last nub
   centres (row padding 5px + half a 18.75px line ≈ 14px) — a hairline running
   past the last mark reads as a conversation that continues somewhere else. */
.process-tracker .trk-ev-list::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 14px;
  bottom: 14px;
  width: 2px;
  background: var(--trk-line);
  border-radius: 2px;
}

.process-tracker .trk-ev {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: baseline;
  column-gap: 10px;
  padding: 5px 0;
}
/* The nub is positioned against the ROW's padding box, whose left edge sits at
   the list's 26px content start; the hairline's centre is at x=7 (left 6 + half
   of 2). So an 8px mark centres at 7 - 4 - 26 = -23px. Every modifier that
   changes the nub's SIZE or the row's PADDING BOX has to redo this arithmetic —
   see `.trk-ev-rev` and `.trk-ev-pend` below. */
.process-tracker .trk-ev-nub {
  position: absolute;
  left: -23px;
  top: 10px;
  width: 8px;
  height: 8px;
  box-sizing: border-box;
  border-radius: 50%;
  border: 2px solid var(--trk-faint);
  background: var(--trk-panel);
}

.process-tracker .trk-ev-what { font-size: 12.5px; line-height: 1.5; color: var(--trk-sub); min-width: 0; }
.process-tracker .trk-ev-who {
  font-family: var(--trk-mono);
  font-size: 10px;
  color: var(--trk-faint);
  white-space: nowrap;
}
.process-tracker .trk-ev-chip {
  font-family: var(--trk-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  padding: 1px 6px;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  color: var(--trk-faint);
  white-space: nowrap;
}
.process-tracker .trk-ev-body {
  grid-column: 1 / -1;
  margin-top: 4px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--trk-sub);
  max-width: 62ch;
}
.process-tracker .trk-ev-file { grid-column: 1 / -1; justify-self: start; margin-top: 6px; }
/* the row's own act, in the trailing column so it lines up with the chips
   above it; navy because it is what you click (07/ago rule), mono uppercase
   because at this size it is a stamp and not a sentence. */
.process-tracker .trk-ev-act {
  grid-column: 3;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  font-family: var(--trk-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--trk-act-ink);
  background: var(--trk-navy);
  border: 1px solid var(--trk-navy);
  border-radius: var(--trk-r-s);
  cursor: pointer;
  white-space: nowrap;
}
.process-tracker .trk-ev-act:hover { filter: brightness(1.07); }

/* THE ANCHOR — a stored revision. Bigger and solid, because this is the only
   thing the eye needs to catch while scrolling the loop. 12px centred on the
   same hairline: 7 - 6 - 26 = -25px, and 2px higher to keep the same centre. */
.process-tracker .trk-ev-rev .trk-ev-nub {
  left: -25px;
  top: 8px;
  width: 12px;
  height: 12px;
  border: none;
  background: var(--trk-sub);
}
.process-tracker .trk-ev-rev .trk-ev-what { color: var(--trk-ink); font-weight: 660; }
.process-tracker .trk-ev-rev .trk-ev-chip { color: var(--trk-ink); border-color: var(--trk-sub); }

/* went out and has not come back — the amber ring is the same mark a waiting
   step wears on the spine, so "out with somebody" reads identically everywhere */
.process-tracker .trk-ev-open .trk-ev-nub { border: 2.5px solid var(--trk-amber); background: var(--trk-panel); }

/* ⚠️ CAME BACK ASKING FOR A CORRECTION, AND IT IS NOT GREEN (owner decision).
   The obvious reading is that anything ARRIVING deserves the arrival colour —
   that is how `.trk-tl-in` works in the email popup above. It does not hold in a
   review loop: a correction also arrives, and painting it green would say
   rework is progress. Neutral solid: it happened, it is history, no colour owed.
   Green in this list belongs to `.trk-ev-closed` alone. */
.process-tracker .trk-ev-back .trk-ev-nub { border-color: var(--trk-faint); background: var(--trk-faint); }

/* came back and nobody has read it yet: navy ring (it is owed an act) plus an
   amber wash across the whole row. The tint bleeds to the panel edges via a
   negative horizontal margin with matching padding — which MOVES THE ROW'S
   PADDING BOX, so the nub has to be pushed back onto the hairline:
     left: -23 + 10 = -13px   (margin-left -10 shifts the padding edge left 10)
     top:   10 + 2  = 12px    (padding-top goes 5 -> 7; the 2px margin-top moves
                               the box and the nub together, so it cancels) */
.process-tracker .trk-ev-pend {
  margin: 2px -10px;
  padding: 7px 10px;
  border-radius: var(--trk-r);
  background: var(--trk-amber-soft);
}
.process-tracker .trk-ev-pend .trk-ev-nub { left: -13px; top: 12px; border: 2.5px solid var(--trk-navy); background: var(--trk-panel); }
.process-tracker .trk-ev-rev.trk-ev-pend .trk-ev-nub { left: -15px; top: 10px; }

/* the event that closes the loop — the only green in the conversation */
.process-tracker .trk-ev-closed .trk-ev-nub { border-color: var(--trk-green); background: var(--trk-green); }

/* ---------------------------------------------------------------------------
   THE SPEC SHEET, WEARING THIS SKIN'S GROUND

   The sheet's cells come from the app's design system, whose fields are drawn
   in `steel` — a COOL near-white ramp meant for the app's cool canvas. Rendered
   on this skin's WARM panel (#fffdf9) they stop being fields: measured on the
   workspace panel before this block existed,

     placeholder  steel-300 #cfc8b7 on #fffdf9  ->  1.63:1
     field border steel-200 #e6e1d5 on #fffdf9  ->  1.27:1

   which is a box you cannot see holding text you cannot read. Nothing was wrong
   with those values on their own ground; they were simply never asked to sit on
   this one.

   So the SKIN adapts the foreign component, scoped to `.process-tracker` — the
   dedicated Spec Sheet page keeps its steel look untouched, which is the whole
   point of it staying intact. The field recesses into `--trk-bg` so it reads as
   an input against the panel it sits on, and every colour comes from the tokens
   this file already defines, in both themes.
--------------------------------------------------------------------------- */
/* The BORDER carries the field, not the fill. Measured on this ground:
     fill  --trk-bg   #f7f4ee on panel #fffdf9  ->  1.08:1   (imperceptible)
     edge  --trk-line #e6e1d5 on panel #fffdf9  ->  1.28:1   (what it was)
     edge  --trk-faint #a09a8c on panel         ->  2.76:1
   Recessing the fill alone changes nothing a reader can see — 1.08 is not a
   step, it is a rounding error. The edge is what says "type here", so the
   resting border goes to `--trk-faint` and the fill only assists it. */
.process-tracker .spec-field {
  background: var(--trk-bg);
  border-color: var(--trk-faint);
}
.process-tracker .spec-field:hover {
  background: var(--trk-panel);
  border-color: var(--trk-sub);
}
/* Focus is NAVY here, like every other focus on this screen — the skin's rule
   is that what you click or focus is navy, and a blueprint ring would be a
   second focus colour on one surface. */
.process-tracker .spec-field:focus-within {
  background: var(--trk-panel);
  border-color: var(--trk-navy);
  box-shadow: 0 0 0 2px var(--trk-navy-soft);
}
/* A cell that HAS content lifts to the panel colour, so filled and empty read
   apart at a glance — the same job `has-[textarea:not(:placeholder-shown)]`
   does on the page, restated in this ground's values. */
.process-tracker .spec-field:has(textarea:not(:placeholder-shown)) {
  background: var(--trk-panel);
}
.process-tracker .spec-field textarea { color: var(--trk-ink); }
.process-tracker .spec-field textarea::placeholder { color: var(--trk-faint); }
.process-tracker .spec-field svg { color: var(--trk-faint); }
.process-tracker .spec-field:focus-within svg { color: var(--trk-navy); }
/* ── APPLICATION STEP (PDS-412) ────────────────────────────────────────────
   Step 4 wears this same skin — same subject bar, same rail, same corner scale
   — because it is the same workspace read on. What it needed and this file did
   not already have is three things, and only three:

     · a row that says where a value CAME FROM (the origin colour code of §4.3),
     · a combobox that filters what has been used and creates from the same
       field (the four Permit registries),
     · a bar pinned to the foot of the workspace for the acts that produce the
       document.

   Everything else on that screen — the buttons, the inputs, the kickers, the
   cards, the dots, the notes — is the vocabulary above, unchanged. Tokens are
   never re-declared here: dark mode rides `.dark .process-tracker` exactly as it does
   for every rule in this file. */


/* one registry card. `.trk-node-card` is the spine's action card — it carries a
   top margin and a 560px cap for a card mounted INSIDE a timeline node — so
   these get their own box rather than fighting those two rules. */
.process-tracker .trk-app-card {
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
  background: var(--trk-bg);
  padding: 12px 13px;
}

/* ---- the origin-coded field row (§4.3) ----
   The colour is the ORIGIN, and the left rule is what makes a column of them
   scannable — a wash behind 121 rows would be unreadable. Green is "the system
   holds it" (a constant, the lot, the client), navy came from triage, amber is
   a permit registry, faint does not apply, and a row that goes out blank keeps
   a neutral rule and a dashed line where the value would be. */
.process-tracker .trk-frow {
  display: grid;
  grid-template-columns: minmax(140px, 232px) 1fr;
  gap: 4px 14px;
  align-items: baseline;
  padding: 5px 0 5px 10px;
  border-left: 2px solid var(--trk-line-soft);
}
.process-tracker .trk-frow-k { font-size: 11.5px; line-height: 1.45; color: var(--trk-faint); }
.process-tracker .trk-frow-v {
  font-family: var(--trk-mono);
  font-size: 12.5px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.process-tracker .trk-frow-hint {
  margin-left: 8px;
  font-family: var(--trk-sans);
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--trk-faint);
}
.process-tracker .trk-frow-na { font-family: var(--trk-sans); font-size: 11.5px; font-style: italic; color: var(--trk-faint); }
.process-tracker .trk-frow-g { border-left-color: var(--trk-green); }
.process-tracker .trk-frow-g .trk-frow-v { color: var(--trk-green); }
.process-tracker .trk-frow-n { border-left-color: var(--trk-navy); }
.process-tracker .trk-frow-n .trk-frow-v { color: var(--trk-navy); }
.process-tracker .trk-frow-a { border-left-color: var(--trk-amber); }
.process-tracker .trk-frow-a .trk-frow-v { color: var(--trk-amber); }
.process-tracker .trk-frow-f { border-left-color: var(--trk-line); }
.process-tracker .trk-frow-b { border-left-color: var(--trk-line); }
.process-tracker .trk-frow-b .trk-frow-v { color: var(--trk-faint); }
/* Typed over the projection (PDS-424) — the row's value came from a person. */
.process-tracker .trk-frow-m { border-left-color: var(--trk-plum); }
.process-tracker .trk-frow-m .trk-frow-v { color: var(--trk-plum); }
/* "goes out blank" drawn as what it is on the paper: a line somebody may write
   on by hand. An em-dash would read as missing data. */
.process-tracker .trk-blankline {
  display: inline-block;
  width: 150px;
  max-width: 100%;
  height: 11px;
  vertical-align: middle;
  border-bottom: 1px dashed var(--trk-faint);
}

/* the legend of the preview — the key without which the colours are decoration */
.process-tracker .trk-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  padding: 9px 20px;
  border-bottom: 1px solid var(--trk-line-soft);
  background: var(--trk-bg);
}
.process-tracker .trk-lg { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--trk-sub); }
.process-tracker .trk-sw { width: 9px; height: 9px; border-radius: 2px; flex-shrink: 0; }
.process-tracker .trk-sw-g { background: var(--trk-green); }
.process-tracker .trk-sw-n { background: var(--trk-navy); }
.process-tracker .trk-sw-a { background: var(--trk-amber); }
.process-tracker .trk-sw-f { background: var(--trk-faint); }
.process-tracker .trk-sw-b { background: none; border: 1px dashed var(--trk-faint); }
.process-tracker .trk-sw-m { background: var(--trk-plum); }
/* PDS-428 — not a sixth origin: a miniature of the mark on the sheet, white
   paper and the wall the value was cut against, so the legend and the box look
   like the same thing. */
.process-tracker .trk-sw-cut {
  background: #fff;
  border: 1px solid var(--trk-line);
  box-shadow: inset -2px 0 0 #b3362b;
}

/* ---- the registry combobox ----
   One field that filters and creates. The list is a POPOVER (absolute), because
   opening it must not push the three cards below it down the pane. */
.process-tracker .trk-cbx { position: relative; max-width: 440px; }
.process-tracker .trk-cbx-shell { display: flex; align-items: center; gap: 8px; }
/* Holds the field and the caret together, so the caret sits INSIDE the box and
   `Clear` keeps its own place beside it — the two never stack. */
.process-tracker .trk-cbx-input-wrap { position: relative; flex: 1; min-width: 0; display: flex; }
/* THE AFFORDANCE THAT SAYS "THERE IS A LIST" (owner's correction, PDS-412).
   Drawn from borders and never a glyph, like every mark in this skin. Faint at
   rest, navy while the list is open — what you click or focus is navy, and a
   control that reports its own state costs one rule. */
.process-tracker .trk-cbx-caret {
  position: absolute;
  right: 1px;
  top: 1px;
  bottom: 1px;
  width: 24px;
  display: grid;
  place-items: center;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
.process-tracker .trk-cbx-caret::after {
  content: "";
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--trk-faint);
}
.process-tracker .trk-cbx-caret:hover::after { border-top-color: var(--trk-sub); }
.process-tracker .trk-cbx-open .trk-cbx-caret::after { border-top-color: var(--trk-navy); }
.process-tracker .trk-cbx-field {
  flex: 1;
  min-width: 0;
  /* room for the caret, so a long value never runs under it */
  padding: 7px 28px 7px 9px;
  font-size: 12.5px;
  font-family: var(--trk-sans);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  background: var(--trk-panel);
  color: var(--trk-ink);
}
.process-tracker .trk-cbx-field::placeholder { color: var(--trk-faint); }
.process-tracker .trk-cbx-field:focus { outline: 2px solid var(--trk-navy); outline-offset: 1px; border-color: var(--trk-navy); }
.process-tracker .trk-cbx-clear {
  flex-shrink: 0;
  padding: 6px 10px;
  font-size: 11px;
  font-weight: 650;
  font-family: var(--trk-sans);
  color: var(--trk-sub);
  background: none;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  cursor: pointer;
}
.process-tracker .trk-cbx-clear:hover { color: var(--trk-navy); border-color: var(--trk-navy); background: var(--trk-navy-soft); }

.process-tracker .trk-cbx-list {
  position: absolute;
  z-index: 20;
  left: 0;
  right: 0;
  top: calc(100% + 3px);
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  background: var(--trk-panel);
  box-shadow: var(--trk-shadow);
}
.process-tracker .trk-cbx-opt {
  display: grid;
  gap: 1px;
  width: 100%;
  padding: 7px 10px;
  text-align: left;
  background: none;
  border: 0;
  border-top: 1px solid var(--trk-line-soft);
  cursor: pointer;
}
.process-tracker .trk-cbx-opt:first-child { border-top: none; }
.process-tracker .trk-cbx-opt:hover, .process-tracker .trk-cbx-opt-on { background: var(--trk-bg); }
.process-tracker .trk-cbx-opt-l { font-size: 12.5px; font-weight: 600; color: var(--trk-ink); }
.process-tracker .trk-cbx-opt-n { font-size: 11px; line-height: 1.45; color: var(--trk-faint); }
.process-tracker .trk-cbx-mark { background: var(--trk-amber-soft); color: inherit; padding: 0; }
/* the create row is GREEN because it is the one option that changes the world
   outside this lead — everything after this permit sees it. */
.process-tracker .trk-cbx-create { border-top: 1px solid var(--trk-line); background: var(--trk-green-soft); }
.process-tracker .trk-cbx-create:hover { background: var(--trk-green-soft); filter: brightness(.98); }
.process-tracker .trk-cbx-create .trk-cbx-opt-l { color: var(--trk-green); }

.process-tracker .trk-cbx-extras {
  margin-top: 8px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 10px;
  max-width: 440px;
}
/* the record's name, which is one field and not half a row of two */
.process-tracker .trk-cbx-extras-wide { grid-column: 1 / -1; }
.process-tracker .trk-cbx-extras-why { grid-column: 1 / -1; margin: 0; font-size: 11px; line-height: 1.45; color: var(--trk-faint); }
.process-tracker .trk-cbx-extras-act { grid-column: 1 / -1; }

/* THE ONE REGISTRY STATE THAT IS NOT FINISHED (PDS-422). Creating writes on the
   first click everywhere except the architect and the engineer, whose licence
   and telephone can only be asked for in this moment — and a step that is kept
   has to look unlike the step that ended. Amber, which in this skin is already
   "attention, not error", against the green of the create row that leads here. */
.process-tracker .trk-cbx-await .trk-cbx-field {
  border-color: var(--trk-amber);
  background: var(--trk-amber-soft);
}
.process-tracker .trk-cbx-await-note {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--trk-amber);
}
.process-tracker .trk-cbx-await-note b { font-weight: 650; }

/* where each option has already been used, so the choice is not made blind */
.process-tracker .trk-used { margin-top: 9px; font-size: 11px; line-height: 1.5; color: var(--trk-faint); }
.process-tracker .trk-used b { color: var(--trk-sub); font-weight: 650; }
.process-tracker .trk-used .trk-used-l { color: var(--trk-sub); font-weight: 600; }

/* ---- the generation bar ----
   Pinned to the foot of the workspace and visible from every rail entry:
   generating is the purpose of this screen, not its fifth step. */
.process-tracker .trk-genbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  padding: 11px 16px;
  border-top: 1px solid var(--trk-line);
  background: var(--trk-bg);
}
.process-tracker .trk-genbar form { display: contents; }


/* ── THE PAPER VIEW (PDS-412) ──────────────────────────────────────────────
   The preview stopped being a list and became the county's own page with the
   values drawn on it. Everything here is geometry-free: PaperLayout hands each
   mark its position as a PERCENTAGE of the sheet, so the only job of this file
   is to say what a mark looks like once it is placed.

   `container-type: inline-size` is what makes the type scale with the sheet:
   the layout gives every mark a font size in `cqw` (1% of the sheet's width),
   which is the same unit its left/width already use. Set a pixel size anywhere
   below and the sheet stops being a rehearsal of the paper at any width. */
.process-tracker .trk-sheet {
  container-type: inline-size;
  position: relative;
  width: 100%;
  background: #fff;
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(60, 50, 30, .06);
}
.process-tracker .trk-sheet + .trk-sheet { margin-top: 18px; }
.process-tracker .trk-sheet-img { display: block; width: 100%; height: auto; }
.process-tracker .trk-sheet-tag {
  font-family: var(--trk-mono);
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--trk-faint);
  margin: 0 0 6px;
}

/* A mark sits exactly on the widget's rectangle. `align-items: center` matches
   the filler, which centres its text on the box's vertical middle rather than
   sitting it on the baseline. */
.process-tracker .trk-mark {
  position: absolute;
  display: flex;
  align-items: center;
  padding: 0 .35cqw;
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  font-family: var(--trk-sans);
  border-radius: 1px;
}

/* THE ORIGIN IS THE WASH BEHIND THE VALUE, not the colour of the text: over a
   scan of a printed form, coloured type reads as part of the form. A tinted
   box behind black-ish type reads as "this is ours", which is the distinction
   the legend promises. */
.process-tracker .trk-mark-filled { color: #10100c; }
.process-tracker .trk-mark-constant,
.process-tracker .trk-mark-lot,
.process-tracker .trk-mark-client   { background: rgba(30, 107, 80, .17); box-shadow: inset 0 -1.5px 0 rgba(30, 107, 80, .55); }
.process-tracker .trk-mark-triage   { background: rgba(45, 61, 95, .16);  box-shadow: inset 0 -1.5px 0 rgba(45, 61, 95, .55); }
.process-tracker .trk-mark-registry { background: rgba(168, 101, 15, .18); box-shadow: inset 0 -1.5px 0 rgba(168, 101, 15, .6); }
/* PDS-424 — typed over the projection. On the sheet this is the one mark whose
   value cannot be checked against any record, which is the whole reason the
   preview colours by origin at all. */
.process-tracker .trk-mark-manual   { background: rgba(122, 75, 125, .18); box-shadow: inset 0 -1.5px 0 rgba(122, 75, 125, .6); }

/* Blank and not-applicable carry NO value, and they are not the same fact: one
   applies and is going out empty, the other was read and set aside. The dashed
   rule says "this line stays empty"; the flat wash says "not this job". */
.process-tracker .trk-mark-blank {
  background: rgba(160, 154, 140, .10);
  box-shadow: inset 0 -1px 0 rgba(160, 154, 140, .75);
}
.process-tracker .trk-mark-na {
  background: repeating-linear-gradient(135deg,
    rgba(160, 154, 140, .16) 0 3px, rgba(160, 154, 140, .04) 3px 6px);
}

/* The divergence marker from the list, kept: a value that is real but did not
   come from where the form expects that answer. Amber outline so it is findable
   on a sheet of 129 boxes without reading one of them. */
.process-tracker .trk-mark-diverged {
  outline: 1.5px solid var(--trk-amber);
  outline-offset: 0;
}

/* PDS-428 — THE VALUE WAS LONGER THAN THE COUNTY'S BOX. The text on the mark is
   already the cut one; what this adds is the wall it was cut against, so a line
   that stops mid-word reads as a CUT and not as a value that ends there.

   TWO PARTS, AND THE SECOND IS NOT DECORATION. The hatched bar is an IN-FLOW
   pseudo-element — it sits immediately after the last character that goes on the
   form, which is the only place a wall means anything; drawn at the box's right
   edge instead, it lands wherever the box happens to end and reads as furniture.
   The bar can be clipped in the one case where the text fills the box to the
   millimetre (the mark is `overflow: hidden`), so the red rule under the whole
   box carries the fact on its own: whatever the width, the field is marked.

   Neither is a box-shadow, because the origin classes above own that property
   and the two facts — where the value came from, and that it does not fit —
   have to be able to show at once.

   The colours are literal and not tokens: the sheet is a picture of white paper
   in both themes, so a mark that followed the dark palette would be tuned for a
   ground it never sits on. */
.process-tracker .trk-mark-cut { border-bottom: 1.5px solid #b3362b; }
.process-tracker .trk-mark-cut::after {
  content: "";
  flex: 0 0 auto;
  align-self: stretch;
  width: .5cqw;
  min-width: 2px;
  margin-left: .25cqw;
  background: repeating-linear-gradient(-45deg,
    #b3362b 0 1.5px, rgba(179, 54, 43, .5) 1.5px 3px);
}

/* The tick is DRAWN and never a glyph — this skin's rule, and here it also
   avoids a font that may not carry the character. Two borders rotated into an
   L, sized to the box it sits in. */
.process-tracker .trk-tick {
  display: block;
  width: 34%;
  height: 62%;
  margin: 0 auto;
  border-right: .28cqw solid #10100c;
  border-bottom: .28cqw solid #10100c;
  transform: rotate(42deg) translateY(-8%);
}
.process-tracker .trk-mark-check { padding: 0; }

/* The stale banner. The pictures are committed artefacts; if the template moves
   under them the overlay would land on the wrong drawing, so the view says so
   instead of drawing something plausible and wrong. */
.process-tracker .trk-stale {
  border: 1px solid var(--trk-amber);
  background: var(--trk-amber-soft);
  color: var(--trk-amber);
  border-radius: var(--trk-r);
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.5;
  margin-bottom: 14px;
}

/* The reason column is ONE LINE (PDS-412). The resolver's sentences run from
   four words to forty, and a column whose height changes per row destroys the
   rhythm that makes two dozen rows scannable — the eye stops finding the values.
   The full sentence rides on the row's title. */
.process-tracker .trk-frow-hint {
  display: inline-block;
  max-width: 46ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

/* ── FIELD TABLE (PDS-412) ─────────────────────────────────────────────────
   Four aligned columns replaced a row of label, dashed rule and a sentence.
   The dashed rule said "empty" in a whole column, and the sentence said the
   same cause once per field it explained. State is now a stamp in its own
   column, and the columns line up, which is what makes two dozen rows
   scannable at all. */
.process-tracker .trk-ftable {
  display: grid;
  /* ⚠️ THE WIDTH GOES WHERE IT CANNOT BE GIVEN BACK (dono, 11/ago, on a shot of
     this table: "trimmed information"). The value column was fixed at 140px
     and the source took 2.2fr, so "Construct new single family residence" came
     out cut at `singl` while the widest column on the screen was empty on four
     rows out of five — the source prints a cause once per run and stays quiet
     after it (PDS-412), so its width was reserved for rows that have nothing.
     It was backwards: prose wraps and loses nothing, a value in a fixed box
     loses letters. Both columns are elastic now, and the value holds the width
     it needs to keep a sentence-long answer on one line.

     A fixed column was never what kept the rule between VALUE and SOURCE
     straight. Grid tracks are sized once for the whole table, so an elastic
     column lands on the same pixel on every row just as a fixed one does. What
     would bend the rule is a cell that SPANS, and that is what went away when
     the value cell started rendering even with nothing in it. */
  grid-template-columns: minmax(160px, 1.15fr) 100px minmax(190px, 1.25fr) minmax(190px, 1.6fr);
  /* ⚠️ NO COLUMN GAP, AND THE PADDING GOES INSIDE THE CELL. With a gap, each
     cell's bottom border stops at the gap and the row separator arrives as four
     detached strokes — which, in a column that is empty on most rows, reads as
     a blank to write on. That is the dashed rule coming back through the side
     door, and it is what this table exists to remove. Rules must run edge to
     edge or not exist. */
  gap: 0;
  /* ⚠️ STRETCH, NEVER `center`. With `align-items: center` a cell is only as
     tall as its own content, so each one puts its bottom border at its own
     bottom and the row separator arrives in pieces at different heights — the
     step you see where the state column meets the source column. Stretching
     makes every cell the height of the row, which is the only way the rule
     lines up across four columns; the vertical centring then belongs INSIDE
     the cell. */
  align-items: stretch;
  font-size: 12.5px;
}
.process-tracker .trk-fhd {
  font-family: var(--trk-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--trk-faint);
  padding-bottom: 5px;
  border-bottom: 1px solid var(--trk-line);
}
/* The SOURCE heading sits over the rule and has to start where its column
   does, or the header and the cells below it would be a padding apart. */
.process-tracker .trk-fhd-r {
  text-align: left;
  border-left: 1px solid var(--trk-line-soft);
  padding-left: 12px;
}
.process-tracker .trk-fcell {
  display: flex;
  align-items: center;
  padding: 5px 12px 5px 0;
  border-bottom: 1px solid var(--trk-line-soft);
  min-width: 0;
}
.process-tracker .trk-fcell:last-child { padding-right: 0; }

/* THE ROW WITH NO VALUE USED TO TAKE THE VALUE COLUMN (`trk-fsrc-wide`,
   grid-column 3 / span 2) so its prose would not be cut off in a narrow one.
   It is gone, and what replaced it is the reason: most rows here have no value,
   so the spanning cell was the majority, and a vertical rule between the two
   columns would have been absent exactly where the table is densest — or worse,
   drawn through the middle of the prose. The source keeps its own column on
   every row. It was handed the width back as `2.2fr` against a fixed value
   column, which overshot in the other direction — the tracks above settle it,
   and the sentence wraps in place instead of being cut. */
.process-tracker .trk-fname {
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--trk-sub);
  border-left: 2px solid var(--trk-line-soft);
  padding-left: 9px;
}
.process-tracker .trk-fsrc { justify-content: flex-start; }
/* ⚠️ THE ELLIPSIS HERE NEVER FIRED, WHICH IS WHY THE VALUE CAME OUT CUT MID-WORD
   AND SAID NOTHING ABOUT IT. The cell is a flex container, so its text is an
   anonymous flex item and `text-overflow` has no box of its own to act on;
   `overflow: hidden` did the cutting alone. The value wraps now instead of
   being cut: it is short by nature — an address, a person's name, a scope of
   work — and a second line costs less than a lost word. `anywhere` is what
   keeps an unbroken token (a long parcel id) inside its column rather than
   under the next one. */
.process-tracker .trk-fval {
  font-family: var(--trk-mono);
  line-height: 1.4;
  overflow-wrap: anywhere;
}

/* THE STAMP CARRIES THE STATE, and `open` is the only one that is work: a box
   nobody owes an answer for is finished, however empty it looks. Amber is this
   skin's colour for waiting, so the eye finds the four that matter among the
   hundred that do not. */
.process-tracker .trk-st {
  display: inline-block;
  font-size: 10px;
  font-weight: 650;
  border-radius: var(--trk-r-s);
  padding: 1px 7px;
  white-space: nowrap;
}
.process-tracker .trk-st-fill { background: var(--trk-green-soft); color: var(--trk-green); }
.process-tracker .trk-st-open { background: var(--trk-amber-soft); color: var(--trk-amber); }
.process-tracker .trk-st-blank { background: rgba(160, 154, 140, .16); color: var(--trk-faint); }
/* The one row on this table a person is answerable for (PDS-424). */
.process-tracker .trk-st-edit { background: var(--trk-plum-soft); color: var(--trk-plum); }
.process-tracker .trk-st-na {
  background: repeating-linear-gradient(135deg,
    rgba(160, 154, 140, .22) 0 3px, rgba(160, 154, 140, .06) 3px 6px);
  color: var(--trk-faint);
}
.dark .process-tracker .trk-st-blank { background: rgba(110, 106, 94, .22); }
/* The hatch was the one stamp with no dark answer: the same warm grey on a
   #161511 ground reads as a smudge. */
.dark .process-tracker .trk-st-na {
  background: repeating-linear-gradient(135deg,
    rgba(140, 134, 120, .20) 0 3px, rgba(140, 134, 120, .05) 3px 6px);
}

/* ── THE THREE THE STAMP WAS MISSING (submission package) ──────────────────
   Amber for everything that is not done is a vocabulary of one word. These
   three finish the ladder, and each one takes the colour the RAIL DOT already
   spends on the same fact — the dots have had the red and the two rings since
   PDS-418, and only the stamp was still flattening them.

   `-block` is the red `--trk-red` that was declared and unused by any stamp,
   while `.trk-d-block` was already painting it two files over.
   `-hold` is a ring rather than a fill because somebody else's clock is not
   our work: it has to read as lighter than `-open` at a glance.
   `-ask` is the same ring in the line grey — a question that is open, which is
   NOT the same fact as a verified absence and must never take the hatch. */
.process-tracker .trk-st-block { background: var(--trk-red-soft); color: var(--trk-red); }
/* ⚠️ FILL, NOT OUTLINE (12/ago, owner: "não gosto desse estilo diferente,
   prefiro que use uma cor diferente no mesmo padrão dos demais"). These two
   shipped as hollow rings, borrowing the rail dots' way of saying "somebody
   else's clock" and "open question". On a stamp the ring reads as a second
   KIND of thing rather than a second state — the eye sorts by shape before it
   sorts by hue — so the difference moved into the colour and the shape went
   back to being the same soft fill every other state uses.

   Navy for `supplier`, and it is the only place this skin spends navy on a
   state: navy is the colour of what you click here, and everywhere else it
   stays that. It earns the exception by being the one state that is nobody's
   move on this screen — the ball is with a supplier, a utility or an agency —
   so it must not read as amber, which is work we owe. */
.process-tracker .trk-st-hold { background: var(--trk-navy-soft); color: var(--trk-navy); }
/* `--trk-sub` on the neutral fill and not `--trk-faint`: at 10px on the dark
   ground the faint grey lands near 3:1 against the panel, and this is the most
   common stamp on an untriaged lead — sixteen of twenty-six on the reference
   house. It also puts the open question a step above the verified absence,
   which is the right order: one is work nobody has started, the other is
   settled. */
.process-tracker .trk-st-ask { background: rgba(160, 154, 140, .16); color: var(--trk-sub); }
.dark .process-tracker .trk-st-ask { background: rgba(110, 106, 94, .22); }
/* A stamp that filters is a control, so it says so on hover and marks itself
   pressed. `button` resets: the element is a button now, not a span. */
.process-tracker button.trk-st {
  font-family: inherit;
  border: 0;
  cursor: pointer;
  padding: 1px 7px;
}
.process-tracker button.trk-st:hover { filter: brightness(.96); }
.process-tracker button.trk-st[aria-pressed="true"] { box-shadow: inset 0 0 0 1px currentColor; }

/* The source cell: a way out where the system has one, a plain fact where it
   does not.

   IT WAS ONE LINE, CUT WITH AN ELLIPSIS, AND IT IS NOT ANY MORE (dono, 11/ago).
   The one-line rule was written for a column that spoke on every row, where
   two dozen sentences of uneven height would have destroyed the rhythm that
   makes the table scannable. That column no longer exists: a cause is printed
   once per run, so roughly one row in five carries prose and the rest are
   quiet. A sentence that appears that rarely can afford the lines it needs,
   and half a sentence explains nothing — the cause is the one thing on this
   row nobody can look up elsewhere. */
/* ⚠️ LEFT, NOT RIGHT. Right-aligned chips of different widths share only their
   right edge, so "Answer UT-02", "Answer PM-18" and "Open triage" came down the
   column with a ragged left edge and read as misaligned — which they were. A
   column of things to click needs one edge to start from. Left also puts the
   chips and the plain sentences on the same line, since a row with no value
   gives its column away and both begin at the value column's edge. */
/* ⚠️ THE RULE LIVES HERE, AND IT IS THE REASON THE CELL NO LONGER SPANS. The
   value and the source were touching with nothing between them, so a monospace
   value and a grey sentence read as one run of text. `align-items: stretch` on
   the table is what lets this border run the full height of the row, so the
   rule arrives as one line down the table instead of a stack of dashes — the
   same rule the row separators follow: edge to edge or not at all. */
.process-tracker .trk-fsrc {
  text-align: left;
  font-size: 10.5px;
  color: var(--trk-faint);
  overflow: hidden;
  border-left: 1px solid var(--trk-line-soft);
  padding-left: 12px;
  /* An edited row puts TWO things here — what the origin still says and the
     button that goes back to it (PDS-424) — and the cell is a flex row. Without
     wrapping, a long source value would push the button out through the
     `overflow: hidden` and the undo would be unreachable on exactly the rows
     that have one. Every other row holds a single child, so this is inert
     there. */
  flex-wrap: wrap;
  gap: 4px 8px;
}
.process-tracker .trk-fsrc-t {
  display: block;
  max-width: 100%;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.process-tracker .trk-fact {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 650;
  color: var(--trk-navy);
  background: var(--trk-navy-soft);
  border-radius: var(--trk-r-s);
  padding: 1px 8px;
  white-space: nowrap;
  text-decoration: none;
}
.process-tracker .trk-fact:hover { filter: brightness(.97); }
/* The undo of an edit, in the origin's own column and in the hand's colour
   (PDS-424): it is not a way out to another screen like its neighbours, it is
   the way back to what the record says. */
.process-tracker .trk-fact-undo { color: var(--trk-plum); background: var(--trk-plum-soft); }
/* The value the origin still holds, printed beside the typed one. Monospace so
   it reads as a value and not as the prose around it. */
.process-tracker .trk-fsrc-was { color: var(--trk-sub); font-size: 10.5px; overflow-wrap: anywhere; }

/* ── TYPING IN THE VALUE COLUMN (PDS-424) ──────────────────────────────────
   The box IS the value cell: same column, same monospace, same width — the
   projection is what it opens holding, so the pane reads as the table it was
   and not as a form.

   ⚠️ AT REST IT DRAWS NO RULE (12/ago, owner). It used to carry a
   `border-bottom` to say "typeable", and on a pane of mostly empty fields that
   put a short line a few pixels above each row's own divider — two horizontal
   lines competing down the whole column, neither of them information. The
   affordance stayed where it costs nothing: the box takes its full border on
   hover and the plum one on focus, and a row whose value was TYPED keeps its
   underline, because that one is a fact and not a hint. */
.process-tracker .trk-fedit { width: 100%; min-width: 0; }
.process-tracker .trk-fin {
  width: 100%;
  min-width: 0;
  font-family: var(--trk-mono);
  font-size: 12px;
  line-height: 1.35;
  color: var(--trk-ink);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--trk-r-s);
  padding: 2px 5px;
}
.process-tracker .trk-fin:hover { border-color: var(--trk-line); background: var(--trk-bg); }
.process-tracker .trk-fin:focus {
  outline: none;
  border-color: var(--trk-plum);
  background: var(--trk-panel);
}
.process-tracker .trk-fin::placeholder { color: var(--trk-faint); font-style: italic; }
/* A row whose value was typed carries the hand's colour in the box itself, so
   the marking survives the eye going straight down the value column. */
.process-tracker .trk-frow-m .trk-fin { color: var(--trk-plum); border-bottom-color: var(--trk-plum); }


/* The certificate and its expiry, side by side: one act, one row. `align-items:
   center` because the two controls have different heights — the drawn attach
   row is taller than the date input — and aligning their tops would leave the
   date floating against a taller neighbour. */
.process-tracker .trk-cred-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  /* ⚠️ `stretch`, NOT `center`. Centring left the two halves at different
     heights — the drawn attach row is two lines here, the date input one — and
     a row whose halves do not close at the same line reads as two rows that
     happen to be adjacent. Both cells now take the row's height, and the row
     takes the taller of the two. */
  align-items: stretch;
  margin-top: 6px;
}
@media (max-width: 640px) {
  .process-tracker .trk-cred-row { grid-template-columns: 1fr; }
}
/* ⚠️ THE ATTACH CONTROL STACKS INSIDE THIS ROW. At full width it is one line —
   the call to the left, the filename pushed to the right — and at half of a
   440px card that line has ~216px for both, so `overflow-wrap: anywhere` did
   what it is there for and broke "Nothing attached yet" mid-word. Two lines,
   left-aligned, and the filename still lands where the placeholder was. */
.process-tracker .trk-cred-row .trk-attach {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 1px;
  /* Tighter than the full-width control: two lines inside a half-width cell,
     against a date input that is one. Trimming here is what lets the pair close
     at ~44px instead of 60. */
  padding: 6px 12px;
}
.process-tracker .trk-cred-row .trk-attach-name { margin-left: 0; text-align: left; }
.process-tracker .trk-cred-row .trk-input { height: 100%; }

/* ── THE SUBMISSION PACKAGE PANEL ──────────────────────────────────────────
   Two tracks, one screen. The panel used to render a filing and a set of gates
   as ONE list: 22 rows in catalogue order where the gate that stops the permit
   was drawn exactly like the question nobody had answered, under six fractions
   that do not add up to each other. Splitting them is structural — no amount of
   colour fixes a list that is two lists.

   The left column is the filing: a checklist, one line per attachment, under
   the county's own four groups — what the fraction counts and what goes in the
   envelope. The right column keys the gates by the MILESTONE each one holds,
   which is the question a gate exists to answer and a fact the catalogue
   already carried in `blocks`.

   ⚠️ THE ORDER WAS TRIED BOTH WAYS on the day it shipped, and the owner settled
   on this one: the filing is what this step IS, and the gates are advice that
   runs beside it. Swapping them is swapping the two blocks in
   `_detail_package.html.erb`; nothing in this file depends on which is which. */

/* The whole, before any row. Every line the panel draws is in this bar —
   package rows AND gates — so it answers the question the 0/9 fraction cannot.

   ⚠️ THE SEGMENTS ARE <rect>s, NOT FLEX CHILDREN, for the reason
   `.trk-clock-bar` states at length: `style_src` in this app's CSP has no
   `unsafe-inline`, so `style="width: 42%"` is dropped by the browser with no
   error and the bar renders as nothing at all. `width`/`x` are presentation
   attributes on a rect and survive. */
.process-tracker .trk-stack {
  flex: 1;
  min-width: 200px;
  height: 10px;
  border-radius: var(--trk-r-s);
  overflow: hidden;
  background: var(--trk-line-soft);
}
.process-tracker .trk-stack svg { display: block; width: 100%; height: 100%; }
.process-tracker .trk-stack rect { cursor: pointer; }
/* Two segments: in the package, and not yet. The four that told blocking from
   supplier from unanswered from not-needed left with the gates column — that
   reading is the Pre-permit's. */
.process-tracker .trk-stack .trk-stack-ok { fill: var(--trk-green); }
.process-tracker .trk-stack .trk-stack-ours { fill: var(--trk-amber); }

.process-tracker .trk-band {
  display: grid;
  gap: 10px;
  padding: 11px 13px;
  margin: 12px 0 16px;
  background: var(--trk-panel);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
}
.process-tracker .trk-band-top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

/* The chips carry the numbers the bar carries as width, and each one is the
   handle that filters both columns by that state. A count of zero stays on
   screen, disabled: a vocabulary that vanishes when it is empty vanishes on the
   day somebody needs to confirm that it IS empty. */
.process-tracker .trk-tally { display: flex; flex-wrap: wrap; gap: 6px; }
.process-tracker .trk-tally button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  font-family: inherit;
  font-size: 11px;
  color: var(--trk-sub);
  background: var(--trk-bg);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
  cursor: pointer;
}
.process-tracker .trk-tally button:hover { border-color: var(--trk-navy); color: var(--trk-navy); }
.process-tracker .trk-tally button[aria-pressed="true"] {
  border-color: var(--trk-sub);
  color: var(--trk-ink);
  font-weight: 650;
  background: var(--trk-panel);
  box-shadow: var(--trk-shadow);
}
.process-tracker .trk-tally button[disabled] { opacity: .45; cursor: default; }
.process-tracker .trk-tally button[disabled]:hover { border-color: var(--trk-line); color: var(--trk-sub); }
.process-tracker .trk-tally .ct { font-family: var(--trk-mono); font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.process-tracker .trk-tally .trk-tally-clear { border-style: dashed; color: var(--trk-faint); }

/* Two columns, divided by a border on the child and never by a gap — the same
   rule the master-detail rails follow. Below `lg` they stack, and the divider
   becomes the top edge of the second one. */
/* ⚠️ `min-width: 0` ON THE COLUMN, or nothing inside it can truncate: a grid
   track defaults to `min-width: auto`, so one long document name widens it past
   its share and the panel grows a horizontal scrollbar instead of an ellipsis.
   Same failure the flex chain has, same cure. `container-type` stays: the chip
   rules below query the column, not the viewport. */
.process-tracker .trk-pkg { display: grid; grid-template-columns: 1fr; gap: 0; }
.process-tracker .trk-pkg > * { min-width: 0; container-type: inline-size; }
.process-tracker .trk-pkg-head { display: flex; align-items: baseline; gap: 9px; margin-bottom: 9px; }
.process-tracker .trk-pkg-head .why { margin-left: auto; font-size: 10.5px; color: var(--trk-faint); }
.process-tracker .trk-pkg-n { font-family: var(--trk-mono); font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--trk-faint); }
/* ⚠️ ONE SIZE FOR EVERY STAMP IN THIS PANEL (12/ago, owner). Sized to content,
   the vocabulary came out in seven widths between 43px ("To file") and 129px
   ("Waiting on Project Dept."), so the left edge of the state column zig-zagged
   down both lists while the right edge stayed put — the eye reads that as
   disorder before it reads any word.

   ⚠️ THE NUMBER IS MEASURED, NOT CHOSEN, AND THE COPY IS THE LEVER. Every
   label `classify` can produce was rendered in this skin and read back, then
   the ones holding the ceiling were shortened until it fell ~30% (owner):

     Under utility review 107 → With utility 66      Not applicable 83 → Not needed 69
     Not operated here    100 → (no longer produced) Not requested  82 → To request 65
     Awaiting decision     99 → In decision 67       With the supplier 96 → Supplier 55
     Not generated yet     99 → To generate 70

   107px → 75px, and 78px is the smallest common size that still fits it. The
   last one to fall was the triage state: `Not answered` (80px) → `No answer`
   (65px), which is why this panel and the Pre-permit rail now word that one
   state differently — a budget, not a disagreement (see `classify`). The
   ceiling is now shared by `Waiting proj.` and `No company`, both 75px.

   `min-width` and not `width`: a label longer than the current champion grows
   the stamp instead of clipping it, which on a state word is the one failure
   that may not happen quietly.

   ⚠️ SCOPED TO `.trk-pkg`, never to `.trk-st` at large. The same stamp serves
   the form-fields pane, where the words are `filled`, `open`, `blank` and the
   pills measure 37–40px — a 78px pill on each of 64 rows there would be a
   wall. */
.process-tracker .trk-pkg .trk-st {
  min-width: 78px;
  text-align: center;
}

.process-tracker .trk-pkg-empty { font-size: 11.5px; color: var(--trk-faint); padding: 8px 0 2px; }

/* The filing, one line per attachment. `-done` is a TINT and not an outline: on
   a column where most rows eventually turn green, a green border on each one
   turns a finished checklist into a stack of alarms. */
.process-tracker .trk-grp { margin-top: 12px; }
.process-tracker .trk-grp:first-of-type { margin-top: 0; }
.process-tracker .trk-grp-head { display: flex; align-items: baseline; gap: 8px; padding-bottom: 4px; }
.process-tracker .trk-pkgchip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 5px 9px;
  margin-top: 4px;
  background: var(--trk-panel);
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r-s);
}
.process-tracker .trk-pkgchip > a { flex: 1; min-width: 0; font-size: 12.5px; color: var(--trk-ink); }
.process-tracker .trk-pkgchip > a:hover { color: var(--trk-navy); }
/* ⚠️ THE DETAIL TAKES A LINE OF ITS OWN, and `order: 3` keeps it BELOW the
   stamp rather than between the name and it — wrapping in DOM order would leave
   the name alone on the first line and push the state down to a third.

   Measured before settling on it: this panel shares the workspace with a 268px
   rail, and the page shell caps the layout, so "the filing" is ~500px wide at
   1440px AND at 1920px. On one line, name + detail + stamp truncates
   "FEMA Elevation Certificate (FF-206)" to "FEMA Elevation Certificate (FF-…" —
   it eats the form number, which is the one part of that name nobody can guess.
   A container query was tried first and thrown away: with the layout capped,
   its wide branch never came up. */
.process-tracker .trk-pkgchip .who {
  flex: 0 0 100%;
  order: 3;
  min-width: 0;
  margin-top: -3px;
  font-size: 10.5px;
  color: var(--trk-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.process-tracker .trk-pkgchip-done { background: var(--trk-green-soft); }
/* The dependency sentence keeps the amber it had as a row: it exists only while
   the precondition is unmet and disappears on its own. */
/* ⚠️ EVERY CHIP IS THE SAME HEIGHT (12/ago, owner). Detail and dependency each
   used to claim a line of their own, so a row carrying both stood 21px taller
   than the one under it and the column read as ragged. They share one line —
   the detail gives way, the dependency does not — and `min-height` holds the
   rhythm for the rows that carry neither. */
.process-tracker .trk-pkgchip { min-height: 52px; }
.process-tracker .trk-pkgchip .who { display: flex; align-items: baseline; gap: 6px; }
.process-tracker .trk-pkgchip .who .d { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.process-tracker .trk-pkgchip .who .dep { flex-shrink: 0; color: var(--trk-amber); }
.process-tracker .trk-pkgchip .who .d + .dep::before { content: "·"; margin-right: 6px; opacity: .55; }


/* ---- the quiet set: every mark below the slice (owner, 14/set/2026) --------
   The slice is the one place on the card that spends colour at full strength.
   Below it — gauge, wait clock, axis — the same green, amber and stage ramp ran
   at full strength too, and three cards side by side fought for the eye. They
   now read from ONE set of neutral tokens, and the only tone that survives with
   a hue is `--trk-ov-red`: the unit past its window. Colour below the slice
   means "this needs you today", and nothing else.

   ⚠️ THE SET IS THE SEAM FOR ALL FOUR OVERVIEWS. Portfolio, contracts,
   permitting and receivables share these rules; a tone changed here changes the
   sixteen panels at once, and no component or view is touched.

   State still rides on FORM first (the bar breaking at the threshold, the bold
   number, the red dot on a blocked row), which is what lets the fills go quiet
   without losing the reader who cannot separate amber from red. */
.process-tracker {
  --trk-ov-mark: var(--trk-faint);
  --trk-ov-track: var(--trk-line-soft);
  --trk-ov-line: var(--trk-faint);
  --trk-ov-red: color-mix(in srgb, var(--trk-red) 70%, var(--trk-panel));
  /* The four design stages keep their order as four steps of the neutral —
     lightness still monotone, so the ramp reads as a scale, not as four states. */
  --trk-ov-st1: color-mix(in srgb, var(--trk-faint) 34%, var(--trk-panel));
  --trk-ov-st2: color-mix(in srgb, var(--trk-faint) 62%, var(--trk-panel));
  --trk-ov-st3: var(--trk-faint);
  --trk-ov-st4: var(--trk-sub);
}

/* ---- the zones below the slice (docs/92) -----------------------------------
   Every panel reads the same way from the slice down, in this order:
     3 · the GAUGE  — the slice's own population reordered by condition, 6px
     4 · the QUEUE  — one row per unit, oldest first, four slots in a fixed order
     5 · the AXIS   — three labels under the wait column, no grid
     6 · the FOOT   — overflow left, total right, anchored to the card's foot
   A zone may go without a mark; it never moves. That is what keeps three
   neighbours in a row aligned with no subgrid and no connector between them,
   and what lets a seventeenth panel be a line in a table instead of a drawing. */

/* 3 · the gauge. ⚠️ THE SLICE'S MECHANISM AT 6px: one <i> per unit, equal flex
   siblings, a 2px gap of paper between them — no number reaches the markup, so
   the CSP has nothing to drop. Past GaugeComponent::GRAIN_LIMIT the gap goes and
   each condition reads as one solid run. */
.process-tracker .trk-ov-gauge { display: flex; flex-direction: column; gap: 7px; min-height: 40px; margin-bottom: 10px; }
.process-tracker .trk-ov-gauge-h { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.process-tracker .trk-ov-gauge-n { font-size: 22px; font-weight: 700; line-height: 1; letter-spacing: -.02em; color: var(--trk-ink); white-space: nowrap; }
.process-tracker .trk-ov-gauge-t { font-size: 12.5px; color: var(--trk-sub); min-width: 0; }
.process-tracker .trk-ov-gauge-k { margin-left: auto; display: flex; gap: 10px; flex-shrink: 0; font-size: 11.5px; color: var(--trk-sub); white-space: nowrap; }
.process-tracker .trk-ov-gauge-k span { display: inline-flex; align-items: center; gap: 5px; }
.process-tracker .trk-ov-gauge-k .trk-ov-swatch { width: 8px; height: 8px; }
.process-tracker .trk-ov-gm { display: flex; height: 6px; gap: 2px; }
.process-tracker .trk-ov-gm-plain { gap: 0; }
.process-tracker .trk-ov-gm-blank { height: 6px; }
.process-tracker .trk-ov-gu { display: block; flex: 1 1 0; min-width: 0; }
.process-tracker .trk-ov-gm .trk-ov-gu:first-child { border-radius: 3px 0 0 3px; }
.process-tracker .trk-ov-gm .trk-ov-gu:last-child  { border-radius: 0 3px 3px 0; }
.process-tracker .trk-ov-gm .trk-ov-gu:only-child  { border-radius: 3px; }
/* The conditions a unit can be in. `track` is the part of the population that
   is NOT in the condition the figure names — a lighter step, never a hue.
   Every tone below reads from the quiet set (`--trk-ov-*`): under the slice,
   colour means exception, and nothing else. */
.process-tracker .trk-ov-gu-amber { background: var(--trk-ov-mark); }
.process-tracker .trk-ov-gu-red   { background: var(--trk-ov-red); }
.process-tracker .trk-ov-gu-green { background: var(--trk-ov-mark); }
.process-tracker .trk-ov-gu-track { background: var(--trk-ov-track); }
.process-tracker .trk-ov-gu-s1 { background: var(--trk-ov-st1); }
.process-tracker .trk-ov-gu-s2 { background: var(--trk-ov-st2); }
.process-tracker .trk-ov-gu-s3 { background: var(--trk-ov-st3); }
.process-tracker .trk-ov-gu-s4 { background: var(--trk-ov-st4); }

/* 3b · the mark's own control. One line, quiet, sitting where the gauge's
   sentence just used the number. It is a form, not a filter bar: nothing below
   it is removed, only the colour of the boundary moves. */
.process-tracker .trk-ov-ctl { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin: -2px 0 8px; font-size: 11.5px; color: var(--trk-sub); }
.process-tracker .trk-ov-ctl select {
  font-size: 11.5px; color: var(--trk-ink); background: transparent;
  border: 1px solid var(--trk-ov-track); border-radius: 4px; padding: 1px 4px; line-height: 1.4;
}

/* 4 · the queue. ONE grid for every panel: identity · what · wait · value. A
   panel omits a slot with a modifier; it never reorders or resizes one. The
   axis below shares the grid so its ruler lands under the bars. */
.process-tracker .trk-ov-q,
.process-tracker .trk-ov-ax { display: grid; grid-template-columns: 68px minmax(0, 1fr) 116px 76px; column-gap: 10px; }
.process-tracker .trk-ov-q-noval  { grid-template-columns: 68px minmax(0, 1fr) 116px; }
.process-tracker .trk-ov-q-nowait { grid-template-columns: 68px minmax(0, 1fr) 76px; }
.process-tracker .trk-ov-q-bare   { grid-template-columns: 68px minmax(0, 1fr); }
.process-tracker .trk-ov-q-rd     { grid-template-columns: 28px minmax(0, 1fr) 116px; }
.process-tracker .trk-ov-q-att    { grid-template-columns: 22px 68px minmax(0, 1fr) 116px auto; }
.process-tracker .trk-ov-q {
  align-items: center;
  min-height: 36px;
  box-sizing: border-box;
  padding: 4px;
  margin: 0 -4px;
  border-bottom: 1px solid var(--trk-line);
  color: inherit;
  text-decoration: none;
}
.process-tracker .trk-ov-queue > .trk-ov-q:last-child { border-bottom: 0; }
.process-tracker a.trk-ov-q:hover { background: var(--trk-line-soft); }
.process-tracker .trk-ov-q-id { font-family: var(--trk-mono); font-size: 12px; color: var(--trk-ink); white-space: nowrap; }
.process-tracker .trk-ov-q-n { font-family: var(--trk-sans); font-size: 13px; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; }
.process-tracker .trk-ov-q-what { min-width: 0; }
.process-tracker .trk-ov-q-a { display: block; font-size: 13px; color: var(--trk-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.process-tracker .trk-ov-q-b { display: block; margin-top: 1px; font-size: 11.5px; color: var(--trk-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.process-tracker .trk-ov-q-n.trk-ov-q-zero,
.process-tracker .trk-ov-q-a.trk-ov-q-zero { color: var(--trk-faint); }
.process-tracker .trk-ov-q-val { font-size: 11.5px; color: var(--trk-sub); text-align: right; white-space: nowrap; }
.process-tracker .trk-ov-q-money { font-family: var(--trk-mono); font-size: 12px; font-variant-numeric: tabular-nums; color: var(--trk-ink); }
.process-tracker .trk-ov-q-faint { color: var(--trk-faint); }
.process-tracker .trk-ov-q-act { text-decoration: underline; text-decoration-color: var(--trk-faint); text-underline-offset: 2px; }

/* The wait clock: a 72×6 bar on the card's ruler, the number beside it in ink.
   ⚠️ STATE BY FORM FIRST. Amber↔red measures ΔE 1.7 under deuteranopia here, so
   a bar past the threshold BREAKS at the tick (2px of paper) and its number goes
   bold; the colour follows. No window: no bar, number only. Blocked: a red dot
   beside the number — red from day one, on a mark, never on the digits. */
.process-tracker .trk-ov-wait { display: flex; align-items: center; gap: 6px; }
.process-tracker .trk-ov-wait svg { display: block; width: 72px; height: 12px; flex: 0 0 72px; }
.process-tracker .trk-ov-wait-blank { display: flex; align-items: center; justify-content: flex-end; width: 72px; height: 12px; flex: 0 0 72px; }
.process-tracker .trk-ov-wait-d { font-family: var(--trk-mono); font-size: 12px; font-variant-numeric: tabular-nums; color: var(--trk-ink); min-width: 32px; }
.process-tracker .trk-ov-wait-nil { color: var(--trk-faint); }
.process-tracker .trk-ov-wait-past { font-weight: 700; }
.process-tracker .trk-ov-wait-dot { display: inline-block; width: 6px; height: 6px; border-radius: 999px; background: var(--trk-red); }
.process-tracker .trk-ov-fill-amber { fill: var(--trk-ov-mark); }
.process-tracker .trk-ov-fill-red   { fill: var(--trk-ov-red); }
/* The only dashed rule on the screen, and it is not a gridline: it is the
   threshold, the one place where dashing means what dashing reads as. */
.process-tracker .trk-ov-tick { stroke: var(--trk-ov-line); stroke-width: 1; stroke-dasharray: 2 2; opacity: .6; }

/* 5 · the axis: zero, the threshold, the maximum. The zero yields when the
   threshold would print over it (QueueAxisComponent::ZERO_NEEDS). The threshold
   label used to be the one red word on a card with nothing overdue on it; it is
   a ruler mark, so it now reads in the neutral like the two beside it. */
.process-tracker .trk-ov-ax { margin-top: 4px; }
.process-tracker .trk-ov-ax svg { display: block; width: 72px; height: 14px; }
.process-tracker .trk-ov-ax-t { font-family: var(--trk-mono); font-size: 10.5px; fill: var(--trk-faint); }
.process-tracker .trk-ov-ax-lim { fill: var(--trk-ov-line); }

/* 6 · the foot, anchored: `margin-top: auto` in the panel's column, so the row's
   stretch lands BETWEEN the queue and the foot and the three cards close level. */
.process-tracker .trk-ov-foot { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--trk-line-soft); display: flex; align-items: baseline; gap: 12px; font-size: 12px; color: var(--trk-sub); }
.process-tracker .trk-ov-foot a { color: var(--trk-sub); text-decoration: underline; text-decoration-color: var(--trk-faint); text-underline-offset: 2px; }
.process-tracker .trk-ov-foot-tot { margin-left: auto; text-align: right; }
.process-tracker .trk-ov-foot-tot b { font-family: var(--trk-mono); font-size: 12.5px; font-weight: 700; color: var(--trk-ink); font-variant-numeric: tabular-nums; }
/* The empty message sits where the queue would start — the blank under it is
   air, and it reads as air only when the sentence is at the top. */
.process-tracker .trk-ov-empty { font-size: 13px; color: var(--trk-faint); padding: 8px 0 12px; }

/* ═══════════════════════════════════════════════════════════════════════════
   PORTFOLIO OVERVIEW — the dashboard at the entrance of Portfolio Management.

   ⚠️ EVERY COLOUR AND EVERY FONT SIZE IN THE CHARTS LIVES HERE, and every
   proportion is a presentation attribute on a <rect>. This is the same
   constraint `.trk-stack` and `.trk-clock-bar` document: `style_src` in this
   app's CSP has no `unsafe-inline`, so `style="width: 42%"` and
   `style="font-size: 30px"` are dropped by the browser with NO error — the bar
   renders as nothing and the number renders tiny. The failure looks like a
   design mistake, which is why it costs an hour every time somebody rediscovers
   it. Widths, heights, x/y, rx, dx and transform survive as attributes; fills
   and strokes come from the classes below.

   ⚠️ THE BARS HERE CARRY NO viewBox, and that is deliberate. The older bars in
   this file use `viewBox="0 0 100 H" preserveAspectRatio="none"`, which is fine
   for a rect and wrong for anything else: with the aspect ratio unlocked, a
   `<text>` inside is stretched horizontally by whatever width the container
   happens to have, and an `rx` corner becomes an ellipse. Without a viewBox
   there is no scaling at all — user units are CSS pixels, so text renders at
   the size set here, corners stay circular, and the proportion comes from
   percentage geometry (`width="75.5%"`) resolved against the SVG's own box.
   That is what lets the aging bars label themselves.

   The charts are hand-drawn rather than handed to the charting library that is
   already in the importmap, and the reason is the theme: dark mode here is a
   class toggle on <html> with no reload, so a chart whose colours were
   serialised into JSON on the server would keep its light-theme palette on a
   dark page. A fill painted `var(--trk-green)` follows the theme for free. */

/* Ordinal ramp for the four design stages: ONE hue, light to dark, so the order
   of the stages is legible in the colour itself. Validated in both modes for
   monotone lightness, adjacent step separation (ΔL ≥ 0.06) and a light end that
   still clears the surface.

   ⚠️ NOT four separate hues. The version this replaced used faint/plum/navy/
   amber while the pipeline panel directly above spent navy and amber on
   statuses — the same two colours meaning two different things on one screen.
   A single-hue ramp cannot make that mistake: the family reads as one scale, and
   the last step lands exactly on `--trk-navy`, so the ramp ends in the palette
   rather than beside it. Purple was tried here first and rejected by the owner. */
.process-tracker {
  --trk-stage-1: #a3aec8;
  --trk-stage-2: #7b89ab;
  --trk-stage-3: #51608a;
  --trk-stage-4: #2d3d5f;
}
.dark .process-tracker {
  --trk-stage-1: #d7dcea;
  --trk-stage-2: #aeb8d0;
  --trk-stage-3: #8592b0;
  --trk-stage-4: #5d6a8b;
}

/* ---- the tooltip -------------------------------------------------------- */
/* A stylesheet rule, so it survives the CSP that would drop the same thing as an
   attribute. It supplements the label — it never carries a fact that exists
   nowhere else on the screen. */
.process-tracker .trk-ov-tip { position: relative; }
.process-tracker .trk-ov-tip::after {
  content: attr(data-tip);
  position: absolute;
  left: 50%;
  bottom: calc(100% + 7px);
  transform: translateX(-50%);
  background: var(--trk-ink);
  color: var(--trk-panel);
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  padding: 4px 9px;
  border-radius: var(--trk-r-s);
  pointer-events: none;
  opacity: 0;
  transition: opacity .12s ease;
  z-index: 20;
}
.process-tracker .trk-ov-tip:hover::after,
.process-tracker .trk-ov-tip:focus-visible::after { opacity: 1; }

/* ---- the overview panels ---------------------------------------------------
   ⚠️ UM NÍVEL SÓ, DESDE QUE O PIPELINE DESCEU PARA OS CARDS (04/set/2026,
   docs/91). Havia dois: quatro painéis de papel e UM cartão em foco, o do
   Pipeline, "papel com tinta dentro" (#efe8da) com a aresta mais escura — a
   única superfície levantada da página, porque a tela não tinha nenhuma
   (medido, painel e chão diferiam 1.08:1). O pipeline agora mora dentro dos
   painéis que servem os seus estágios, então nenhum painel é o assunto da
   página e nenhum sobe: `.trk-ov-panel-focus`, o `focus:` do PanelComponent e
   as compensações `:not(.trk-ov-panel-focus)` saíram com o cartão.

   ⚠️ OS PAINÉIS SOBEM PARA O PAPEL, NÃO AFUNDAM NO CHÃO (24/ago/2026, "lifted
   paper", escolhido pelo dono entre quatro propostas de fundo). Com a laje
   removida (`.trk-page`, 21/ago/2026) o chão passou a ser o canvas #eee9dd e o
   recesso antigo (#e3dfd4) media **1.02 : 1** contra ele, bege no bege. Os
   painéis são papel (`--trk-panel`) com sombra, e as marcas pintadas em
   `--trk-line-soft` (hover da linha, grade do aging, chips, trilho do meter)
   valem como foram desenhadas. Sobrou UMA compensação, abaixo: o fio entre
   linhas fica em `--trk-line`, porque sobre papel branco o `-soft` da base mede
   1.06 : 1 e estas listas são densas.

   ⚠️ OS HEX SÃO FIXOS POR TEMA, E ISSO É DELIBERADO. A aresta vinha de
   `color-mix` com `--trk-ink` para inverter sozinha no escuro; o dono aprovou um
   mockup com os valores medidos nos dois temas, então eles entram como estão.
   Ao mexer em um, mexe-se no par — claro e `.dark` — ou o escuro fica para trás. */
.process-tracker .trk-ov-panel {
  background: var(--trk-panel);
  border: 1px solid #e0dbcf;
  border-radius: var(--trk-r-lg);
  padding: 16px 18px;
  box-shadow: var(--trk-shadow);
}
/* ⚠️ `.dark`, NOT `prefers-color-scheme`. This app's dark mode is a class the
   user toggles (`@custom-variant dark (&:where(.dark, .dark *))`); keying off
   the OS preference paints the dark edge on a light page whenever the two
   disagree. Só a aresta precisa desta regra — `--trk-panel` já troca sozinho no
   bloco escuro. */
.dark .process-tracker .trk-ov-panel { border-color: #35312a; }

.process-tracker .trk-ov-panel-t { font-size: 13.5px; }
.process-tracker .trk-ov-panel-s { font-size: 11.5px; margin-top: 2px; }
/* ---- pipeline: one stripe per unit of work ------------------------------ */
/* ⚠️ THE PROPORTION COMES FROM THE STRIPES BEING SIBLINGS, and there is no
   number anywhere in the markup to make it happen. Every stripe is one unit of
   work and every stripe is `flex: 1 1 0` inside ONE row, so they all resolve to
   the same width and a stage ends up exactly as wide as its own count. The
   segment wrapper is `display: contents` — it groups in the DOM (first/last
   rounding, the seam, the anchored label) without generating a box.

   The two spellings that do NOT work here, both tried: `style="flex: <count>"`
   per segment, which this app's CSP (`style_src :self`, no `unsafe-inline`)
   drops in silence; and a shrinkable stripe with a real segment box, which
   collapses the row because a shrinkable flex item contributes its MINIMUM, not
   its basis, to the intrinsic width of its ancestors — each segment then sized
   itself to its LABEL (measured: 11 stripes inside a 119px segment). The line
   below carries `flex: 1 1 0` for the same reason: a definite width, never one
   inferred from its content. */
.process-tracker .trk-ov-u {
  display: block;
  flex: 1 1 0;
  min-width: 0;
  height: 32px;
  /* The grain: a hairline of the surface colour between one unit and the next.
     Never a border in ink — that would be a mark that is not data. */
  border-right: var(--trk-grain, 1px) solid var(--trk-surface, var(--trk-panel));
  position: relative;
  transition: filter .1s ease;
}
.process-tracker .trk-ov-u:hover,
.process-tracker .trk-ov-u:focus-visible { filter: brightness(1.14); outline: none; z-index: 4; }
/* The seam between two stages: the same surface colour, twice as wide as the
   grain, so a stage reads as one run without the colours ever touching. That gap
   is also the secondary encoding the amber/green pair needs — measured ΔE 7.5
   under protanopia in dark mode, inside the 6–8 floor band. */
.process-tracker .trk-ov-seg + .trk-ov-seg > .trk-ov-u:first-child { border-left: 2px solid var(--trk-surface, var(--trk-panel)); }
.process-tracker .trk-ov-seg > .trk-ov-u:first-child { border-radius: 5px 0 0 5px; }
.process-tracker .trk-ov-seg > .trk-ov-u:last-child  { border-radius: 0 5px 5px 0; border-right-width: 0; }
.process-tracker .trk-ov-seg > .trk-ov-u:only-child  { border-radius: 5px; }

/* ⚠️ A FITA É LAVADA, O SWATCH NÃO (dono, 08/set/2026, docs/92 §6). A fita é um
   bloco de 28px na largura inteira do card, e a régua do /dataviz é explícita:
   preenchimento saturado é para marca PEQUENA, nunca para bloco grande. Medido
   contra o papel, o navy dava 10,63:1 e o cinza 2,76 — quatro vezes de peso
   entre dois cards da mesma fileira, e era por isso que Permitting (cinza 2,76 +
   azul-claro 3,44) lia melhor que Portfolio (navy 10,63 + âmbar + verde). Cada
   tom é lavado em direção ao PAPEL até a faixa do Permitting; a identidade fica
   inteira no swatch de 10px da cabeça, que é marca pequena e pode ser saturada.

   ⚠️ A PORCENTAGEM É POR TOM, E O ÂMBAR TEM TETO. Lavar tudo igual colapsa o
   único par que divide uma fita — pendente (cinza) e em redação (âmbar) no
   Drafting Backlog: a 70% o âmbar vira bege e o par cai para ΔE 7,4 (piso 15).
   O teto medido é 90% no claro (ΔE 15,4) e 80% no escuro (ΔE 16,1). O navy, que
   era o outlier, não divide fita com ninguém e desce a 60%. */
.process-tracker .trk-ov-seg-navy  > .trk-ov-u { background: color-mix(in srgb, var(--trk-navy) 60%, var(--trk-panel)); }
.process-tracker .trk-ov-seg-amber > .trk-ov-u { background: color-mix(in srgb, var(--trk-amber) 90%, var(--trk-panel)); }
.process-tracker .trk-ov-seg-green > .trk-ov-u { background: color-mix(in srgb, var(--trk-green) 70%, var(--trk-panel)); }

/* The sliver a stage keeps while it holds nothing: outlined instead of filled,
   ⚠️ STILL IN ITS OWN COLOUR. A grey placeholder broke the one thing that makes
   the ribbon readable — colour and order matching the labels — so the empty stage
   became unidentifiable exactly when the reader needed to know WHICH one it was.
   It keeps the hue and drops the fill, and it never shrinks. */
.process-tracker .trk-ov-u-empty {
  /* Wide enough to carry its own short name above it, and no wider: the sliver
     holds nothing, so its width claims nothing either. */
  flex: 0 0 72px;
  background: none !important;
  border: 1px dashed currentColor;
  border-radius: 5px;
  opacity: .5;
}
.process-tracker .trk-ov-seg-navy  { color: var(--trk-navy); }
.process-tracker .trk-ov-seg-amber { color: var(--trk-amber); }
.process-tracker .trk-ov-seg-green { color: var(--trk-green); }

/* ---- the slice: a stage of the pipeline inside its own panel ------------
   ⚠️ THE BAND CAME DOWN INTO THE CARDS (owner, 04/set/2026, docs/91). It used
   to be one full-width line in a raised card above the grid; now each stage
   panel opens with ITS OWN segment, at the panel's full width, and the panels
   sit in pipeline order. The head carries the count that the band's anchored
   label used to — there is always room for it there — and the legend beside it
   names the stage(s), which is what keeps the idle grey (2.76:1 on paper) legal.

   ⚠️ THE RIBBON BLEEDS TO THE CARD'S OWN EDGES, AND THERE IS NO CONNECTOR. Three
   splices were drawn: an arrowhead + rail + notch, a wire behind the row, and
   this. The first two only read if the three ribbons share a y, and a subtitle
   that wraps on a narrow window moves one of them — the bleed has nothing to
   misalign. The negative margin is the panel's padding plus its border (18 + 1),
   so the ribbon crosses the border and stops at the outer edge. On the row's
   first and last panel the outer end stays inset and rounded, so the row still
   reads as one ribbon with two ends; under `lg` the panels stack and every
   ribbon runs edge to edge. */
.process-tracker .trk-ov-slice { margin: -2px 0 14px; }
.process-tracker .trk-ov-slice-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}
/* ⚠️ THE NAME IS THE HEAD, THE COUNT IS A NUMBER (owner, 08/set/2026, docs/92).
   "1 of 2 leads in permitting", repeated with the same denominator on three
   cards, was a fraction read three times to learn which stage the card is. The
   name opens the head in its own colour; the count sits at the right edge over
   the end of the ribbon; the denominator is the line above the row, once. */
.process-tracker .trk-ov-slice-name {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--trk-ink);
  white-space: nowrap;
}
.process-tracker .trk-ov-slice-name + .trk-ov-slice-name::before { content: "·"; color: var(--trk-faint); font-weight: 400; margin-right: 2px; }
.process-tracker .trk-ov-slice-of { font-size: 12.5px; font-weight: 400; color: var(--trk-sub); }
.process-tracker .trk-ov-slice-count {
  margin-left: auto;
  font-size: 28px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--trk-ink);
}

/* ⚠️ `flex-wrap: nowrap` is the invariant of the ribbon: one row, whatever the
   counts. The stripes divide the line's DEFINITE width equally, which is what
   makes a stage as wide as its own count (see the stripe rules above). */
.process-tracker .trk-ov-line {
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  min-width: 0;
  --trk-surface: var(--trk-panel);
}
/* The segment groups in the DOM and not in the layout — see the stripe rules. */
.process-tracker .trk-ov-seg { display: contents; }
/* Past ~150 stripes the 1px grain is more border than colour, so it goes and
   each stage reads as one solid run. */
.process-tracker .trk-ov-line-plain { --trk-grain: 0px; }

.process-tracker .trk-ov-slice .trk-ov-line { margin-inline: -19px; }
.process-tracker .trk-ov-slice .trk-ov-u { height: 28px; }
/* Squared where it runs off the card. Six classes deep on purpose: it has to
   beat the stripe's own `:first-child` / `:only-child` rounding above. */
.process-tracker .trk-ov-slice .trk-ov-seg:first-child > .trk-ov-u:first-child {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
.process-tracker .trk-ov-slice .trk-ov-seg:last-child > .trk-ov-u:last-child {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
/* The empty sliver never crosses the border: an outline running off the card
   reads as a defect, not as an empty stage. When the whole ribbon is empty the
   slivers share the width — dashed tracks say "empty" better than 72px stubs
   sitting at the left of a blank line (seen on the empty dev database). */
.process-tracker .trk-ov-slice .trk-ov-seg:first-child > .trk-ov-u-empty { margin-left: 19px; }
.process-tracker .trk-ov-slice .trk-ov-seg:last-child > .trk-ov-u-empty { margin-right: 19px; }
.process-tracker .trk-ov-slice .trk-ov-line-empty .trk-ov-u-empty { flex: 1 1 0; }
@media (min-width: 1024px) {
  .process-tracker .trk-ov-stage-row > .trk-ov-panel:first-child .trk-ov-slice .trk-ov-line { margin-left: 0; }
  .process-tracker .trk-ov-stage-row > .trk-ov-panel:first-child .trk-ov-slice .trk-ov-seg:first-child > .trk-ov-u:first-child {
    border-top-left-radius: 5px;
    border-bottom-left-radius: 5px;
  }
  .process-tracker .trk-ov-stage-row > .trk-ov-panel:first-child .trk-ov-slice .trk-ov-seg:first-child > .trk-ov-u-empty { margin-left: 0; }
  .process-tracker .trk-ov-stage-row > .trk-ov-panel:nth-child(3) .trk-ov-slice .trk-ov-line { margin-right: 0; }
  .process-tracker .trk-ov-stage-row > .trk-ov-panel:nth-child(3) .trk-ov-slice .trk-ov-seg:last-child > .trk-ov-u:last-child {
    border-top-right-radius: 5px;
    border-bottom-right-radius: 5px;
  }
  .process-tracker .trk-ov-stage-row > .trk-ov-panel:nth-child(3) .trk-ov-slice .trk-ov-seg:last-child > .trk-ov-u-empty { margin-right: 0; }

  /* ⚠️ O SUBTÍTULO RESERVA DUAS LINHAS NA FILEIRA DE ESTÁGIOS. A fatia abre logo
     abaixo do cabeçalho, então um subtítulo de uma linha ao lado de dois de duas
     levantava a fita daquele card ~17px, e a fileira parava de ler como uma linha
     só — que é justamente o que carrega a continuidade desde que os conectores
     caíram (a sangria não tem o que desalinhar, mas o cabeçalho acima dela tem).
     Reservar a segunda linha iguala os três cabeçalhos sem cortar texto.
     Teto conhecido: um subtítulo que passe de DUAS linhas desalinha de novo; aí
     encurta-se aquela frase, não se reserva uma terceira linha em todos os cards. */
  .process-tracker .trk-ov-stage-row .trk-ov-panel-s { min-height: 2lh; }
}

/* ---- the total: the denominator, once, above the row ----------------------
   "18 contracts in flight" used to open every slice as "N of 18 …". It is one
   fact about the screen, so it is said once, where the row begins. */
.process-tracker .trk-ov-total { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; font-size: 12.5px; color: var(--trk-sub); }
.process-tracker .trk-ov-total-label { font-family: var(--trk-mono); font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--trk-faint); margin-right: 4px; }
.process-tracker .trk-ov-total b { font-size: 22px; font-weight: 700; line-height: 1; letter-spacing: -.02em; color: var(--trk-ink); }

/* ---- the exits: the terminal states, in one line under the row ------------
   An outcome is not a stage, so it is never on a ribbon. Round dots where the
   stages carry squares, so the two kinds are told apart by shape as well as by
   colour. `summary` is the one figure a process states for the whole line (AR's
   outstanding total, the hero of its band). */
.process-tracker .trk-ov-exits {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 18px;
  padding: 10px 4px 0;
  margin-bottom: 16px;
  font-size: 12.5px;
  color: var(--trk-sub);
}
.process-tracker .trk-ov-exits-label {
  margin-right: auto;
  font-family: var(--trk-mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--trk-faint);
}
.process-tracker .trk-ov-exit { display: flex; align-items: center; gap: 8px; white-space: nowrap; transition: color .1s ease; }
.process-tracker .trk-ov-exit:hover { color: var(--trk-ink); }
.process-tracker .trk-ov-exit-v { font-size: 14px; font-weight: 700; color: var(--trk-ink); }

/* ---- the pipeline vocabulary: one colour per meaning ----------------------
   Contract Development paints its pipeline by WHOSE BALL IT IS, and each mark
   below is a state the reader can act on:

     idle   nothing started        --trk-faint
     amber  the ball is ours       --trk-amber
     wait   waiting on the client  --trk-stage-2
     owed   waiting on the money   --trk-stage-4
     green  it ended well          (--trk-green, on .trk-ov-dot)
     red    it ended badly         (--trk-red,   on .trk-ov-dot)

   ⚠️ THE TWO WAITING STATES SHARE A HUE ON PURPOSE, in two steps. They are the
   same situation — somebody outside the office is holding the contract — and the
   step says how far along it is. Giving them unrelated hues was tried and failed
   twice over: `--trk-plum` already means "the hand" on this skin (PDS-424) and
   `--trk-navy` already means "what you click or focus", so both would have made
   one colour mean two things; and measured in dark mode, navy #9aa8c6 against
   plum #c79ad0 is ΔE 1.8 under deuteranopia — the same colour to a reader who
   has it. The two ramp steps measure ΔE 7.4 instead.

   ⚠️ USE THE RAMP STEPS, NOT `--trk-navy`, for the deeper of the two. In dark
   mode `--trk-navy` inverts to a LIGHT blue (#9aa8c6) and would collide with the
   lighter step; `--trk-stage-4` stays the darker one in both modes, which is the
   whole reason the pair separates.

   No 6-hue categorical palette drawn from this app passes the /dataviz checks —
   docs/56 recorded the same thing and reached the same conclusion: these are
   product entity colours and they are not repainted for one screen. What makes
   it safe is that colour is never the only carrier here — every tile group
   states its count above it and every legend row carries its label. */
/* O cinza e o azul-claro já estavam na faixa (2,76 e 3,44) — são justamente os
   dois tons que faziam Permitting ler melhor. Ficam inteiros. */
.process-tracker .trk-ov-seg-idle > .trk-ov-u { background: var(--trk-faint); }
.process-tracker .trk-ov-seg-wait > .trk-ov-u { background: var(--trk-stage-2); }
.process-tracker .trk-ov-seg-owed > .trk-ov-u { background: color-mix(in srgb, var(--trk-stage-4) 60%, var(--trk-panel)); }
/* ⚠️ NO ESCURO OS PESOS SÃO OUTROS, então as porcentagens são outras. Lá o azul-
   claro (8,47) e o âmbar (7,64) é que gritam, enquanto `owed` já mede 3,13 e não
   tem o que lavar. Ao mexer num par, mexe-se nos dois — claro e escuro. */
.dark .process-tracker .trk-ov-seg-owed  > .trk-ov-u { background: var(--trk-stage-4); }
.dark .process-tracker .trk-ov-seg-green > .trk-ov-u { background: color-mix(in srgb, var(--trk-green) 60%, var(--trk-panel)); }
.dark .process-tracker .trk-ov-seg-amber > .trk-ov-u { background: color-mix(in srgb, var(--trk-amber) 80%, var(--trk-panel)); }
.dark .process-tracker .trk-ov-seg-wait  > .trk-ov-u { background: color-mix(in srgb, var(--trk-stage-2) 60%, var(--trk-panel)); }
.process-tracker .trk-ov-seg-idle { color: var(--trk-faint); }
.process-tracker .trk-ov-seg-wait { color: var(--trk-stage-2); }
.process-tracker .trk-ov-seg-owed { color: var(--trk-stage-4); }

/* The legend mark for an in-flight state. Square, because it is a stage of work;
   the round `.trk-ov-dot` stays with the two terminal states, so the two kinds
   of row are told apart by shape as well as by colour. */
.process-tracker .trk-ov-swatch { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.process-tracker .trk-ov-swatch-idle  { background: var(--trk-faint); }
.process-tracker .trk-ov-swatch-amber { background: var(--trk-amber); }
.process-tracker .trk-ov-swatch-wait  { background: var(--trk-stage-2); }
.process-tracker .trk-ov-swatch-owed  { background: var(--trk-stage-4); }
.process-tracker .trk-ov-swatch-navy  { background: var(--trk-navy); }
.process-tracker .trk-ov-swatch-green { background: var(--trk-green); }

.process-tracker .trk-ov-dot { width: 10px; height: 10px; border-radius: 999px; flex-shrink: 0; }
.process-tracker .trk-ov-dot-navy  { background: var(--trk-navy); }
.process-tracker .trk-ov-dot-amber { background: var(--trk-amber); }
.process-tracker .trk-ov-dot-green { background: var(--trk-green); }
.process-tracker .trk-ov-dot-red   { background: var(--trk-red); }

/* ---- lead chips: the sample on a Design Readiness row's second line ------ */
.process-tracker .trk-ov-chip {
  display: inline-block;
  font-family: var(--trk-mono);
  font-size: 11px;
  line-height: 1.4;
  padding: 1px 6px;
  border-radius: var(--trk-r-s);
  background: var(--trk-line-soft);
  color: var(--trk-ink);
  white-space: nowrap;
}
.process-tracker a.trk-ov-chip:hover,
.process-tracker a.trk-ov-chip:focus-visible { background: var(--trk-line); outline: none; }

/* The overflow control is a <summary>: it opens the rest in place, with no JS
   and no navigation, because the stage a lead stands at is derived and cannot be
   filtered for on the Hub. */
.process-tracker .trk-ov-more {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  padding: 1px 6px;
  border-radius: var(--trk-r-s);
  border: 1px dashed var(--trk-faint);
  color: var(--trk-sub);
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}
.process-tracker .trk-ov-more::-webkit-details-marker { display: none; }
.process-tracker .trk-ov-more:hover,
.process-tracker .trk-ov-more:focus-visible { color: var(--trk-ink); border-color: var(--trk-sub); outline: none; }
/* ⚠️ OPEN, THE CONTROL MOVES TO THE END AND CHANGES WHAT IT SAYS. Left alone it
   sits in the middle of the chips it just revealed, still promising "+3 more"
   while those three are on screen beside it. `order` works because the <details>
   is `display: contents`, so summary and chips are siblings in the same flex
   row. */
.process-tracker details[open] > .trk-ov-more { color: var(--trk-ink); border-style: solid; order: 1; }
.process-tracker .trk-ov-more-open { display: none; }
.process-tracker details[open] > .trk-ov-more .trk-ov-more-shut { display: none; }
.process-tracker details[open] > .trk-ov-more .trk-ov-more-open { display: inline; }

/* ⚠️ A TINTA FRACA É CORRIGIDA REDEFININDO O TOKEN DENTRO DO CARTÃO, não marca a
   marca. `--trk-faint` media 2,35 : 1 sobre o cartão recuado e mede 2,75 sobre o
   papel para onde o cartão subiu (24/ago/2026) — nos dois casos abaixo do piso de
   3 para texto pequeno — e ele está em eixo, código de lead, subtítulo, "N more",
   "no invoice". Uma redefinição local cascateia para todos os descendentes de uma
   vez, incluindo os `fill` de SVG, e nenhum call site precisa saber.

   ⚠️ E SÓ NO CLARO. No escuro a mesma tinta sobre o mesmo recuo mede 3,38 e
   passa; subir lá achataria o terceiro nível de tinta sem motivo. O defeito é de
   um tema, então a correção é de um tema — `html:not(.dark)`, e não uma regra
   espelhada. O valor escolhido (53% da tinta cheia) mede 3,2 : 1: acima do piso e
   ainda abaixo de `--trk-sub` (4,8), que é o segundo nível e precisa continuar
   sendo outra coisa. */
html:not(.dark) .process-tracker .trk-ov-panel {
  --trk-faint: color-mix(in srgb, var(--trk-ink) 53%, transparent);
}
/* ═══════════════════════════════════════════════════════════════════════════
   PLAN REVIEW — step 5 (PDS-463)

   The skin stays the app's: cream chrome, white surface, navy as the one
   accent. What this section adds is COLOUR WHERE THE SCREEN CHANGES MEANING,
   because this is the first Permitting screen whose lines come from three
   different mouths — the portal, an e-mail, and us — and a wall of one colour
   makes the reader work out which is which by reading every line.

   Three places carry it, and nowhere else:
     · the section headings, so a panel reads as a thing you act on;
     · the timeline nubs, one colour per channel;
     · the side cards, whose pill says where the value on screen came from.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- a panel of the working column ---- */
.process-tracker .trk-pr-card {
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
  background: var(--trk-panel);
  padding: 13px 15px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* The heading is navy, which in this skin is the colour of something you
   operate — the same ink the primary action wears. */
.process-tracker .trk-pr-head {
  margin: 0;
  font-size: 13px;
  font-weight: 650;
  color: var(--trk-navy);
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ---- the status band ---- */
.process-tracker .trk-pr-band {
  border-radius: var(--trk-r);
  padding: 13px 16px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  border-left: 3px solid transparent;
}
.process-tracker .trk-pr-band .trk-pr-band-title {
  font-size: 15px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
/* ⚠️ THE ACTION IS PUSHED RIGHT, NOT "the last child". `> *:last-child` looked
   equivalent and was not: with no permit there is no button, and the rule then
   pushed the SENTENCE to the right edge of an otherwise empty band. */
.process-tracker .trk-pr-band .trk-pr-band-title > form { margin-left: auto; }
.process-tracker .trk-pr-band .trk-pr-band-sub { font-size: 12.5px; color: var(--trk-sub); margin: 0; }
.process-tracker .trk-pr-band-good { background: var(--trk-green-soft); border-left-color: var(--trk-green); }
.process-tracker .trk-pr-band-good .trk-pr-band-title { color: var(--trk-green); }
.process-tracker .trk-pr-band-warn { background: var(--trk-amber-soft); border-left-color: var(--trk-amber); }
.process-tracker .trk-pr-band-warn .trk-pr-band-title { color: var(--trk-amber); }
.process-tracker .trk-pr-band-bad { background: var(--trk-red-soft); border-left-color: var(--trk-red); }
.process-tracker .trk-pr-band-bad .trk-pr-band-title { color: var(--trk-red); }
/* A status the county's ladder does not carry — a rung we have not catalogued,
   or a word somebody typed by hand. It is not good news and not a warning: it
   is information we cannot classify, and navy is this skin's colour for that.
   ⚠️ MIXED INTO THE PANEL AND NOT INTO TRANSPARENT. Navy at 13% over the cream
   ground comes out muddy grey — the band read as disabled rather than as a
   state. Over the panel's near-white it reads as the blue it is. */
.process-tracker .trk-pr-band-flat {
  background: color-mix(in srgb, var(--trk-navy) 11%, var(--trk-panel));
  border-left-color: var(--trk-navy);
}
.process-tracker .trk-pr-band-flat .trk-pr-band-title { color: var(--trk-navy); }

/* ---- the timeline ----
   THE DATE IS A GUTTER AND NOT A CHIP INSIDE THE CARD. Every line of this log
   is "on this day, this channel said this", and the day is what the reader
   scans down; putting it in its own right-aligned mono column turns the list
   into something you can read chronologically without reading it at all.
   No box around each entry either — nine boxes stacked is nine borders
   competing with the one thing that separates the lines, which is the nub. */
.process-tracker .trk-prtl { display: grid; grid-template-columns: 88px 18px 1fr; gap: 0 12px; }
.process-tracker .trk-prtl-when {
  font-family: var(--trk-mono);
  font-size: 11.5px;
  color: var(--trk-faint);
  text-align: right;
  padding-top: 3px;
  white-space: nowrap;
}
.process-tracker .trk-prtl-rail { display: flex; flex-direction: column; align-items: center; }
.process-tracker .trk-prtl-rail i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-top: 6px;
  flex: none;
  background: var(--trk-faint);
}
.process-tracker .trk-prtl-rail s { flex: 1; width: 1.5px; background: var(--trk-line); margin-top: 3px; }
.process-tracker .trk-prtl-row:last-child .trk-prtl-rail s { display: none; }
.process-tracker .trk-prtl-body { padding: 0 0 15px; min-width: 0; }
.process-tracker .trk-prtl-title { font-size: 13.5px; font-weight: 600; color: var(--trk-ink); }
/* The channel rides on the title line, small and mono, because it qualifies
   the sentence rather than labelling the row. */
.process-tracker .trk-prtl-via {
  font-family: var(--trk-mono);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--trk-faint);
  margin-left: 8px;
}
.process-tracker .trk-prtl-detail { font-size: 12.5px; color: var(--trk-sub); margin: 2px 0 0; }

/* ONE COLOUR PER MOUTH. Navy is us; green is the portal telling us something
   moved forward; red is the portal telling us something came back; a hollow
   amber ring is the open end of the line, where nothing has been said yet and
   the county does not announce success. */
.process-tracker .trk-prtl-us   .trk-prtl-rail i { background: var(--trk-navy); }
.process-tracker .trk-prtl-good .trk-prtl-rail i { background: var(--trk-green); }
.process-tracker .trk-prtl-bad  .trk-prtl-rail i { background: var(--trk-red); }
.process-tracker .trk-prtl-wait .trk-prtl-rail i {
  background: var(--trk-panel);
  border: 2px solid var(--trk-amber);
}
.process-tracker .trk-prtl-wait .trk-prtl-title { color: var(--trk-amber); }

/* ---- the side cards ---- */
.process-tracker .trk-pr-side {
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
  background: var(--trk-panel);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.process-tracker .trk-pr-side-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--trk-navy);
}
/* WHERE THE VALUE CAME FROM, as a pill on the card that shows it. The manual
   fallback and a portal reading look identical once written down, and which
   one it is decides whether you trust it. */
.process-tracker .trk-pr-pill {
  margin-left: auto;
  font-family: var(--trk-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 999px;
  color: var(--trk-green);
  background: var(--trk-green-soft);
}
.process-tracker .trk-pr-pill-manual { color: var(--trk-amber); background: var(--trk-amber-soft); }
.process-tracker .trk-pr-kv { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; margin: 0; font-size: 12.5px; }
.process-tracker .trk-pr-kv dt { color: var(--trk-faint); }
.process-tracker .trk-pr-kv dd { margin: 0; font-family: var(--trk-mono); font-size: 12px; color: var(--trk-ink); text-align: right; }
/* A clock row is chrome inside a panel — the cream ground, so the numbers read
   as instrument readings and not as content. */
.process-tracker .trk-pr-clock {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: baseline;
  background: var(--trk-bg);
  border-radius: var(--trk-r);
  padding: 7px 11px;
  font-size: 12.5px;
  color: var(--trk-sub);
}
.process-tracker .trk-pr-clock b { font-family: var(--trk-mono); font-weight: 500; color: var(--trk-ink); }
.process-tracker .trk-pr-clock.trk-pr-clock-warn { background: var(--trk-amber-soft); }
.process-tracker .trk-pr-clock.trk-pr-clock-warn b { color: var(--trk-amber); }

/* ---- the lot's records, after a search ---- */
.process-tracker .trk-pr-rec {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 7px 11px;
  border-radius: var(--trk-r);
  border: 1px solid var(--trk-line-soft);
  font-size: 12.5px;
}
.process-tracker .trk-pr-rec-on { border-color: var(--trk-green); background: var(--trk-green-soft); }
.process-tracker .trk-pr-rec .trk-pr-rec-no { font-family: var(--trk-mono); font-weight: 600; color: var(--trk-ink); }

/* ---- PLAN REVIEW · the file-verification layer (PDS-464) ----
   One row per document of the package, and the row is where the correction
   happens: the county refuses a FILE, names it, and everything not named is
   already accepted. The expanded block belongs to the row it corrects — a modal
   would take the file name off screen at the moment somebody is comparing it. */
.process-tracker .trk-pr-file {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 10px;
  align-items: center;
  padding: 7px 11px;
  border-radius: var(--trk-r);
  font-size: 12.5px;
}
.process-tracker .trk-pr-file .trk-pr-file-name { font-family: var(--trk-mono); font-size: 12px; color: var(--trk-ink); }
.process-tracker .trk-pr-file .trk-pr-file-v { font-family: var(--trk-mono); font-size: 11px; color: var(--trk-faint); }
.process-tracker .trk-pr-file-on { background: var(--trk-red-soft); }

/* The state chip. Green is the only one that means "the county is done with it",
   and it is derived from the permit status — never from a tick. */
.process-tracker .trk-pr-chip {
  font-family: var(--trk-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 999px;
  white-space: nowrap;
  color: var(--trk-sub);
  background: color-mix(in srgb, var(--trk-ink) 7%, transparent);
}
.process-tracker .trk-pr-chip-good { color: var(--trk-green); background: var(--trk-green-soft); }
.process-tracker .trk-pr-chip-bad { color: var(--trk-red); background: var(--trk-red-soft); }
.process-tracker .trk-pr-chip-warn { color: var(--trk-amber); background: var(--trk-amber-soft); }

/* THE COUNTY'S REFUSAL LETTERS, ONE ROW EACH (PDS-464). The unit of work is the
   letter: a pending one opens its own form, a handled one collapses to what it
   named. A permit accumulates these over its life and one can arrive after
   issuance, so this list is never gated on the permit's status. */
.process-tracker .trk-pr-letters {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}
.process-tracker .trk-pr-letter {
  border: 1px solid var(--trk-line);
  border-radius: var(--trk-r);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 13px;
}
/* The one still owed reads like the correction blocks: a red spine. */
.process-tracker .trk-pr-letter-open {
  border-left: 2px solid var(--trk-red);
  background: var(--trk-line-soft);
}
.process-tracker .trk-pr-letter-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.process-tracker .trk-pr-letter-date {
  font-family: var(--trk-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--trk-ink);
}
.process-tracker .trk-pr-letter-done {
  margin: 0;
  padding-left: 16px;
  font-size: 12.5px;
  color: var(--trk-sub);
}

/* The correction, hanging off the row it belongs to. */
.process-tracker .trk-pr-fix {
  border-left: 2px solid var(--trk-red);
  padding: 8px 12px;
  margin: 2px 0 6px 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 13px;
}
.process-tracker .trk-pr-fix-what {
  background: var(--trk-line-soft);
  border-radius: var(--trk-r);
  padding: 9px 11px;
  font-size: 12.5px;
  color: var(--trk-sub);
}
.process-tracker .trk-pr-fix-what b { color: var(--trk-ink); font-weight: 600; }

/* The closed list of reasons, as pickable pills. A select would hide five of the
   six, and the operator is comparing them against a letter. */
.process-tracker .trk-pr-reason {
  font-size: 12px;
  padding: 4px 9px;
  border-radius: var(--trk-r);
  border: 1px solid var(--trk-line);
  color: var(--trk-sub);
  background: var(--trk-panel);
  cursor: pointer;
}
.process-tracker .trk-pr-reason:hover { border-color: var(--trk-navy); color: var(--trk-navy); }
.process-tracker input[type="radio"]:checked + .trk-pr-reason,
.process-tracker .trk-pr-reason-on {
  border-color: var(--trk-navy);
  color: var(--trk-navy);
  background: var(--trk-navy-soft);
}

/* ---- PLAN REVIEW · the technical review (PDS-465) ----
   One row per reviewing section. There is NO fixed list — the county opens what
   the lot needs (7 on one permit, 9 on another) — so nothing here is keyed by
   name and the row has to read well whatever the county called it. */
.process-tracker .trk-pr-sec {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 10px;
  align-items: center;
  padding: 7px 11px;
  border-radius: var(--trk-r);
  background: var(--trk-bg);
  font-size: 12.5px;
}
.process-tracker .trk-pr-sec .trk-pr-sec-name { color: var(--trk-ink); }
.process-tracker .trk-pr-sec .trk-pr-sec-when { font-family: var(--trk-mono); font-size: 11px; color: var(--trk-faint); }
.process-tracker .trk-pr-sec-on { background: var(--trk-red-soft); }
.process-tracker .trk-pr-sec-count {
  font-family: var(--trk-mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--trk-navy);
}

/* How much of the round is done. A bar and not a number alone, because "4 of 7"
   is read as progress and the eye gets it before the digits do. */
.process-tracker .trk-pr-prog {
  height: 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--trk-navy) 11%, var(--trk-panel));
  overflow: hidden;
}
.process-tracker .trk-pr-prog svg { display: block; width: 100%; height: 100%; }
.process-tracker .trk-pr-prog rect { fill: var(--trk-green); }
/* A round is 7 of 7 finished and still bad news. Painting the deficient share
   red is the difference between "done" and "done, and three came back". */
.process-tracker .trk-pr-prog rect.trk-pr-prog-bad { fill: var(--trk-red); }

/* The round strip, in the card (navigation) and in the side panel (state).
   THE THIRD BOX IS THE POINT: the county charges re-submittal from the third
   submission on, and nobody is told that at the portal. */
.process-tracker .trk-pr-round {
  font-family: var(--trk-mono);
  font-size: 11px;
  font-weight: 700;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--trk-line);
  color: var(--trk-sub);
  text-decoration: none;
}
.process-tracker .trk-pr-round:hover { border-color: var(--trk-navy); color: var(--trk-navy); }
.process-tracker .trk-pr-round-on {
  border-color: var(--trk-navy);
  color: var(--trk-navy);
  background: var(--trk-navy-soft);
}
.process-tracker .trk-pr-roundbox {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 4px;
  border-radius: var(--trk-r);
  background: var(--trk-bg);
}
.process-tracker .trk-pr-roundbox b { font-family: var(--trk-mono); font-size: 13px; color: var(--trk-sub); }
.process-tracker .trk-pr-roundbox span { font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--trk-faint); }
/* Costs money. The tint survives being the current round, which is exactly the
   moment somebody needs to know. */
.process-tracker .trk-pr-roundbox-fee { background: var(--trk-amber-soft); }
.process-tracker .trk-pr-roundbox-fee b,
.process-tracker .trk-pr-roundbox-fee span { color: var(--trk-amber); }
.process-tracker .trk-pr-roundbox-on { background: var(--trk-navy-soft); }
.process-tracker .trk-pr-roundbox-on b,
.process-tracker .trk-pr-roundbox-on span { color: var(--trk-navy); }

/* The one clock with a statute behind it. Red, not amber: ten business days is
   not a nudge — missing it denies the application (F.S. 553.79). */
.process-tracker .trk-pr-clock-bad { background: var(--trk-red-soft); }
.process-tracker .trk-pr-clock-bad b { color: var(--trk-red); }

/* ---- PLAN REVIEW · the comments and the round's package (PDS-466) ----
   One block per numbered comment of the county's letter. The verbatim text is
   the widest thing on the row on purpose: it is what the vendor has to read and
   what the narrative reprints, and the fields that classify it are furniture
   around it. */
.process-tracker .trk-pr-cmt {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  border-radius: var(--trk-r);
  background: var(--trk-bg);
  border-left: 2px solid var(--trk-line);
}
.process-tracker .trk-pr-cmt-no {
  font-family: var(--trk-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--trk-navy);
}
/* Quoted, because it is quoted: the county's words, not ours. */
.process-tracker .trk-pr-cmt-body {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--trk-ink);
  padding-left: 9px;
  border-left: 2px solid color-mix(in srgb, var(--trk-navy) 20%, transparent);
}

/* ---- PLAN REVIEW · issuance (PDS-468) ----
   Each block of the "to issue" card is one thing owed, and each one is owned
   somewhere else — the fees by the Pre-permit gate, page two by the Application.
   The left border is the visual promise that this is a view and not a home. */
.process-tracker .trk-pr-fee {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 9px 12px;
  border-radius: var(--trk-r);
  background: var(--trk-bg);
  border-left: 2px solid color-mix(in srgb, var(--trk-navy) 25%, transparent);
  font-size: 12.5px;
}
