/* "Cercis Ink" design-system primitives — docs "README cercis ui.md".
   Plain CSS rather than Tailwind utilities: these values are exact tokens from the
   Claude Design handoff (hex colours, px sizes, rgba shadows), not points on Tailwind's
   discrete scale, so hand-authoring them here is more accurate than approximating with
   arbitrary-value utility classes everywhere they're used. */

:root {
  --ink-chrome: #101A28;
  --ink-primary: #1E4E8C;
  --ink-primary-hover: #16386A;
  --ink-primary-tint-bg: #E3ECF7;
  --ink-primary-tint-text: #1E4E8C;
  --ink-text: #101A28;
  --ink-text-muted: #3C4854;
  --ink-text-secondary: #5B6875;
  --ink-text-faint: #8B97A3;
  --ink-text-ghost: #97A3AF;
  --ink-text-ghost-2: #A2AEB9;
  --ink-text-ghost-3: #B7C1CB;
  --ink-rule: #DDE3EA;
  --ink-rule-soft: #EDF1F4;
  --ink-rule-soft-2: #F5F7F9;
  --ink-surface-sunken: #F7F9FB;
  --ink-surface-sunken-2: #FBFCFD;
  --ink-success-bg: #E7F2EC;
  --ink-success-text: #166139;
  --ink-warn-bg: #FBF2E1;
  --ink-warn-text: #8A5606;
  --ink-warn-text-strong: #7A4E06;
  --ink-warn-border: #E3C98F;
  --ink-warn-accent: #B4700A;
  --ink-danger-bg: #FAEAE8;
  --ink-danger-text: #8E1F19;
  --ink-danger-border: #F0DCDA;
  --ink-neutral-bg: #EEF1F4;
  --ink-neutral-text: #6B7885;
  --ink-canvas: #EEF1F5;
  --ink-paper-alt: #FCFDFE;
  --ink-trough: #E5EAF0;
  --ink-chrome-raised: #26344A;
  --ink-chrome-text: #93A4B8;
  --ink-control-border: #D3DAE1;
  --ink-control-hover: #F4F6F8;
  --ink-danger: #B3261E;
  --ink-success: #1F7A4D;
  --ink-warn-dot: #D9901C;
  --ink-warn-surface: #FDFBF5;
  --ink-focus-ring: #A9C6E8;
  --ink-paper: #FFFFFF;
}

/* Content card shell — 11px radius, 1px #DDE3EA border, the one approved card shadow. */
.ink-card {
  background: #fff;
  border: 1px solid var(--ink-rule);
  border-radius: 11px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(16, 26, 40, 0.07);
}

/* A card that hosts a dropdown cannot clip.
   `.ink-card` sets `overflow: hidden` so a square child never shows through a rounded corner, and
   that is right for almost everything — but an absolutely positioned menu is the one child that
   legitimately has to escape. On a tall card nobody notices; on a short one the menu is cut off at
   the card's own bottom edge, which is CR-166: an Add menu whose third item was invisible on any
   order form with no rows yet.

   Its own class rather than a Tailwind `!overflow-visible` on the element. That was the first fix
   and it did nothing: the `!` variant was never generated into the compiled stylesheet, so the
   class matched no rule at all — and even generated, `cercis-ink.css` loads last, so a same
   specificity utility would lose to `.ink-card` on source order. A rule here beats both. */
.ink-card-menus {
  overflow: visible;
}

.ink-card-header {
  padding: 14px 18px 12px;
  border-bottom: 1px solid var(--ink-rule-soft);
}

/* Modifier for headers that carry a right-aligned action (Add from library, EN/FR toggle)
   instead of just a stacked title + subtitle. */
.ink-card-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.ink-card-danger {
  border-color: var(--ink-danger-border);
}

.ink-card-body {
  padding: 16px 18px;
}

.ink-section-title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink-text);
  line-height: 1.2;
}

.ink-page-title {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.08;
  color: var(--ink-text);
}

.ink-card-subtitle {
  font-size: 12px;
  color: var(--ink-text-faint);
  margin-top: 1px;
}

.ink-micro-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-text-ghost);
}

/* Small pill badges — tint background + matching text, never a solid fill. Matches every
   status chip across the Cercis Ink canvas turns (6a/6b/9a/9b/10a/12a). */
.ink-pill {
  display: inline-flex;
  align-items: center;
  padding: 1px 7px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
}

.ink-pill-lg {
  padding: 2px 9px;
  font-size: 11px;
  border-radius: 4px;
}

.ink-pill-primary { background: var(--ink-primary-tint-bg); color: var(--ink-primary-tint-text); }
.ink-pill-success { background: var(--ink-success-bg); color: var(--ink-success-text); }
.ink-pill-warn { background: var(--ink-warn-bg); color: var(--ink-warn-text); }
.ink-pill-danger { background: var(--ink-danger-bg); color: var(--ink-danger-text); }
.ink-pill-neutral { background: var(--ink-neutral-bg); color: var(--ink-neutral-text); }
/* Canvas 78a. The fifth tone exists because that turn colours a change request by WHOSE MOVE IT IS
   rather than by how far along it is — yours, the reporter's, the build's, or yours-and-Steve's to
   look at. Four owners need four colours, and the four we had were carrying a different meaning:
   green already means "good", which is wrong for "somebody still has to check this".
   Values from 78a's own chips: #EFEBF7 on #4E3E78. */
.ink-pill-violet { background: #EFEBF7; color: #4E3E78; }

/* Document kind — Turn 67b. Deliberately the one SOLID chip in the system, and the exception
   to the tint-never-fill rule above, because it is not a status: it is what the thing IS, and
   67a makes it the column the eye lands on first. A tinted pill would sit at the same weight
   as the verdict beside it, which is the confusion the two columns exist to end.

   Two colours, because there are two families and they end up in two places: a CATALOGUE
   document changes what can be ordered, a POSITION document says what happened to an order
   already placed. Colour carries that split without a person reading a word. */
.ink-kind {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.ink-kind-catalogue { background: var(--ink-success); color: #fff; }
.ink-kind-position { background: var(--ink-primary); color: #fff; }
.ink-kind-none { background: var(--ink-neutral-bg); color: var(--ink-neutral-text); }

/* Verdict dot — a colour cue ahead of the word, so a column of outcomes can be scanned
   without reading it. Paired with the label, never used alone: a dot on its own is a legend
   somebody has to learn. */
.ink-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  display: inline-block;
  flex: none;
}

.ink-dot-success { background: var(--ink-success); }
.ink-dot-warn { background: var(--ink-warn-dot); }
.ink-dot-danger { background: var(--ink-danger); }
.ink-dot-quiet { background: var(--ink-text-ghost-3); }

/* Amber "open loop" callout — deadline pressure, availability warnings, delete costs. */
.ink-callout-warn {
  border-radius: 8px;
  background: var(--ink-warn-bg);
  border-left: 3px solid var(--ink-warn-accent);
  padding: 10px 12px;
  font-size: 11.5px;
  color: var(--ink-warn-text-strong);
  line-height: 1.45;
}

.ink-callout-danger {
  border-radius: 8px;
  background: var(--ink-danger-bg);
  border-left: 3px solid #B3261E;
  padding: 10px 12px;
  font-size: 11.5px;
  color: var(--ink-danger-text);
  line-height: 1.45;
}

.ink-link {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-primary);
}
.ink-link:hover { color: var(--ink-primary-hover); text-decoration: underline; }

/* ActionModal shell (docs "README cercis ui.md" component inventory) — one question, a small
   set of mutually exclusive answer rows (only the selected one expands), optional evidence,
   a dark consequence bar stating every write before commit. */
.ink-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(16, 26, 40, 0.5);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.ink-modal-box {
  background: #fff;
  border-radius: 12px;
  width: 100%;
  max-width: 640px;
  /* CR-385. `vh` on iOS Safari measures the viewport with the browser chrome hidden, so 90vh in
     portrait can be taller than what is actually on screen — and the part that falls off the bottom
     is the footer, which is where the confirm button lives. `dvh` measures what is visible now. The
     `vh` line stays as the fallback for anything that does not know `dvh`. */
  max-height: 90vh;
  max-height: 90dvh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 18px 50px rgba(16, 26, 40, 0.28);
  overflow: hidden;
}

.ink-modal-header {
  padding: 18px 24px 16px;
  border-bottom: 1px solid var(--ink-rule-soft);
}

.ink-modal-title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 20px;
  font-weight: 700;
  color: var(--ink-text);
  line-height: 1.2;
}

.ink-modal-subtitle {
  font-size: 13px;
  color: var(--ink-text-secondary);
  margin-top: 2px;
}

.ink-modal-body {
  padding: 18px 24px;
  overflow-y: auto;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* One answer row — collapsed by default, the selected one expands and gets the tinted
   border. Exactly RecordReceivingModal's existing visual pattern, generalized. */
.ink-answer-row {
  border-radius: 9px;
  border: 1px solid var(--ink-rule);
  padding: 11px 13px;
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s;
}
.ink-answer-row:hover { border-color: #B9C3CD; }
.ink-answer-row.selected {
  border: 2px solid var(--ink-primary);
  background: #F6F9FD;
  padding: 10px 12px;
}

.ink-answer-label {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-text);
}

.ink-answer-sublabel {
  font-size: 12px;
  color: var(--ink-text-secondary);
  margin-top: 1px;
  margin-left: 26px;
}

.ink-answer-detail {
  margin-top: 10px;
  margin-left: 26px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* 14a draws this as the modal's bottom edge, not a floating box: one full-bleed dark strip
   with the consequence on the left and Cancel/commit on the right. Splitting it into a
   rounded card plus a separate white button row is what made the dark block read as
   free-floating — the statement and the button that enacts it belong on one line. */
.ink-consequence-bar {
  background: var(--ink-chrome);
  padding: 14px 24px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

/* On dark: the commit button keeps .ink-btn-primary, but Cancel needs a border rather than
   the light-surface ghost, which is invisible here. */
.ink-btn-on-dark {
  height: 38px;
  padding: 0 15px;
  border: 1px solid #3B4A60;
  border-radius: 8px;
  background: transparent;
  color: #D8E0E9;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.ink-btn-on-dark:hover:not(:disabled) { background: #26344A; color: #fff; }
.ink-btn-on-dark:disabled { opacity: .5; cursor: not-allowed; }

.ink-consequence-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8DA0B5;
}

.ink-consequence-text {
  font-size: 13px;
  color: #E4EAF1;
}

.ink-modal-footer {
  padding: 16px 24px 20px;
  border-top: 1px solid var(--ink-rule-soft);
  display: flex;
  align-items: center;
  gap: 10px;
  /* CR-385. Same rule as the selection bar: a confirm button that has been pushed past the right
     edge is not a button. Two buttons fit a phone; a third, or one with a long label, did not. */
  flex-wrap: wrap;
}

/* The named, dated, linked block a hard-blocked action (e.g. Close Order with open issues)
   shows instead of a generic "cannot do this" message. */
.ink-blocker-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--ink-warn-bg);
  border-left: 3px solid var(--ink-warn-accent);
}

/* --- Turn 40: audience markers -------------------------------------------
   Only restricted regions get marked, so an unmarked page reads as universal.
   The wrapper is inert until a platform user turns markers on. */
.ink-audience {
  position: relative;
}
.ink-audience.marked {
  border-radius: 8px;
  padding: 10px 12px;
}
/* Solid, not dashed. A dashed edge reads as an annotation someone switched on; these regions
   are permanent, so they get a real border. */
.ink-audience.marked::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid currentColor;
  border-radius: 8px;
  opacity: .30;
  pointer-events: none;
}
.ink-audience-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 18px;
  padding: 0 7px;
  margin-bottom: 6px;
  border-radius: 4px;
  border: 1px solid currentColor;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .06em;
}
.ink-audience-chip .dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
}
.ink-audience-platform { color: #6D4AA8; }
.ink-audience-platform.marked { background: #6D4AA814; }
.ink-audience-buyer { color: #1E4E8C; }
.ink-audience-buyer.marked { background: #1E4E8C14; }
.ink-audience-grower { color: #2E7D5B; }
.ink-audience-grower.marked { background: #2E7D5B14; }

/* --- Turn 53: capability chips -------------------------------------------
   A capability is editable, so its OFF state has to be visible. Rendered as a
   filled green pill with no unchecked counterpart it reads as status, and a
   capability that is off becomes indistinguishable from one that doesn't
   apply here at all. */
.ink-cap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px;
  border-radius: 6px;
  border: 1px solid #DDE3EA;
  background: #fff;
  color: #8B97A3;
  font-size: 11.5px;
  cursor: pointer;
}
.ink-cap:hover { background: #F2F5F8; }
.ink-cap.on {
  background: #EAF4EE;
  border-color: #C4E0D0;
  color: #166139;
  font-weight: 600;
}
.ink-cap.on:hover { background: #E0EFE6; }
/* Always-on, e.g. Prepare orders at a store — a real state, not a dead toggle. */
.ink-cap.locked { cursor: default; opacity: .75; }
.ink-cap.locked:hover { background: #EAF4EE; }
.ink-cap-box {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  border: 1.5px solid #CBD4DD;
  box-sizing: border-box;
}

/* =========================================================================
   Form + control primitives — the DaisyUI replacement vocabulary.

   Direction (Mike, 2026-08-02): move off DaisyUI onto Ink. These exist so a
   page we touch can drop btn/input-bordered/tabs/alert without hand-rolling
   Tailwind each time. Sizes and radii are the handoff's tokens verbatim:
   control heights 28 chip / 30-32 inline / 34 compact / 36 standard /
   38-44 commit; radius 8px button+input, 7px small button.
   ========================================================================= */

/* --- Buttons. "One solid button per record" — reach for -secondary or
       -quiet unless this is THE action on the screen. --- */
.ink-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 36px;
  padding: 0 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}
.ink-btn:disabled,
.ink-btn[disabled] { opacity: .5; cursor: not-allowed; }
.ink-btn:focus-visible {
  outline: 2px solid var(--ink-focus-ring);
  outline-offset: 2px;
}

.ink-btn-primary { background: var(--ink-primary); color: #fff; }
.ink-btn-primary:hover:not(:disabled) { background: var(--ink-primary-hover); }

.ink-btn-secondary {
  background: #fff;
  border-color: var(--ink-control-border);
  color: var(--ink-text-muted);
}
.ink-btn-secondary:hover:not(:disabled) { background: var(--ink-control-hover); }

.ink-btn-quiet {
  background: transparent;
  color: var(--ink-text-secondary);
  font-weight: 500;
  padding: 0 10px;
}
.ink-btn-quiet:hover:not(:disabled) { background: var(--ink-rule-soft); color: var(--ink-text); }

.ink-btn-danger { background: var(--ink-danger); color: #fff; }
.ink-btn-danger:hover:not(:disabled) { background: #8E1F19; }

.ink-btn-danger-quiet {
  background: #fff;
  border-color: var(--ink-danger-border);
  color: var(--ink-danger-text);
}
.ink-btn-danger-quiet:hover:not(:disabled) { background: var(--ink-danger-bg); }

/* A button on the selection bar's solid primary surface. Not `.ink-btn-on-dark` — that one is
   sized and bordered for the near-black chrome, and its #3B4A60 border vanishes against blue.
   Eight sites were hand-rolling this as
   `bg-white/15 hover:bg-white/25 !border-transparent !text-white`, two of those four fighting
   `.ink-btn`'s own declarations with `!important`. */
.ink-btn-on-primary {
  background: rgb(255 255 255 / 0.15);
  border-color: transparent;
  color: #fff;
}
.ink-btn-on-primary:hover:not(:disabled) { background: rgb(255 255 255 / 0.25); color: #fff; }

.ink-btn-xs { height: 28px; padding: 0 11px; font-size: 12px; border-radius: 7px; }
.ink-btn-sm { height: 30px; padding: 0 12px; font-size: 12.5px; border-radius: 7px; }
.ink-btn-commit { height: 40px; padding: 0 20px; font-size: 13.5px; }
.ink-btn-block { width: 100%; }

/* --- Text inputs --- */
.ink-input,
.ink-select,
.ink-textarea {
  width: 100%;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--ink-control-border);
  border-radius: 8px;
  background: #fff;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 13px;
  color: var(--ink-text);
}
.ink-textarea {
  height: auto;
  padding: 9px 12px;
  line-height: 1.5;
  resize: vertical;
}
.ink-input::placeholder,
.ink-textarea::placeholder { color: var(--ink-text-ghost); }
.ink-input:focus,
.ink-select:focus,
.ink-textarea:focus {
  outline: none;
  border-color: var(--ink-primary);
  box-shadow: 0 0 0 3px rgba(30, 78, 140, .12);
}
.ink-input:disabled,
.ink-select:disabled,
.ink-textarea:disabled {
  background: var(--ink-surface-sunken);
  color: var(--ink-text-faint);
  cursor: not-allowed;
}
.ink-input-invalid,
.ink-input-invalid:focus {
  border-color: var(--ink-danger);
  box-shadow: 0 0 0 3px rgba(179, 38, 30, .12);
}
/* Sized to what the app actually asks for. The 38px default suits a standalone form; dense
   admin grids and toolbars wanted smaller, and ~180 call sites were getting there with
   !h-8 !text-[12.5px] — overriding the component rather than choosing a variant of it. These
   two are those exact sizes, so the override can go and the numbers live here instead. */
.ink-input-sm,
.ink-select-sm { height: 32px; padding: 0 10px; font-size: 12.5px; }
.ink-input-xs,
.ink-select-xs { height: 28px; padding: 0 8px; font-size: 12px; }

/* Turn 5 — a control inside a grid cell draws no box until it is pointed at or typed in. Every
   cell wearing its own input cost the order form sheet ~30px of width and most of a row's height
   per column, whether or not anybody was typing; the value now reads as text and the box arrives
   on hover. A select's caret arrives the same way. Declared after the base rules so it wins. */
.ink-cell-input,
.ink-cell-select {
  height: 24px;
  padding: 0 6px;
  font-size: 12px;
  border-color: transparent;
  background-color: transparent;
  border-radius: 6px;
}
.ink-cell-select { appearance: none; -webkit-appearance: none; cursor: pointer; }
.ink-cell-input:hover,
.ink-cell-select:hover { border-color: var(--ink-control-border); background-color: #fff; }
.ink-cell-select:hover,
.ink-cell-select:focus { appearance: auto; -webkit-appearance: auto; }
.ink-cell-input:focus,
.ink-cell-select:focus {
  border-color: var(--ink-primary);
  background-color: #fff;
  box-shadow: 0 0 0 2px rgba(30, 78, 140, .12);
}

/* Turn 101a — "every affordance is on at once": fourteen rows of chevrons and dotted underlines on the order form
   sheet. A chooser shows on the row under the pointer; at rest the row reads as its values. Pointer devices only — a
   touch screen has no hover, so there the controls stay drawn. The amber dots are not touched: they say something. */
@media (hover: hover) {
  [data-sheet-grid] tbody tr:not(:hover) select.ink-cell-input:not(:focus) { appearance: none; -webkit-appearance: none; }
  [data-sheet-grid] tbody tr:not(:hover) .border-dotted { border-bottom-color: transparent; }
}

/* The same story one layer down, found 2026-08-03. `.ink-textarea` had no size variants at all,
   so seven sites reached past it with `!text-[12.5px]` or `font-mono !text-[12px]` — and those
   seven fell into exactly two groups, which is what a missing variant looks like. */
.ink-textarea-sm { font-size: 12.5px; }
/* Anything the reader has to transcribe or compare character by character — imported markup in a
   textarea, a PO number in an input. Mono because an O and a 0 have to be told apart. */
.ink-input-code,
.ink-textarea-code {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 12px;
}

/* A record's own name, edited in place at the top of its page — bigger than a form field
   because it is the heading. Three pages had built it at three sizes (44/15, 44/16, 36/16);
   the two 44px ones are unified here, which is the point of having the variant. */
.ink-input-title { height: 44px; font-size: 16px; font-weight: 600; }

/* --- Field scaffolding: micro-label above the control, help text under it --- */
.ink-field { display: flex; flex-direction: column; gap: 5px; }
.ink-label { font-size: 12px; font-weight: 600; color: var(--ink-text-muted); }
.ink-help { font-size: 11.5px; color: var(--ink-text-faint); line-height: 1.45; }
.ink-error-text { font-size: 11.5px; color: var(--ink-danger-text); }

.ink-check { width: 16px; height: 16px; accent-color: var(--ink-primary); cursor: pointer; }
/* Radios had no Ink style at all, so 20 of them were still on DaisyUI's. Same treatment as
   .ink-check — accent-color lets the browser draw a native control in the brand colour, which
   stays correct in forced-colours and high-contrast modes where a hand-drawn one does not. */
.ink-radio { width: 16px; height: 16px; accent-color: var(--ink-primary); cursor: pointer; }
.ink-check-row {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13px;
  color: var(--ink-text-muted);
  cursor: pointer;
}

/* --- Sub-view tabs. A 2.5px bottom border, deliberately NOT pills: pills read
       as buttons and imply an action, and these are places. --- */
.ink-tabs {
  display: flex;
  align-items: center;
  gap: 22px;
  border-bottom: 1px solid var(--ink-rule);
  /* A record with nine views does not fit a phone. Scrolling the strip keeps every tab reachable
     and the row intact; wrapping would push the page content down by a line at every width. */
  overflow-x: auto;
  /* CR-170. `overflow-x: auto` makes overflow-y compute to `auto` as well, and the active tab's
     -1px margin overhangs by exactly enough to trip it — so a strip that fits perfectly well was
     painting a stray vertical scrollbar at its right edge. Both bars go: the strip is scrolled by
     touch and trackpad, and a visible track here was never the affordance, only the accident. */
  scrollbar-width: none;
}
.ink-tabs::-webkit-scrollbar { display: none; }
/* CR-385. Six stations with counts do not fit a phone, and the strip scrolls with its scrollbar
   deliberately hidden — so every pixel of gap is a tab you have to discover by swiping for. Phones
   only; the desktop strip is unchanged. */
@media (max-width: 639px) {
  .ink-tabs { gap: 12px; }
}
.ink-tab {
  padding: 0 2px 11px;
  border: none;
  border-bottom: 2.5px solid transparent;
  margin-bottom: -1px;
  background: none;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 14px;
  color: var(--ink-text-secondary);
  cursor: pointer;
  white-space: nowrap;
  /* Tabs were buttons only until 2026-08-14. An addressable view wants an anchor, so the class
     has to suppress the link underline and sit on the baseline like the buttons beside it. */
  text-decoration: none;
  flex: none;
}
.ink-tab:hover { color: var(--ink-text); }
.ink-tab.active {
  border-bottom-color: var(--ink-primary);
  font-weight: 600;
  color: var(--ink-text);
}
.ink-tab-count {
  margin-left: 7px;
  padding: 1px 7px;
  border-radius: 9px;
  background: var(--ink-neutral-bg);
  color: var(--ink-neutral-text);
  font-size: 11.5px;
  font-weight: 600;
}
.ink-tab.active .ink-tab-count {
  background: var(--ink-primary-tint-bg);
  color: var(--ink-primary);
}
/* Turn 1b. Setup's badge counts what is OUTSTANDING rather than what the tab holds, so it wears the
   colour that means look-at-this — and keeps it when the tab is active, because the count is about
   the form rather than about which tab you are standing on. */
.ink-tab-count-warn,
.ink-tab.active .ink-tab-count-warn {
  background: var(--ink-warn-bg);
  color: var(--ink-warn-text);
}

/* --- Callouts. warn/danger already exist above; these complete the set. --- */
.ink-callout-info {
  padding: 10px 13px;
  border-radius: 8px;
  background: var(--ink-primary-tint-bg);
  color: var(--ink-primary);
  font-size: 12.5px;
  line-height: 1.5;
}
/* For saying why a control is absent. Deliberately grey: a read-only page is a fact about
   this reader, not a warning or a problem with the record. */
.ink-callout-neutral {
  padding: 10px 13px;
  border-radius: 8px;
  background: var(--ink-canvas);
  color: var(--ink-text-muted);
  font-size: 12.5px;
  line-height: 1.5;
}
.ink-callout-success {
  padding: 10px 13px;
  border-radius: 8px;
  background: var(--ink-success-bg);
  color: var(--ink-success-text);
  font-size: 12.5px;
  line-height: 1.5;
}

/* --- Misc --- */
.ink-divider {
  height: 1px;
  background: var(--ink-rule-soft);
  border: 0;
  margin: 16px 0;
}
.ink-spinner {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(16, 26, 40, .15);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: ink-spin .6s linear infinite;
}
.ink-spinner-lg { width: 28px; height: 28px; border-width: 3px; }
@keyframes ink-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .ink-spinner { animation-duration: 1.8s; }
}

/* Mobile: the handoff calls for 48-52px targets on touch (30b). */
@media (max-width: 640px) {
  .ink-btn { height: 48px; font-size: 14px; }
  .ink-btn-xs, .ink-btn-sm { height: 40px; }
  .ink-input, .ink-select { height: 48px; font-size: 15px; }
}

/* File input — its own primitive because a file control can't take .ink-input's
   fixed height and padding; the button part needs styling separately. */
.ink-file {
  width: 100%;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 12.5px;
  color: var(--ink-text-muted);
}
.ink-file::file-selector-button {
  height: 30px;
  margin-right: 10px;
  padding: 0 12px;
  border: 1px solid var(--ink-control-border);
  border-radius: 7px;
  background: #fff;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-text-muted);
  cursor: pointer;
}
.ink-file::file-selector-button:hover { background: var(--ink-control-hover); }

/* =========================================================================
   Turn 31 — the specimen sheet's remaining parts.
   Rules this section encodes:
     * a disabled button is greyed and silent; a BLOCKED button is greyed and
       carries a reason beside it;
     * filter chips (h28 pills, clickable) and status chips (r5 rectangles,
       never clickable) must be visually unmistakable — they sit two bars
       apart on every page;
     * error text replaces helper text in the same slot, so nothing shifts;
     * loading is a skeleton with real geometry, never a spinner;
     * amber appears once per view — row tint, dot, chip and tile share one
       budget.
   ========================================================================= */

/* Blocked ≠ disabled: the reason sits beside the control. */
.ink-blocked { display: inline-flex; align-items: center; gap: 9px; }
.ink-blocked-reason { font-size: 11.5px; color: var(--ink-warn-text); }

/* Filter chip — h28, r14, pressable. Never used for status. */
.ink-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 12px;
  border: 1px solid var(--ink-control-border);
  border-radius: 14px;
  background: #fff;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 12.5px;
  color: var(--ink-text-muted);
  cursor: pointer;
  white-space: nowrap;
}
.ink-filter-chip:hover { background: var(--ink-control-hover); }
.ink-filter-chip.active {
  background: var(--ink-chrome);
  border-color: var(--ink-chrome);
  color: #fff;
  font-weight: 500;
}
.ink-filter-chip .count { opacity: .6; }
.ink-filter-chip:focus-visible { outline: 2px solid var(--ink-focus-ring); outline-offset: 2px; }

/* Segmented control — Turn 82a. Two or three views of the SAME list, exactly
   one of them on. Two chips side by side say "two independent filters, either
   or both", which is a different promise; a recessed track with one lit segment
   says the choice is exclusive before anything is read. Use it for scope
   (Everyone / Mine) and range (7 days / All time); keep .ink-filter-chip for
   filters that genuinely combine. */
.ink-seg {
  display: inline-flex;
  padding: 2px;
  border-radius: 8px;
  background: #F2F5F8;
  border: 1px solid var(--ink-control-border);
}
.ink-seg-btn {
  padding: 5px 11px;
  border-radius: 6px;
  border: 0;
  background: transparent;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-text-muted);
  cursor: pointer;
  white-space: nowrap;
}
.ink-seg-btn:hover { color: var(--ink-text); }
.ink-seg-btn.active { background: var(--ink-chrome); color: #fff; }
.ink-seg-btn.active:hover { color: #fff; }
.ink-seg-btn .count { opacity: .6; margin-left: 4px; }
.ink-seg-btn:focus-visible { outline: 2px solid var(--ink-focus-ring); outline-offset: 2px; }

/* Toggle — for a setting. (A radio card, .ink-answer-row, is for an exclusive answer.) */
.ink-toggle {
  position: relative;
  /* inline-block so the track still sizes when it is a <span> inside a larger button —
     Turn 53's sign-in control is one clickable box, not a toggle beside a label. */
  display: inline-block;
  width: 38px;
  height: 22px;
  border-radius: 11px;
  background: #C6D0DA;
  border: none;
  cursor: pointer;
  transition: background-color .15s ease;
  flex-shrink: 0;
}
.ink-toggle::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  transition: transform .15s ease;
}
.ink-toggle.on { background: var(--ink-primary); }
/* Green when the ON state is itself the reassuring one, e.g. "Can sign in" (53a) — a blue
   track inside a green panel reads as a second, unrelated control. */
.ink-toggle.on.on-success { background: #1F7A4D; }
.ink-toggle.on::after { transform: translateX(16px); }
.ink-toggle:disabled { opacity: .55; cursor: not-allowed; }
.ink-toggle:focus-visible { outline: 2px solid var(--ink-focus-ring); outline-offset: 2px; }

/* Skeleton — real geometry so nothing jumps when data lands. */
.ink-skeleton {
  background: linear-gradient(90deg, #EEF1F4 25%, #F6F8FA 37%, #EEF1F4 63%);
  background-size: 400% 100%;
  border-radius: 5px;
  animation: ink-shimmer 1.4s ease infinite;
}
@keyframes ink-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .ink-skeleton { animation: none; } }

/* Row states. Whole-row amber tint means the row needs you — spend it once. */
.ink-row { background: #fff; }
.ink-row-zebra { background: var(--ink-paper-alt); }
.ink-row-needs-you { background: var(--ink-warn-surface); }
/* Turn 48: "too late". A deadline that has passed cannot be acted on, only accounted for, so
   it needs a state distinct from "act now" — amber says hurry, this says the season is gone. */
.ink-row-lost { background: var(--ink-danger-bg); }
.ink-row-receded { background: #fff; color: var(--ink-text-ghost-3); }
.ink-row-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.ink-row-dot-warn { background: var(--ink-warn-dot); }
.ink-row-dot-danger { background: var(--ink-danger); }
.ink-row-dot-ok { background: var(--ink-success); }
.ink-row-dot-idle { background: #C6D0DA; }

/* Metric tile — at most one amber per view. */
.ink-tile {
  background: #fff;
  padding: 13px 16px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.ink-tile-value {
  font-family: Fraunces, Georgia, serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
  color: var(--ink-text);
  font-variant-numeric: tabular-nums;
}
.ink-tile-amber { background: var(--ink-warn-surface); }
.ink-tile-amber .ink-tile-value { color: var(--ink-warn-accent); }
.ink-tile-grid {
  display: grid;
  gap: 1px;
  background: #E5EAF0;
  border: 1px solid #E5EAF0;
  border-radius: 9px;
  overflow: hidden;
}

/* The states nobody draws. No illustrations — if there's something to do it's a button. */
.ink-state { padding: 22px 18px; text-align: left; }
.ink-state-title { font-size: 13.5px; font-weight: 600; color: var(--ink-text); }
.ink-state-body { font-size: 12.5px; color: var(--ink-text-secondary); line-height: 1.5; margin-top: 3px; }
.ink-state-empty { font-size: 13px; color: var(--ink-text-faint); padding: 16px 18px; }

/* Table — a document app's default way of showing rows. Header is the sunken
   surface, dividers are rule-soft, money right-aligned and tabular. */
.ink-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ink-table thead th {
  text-align: left;
  padding: 9px 12px;
  background: var(--ink-surface-sunken);
  border-bottom: 1px solid var(--ink-rule);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-text-ghost);
  white-space: nowrap;
}
.ink-table tbody td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--ink-rule-soft);
  color: var(--ink-text-muted);
  vertical-align: middle;
}
.ink-table tbody tr:last-child td { border-bottom: 0; }
.ink-table-zebra tbody tr:nth-child(even) { background: var(--ink-paper-alt); }
.ink-table-sm thead th { padding: 7px 10px; }
.ink-table-sm tbody td { padding: 7px 10px; }
.ink-table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── The logged-out shell (Turn 6c, 7a, 23a) ───────────────────────────────────
   The front door is the one page seen by people who aren't customers yet, so it
   spends its budget differently: a photograph under a three-stop scrim on the
   left, the panel that does the work on the right. Same tokens as everywhere
   else — same navy, same radii, same 38px controls. */
.ink-split {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  min-height: 560px;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--ink-rule);
  box-shadow: 0 6px 24px rgba(16, 26, 40, 0.13);
  background: #fff;
}
.ink-split-brand {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 34px 34px 28px;
  background-color: var(--ink-chrome);
  background-size: cover;
  background-position: center;
  color: #fff;
  isolation: isolate;
}
/* A photograph needs more cover than a flat panel does — 62% → 80% → 95%. */
.ink-split-brand::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    160deg,
    rgba(16, 26, 40, 0.62) 0%,
    rgba(16, 26, 40, 0.80) 55%,
    rgba(16, 26, 40, 0.95) 100%
  );
}
/* Top-left exit from a form somebody may have opened by mistake. On the photograph, so it takes
   the same white as the headline rather than the link colour, which would vanish into the scrim. */
.ink-split-back {
  align-self: flex-start;
  color: #fff;
  font-size: 12.5px;
  text-decoration: none;
  opacity: 0.85;
  margin-bottom: 18px;
}
.ink-split-back:hover { opacity: 1; text-decoration: underline; }

.ink-split-headline {
  font-family: Fraunces, Georgia, serif;
  font-size: clamp(26px, 3.1vw, 38px);
  line-height: 1.14;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}
.ink-split-sub {
  font-size: 13.5px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.78);
  margin-top: 14px;
  max-width: 42ch;
}
.ink-split-foot { font-size: 11.5px; color: rgba(255, 255, 255, 0.55); }
.ink-split-form { padding: 34px 32px; display: flex; flex-direction: column; justify-content: center; }
@media (max-width: 900px) {
  .ink-split { grid-template-columns: 1fr; min-height: 0; }
  .ink-split-brand { padding: 26px 24px; min-height: 210px; }
  .ink-split-form { padding: 26px 22px; }
}

/* Numbered process steps. Used where someone is mid-flow and needs to know how
   much is left — an application that goes into a void is where drop-off happens. */
.ink-steps { display: flex; flex-direction: column; gap: 14px; }
.ink-step { display: flex; gap: 12px; align-items: flex-start; }
.ink-step-num {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  border-radius: 999px;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 600;
  border: 1px solid currentColor;
  margin-top: 1px;
}
.ink-step-title { font-size: 13px; font-weight: 600; }
.ink-step-body { font-size: 12.5px; line-height: 1.5; opacity: .74; margin-top: 1px; }
.ink-step[data-done="true"] .ink-step-num { background: var(--ink-success); border-color: var(--ink-success); color: #fff; }
.ink-step[data-current="true"] .ink-step-num { background: #fff; color: var(--ink-primary); border-color: #fff; }

/* Password rules, shown rather than sprung. The symbol rule is the one people
   fail, and the one help text has to explain after the fact if it isn't listed. */
.ink-rulecheck { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 14px; margin-top: 8px; }
.ink-rulecheck-row { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ink-text-faint); }
.ink-rulecheck-row::before {
  content: "";
  width: 13px; height: 13px;
  border-radius: 999px;
  border: 1.5px solid var(--ink-control-border);
  flex: 0 0 auto;
}
.ink-rulecheck-row[data-met="true"] { color: var(--ink-success-text); }
.ink-rulecheck-row[data-met="true"]::before {
  background: var(--ink-success) no-repeat center;
  border-color: var(--ink-success);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2l2.2 2.2 4.8-4.8' fill='none' stroke='%23fff' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ink-rulecheck-summary { font-size: 11.5px; font-weight: 600; color: var(--ink-success-text); min-height: 15px; }

/* A password field with a Show control sitting inside its right edge. */
.ink-input-affix { position: relative; display: block; }
.ink-input-affix > .ink-input { padding-right: 56px; }
.ink-input-affix > .ink-affix-btn {
  position: absolute;
  right: 8px; top: 50%;
  transform: translateY(-50%);
  background: none; border: 0;
  font-size: 11.5px; font-weight: 600;
  color: var(--ink-text-secondary);
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 5px;
}
.ink-input-affix > .ink-affix-btn:hover { background: var(--ink-control-hover); color: var(--ink-text); }

/* Quiet third-party sign-in. A convenience for a minority — they should not be
   the visual peer of the primary action, and their brand colours shouldn't
   out-shout ours. */
.ink-oauth-row { display: flex; gap: 8px; }
.ink-oauth {
  flex: 1 1 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 36px; padding: 0 10px;
  border: 1px solid var(--ink-control-border);
  border-radius: 8px;
  background: #fff;
  font-size: 12.5px; font-weight: 500;
  color: var(--ink-text-muted);
  text-decoration: none;
}
.ink-oauth:hover { background: var(--ink-control-hover); border-color: #C3CCD5; }
.ink-oauth svg { width: 15px; height: 15px; flex: 0 0 auto; }

/* Language selector — chrome, not a form field. Lives in the dark top bar on the buyer and
   seller layouts and in the white header when logged out, so it inherits the surrounding
   colour and stays transparent rather than stamping a white .ink-select across the bar. */
/* --- Toolbar identity cluster (chrome bar #1) -----------------------------
   The design draws the right-hand side of the top bar as fills, never outlines,
   and one size smaller than the nav. Ringing each control makes all three read
   as buttons, which is why the identity side was outweighing the nav it sits
   opposite. Colours are rgba rather than Tailwind /opacity so they work on both
   bar shades without the utility-opacity trap. */
.ink-bar-id {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 8px;
  border-radius: 8px;
  color: #D8E0E9;
  font-size: 13px;
  font-weight: 500;
}
.ink-bar-id:hover { background: rgba(255,255,255,.10); color: #fff; }
.ink-bar-avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: rgba(255,255,255,.16);
  color: #fff;
  font-size: 11.5px;
  font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.ink-bar-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 10px;
  border-radius: 7px;
  background: rgba(255,255,255,.10);
  color: #fff;
  font-size: 12.5px;
  font-weight: 600;
}
.ink-bar-chip:hover { background: rgba(255,255,255,.18); }
.ink-bar-caret { font-size: 10px; color: #7C8EA3; line-height: 1; }

/* CR-171. A tab in the dark bar. The inactive state is deliberately a shade off white:
   without it "active" has to be carried by the plate alone, and on a navy bar a faint plate
   reads as a hover that got stuck. */
.ink-bar-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 14px;
  color: rgba(255,255,255,.78);
}
.ink-bar-tab:hover { background: rgba(255,255,255,.14); color: #fff; }
.ink-bar-tab.active {
  background: rgba(255,255,255,.13);
  color: #fff;
  font-weight: 600;
}

/* CR-179. The Draft Orders shortcut on the Shop tab row. Deliberately not an .ink-tab: the tabs
   beside it are places inside Shop and this one leaves, so it reads as a link in a plate rather
   than as a fourth view. The empty state stays on the row and stops being a control — muted, no
   pointer, not focusable — because a shortcut that disappears at nought is one nobody learns. */
.ink-draft-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex-shrink: 0;
  align-self: center;
  padding: 5px 11px;
  margin-bottom: 9px;
  border: 1px solid #DDE3EA;
  border-radius: 8px;
  background: #fff;
  color: var(--ink-primary);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
}
.ink-draft-link:hover { background: #F5F9FE; border-color: #C3D3E6; }
.ink-draft-link.is-empty {
  color: #A2AEB9;
  background: #F7F9FB;
  cursor: default;
}

/* 79c — badged by urgency, not by count. The number is something the buyer already knows; ochre
   says a draft's order form closes inside the week, which is the one thing the button can tell
   them that they do not. */
.ink-draft-link.is-urgent {
  color: #8A5606;
  background: #FFF8EC;
  border-color: #E8CF9B;
}
.ink-draft-link.is-urgent:hover { background: #FDF2DC; border-color: #DDBE79; }

/* A keystroke, printed. CR-173: ⌘⇧K is how a change request gets filed and the page that
   collects them never said so. Inline-block with a baseline nudge so it sits in a sentence
   without pushing the line-height around. */
.ink-kbd {
  display: inline-block;
  padding: 1px 5px;
  border: 1px solid #DDE3EA;
  border-bottom-width: 2px;
  border-radius: 5px;
  background: #F7F9FB;
  color: #5B6875;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  vertical-align: 1px;
}

.lang-select {
  height: 28px;
  width: auto;
  padding: 0 2px 0 4px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  /* currentColor, not a fixed grey: this also sits in the white logged-out header. */
  color: currentColor;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 500;
  opacity: .68;
  cursor: pointer;
}
.lang-select:hover { opacity: 1; }
.lang-select:focus-visible { outline: 2px solid var(--ink-focus-ring); outline-offset: 2px; }
/* The dropdown itself is drawn by the OS on the page background, so its text has to be dark
   regardless of what the bar behind the closed control is. */
.lang-select option { color: var(--ink-text); background: #fff; }

/* --- Token utilities ------------------------------------------------------
   Pages were reaching for these tokens through inline style="color:var(--ink-…)".
   That works, but an inline style cannot be overridden by a class, so a page
   styled that way stops answering to the design system — the same failure as an
   imported description arriving with font-size:30px baked in. Same tokens, now
   as classes, so the stylesheet stays in charge. */
.ink-t          { color: var(--ink-text); }
.ink-t-muted    { color: var(--ink-text-muted); }
.ink-t-secondary{ color: var(--ink-text-secondary); }
.ink-t-faint    { color: var(--ink-text-faint); }
.ink-t-ghost    { color: var(--ink-text-ghost); }
.ink-t-ghost-2  { color: var(--ink-text-ghost-2); }
.ink-t-ghost-3  { color: var(--ink-text-ghost-3); }
.ink-bd         { border-color: var(--ink-rule); }
.ink-bd-soft    { border-color: var(--ink-rule-soft); }
.ink-bg-sunken  { background: var(--ink-surface-sunken); }
.ink-bg-sunken-2{ background: var(--ink-surface-sunken-2); }
.ink-t-primary  { color: var(--ink-primary); }
.ink-t-warn     { color: var(--ink-warn-text); }
.ink-t-warn-accent { color: var(--ink-warn-accent); }
.ink-t-success  { color: var(--ink-success-text); }
.ink-t-danger   { color: var(--ink-danger-text); }
.ink-bg-warn    { background: var(--ink-warn-bg); }
.ink-bg-warn-surface { background: var(--ink-warn-surface); }
.ink-bg-warn-dot { background: var(--ink-warn-dot); }
.ink-bg-success { background: var(--ink-success); }
.ink-bd-warn    { border-color: var(--ink-warn-border); }
.ink-bg-primary-tint { background: var(--ink-primary-tint-bg); }
.ink-bg-chrome  { background: var(--ink-chrome); }

/* Solid primary surface and the text that sits on it. Added because the selection bar and the
   "Default" photo marker were the last two places still reaching for DaisyUI's `bg-primary` /
   `text-primary-content`, which are theme colours the Ink palette doesn't own. */
.ink-bg-primary { background: var(--ink-primary); }
.ink-t-on-primary { color: #fff; }

/* The rule colour used as *text* — separator dots between metadata, and nothing else. Its own
   class because no text token is this light; `.ink-t-ghost-3` (#B7C1CB) reads as content. */
.ink-t-rule { color: var(--ink-rule); }

/* Initials avatar. Four pages were each hand-assembling the same circle out of six utilities
   plus an inline `background:var(--ink-primary)`, at three different sizes and two different
   font sizes for the same size of circle. One part, three sizes. */
.ink-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: 9999px;
  background: var(--ink-primary);
  color: #fff;
  font-weight: 600;
  line-height: 1;
}
.ink-avatar-sm { width: 28px;  height: 28px;  font-size: 12px; }
.ink-avatar-md { width: 44px;  height: 44px;  font-size: 15px; }
.ink-avatar-lg { width: 52px;  height: 52px;  font-size: 17px; }
/* A person who isn't the subject of the page — an unselected teammate in a picker. */
.ink-avatar-quiet { background: var(--ink-text-ghost); }

/* Calendar events. A deadline, an arrival and a receiving day each own three colours — a tint,
   an accent and a text — and MyCalendar shows the same event two ways: a tinted pip in the month
   grid, and a bare accent bar in the next-14-days list. So the kind class carries the three
   colours as custom properties and the shape classes spend them. It was three C# switch
   expressions returning `var()` strings into inline styles, which put the page in charge of
   what a calendar event looks like. */
.ink-cal-deadline  { --ink-cal-accent: var(--ink-warn-accent);  --ink-cal-tint: var(--ink-warn-bg);         --ink-cal-text: var(--ink-warn-text); }
.ink-cal-arriving  { --ink-cal-accent: var(--ink-primary);      --ink-cal-tint: var(--ink-primary-tint-bg); --ink-cal-text: var(--ink-primary); }
.ink-cal-receiving { --ink-cal-accent: var(--ink-success-text); --ink-cal-tint: var(--ink-success-bg);      --ink-cal-text: var(--ink-success-text); }
/* A date the grower has agreed to, as against one the season plan proposes. Deliberately a firmer
   reading of Arriving's own colour rather than a new hue — it is the same delivery, further along,
   and a fourth colour on a month grid buys noise rather than meaning. */
.ink-cal-confirmed { --ink-cal-accent: var(--ink-primary);      --ink-cal-tint: var(--ink-primary-tint-bg); --ink-cal-text: var(--ink-primary); }
.ink-cal-confirmed .ink-cal-bar { box-shadow: inset 0 0 0 1px var(--ink-primary); }

/* Month grid: the tinted pip. */
.ink-cal-event {
  display: block;
  border-radius: 4px;
  padding: 4px 6px;
  font-size: 10.5px;
  line-height: 1.25;
  background: var(--ink-cal-tint);
  border-left: 3px solid var(--ink-cal-accent);
  color: var(--ink-cal-text);
}
/* Next-14-days list: the accent as a bare rule, and the detail line in the kind's text colour. */
.ink-cal-bar { background: var(--ink-cal-accent); }
.ink-cal-t   { color: var(--ink-cal-text); }

/* 47a's description editor and the buyer surfaces that render what it writes. One rule for
   both, which is the point: the editor and the card must not disagree about a paragraph. */
.ink-rich {
  font-size: 13.5px;
  color: #26313D;
  line-height: 1.6;
}
.ink-rich p { margin: 0 0 9px; }
.ink-rich p:last-child { margin-bottom: 0; }
.ink-rich strong, .ink-rich b { font-weight: 600; color: var(--ink-text); }
.ink-rich em, .ink-rich i { font-style: italic; }
.ink-rich ul { list-style: disc; padding-left: 20px; margin: 0 0 9px; }
.ink-rich ol { list-style: decimal; padding-left: 20px; margin: 0 0 9px; }
.ink-rich li { margin-bottom: 3px; }
.ink-rich a { color: var(--ink-primary); text-decoration: underline; }

.ink-rich-editor {
  min-height: 132px;
  padding: 15px 18px 17px;
  outline: none;
}
.ink-rich-editor:focus-visible { box-shadow: inset 0 0 0 2px var(--ink-focus-ring); }
.ink-rich-editor:empty::before {
  content: attr(data-placeholder);
  color: var(--ink-text-ghost);
}

.ink-editor-btn {
  display: flex;
  align-items: center;
  height: 27px;
  padding: 0 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  font-family: Poppins, system-ui, sans-serif;
  font-size: 12px;
  color: var(--ink-text-muted);
  cursor: pointer;
}
.ink-editor-btn:hover { background: var(--ink-control-hover); }

/* Hover states for the token utilities above. Tailwind's `hover:` prefix cannot reach a
   class it did not generate — `hover:ink-bg-sunken` compiles to nothing at all, and eight
   rows across the app were silently missing their hover as a result. The `!` modifier fails
   the same way: an element classed `!ink-t-faint` matches no rule, because the literal class
   name includes the bang. Same family as the `/NN` opacity trap in DESIGN_PORT.md. */
.ink-hover-bg-sunken:hover   { background: var(--ink-surface-sunken); }
.ink-hover-bg-sunken-2:hover { background: var(--ink-surface-sunken-2); }
.ink-hover-t:hover           { color: var(--ink-text); }
.ink-hover-t-muted:hover     { color: var(--ink-text-muted); }
.ink-hover-t-danger:hover    { color: var(--ink-danger-text); }
.ink-bg-canvas  { background: var(--ink-canvas); }
.ink-bg-trough  { background: var(--ink-trough); }

/* --- Platform rail (Turn 44b) ---------------------------------------------
   Restyles the existing DaisyUI drawer and menu rather than replacing them. The
   drawer's responsive behaviour already works — it collapses on mobile and the
   right things disappear — so only the surface changes.

   Purple because Turn 40a says a restricted surface carries the wash, and the
   platform frame is the largest restricted surface in the product while being,
   until now, the only region drawn in plain white. Descendant selectors do the
   work so the markup keeps its DaisyUI classes untouched. */
/* Floats on the canvas rather than filling the viewport edge-to-edge: the rail is a panel, and
   a panel with corners reads as one object you could put away. Flush to the edge it reads as
   the window itself. */
/* 44b's rail verbatim: flex:0 0 232px; margin:9px; border-radius:11px; background:#3A2C55.
   The lighter #7E68A0 is the *selected item* sitting on this, not the rail — reading it as the
   surface made the whole thing a shade of lavender. */
.ink-rail {
  background: #3A2C55;
  color: #CFC3E2;
  border-radius: 11px;
}
.ink-rail-canvas { background: var(--ink-canvas); }
.ink-rail .menu { background: transparent; border: none; }
.ink-rail .menu li > a,
.ink-rail .menu li > button,
.ink-rail .menu li > .menu-dropdown-toggle {
  color: #CFC3E2;
  border-radius: 7px;
}
.ink-rail .menu li > a:hover,
.ink-rail .menu li > button:hover { background: #ffffff14; color: #fff; }
/* The selected item is the design's lighter purple, not a white tint — it is the one place the
   rail brightens, which is what makes "where am I" readable at a glance. */
.ink-rail .menu li > a.active,
.ink-rail .menu li > a[aria-current="page"] { background: #7E68A0; color: #fff; }
.ink-rail .menu-title { color: #9B87BC; font-weight: 600; }
/* The language picker borrows currentColor, which in the rail is the light text — so it needs
   toning down or it reads as a bright box in the corner. */
.ink-rail .lang-select { border-color: #ffffff40; color: #CFC3E2; }
.ink-rail hr { border-color: #ffffff1F; }

.ink-rail-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #9B87BC;
  padding: 0 12px;
}
.ink-rail-divider { border-top: 1px solid #4E3D70; margin: 10px 0; }
.ink-rail-count {
  margin-left: auto;
  padding: 1px 7px;
  border-radius: 9px;
  background: #ffffff26;
  color: #fff;
  font-size: 11px;
  font-weight: 600;
}
/* The person, at the foot of the rail — one identity in one place, rather than
   an avatar in the rail and another in a bar above it. */
.ink-rail-user {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 12px;
  border-radius: 8px;
  color: #E3D6F5;
}
.ink-rail-user:hover { background: #ffffff14; }
.ink-rail-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #ffffff26;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11.5px;
  font-weight: 600;
  flex-shrink: 0;
}

/* --- Command palette (29b) + its rail trigger (45a) -----------------------
   The trigger is a rail row, not a button: same 31px height and 7px radius as the nav items
   above it, so it reads as part of the rail rather than a control sitting on top of one. */
.ink-rail-search {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 31px;
  padding: 0 10px;
  border-radius: 7px;
  background: #ffffff14;
  color: #B7A6D0;
  font-size: 12px;
}
.ink-rail-search:hover { background: #ffffff24; color: #fff; }

/* A native <dialog> opened with showModal(), not a fixed-position div. The rail this is
   launched from sits inside DaisyUI's drawer, which carries a transform — and a transform makes
   its element a containing block for position:fixed, so a fixed overlay was being trapped inside
   the 232px rail instead of covering the viewport. showModal() puts the dialog in the browser's
   top layer, which no ancestor transform, clip or z-index can contain.

   38px from the top, not centred: the panel opens where the eye already is, and leaves the
   results room to grow downward instead of pushing the input around as they load. */
.ink-palette-dialog {
  padding: 0;
  border: none;
  background: transparent;
  overflow: visible;
  width: 100%;
  max-width: min(680px, 92vw);
  margin: 38px auto auto auto;
}
.ink-palette-dialog::backdrop { background: rgba(16, 26, 40, .42); }

.ink-palette {
  width: 100%;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 26px 60px rgba(16, 26, 40, .42);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.ink-palette-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #97A3AF;
}

.ink-palette-row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 9px 20px;
  text-align: left;
  cursor: pointer;
  border-left: 3px solid transparent;
}
.ink-palette-row.is-selected {
  background: #F6F9FD;
  border-left-color: #1E4E8C;
}
.ink-palette-row-best { padding-top: 10px; padding-bottom: 10px; }

.ink-palette-key {
  font-family: "IBM Plex Mono", monospace;
  padding: 2px 6px;
  border: 1px solid #E5EAF0;
  border-radius: 4px;
  background: #fff;
}

/* --- Native <dialog> ------------------------------------------------------
   For a dialog opened with showModal(), the browser already supplies the backdrop
   and the centring — so unlike .ink-modal-backdrop (which is for a div-based
   modal) this only has to stop the UA styling fighting the box inside it. */
.ink-dialog {
  padding: 0;
  border: none;
  background: transparent;
  max-width: min(640px, 92vw);
  overflow: visible;
}
.ink-dialog::backdrop { background: rgba(16, 26, 40, 0.5); }

/* --- Wizard progress ------------------------------------------------------
   Replaces DaisyUI `steps`. Not tabs: these are stages you pass through, so a
   completed one stays marked rather than deselecting when you move on. The rail
   is drawn behind the dots so it reads as one path, not five separate labels.

   Named -wizard- because `.ink-steps` was already taken by the vertical numbered
   list above (Onboarding's "how much is left" panel). Sharing the name meant this
   block never set flex-direction, so it inherited `column` from that one and every
   wizard rendered its progress as a vertical stack of sliders. Two components, two
   names. */
.ink-progress-steps {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  width: 100%;
}
.ink-progress-step {
  flex: 1;
  position: relative;
  text-align: center;
  padding-top: 22px;
  font-size: 11.5px;
  line-height: 1.3;
  color: var(--ink-text-faint);
}
.ink-progress-step::before {
  content: "";
  position: absolute;
  top: 6px;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--ink-rule);
}
.ink-progress-step::after {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--ink-rule);
}
/* The rail should stop at the first and last dot rather than running off the ends. */
.ink-progress-step:first-child::before { left: 50%; }
.ink-progress-step:last-child::before { right: 50%; }
.ink-progress-step.done {
  color: var(--ink-primary);
  font-weight: 600;
}
.ink-progress-step.done::before { background: var(--ink-primary); }
.ink-progress-step.done::after {
  background: var(--ink-primary);
  border-color: var(--ink-primary);
}

/* Menu rows inside <InkDropdown>. Replaces DaisyUI's .menu, whose li>a styling was the only
   reason those markup shapes existed — a nested ul of anchors to get padding and a hover. */
.ink-menu { padding: 6px; display: flex; flex-direction: column; gap: 1px; }
.ink-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 10px;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.25;
  color: var(--ink-ink, #101A28);
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
.ink-menu-item:hover { background: #F2F5F8; }
.ink-menu-item.active { background: #E8F0F9; color: #1E4E8C; font-weight: 600; }
.ink-menu-item.unread { background: rgba(30, 78, 140, 0.05); }
.ink-menu-label {
  padding: 6px 10px 2px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #8B97A3;
}

/* The order-form grid's Manage column pins to the right edge. It holds the row's remove and
   edit controls, and it sat at the far end of a table that is deliberately wider than its
   container — so on any form with a few ship periods it scrolled out of reach and the only way
   to delete a line was to scroll sideways hunting for it. */
.ink-grid-pin {
  position: sticky;
  right: 0;
  z-index: 2;
  background: #F7F9FB;
  border-left: 4px solid #DDE3EA;
}
.ink-grid-pin::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -8px;
  width: 8px;
  pointer-events: none;
  background: linear-gradient(to right, rgba(16, 26, 40, 0), rgba(16, 26, 40, 0.06));
}
thead .ink-grid-pin { z-index: 3; }

/* ── Design-spec panel patterns ────────────────────────────────────────────────
   Ported from the design canvases' own inline styles (docs/Claude Design Files/
   design_handoff_cercis_ui/ — five Canvas *.dc.html files), so a page reaches the design by
   applying classes rather than copying a wall of style="". Every value resolves to a token
   already declared at the top of this file — the canvas's palette was encoded here long ago;
   what pages were missing was the markup vocabulary to reach it. */

/* A panel whose state is unresolved: 18a's "Before you publish" while work is left. */
.ink-card-attention {
  border: 1.5px solid var(--ink-warn-border);
  box-shadow: 0 1px 3px rgba(180, 112, 10, 0.10);
}
.ink-card-attention > .ink-card-header {
  background: var(--ink-warn-surface);
  border-bottom-color: #F0E6D2;
}
.ink-card-resolved { border: 1.5px solid var(--ink-rule); }

/* Checklist rows. A pass is quiet; anything outstanding takes the tint, which is what
   makes the panel scan before any single line of it is read. */
.ink-check-list { padding: 6px 0; }
.ink-check-row {
  padding: 9px 18px;
  display: flex;
  align-items: center;
  gap: 11px;
  border-bottom: 1px solid var(--ink-rule-soft-2);
}
.ink-check-row:last-child { border-bottom: 0; }
.ink-check-row-todo { background: var(--ink-warn-surface); }
.ink-check-row .ink-check-tick { width: 14px; height: 14px; color: var(--ink-success); flex-shrink: 0; }
.ink-check-row .ink-check-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--ink-warn-dot); flex-shrink: 0; margin: 0 3px;
}
/* An open item that cannot stop a publish. Same dot, drained of the warning colour — it is
   information, and the warn dot on an unwarnable row reads as a blocker. */
.ink-check-row .ink-check-dot-quiet { background: var(--ink-text-ghost-3); }
.ink-check-body { flex: 1; min-width: 0; }
.ink-check-title { font-size: 12.5px; color: var(--ink-text-secondary); }
.ink-check-row-todo .ink-check-title { font-weight: 600; color: var(--ink-text); }
.ink-check-consequence { font-size: 11.5px; color: var(--ink-warn-text); }

/* Label/value lines — "Buying groups … None", "Stores reached … 0". */
.ink-metric-list { padding: 13px 18px; display: flex; flex-direction: column; gap: 9px; }
.ink-metric-row { display: flex; align-items: center; gap: 10px; }
.ink-metric-row > .ink-metric-label { flex: 1; font-size: 12.5px; color: var(--ink-text-muted); }
.ink-metric-row > .ink-metric-value { font-size: 12.5px; color: var(--ink-text); }
.ink-metric-value-attention { color: var(--ink-warn-accent); font-weight: 500; }

/* The design's quiet note box — no left accent, unlike .ink-callout-warn. */
.ink-note {
  padding: 9px 11px;
  border-radius: 7px;
  background: var(--ink-warn-bg);
  font-size: 11.5px;
  color: var(--ink-warn-text-strong);
  line-height: 1.45;
}

/* Dot + title + timestamp, as in 18a's Recent panel. */
.ink-timeline { padding: 12px 18px 14px; display: flex; flex-direction: column; gap: 10px; }
.ink-timeline-item { display: flex; gap: 11px; }
.ink-timeline-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-primary); flex-shrink: 0; margin-top: 4px;
}
.ink-timeline-dot-quiet { background: #C6D0DA; }
.ink-timeline-title { font-size: 12.5px; color: var(--ink-text); }
.ink-timeline-meta { font-size: 11px; color: var(--ink-text-faint); }

/* ── 4a shipment rows ──────────────────────────────────────────────────────────
   Values from the turn's own markup: a lighter border than a card, a smaller radius, and a
   faintly cool head so a shipment reads as an item inside a panel rather than a card of its
   own. */
.ink-loop {
  border: 1px solid #E4EBF3;
  border-radius: 9px;
  overflow: hidden;
}
.ink-loop-head {
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  background: #FAFCFE;
}
.ink-loop-attention { border-color: var(--ink-warn-border); }
.ink-loop-attention > .ink-loop-head { background: var(--ink-warn-surface); }
.ink-loop-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.ink-loop-name { min-width: 150px; display: flex; flex-direction: column; gap: 1px; }
.ink-loop-title { font-size: 14px; font-weight: 600; color: var(--ink-text); }
.ink-loop-sub { font-size: 12px; color: var(--ink-text-faint); }

/* ── 4a status strip ───────────────────────────────────────────────────────────
   Five cells sharing a hairline: the grid gap IS the rule, so the strip reads as one object
   divided rather than five cards abutting. Values from the turn's markup. */
.ink-strip {
  display: grid;
  gap: 1px;
  background: var(--ink-trough);
  border: 1px solid var(--ink-trough);
  border-radius: 9px;
  overflow: hidden;
}
.ink-strip-cell {
  background: #fff;
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
/* The cell holding the reader's own next move is the only tinted one. */
.ink-strip-cell-attention { background: var(--ink-warn-surface); }
.ink-strip-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-text-ghost);
}
.ink-strip-cell-attention .ink-strip-label { color: var(--ink-warn-accent); }
.ink-strip-value { font-size: 15px; font-weight: 600; color: var(--ink-text); }
.ink-strip-sub { font-size: 12px; color: var(--ink-text-secondary); }
.ink-strip-cell-attention .ink-strip-sub { color: var(--ink-warn-text); }

/* ── 4a rail rows (documents, activity) ────────────────────────────────────────
   A list inside a panel, not a table: no row borders, tight padding, and the meta line a full
   step lighter than the title so the eye lands on the name first. */
.ink-rail-list { padding: 6px 0; }
.ink-rail-row {
  padding: 9px 18px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.ink-rail-row-title { font-size: 12.5px; font-weight: 500; color: var(--ink-text); }
.ink-rail-row-meta { font-size: 11px; color: var(--ink-text-ghost-2); }
.ink-rail-row-icon { width: 15px; height: 15px; flex-shrink: 0; color: var(--ink-text-secondary); }
.ink-rail-row-action { width: 15px; height: 15px; flex-shrink: 0; color: var(--ink-text-faint); }
.ink-rail-count { font-size: 12px; color: var(--ink-text-faint); }

/* The canvas's third family, and its most-used one: order numbers, item numbers and activity
   timestamps. It was named in .ink-audience-chip but never loaded, so every one of those fell
   back to the OS monospace. */
.ink-mono {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}

/* ── 4a page frame ─────────────────────────────────────────────────────────────
   The header, tabs and status strip form a white band; everything below floats on the canvas
   grey. That separation is what makes the panels read as objects on a surface rather than
   sections of one long white page. */
.ink-record-band {
  background: #fff;
  padding: 0 32px;
}
/* Only the last band in a run carries the rule, so a back-link band stacked above the header
   band does not draw two lines. */
.ink-record-band + .ink-record-band,
.ink-record-band:last-of-type { border-bottom: 1px solid var(--ink-rule); }
.ink-record-body {
  background: var(--ink-canvas);
  padding: 22px 32px 34px;
}
/* The record's name. 29px is the canvas's own size — a page about one thing should say what
   that thing is at the size of a headline. */
.ink-record-title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 29px;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.05;
  color: var(--ink-text);
}
/* Turn 71a — marks which end of a two-party record the viewer is. Not .ink-pill-*: that
   namespace belongs to StatusChip, and this is an identity tag, not a status. */
.ink-you-tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--ink-accent, #1E4E8C);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
}

@media (max-width: 640px) {
  .ink-record-band { padding: 0 16px; }
  .ink-record-body { padding: 16px 16px 24px; }
  /* Two names now share this row, so they stack on a phone rather than sitting side by side. */
  .ink-record-title { font-size: 20px; }
}

/* ── 4a activity feed ──────────────────────────────────────────────────────────
   A feed, not a table: a 7px dot carrying the event's kind, the message at reading size, and
   the timestamp in mono a step below it. Values from the turn. */
.ink-feed { padding: 14px 18px; display: flex; flex-direction: column; gap: 13px; }
.ink-feed-item { display: flex; gap: 11px; }
.ink-feed-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-top: 5px;
  flex-shrink: 0;
  background: #C6D0DA;
}
.ink-feed-dot-issue { background: var(--ink-danger); }
.ink-feed-dot-move { background: var(--ink-warn-dot); }
.ink-feed-dot-done { background: var(--ink-success); }
.ink-feed-msg { font-size: 12.5px; color: var(--ink-text); line-height: 1.4; }
/* Routine bookkeeping reads a step back, so the eye finds what happened to the goods. */
.ink-feed-item-quiet .ink-feed-msg { color: var(--ink-text-secondary); }
.ink-feed-time {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 11px;
  color: var(--ink-text-ghost-2);
  margin-top: 2px;
}

/* ---------------------------------------------------------------------------
   Turn 56 — the change-request panel
   (docs/Claude Design Files/design_handoff_cercis_ui/BRIEF_change_requests.md).

   404px, pinned near the top rather than centred: it is an annotation on the page
   underneath, and the page has to stay visible for the note to be about anything.
   --------------------------------------------------------------------------- */
.ink-cr-dialog {
  padding: 0;
  border: none;
  background: transparent;
  overflow: visible;
  width: 100%;
  max-width: min(404px, 92vw);
  margin: 18px auto auto auto;
}
.ink-cr-dialog::backdrop { background: rgba(16, 26, 40, .32); }

.ink-cr-panel {
  width: 100%;
  background: #fff;
  border-radius: 11px;
  box-shadow: 0 18px 40px rgba(16, 26, 40, .28);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.ink-cr-tab {
  padding: 10px 14px;
  font-size: 12px;
  color: var(--ink-text-secondary);
  display: flex;
  align-items: center;
  gap: 7px;
  border-bottom: 2px solid transparent;
  cursor: pointer;
}
.ink-cr-tab.active {
  font-weight: 600;
  color: var(--ink-text);
  background: #fff;
  border-bottom-color: var(--ink-primary);
}

/* Questions awaiting your reply, never unread — same rule as the bell (29a). */
.ink-cr-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: #B4690E;
  color: #fff;
  font-size: 9.5px;
  font-weight: 700;
}

.ink-cr-body { min-height: 58px; font-size: 12px; line-height: 1.5; }

.ink-cr-key {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-text-faint);
  width: 52px;
  flex-shrink: 0;
}

.ink-cr-chip {
  padding: 3.5px 9px;
  border-radius: 12px;
  background: #F2F5F8;
  color: var(--ink-text-secondary);
  font-size: 10.5px;
  cursor: pointer;
}
.ink-cr-chip.on { background: #101A28; color: #fff; font-weight: 600; }

/* Two seconds, bottom right, dark. Above the dialog's top layer is impossible, so this
   only ever shows once the panel has closed. */
.ink-cr-toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 268px;
  padding: 9px 12px;
  border-radius: 8px;
  background: #101A28;
  box-shadow: 0 18px 40px rgba(16, 26, 40, .34);
}
.ink-cr-toast-tick {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--ink-success);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
}

/* 56d — the batch file, shown as the file it becomes. */
.ink-cr-file {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 11.5px;
  line-height: 1.75;
  color: #C6D2E0;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Tailwind's font-mono resolves to the system stack; IBM Plex Mono is loaded in App.razor but
   nothing points at it. Machine ids — CR numbers, routes, component paths, viewports — are
   exactly what the design system reserves it for, so they ask for it by name.
   (Repointing --font-mono globally would do the same for the whole app; that is a bigger
   decision than turn 56, so this stays scoped to what 56 renders.) */
.ink-mono { font-family: 'IBM Plex Mono', ui-monospace, monospace; }

/* The name of the record being administered, under the "Administering" label in the rail.

   Its own element rather than DaisyUI's `.menu-title`: `.menu :where(li)` is
   `display:flex; flex-direction:column`, so `truncate`'s `text-overflow: ellipsis` lands on a
   flex container and does nothing — "Brookdale Tree Nurseries" ran straight out of the 232px
   rail. A block box with the text in it is what ellipsis needs. */
.ink-rail-name {
  display: block;
  padding: 2px 12px 6px;
  font-size: 13px;
  font-weight: 600;
  color: #EDE7F6;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Turn 104a — the administering block as a file you have open: bordered and tinted, the business's initial in a chip,
   a line saying you are acting as them while in their workspace, and a way out. */
/* Turn 105: nested under Buyers or Sellers, so one level in — and DaisyUI's own submenu indent and rule line are
   switched off inside it, or the block would be indented twice and ruled down its left edge. */
/* Nested, the block became a direct child of the parent's <li>, and DaisyUI makes every such child a column-flow grid —
   the head, the two pages and Close were laid side by side, the name squeezed to nothing and Close run off the rail.
   A block box, not a link: no hover fill, no pointer, and its text wraps and selects like text. */
.ink-rail .menu .ink-rail-entity {
  display: block;
  cursor: default;
  text-wrap: wrap;
  user-select: auto;
}
.ink-rail .menu .ink-rail-entity:hover { background: rgba(237, 231, 246, .06); box-shadow: none; }
html.rail-collapsed .ink-rail .menu .ink-rail-entity:hover { background: transparent; }
.ink-rail .menu .ink-rail-entity ul { margin-inline-start: 0; padding-inline-start: 0; }
.ink-rail .menu .ink-rail-entity ul::before { display: none; }
html.rail-collapsed .ink-rail .ink-rail-entity { margin-left: 0; padding: 2px 0; border-color: transparent; background: transparent; }
.ink-rail-entity {
  margin: 4px 0 4px 12px;
  border: 1px solid rgba(237, 231, 246, .16);
  background: rgba(237, 231, 246, .06);
  border-radius: 10px;
  padding: 6px 4px 4px;
}
.ink-rail-entity-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 4px 8px 6px;
  min-width: 0;
}
.ink-rail-entity-head .ink-rail-name { padding: 0; }
.ink-rail-entity-chip {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #EDE7F6;
  color: #4E3D70;
  font-size: 12px;
  font-weight: 700;
}
.ink-rail-acting {
  margin: 4px 6px 2px;
  padding: 6px 8px;
  border-radius: 7px;
  background: rgba(201, 138, 18, .16);
  color: #F3D9A4;
  font-size: 11px;
  line-height: 1.45;
}
.ink-rail-leave {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 4px;
  padding: 6px 12px;
  border-top: 1px solid rgba(237, 231, 246, .12);
  color: #B8A8D6;
  font-size: 12px;
}
.ink-rail-leave:hover { color: #fff; }

/* ─── Turn 79a — the drawer over Shop ────────────────────────────────────────────────────────

   A panel over a page, not a page wearing a panel's clothes. Shop is overlaid and never pushed:
   pushing would reflow the four-column grid to three and lose the reader's place, which defeats
   the whole point of checking drafts without leaving Shop.

   The scrim is z-40, below the buyer header's sticky z-50, so the nav stays live and unshaded
   with no hardcoded header height to go stale. Fixed positioning is safe here because Shop
   renders in DaisyUI's `.drawer-content`, which carries no transform — unlike `.drawer-side`,
   where the command palette had to fall back to a top-layer <dialog>. */
.ink-drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(16, 26, 40, 0.42);
}

.ink-drawer-panel {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  z-index: 45;
  width: min(460px, 100vw);
  display: flex;
  flex-direction: column;
  background: #fff;
  box-shadow: -18px 0 50px rgba(16, 26, 40, 0.24);
}

.ink-drawer-header {
  padding: 20px 24px 14px;
  border-bottom: 1px solid var(--ink-rule-soft);
  flex-shrink: 0;
}

.ink-drawer-title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 22px;
  font-weight: 700;
  color: var(--ink-text);
  line-height: 1.15;
}

/* The list scrolls, the footer is pinned, and the fade says there is more below — a hard cut at
   the panel bottom reads as the end of the list. */
.ink-drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%);
}

.ink-drawer-footer {
  flex-shrink: 0;
  padding: 12px 20px 14px;
  border-top: 1px solid var(--ink-rule-soft);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 12px;
  color: var(--ink-text-secondary);
}

/* One card per draft. Only the urgent one is coloured: an ochre spine on one of three is
   legible, the same treatment on all three is wallpaper. */
.ink-drawer-card {
  border: 1px solid var(--ink-rule-soft);
  border-left-width: 3px;
  border-left-color: transparent;
  border-radius: 10px;
  padding: 12px 14px 13px;
  background: #fff;
}

.ink-drawer-card.is-soon { border-left-color: #C98A16; background: #FFFCF5; }
.ink-drawer-card.is-closed { border-left-color: #B3261E; background: #FEF7F6; }

/* CR-178 — an icon that is a state, not a command. Bookmark is the first of these: outline means
   not marked, filled means marked, and the button itself has to stay quiet enough that a wall of
   cards does not read as a wall of controls.

   Sized to line up with .ink-btn-sm beside it, so the card's action row keeps one baseline. */
.ink-icon-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: #8B97A3;
  cursor: pointer;
}
.ink-icon-toggle:hover { background: #F2F5F8; color: #5B6875; }
.ink-icon-toggle.active { color: var(--ink-primary); }
.ink-icon-toggle.active:hover { background: #EEF4FC; color: var(--ink-primary); }
.ink-icon-toggle:focus-visible { outline: 2px solid var(--ink-primary); outline-offset: 1px; }

/* ─── CR-188 — the platform rail, collapsed to its icons ─────────────────────────────────────

   Desktop only. Below lg the rail is already behind DaisyUI's drawer toggle, so there is nothing
   permanently taking up room and nothing to collapse.

   Driven off a class on <html>, set by js/rail-collapse.js before first paint. Width and nothing
   else animates: the labels are hidden rather than faded, because a half-faded word mid-transition
   reads as a rendering fault. */
.ink-rail { transition: width .16s ease; }

@media (min-width: 1024px) {
  html.rail-collapsed .ink-rail {
    width: 60px;
    padding-left: 6px;
    padding-right: 6px;
  }

  /* Every rail row is an icon followed by a label span, so hiding the spans is the whole of the
     collapsed state. The count badge goes with them — a number with nothing to count is noise. */
  html.rail-collapsed .ink-rail .menu li > a > span,
  html.rail-collapsed .ink-rail .menu li > button > span,
  html.rail-collapsed .ink-rail .menu li > details > summary > span,
  html.rail-collapsed .ink-rail .ink-rail-label,
  html.rail-collapsed .ink-rail .ink-rail-name,
  html.rail-collapsed .ink-rail .ink-rail-count,
  html.rail-collapsed .ink-rail .ink-rail-brandword,
  html.rail-collapsed .ink-rail .ink-rail-collapsible { display: none; }

  /* A section heading with its words hidden would be an empty purple gap where a divider belongs. */
  html.rail-collapsed .ink-rail .menu li.ink-micro-label { display: none; }

  html.rail-collapsed .ink-rail .menu li > a,
  html.rail-collapsed .ink-rail .menu li > button,
  html.rail-collapsed .ink-rail .menu li > details > summary {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }

  /* CR-216, replacing CR-188 round 3. The sub-list under Setup used to be hidden outright while
     the rail was narrow, because its children were the only rows in the rail with no icon of their
     own — hiding the labels left five blank purple rows under the gear. The children have icons
     now (CercisAdminMenu.razor), so the reason to hide them is gone and the collapsed rail says
     where it can go instead of ending at a gear.

     What is left is the indent: a nested <ul> carries DaisyUI's 1rem margin and the hairline that
     draws the tree, and neither has room at 48px. */
  html.rail-collapsed .ink-rail .menu li > details > ul {
    margin-inline-start: 0;
    padding-inline-start: 0;
  }
  html.rail-collapsed .ink-rail .menu li > details > ul::before { display: none; }
  html.rail-collapsed .ink-rail .menu li > details > summary::after,
  html.rail-collapsed .ink-rail .menu li > details > summary::marker { display: none; content: none; }

  html.rail-collapsed .ink-rail .ink-rail-user { justify-content: center; }

  /* CR-216 — the two rows that were overflowing to the right of a 60px rail, on all three rails.
     Both are controls sized by their own content rather than by the rail: the search row is an
     icon, a label and a ⌘K hint, and the language <select> is width:auto around whichever language
     name is selected. Neither shrinks, so both simply spilled past the purple edge. */
  html.rail-collapsed .ink-rail .ink-rail-search {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }
  html.rail-collapsed .ink-rail .ink-rail-search span { display: none; }

  /* Hidden rather than narrowed: a native select shows the selected option's own text, so there is
     no width at which "Français" fits in 48px. It is one click away — the rail expands. */
  html.rail-collapsed .ink-rail .ink-rail-lang { display: none; }
}

/* The toggle itself. Bottom of the rail, under the divider, because it is about the furniture and
   not one of the places the rail goes. */
.ink-rail-collapse-btn {
  display: none;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 11px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: #B7A6D0;
  font-size: 12.5px;
  cursor: pointer;
}
@media (min-width: 1024px) {
  .ink-rail-collapse-btn { display: flex; }
}
.ink-rail-collapse-btn:hover { background: #ffffff14; color: #fff; }
html.rail-collapsed .ink-rail-collapse-btn { justify-content: center; padding-left: 0; padding-right: 0; }
html.rail-collapsed .ink-rail-collapse-btn svg { transform: rotate(180deg); }

/* ── The line — Turn 81a ────────────────────────────────────────────────────
   Seven stations, and the one element both home pages open with. Dark on
   purpose: it is the frame the rest of the page sits inside, not another card
   in the stack. Station colour carries ownership, so a glance answers "whose
   move is it" before any number is read. */
.ink-line {
  background: var(--ink-chrome);
  border-radius: 12px;
  padding: 22px 24px 24px;
  box-shadow: 0 8px 28px rgba(16, 26, 40, 0.16);
}
.ink-line-stations {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
}
@media (min-width: 640px)  { .ink-line-stations { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .ink-line-stations { grid-template-columns: repeat(4, 1fr); } }
/* Six stations with the gate between the third and the fourth, so the gate gets a hairline column
   rather than a card's worth of width. */
@media (min-width: 1360px) { .ink-line-stations { grid-template-columns: repeat(3, 1fr) 52px repeat(3, 1fr); } }

.ink-line-owner {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #6B7F96;
  margin-bottom: 8px;
  display: block;
}
.ink-line-station {
  display: block;
  padding: 13px 13px 15px;
  border-radius: 9px;
  background: #1B2839;
  border: 1px solid transparent;
  min-height: 108px;
  text-decoration: none;
  transition: background 120ms ease, transform 120ms ease;
}
.ink-line-station:hover { background: #22334A; text-decoration: none; transform: translateY(-1px); }
.ink-line-name { font-size: 13.5px; font-weight: 700; color: #fff; }
.ink-line-count {
  font-family: Fraunces, Georgia, serif;
  font-size: 27px;
  font-weight: 700;
  color: #fff;
  line-height: 1.1;
  margin-top: 4px;
}
/* Zero is not a failure — a clear station is the good outcome, so it recedes
   rather than shouting a big white nought at somebody who cleared it. */
.ink-line-count-zero { color: #55677E; }
.ink-line-detail { font-size: 11.5px; color: #93A4B8; line-height: 1.45; margin-top: 3px; }
.ink-line-held {
  display: inline-block;
  margin-top: 7px;
  padding: 2px 7px;
  border-radius: 6px;
  background: #ffffff14;
  color: #E4CFA0;
  font-size: 10.5px;
  font-weight: 600;
}

/* Ownership. Purple is the developer's, blue the product partner's, green the
   system's — the same three the canvas uses, so the drawing and the app agree. */
.ink-line-developer { background: #2C2143; border-color: #4E3D70; }
.ink-line-developer:hover { background: #362851; }
.ink-line-developer .ink-line-detail { color: #CFC3E2; }
.ink-line-owner-developer { color: #B58BE8; }

.ink-line-product { background: #1A2A40; border-color: #2F4C72; }
.ink-line-product:hover { background: #21344E; }
.ink-line-product .ink-line-detail { color: #A8C4E4; }
.ink-line-owner-product { color: #7FB2E8; }

.ink-line-system { background: #152A20; border-color: #2F5F45; }
.ink-line-system:hover { background: #1B3529; }
.ink-line-system .ink-line-detail { color: #9FC9B0; }
.ink-line-owner-system { color: #4FBF7B; }

/* Yours. A ring rather than another fill, because the fill already says whose
   station it is — this says which of them is you, looking at it now. */
.ink-line-mine { box-shadow: 0 0 0 2px #ffffff40; }

/* ---------------------------------------------------------------- the gate

   The door out of the build queue, between 04 and 05. It is deliberately not a
   card: no fill, no radius, no hover lift, nothing to select. A station is a
   place work sits; this is a condition work has to satisfy, and drawing it as
   an eighth box would have made it an eighth station.

   It keeps its slot when open. Removing it would reflow the row every time the
   last question is answered, and an absent gate reads as a missing element
   rather than as a clear one. */
.ink-line-gate-slot {
  display: flex;
  align-items: stretch;
  justify-content: center;
  /* On the wide layout it is a hairline column between two cards; when the grid
     wraps to 2 or 4 up it spans the row and lies down as a divider. */
  grid-column: span 1;
}
@media (max-width: 1359px) {
  .ink-line-gate-slot { grid-column: 1 / -1; }
  .ink-line-gate { flex-direction: row !important; gap: 9px !important; padding: 7px 0 !important;
                   border-left: 0 !important; border-right: 0 !important;
                   border-top: 1px dashed #2B3646; border-bottom: 1px dashed #2B3646; }
}

.ink-line-gate,
.ink-line-tab-gate {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 2px;
  text-decoration: none;
  color: #4A5A70;
  border-left: 1px dashed #2B3646;
  border-right: 1px dashed #2B3646;
  transition: background 120ms ease, color 120ms ease;
}
.ink-line-gate { padding: 10px 6px; align-self: stretch; }
.ink-line-tab-gate { padding: 0 0 11px; align-self: stretch; }

.ink-line-gate:hover,
.ink-line-tab-gate:hover { text-decoration: none; color: #6C819B; background: #ffffff08; }

/* Shut is the only state with anything to say, so it is the only one that
   spends colour. */
.ink-line-gate-shut,
.ink-line-tab-gate-shut {
  color: #E0B341;
  background: rgba(224, 179, 65, 0.07);
  border-left-color: #46536A;
  border-right-color: #46536A;
}
.ink-line-gate-shut:hover,
.ink-line-tab-gate-shut:hover { color: #EFC65C; background: rgba(224, 179, 65, 0.12); }

/* The keeper, not an owner — the gate holds no work, it holds a decision, and
   naming him is the difference between "these are blocked" and "these are
   waiting on Mike". Purple because that is the developer's colour everywhere
   else on the line. */
.ink-line-gate-keeper {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #5B4A7A;
  margin-bottom: 3px;
}
.ink-line-gate-shut .ink-line-gate-keeper,
.ink-line-tab-gate-shut .ink-line-gate-keeper { color: #8B6FBE; }

.ink-line-gate-count {
  font-family: Fraunces, Georgia, serif;
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
}
/* The plan chip. Green for ready, purple for in progress — the developer's
   colour, because a plan being written is Claude's work on Mike's station —
   and grey for a row nobody has asked about. */
.ink-plan-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 21px;
  padding: 0 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.ink-plan-chip-ready { background: #EAF1E9; color: #2F7D4E; }
.ink-plan-chip-waiting { background: #EDE7F6; color: #4E3D70; }
.ink-plan-chip-none { background: #F1F3F6; color: #8B97A3; }
/* Large is the one size worth interrupting for: it is the request that needs
   more information before it is worth queueing, and the point of reading it
   early is to find that out early. */
.ink-plan-chip-large { background: #FBF0E4; color: #8A4B12; }

.ink-line-gate-word {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A98A3C;
}

/* ── The line as a tab bar — Turn 82a ───────────────────────────────────────
   On a station page the line is not a picture, it is the page's tab bar, and
   the first version of "which one am I on" was a ring on a raised card — the
   marker a *selected card* takes, not the one a *tab* takes. A tab joins the
   thing it selects. So the strip loses its bottom radius and its drop shadow,
   the six unselected stations recede into the chrome, and the selected one
   turns white and runs straight into the page below with no gap at all.

   Ownership survives as a 3px top edge. It is the only part of the fill that
   still reads once the card is flat, and losing purple-Mike / blue-Steve
   across the row would cost more than the fill was worth. */
.ink-line-tabs {
  background: var(--ink-chrome);
  border-radius: 12px 12px 0 0;
  padding: 15px 20px 0;
}
/* The masthead. Title and one sentence on the left, the two counts on the
   right — they are a status readout, not part of the sentence, and reading
   left to right past them to reach the tabs was the old strip's problem. */
.ink-line-tabs-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 28px;
  padding-bottom: 13px;
}
.ink-line-tabs-id {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1 1 auto;
  min-width: 0;
}
.ink-line-tabs-title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #EEF3F8;
}
/* No max-width: the sentence is meant to sit on one line, and it fits once the
   week's counts are off the right-hand side. It still wraps when the viewport
   is genuinely too narrow — this caps nothing, it just stops capping early. */
.ink-line-tabs-helper {
  font-size: 12px;
  line-height: 1.55;
  color: var(--ink-chrome-text);
}
.ink-line-tabs-helper b { color: #C2CEDC; font-weight: 600; }

/* Big enough to read across the room, and grey rather than white — it is the
   size of the pile, not a heading. */
.ink-line-tabs-stats {
  flex: 0 0 auto;
  white-space: nowrap;
  font-size: 15px;
  color: #8496AA;
}
.ink-line-tabs-stats b { color: #C2CEDC; font-weight: 600; }

/* Seven tabs and, between the fourth and the fifth, a 52px column for the gate.
   Below the full-width layout the row wraps, so the gate spans it and lies down
   as a divider instead — same statement, different orientation. */
.ink-line-tabs-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 5px;
  align-items: end;
}
@media (max-width: 1179px) {
  .ink-line-tabs-row .ink-line-tab-gate {
    grid-column: 1 / -1;
    flex-direction: row;
    gap: 9px;
    padding: 7px 0;
    border-left: 0;
    border-right: 0;
    border-top: 1px dashed #2B3646;
    border-bottom: 1px dashed #2B3646;
  }
  .ink-line-tabs-row .ink-line-gate-keeper { margin-bottom: 0; }
}
@media (min-width: 640px)  { .ink-line-tabs-row { grid-template-columns: repeat(4, 1fr); } }
/* Three stations, the gate, three stations. It was 4 + gate + 3 for the seven-station line; when
   Sorting merged away the six stations plus the gate made seven children in an eight-slot grid, so
   the gate took a full column and Building was crushed into the 52px one. */
@media (min-width: 1180px) { .ink-line-tabs-row { grid-template-columns: repeat(3, minmax(0, 1fr)) 52px repeat(3, minmax(0, 1fr)); } }

.ink-line-tab {
  display: block;
  padding: 10px 12px 12px;
  border-radius: 9px 9px 0 0;
  background: #18222F;
  border-top: 3px solid #33465E;
  text-decoration: none;
  transition: background 120ms ease;
}
.ink-line-tab:hover { background: #202D3D; text-decoration: none; }

.ink-line-tab-owner {
  display: block;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #4D5F76;
}
.ink-line-tab-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 5px;
}
.ink-line-tab-name { font-size: 12.5px; font-weight: 600; color: #93A4B8; }
.ink-line-tab-count {
  font-family: Fraunces, Georgia, serif;
  font-size: 19px;
  font-weight: 700;
  color: #6B7F96;
}
.ink-line-tab-count-zero { color: #3E4E62; }
.ink-line-tab-held { font-size: 9.5px; font-weight: 600; color: #E0B341; }

/* The one you chose. White, taller, and lifted out of the chrome by an upward
   shadow — nothing below it, because below it is the page it belongs to. */
.ink-line-tab-here {
  background: #fff;
  padding: 12px 13px 16px;
  box-shadow: 0 -3px 16px rgba(0, 0, 0, 0.28);
}
.ink-line-tab-here:hover { background: #fff; }
.ink-line-tab-here .ink-line-tab-name { font-size: 13.5px; font-weight: 700; color: #101A28; }
.ink-line-tab-here .ink-line-tab-count { font-size: 23px; color: #101A28; }
.ink-line-tab-here .ink-line-tab-count-zero { color: #8B97A3; }
.ink-line-tab-detail {
  display: block;
  font-size: 11px;
  color: #5B6875;
  line-height: 1.45;
  margin-top: 2px;
}

/* Ownership, reduced to the edge. Brighter on the selected tab: against white
   the dark border colours disappear. */
.ink-line-edge-anyone { border-top-color: #33465E; }
.ink-line-edge-developer { border-top-color: #4E3D70; }
.ink-line-edge-product { border-top-color: #35516F; }
.ink-line-edge-system { border-top-color: #2F5F45; }
.ink-line-tab-here.ink-line-edge-anyone { border-top-color: #6B7F96; }
.ink-line-tab-here.ink-line-edge-developer { border-top-color: #B58BE8; }
.ink-line-tab-here.ink-line-edge-product { border-top-color: #7FB2E8; }
.ink-line-tab-here.ink-line-edge-system { border-top-color: #4FBF7B; }
.ink-line-tab-here .ink-line-owner-developer { color: #8B5FC7; }
.ink-line-tab-here .ink-line-owner-product { color: #1E4E8C; }
.ink-line-tab-here .ink-line-owner-system { color: #2F5F45; }

.ink-line-foot {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--ink-chrome-raised);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 18px;
  font-size: 12px;
  color: var(--ink-chrome-text);
}
.ink-line-foot b { color: #C2CEDC; }

/* ── The work loop — Turn 81b ────────────────────────────────────────────────
   Triage and the build list are the two lists on the home page you act on
   rather than read, and they were built in the same weight as every other
   list in the app. These give them their own. */

/* The violet solid. Deliberately NOT the blue primary: blue is the app's
   "confirm" and it is everywhere, and the exits on a triage row are not
   confirmations — they are three different futures for the same request.
   The rail's own purple, so the loop reads as staff work rather than store
   work wherever it appears. */
.ink-btn-violet {
  background: #3A2C55;
  color: #fff;
}
.ink-btn-violet:hover:not(:disabled) { background: #2F2446; }

/* A list of things to act on: one card, hairline between rows, no box per
   row. Twelve bordered boxes stacked read as twelve separate decisions;
   they are one pass down one list. */
.ink-worklist { display: flex; flex-direction: column; }
.ink-worklist-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 16px;
  border-top: 1px solid var(--ink-rule-soft);
  transition: background-color .12s ease;
}
.ink-worklist-row:first-child { border-top: none; }
.ink-worklist-row:hover { background: var(--ink-surface-sunken-2); }
.ink-worklist-id {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  color: var(--ink-text-ghost);
  width: 54px;
  flex-shrink: 0;
}
.ink-worklist-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-text);
  line-height: 1.35;
}
.ink-worklist-meta {
  font-size: 11.5px;
  color: var(--ink-text-faint);
  margin-top: 2px;
}
/* The row's own actions. Kept off the hover state on purpose — a control that
   appears when the pointer arrives cannot be aimed for. */
.ink-worklist-actions { display: flex; gap: 6px; flex-shrink: 0; }

/* Section heading for those lists: the label is a micro-cap, the sentence
   after it is the instruction. A count chip is not needed — the rows are
   right there and countable. */
.ink-worklist-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 9px;
}

/* Held at the gate. Amber because it is the one list on the page that is NOT
   yours to move — warn colours already mean "someone else, and it is costing
   something", which is exactly what a held request is. */
.ink-held {
  background: var(--ink-warn-surface);
  border: 1px solid var(--ink-warn-border);
  border-radius: 9px;
  padding: 11px 13px;
}
.ink-held-id {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  color: var(--ink-warn-accent);
}
.ink-held-meta { font-size: 11.5px; color: var(--ink-warn-text); margin-top: 3px; }
.ink-held-label { color: var(--ink-warn-text-strong); }

/* "brief ready" — the queue's readiness marker. Green when the request
   carries acceptance criteria, because that is the only thing on a change
   request that says what "done" means. */
.ink-ready {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--ink-success-text);
  white-space: nowrap;
}
.ink-ready-none { color: var(--ink-text-ghost-2); }

/* CR-321 / Turn 86 — how a request, a plan and a note read once they are no
   longer showing their own source.

   The panes used to render Markdown with `whitespace-pre-line`, so Steve's memo
   arrived on screen with its asterisks and backticks intact. Markdig renders it
   now (`RequestReading.ToHtml`, with raw HTML disabled), and these are the tags
   it actually emits.

   Scoped under `.ink-md` rather than styling bare tags, because these live
   inside a page that has its own `p`, `ul` and `table` rules. */
.ink-md > :first-child { margin-top: 0; }
.ink-md > :last-child { margin-bottom: 0; }
.ink-md p { margin: 0 0 0.65em; }
.ink-md strong { font-weight: 600; color: #101A28; }
.ink-md em { font-style: italic; }
.ink-md a { color: #2C6CB0; text-decoration: underline; }

/* A measure, and it is the other half of "reading it is not easy". A question
   runs the full width of a 900px pane otherwise, which is roughly 160 characters
   a line — about twice what anybody reads comfortably. Paragraphs get the cap;
   tables and code do not, because those are read by scanning across. */
.ink-md p, .ink-md li, .ink-md blockquote { max-width: 78ch; }

.ink-md code {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 0.92em;
  background: #F2F5F8;
  border: 1px solid #E4E9EF;
  border-radius: 4px;
  padding: 0 4px;
  /* CR-385. Inline code on these pages is mostly file paths —
     `src/Components/Pages/Platform/Settings/ChangeRequestQueue.razor` is sixty-two characters and
     will not break at a slash on its own. On a phone one of them widens its container and takes the
     whole page sideways with it, which is the worst version of this bug because it moves everything
     rather than one control. `pre` already scrolls; inline code has nowhere to scroll, so it wraps. */
  overflow-wrap: anywhere;
}
.ink-md pre {
  background: #F7F9FB;
  border: 1px solid #E4E9EF;
  border-radius: 8px;
  padding: 10px 12px;
  overflow-x: auto;
  margin: 0 0 0.65em;
}
.ink-md pre code { background: none; border: 0; padding: 0; font-size: 0.95em; }

/* A heading inside a body is a heading of that body, not of the page — one step
   up in weight and nothing else, or a memo's part titles start competing with
   the pane's own labels. */
.ink-md h1, .ink-md h2, .ink-md h3, .ink-md h4, .ink-md h5, .ink-md h6 {
  font-size: 1em;
  font-weight: 600;
  color: #101A28;
  margin: 1em 0 0.4em;
}
.ink-md blockquote {
  border-inline-start: 2px solid #DDE3EA;
  padding-inline-start: 11px;
  margin: 0 0 0.65em;
  color: #3C4854;
}
.ink-md ul, .ink-md ol { margin: 0 0 0.65em; padding-inline-start: 1.25em; }
.ink-md ul { list-style: disc; }
.ink-md ol { list-style: decimal; }
.ink-md li { margin-bottom: 0.28em; }
.ink-md li > p { margin: 0; }

/* An acceptance criterion is a box somebody is going to tick, and drawing it as
   a bullet loses that. Markdig's task list emits a disabled checkbox. */
.ink-md li.task-list-item { list-style: none; margin-inline-start: -1.25em; }
.ink-md li.task-list-item input { margin-inline-end: 7px; accent-color: #2C6CB0; }

/* Steve's memos are largely tables — the column-mapping one is nine rows of
   target and meaning — and they were arriving as run-together pipe characters. */
.ink-md table { border-collapse: collapse; margin: 0 0 0.65em; font-size: 0.95em; display: block; overflow-x: auto; }
.ink-md th, .ink-md td { border: 1px solid #E4E9EF; padding: 5px 9px; text-align: start; vertical-align: top; }
.ink-md th { background: #F7F9FB; font-weight: 600; color: #101A28; white-space: nowrap; }
.ink-md hr { border: 0; border-top: 1px solid #E4E9EF; margin: 1em 0; }

/* ══════════════════════════════════════════════════════════════════════════
   The Forge — canvas Turn 93a.

   Replaces the seven-card Factory Line on the home rendering. The argument the
   drawing makes, and the reason the CSS is shaped the way it is:

   - **A pile is not a station** (87a). Caught and Shipped are owned by "anyone"
     and "system", which are two ways of saying nobody works there. They lose the
     card, the count badge and the owner line and become textured heaps — read as
     accumulation, not process.
   - **Machines show they are machines.** Each carries a tread along its bottom
     edge in its own colour.
   - **Questions is a lamp, not a station.** At zero it was a card spending a
     seventh of the strip to say nothing is happening; as a chip on Processing it
     describes what is holding the machine up.
   - **The two gaps are the two places a human decides** (93a). Sending a brief
     in, and publishing built code. Drawn identically because they are the same
     kind of act — everything else on the line runs on its own.

   The metaphor lives here and nowhere else (Turn 92): the strip carries the
   names and the heat; every other surface says "brief".
   ══════════════════════════════════════════════════════════════════════════ */

.ink-forge {
  background: #0D1620;
  border-radius: 12px;
  padding: 20px 24px 24px;
  box-shadow: 0 8px 28px rgba(13, 22, 32, 0.22);
}
/* CR-391. On a phone the Forge is most of the first screen before a single request appears, and
   Mike's ask is the tabs and the list. It is the headline of the platform home page and only
   context on a station page, so it goes at that width rather than shrinking — `.ink-forge-onstation`
   is what the station pages mark it with, and the home page keeps it at every size. */
@media (max-width: 639px) {
  .ink-forge-onstation { display: none; }
}

.ink-forge-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 20px;
  flex-wrap: wrap;
}

.ink-forge-title {
  font-family: Fraunces, Georgia, serif;
  font-size: 21px;
  font-weight: 700;
  color: #fff;
  line-height: 1;
}

.ink-forge-sub { font-size: 12.5px; color: #6B7F96; margin-top: 6px; }
.ink-forge-sub b { color: #F0C070; }

.ink-forge-stats { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.ink-forge-stat { display: flex; align-items: baseline; gap: 6px; }
.ink-forge-stat b {
  font-family: Fraunces, Georgia, serif;
  font-size: 21px;
  font-weight: 700;
  color: #fff;
}
.ink-forge-stat span { font-size: 12.5px; color: #6B7F96; }
.ink-forge-stat-ready b   { color: #F0C070; }
.ink-forge-stat-furnace b { color: #FF7A2F; }
.ink-forge-stat-publish b { color: #8FB4D4; }
.ink-forge-rule { width: 1px; height: 26px; background: #24303F; }

/* `align-items: end` is what sits the two piles and the three machines on one
   floor while letting the furnace be taller than everything else. The furnace
   column is 1.6fr — it is the machine that does the work, and on the canvas the
   scale was the one thing worth a slider. */
.ink-forge-strip {
  display: grid;
  grid-template-columns: 148px 1fr 92px 1.6fr 92px 1fr 148px;
  gap: 11px;
  align-items: end;
}

/* ── the piles ─────────────────────────────────────────────────────────── */

.ink-forge-pile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  padding-bottom: 6px;
  text-decoration: none;
}
.ink-forge-heap { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.ink-forge-heap i { display: block; }
.ink-forge-heap i:nth-child(1) { width: 66px;  height: 8px;  border-radius: 3px 3px 0 0; }
.ink-forge-heap i:nth-child(2) { width: 94px;  height: 10px; border-radius: 2px; }
.ink-forge-heap i:nth-child(3) { width: 126px; height: 12px; border-radius: 2px; }

/* 58deg hatching reads as loose material seen from the side. Cool blues for what
   has arrived, green for what has left — the same two owner colours the tab strip
   uses, so the piles and the stations share one scheme. */
.ink-forge-pile-in i:nth-child(1)  { background: repeating-linear-gradient(58deg, #26344A 0 4px, #1F2B3D 4px 8px); }
.ink-forge-pile-in i:nth-child(2)  { background: repeating-linear-gradient(58deg, #2B3A51 0 4px, #222E42 4px 8px); }
.ink-forge-pile-in i:nth-child(3)  { background: repeating-linear-gradient(58deg, #30405A 0 4px, #253248 4px 8px); }
.ink-forge-pile-out i:nth-child(1) { background: repeating-linear-gradient(58deg, #24402F 0 4px, #1D3325 4px 8px); }
.ink-forge-pile-out i:nth-child(2) { background: repeating-linear-gradient(58deg, #22402C 0 4px, #294934 4px 8px); }
.ink-forge-pile-out i:nth-child(3) { background: repeating-linear-gradient(58deg, #2F5F45 0 4px, #254734 4px 8px); }

.ink-forge-pile-label { display: flex; align-items: baseline; gap: 8px; }
.ink-forge-pile-label span { font-size: 14px; font-weight: 600; color: #93A4B8; }
.ink-forge-pile-label b {
  font-family: Fraunces, Georgia, serif;
  font-size: 22px;
  font-weight: 700;
  color: #6B7F96;
}
.ink-forge-pile:hover .ink-forge-pile-label span { color: #C2CEDC; }

/* ── the machines ──────────────────────────────────────────────────────── */

.ink-forge-machine {
  position: relative;
  display: block;
  text-decoration: none;
  border-radius: 10px;
  padding: 13px 15px 0;
  overflow: hidden;
}
.ink-forge-machine-body { display: flex; flex-direction: column; gap: 8px; }

.ink-forge-owner {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.08em;
}
.ink-forge-name {
  display: flex;
  align-items: baseline;
  gap: 9px;
  font-family: Fraunces, Georgia, serif;
  font-weight: 700;
  line-height: 1;
}
.ink-forge-what { font-size: 11.5px; line-height: 1.45; color: #5B6875; }

/* The tread. Every machine has one along its bottom edge, bled past the padding —
   it is the edge of the thing, not a bar inside it. */
.ink-forge-tread { height: 13px; margin: 0 -15px; }

/* Processing — an open fire. White card, you can see into it (89a). The class names keep
   the drawing's own words: they describe the shape, not the machine (CR-334's rule). */
.ink-forge-shaping-slot { position: relative; }
.ink-forge-shaping-glow {
  position: absolute;
  left: -14px; right: -14px; bottom: -20px; height: 44px;
  background: radial-gradient(ellipse at 50% 50%, rgba(240, 170, 60, 0.30), rgba(240, 170, 60, 0) 72%);
  pointer-events: none;
}
.ink-forge-shaping {
  background: #fff;
  border-top: 3px solid #F0A028;
  box-shadow: 0 6px 26px rgba(240, 160, 40, 0.18);
}
.ink-forge-shaping .ink-forge-owner { color: #B8700C; }
.ink-forge-shaping .ink-forge-name { font-size: 23px; color: #101A28; }
.ink-forge-shaping:hover { box-shadow: 0 8px 32px rgba(240, 160, 40, 0.30); }

/* The bar of stock across the bottom: lengths of metal seen end-on, banded in the
   colours of the three chips above it. */
.ink-forge-shaping .ink-forge-tread {
  background: linear-gradient(90deg,
    #7C8794 0 44%, #5F6B78 44% 46%, #A8B2BC 46% 61%, #5F6B78 61% 63%,
    #B8700C 63% 77%, #5F6B78 77% 79%, #F0A028 79% 89%, #5F6B78 89% 91%, #C4693A 91% 100%);
}

.ink-forge-chips { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; padding-bottom: 2px; }
.ink-forge-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border-radius: 5px;
  font-size: 10.5px;
  font-weight: 600;
}
.ink-forge-chip i { width: 6px; height: 6px; border-radius: 50%; display: block; }
.ink-forge-chip-ready    { background: #FDF1DC; color: #8A5606; }
.ink-forge-chip-ready i  { background: #F0A028; }
.ink-forge-chip-answer   { background: #F7EEE6; color: #8A5606; }
.ink-forge-chip-answer i { background: #C4693A; }
.ink-forge-chip-unread   { background: #F1F4F8; color: #5B6875; }
.ink-forge-chip-unread i { background: #8B97A3; }

/* The Cercis Code Crucible — a sealed vessel running hotter (89a). Dark shell, red
   light escaping at the seams, molten edge along the bottom. The class names keep
   "furnace": they describe the shape, and the machine's name is one const in
   `FactoryLine.razor` precisely so a rename does not reach the stylesheet (CR-334). */
.ink-forge-furnace-slot { position: relative; }
.ink-forge-furnace-glow {
  position: absolute;
  left: -20px; right: -20px; bottom: -26px; height: 66px;
  background: radial-gradient(ellipse at 50% 50%, rgba(255, 70, 10, 0.46), rgba(255, 70, 10, 0) 72%);
  pointer-events: none;
}
.ink-forge-furnace {
  background: #1B1210;
  border-radius: 12px;
  border-top: 4px solid #E03616;
  padding: 26px 20px 0;
  box-shadow: 0 10px 38px rgba(224, 54, 22, 0.34);
}
.ink-forge-furnace .ink-forge-machine-body { gap: 12px; }
/* The heat inside it, thrown up from the hearth. Sits under the content, which is
   why every child of the furnace is positioned. */
.ink-forge-furnace-hearth {
  position: absolute;
  left: 50%; bottom: -34px;
  width: 220px; height: 96px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 100%, rgba(255, 110, 26, 0.52), rgba(255, 110, 26, 0) 70%);
  pointer-events: none;
}
/* Only the content is lifted, and it is named rather than `> *` — the hearth is a sibling with the
   same specificity, so a wildcard here would set it back to `relative` and put the glow in front of
   the text it is meant to sit behind. */
.ink-forge-furnace > .ink-forge-machine-body { position: relative; }
.ink-forge-furnace .ink-forge-owner { color: #E8724A; }
.ink-forge-furnace .ink-forge-name { font-size: 26px; color: #FFE4D2; }
.ink-forge-furnace .ink-forge-name b { color: #FF9A5C; }
.ink-forge-furnace .ink-forge-what { font-size: 12.5px; color: #C89A88; }
.ink-forge-temp { font-size: 10px; font-weight: 600; color: #FF8A4A; }
.ink-forge-furnace:hover { box-shadow: 0 12px 44px rgba(224, 54, 22, 0.46); }

.ink-forge-charge { display: flex; flex-direction: column; gap: 6px; }
.ink-forge-charge-label {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: #A0705C;
}
.ink-forge-charge-row { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.ink-forge-charge-row span {
  padding: 3px 7px;
  border-radius: 5px;
  background: #3A1C14;
  color: #F0A080;
  font-size: 10.5px;
  font-weight: 600;
}

.ink-forge-piece { display: flex; flex-direction: column; gap: 6px; padding-bottom: 4px; }
.ink-forge-piece-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ink-forge-piece-head b {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 400;
  color: #E8A088;
}
.ink-forge-piece-head span { font-size: 11px; color: #C89A88; }

/* Indeterminate on purpose. The canvas drew "step 2 of 4" over a half-filled bar
   and nothing in the model knows how far through a build is — a determinate bar
   with no data behind it is a lie told precisely. This says running.

   **It no longer moves — CR-446.** Mike: *"the moving red/orange line in the Cercis
   Code Crucible is distracting."* It slid across every 2.6 seconds, forever, on a
   page whose whole job is reading a list beside it — motion in peripheral vision
   that never resolves, because there is nothing for it to resolve to.

   The bar stays. It marks which piece is in the furnace and that is worth keeping;
   what it cannot honestly carry is progress. This is exactly the appearance the
   reduced-motion rule already specified, now the appearance for everyone — the
   accessible version turned out to be the right one, which is usually the way. */
.ink-forge-burn { height: 6px; border-radius: 3px; background: #3A1C14; overflow: hidden; }
.ink-forge-burn i {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 3px;
  opacity: 0.55;
  background: linear-gradient(90deg, #E03616, #FFB35C);
}

.ink-forge-furnace .ink-forge-tread {
  height: 16px;
  margin: 0 -20px;
  background: linear-gradient(90deg, #FFF0C4, #FFA23C, #E03616, #FF6B1A, #C21807, #FF8A2F);
}

/* Testing — a cold bench. Nothing is being made here; something is being tried. */
.ink-forge-proving {
  background: #18222F;
  border-top: 3px solid #35516F;
}
.ink-forge-proving .ink-forge-owner { color: #4D5F76; }
.ink-forge-proving .ink-forge-name { font-size: 21px; color: #C2CEDC; }
.ink-forge-proving .ink-forge-name b { color: #93A4B8; }
.ink-forge-proving .ink-forge-tread { background: repeating-linear-gradient(90deg, #3F627F 0 3px, #20303F 3px 14px); }
.ink-forge-proving:hover { background: #1D2836; }

.ink-forge-where { font-size: 10px; font-weight: 600; color: #6B7F96; }
.ink-forge-note {
  padding: 2px 7px;
  border-radius: 5px;
  background: #26344A;
  color: #93A4B8;
  font-size: 10.5px;
  font-weight: 600;
}

/* ── the two gaps ──────────────────────────────────────────────────────── */

/* Both crossings are drawn identically — same squares, same arrow, same two-line
   label — because they are the same kind of act. The three squares cool from the
   colour of the station behind into the colour of the one ahead, so the pair reads
   as one gesture repeated rather than two unrelated widgets (93a). */
.ink-forge-gap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding-bottom: 24px;
  background: none;
  border: 0;
  text-decoration: none;
  cursor: pointer;
  font: inherit;
}
.ink-forge-gap-squares { display: flex; align-items: center; gap: 4px; }
.ink-forge-gap-squares i { width: 6px; height: 6px; border-radius: 2px; display: block; }
.ink-forge-gap-arrow { font-size: 13px; margin-left: 1px; }
.ink-forge-gap-label { font-size: 10.5px; font-weight: 600; text-align: center; line-height: 1.35; }
.ink-forge-gap-count { font-size: 10px; color: #4D5F76; text-align: center; }

.ink-forge-gap-send i:nth-child(1) { background: #A8B2BC; }
.ink-forge-gap-send i:nth-child(2) { background: #B8700C; }
.ink-forge-gap-send i:nth-child(3) { background: #F0A028; }
.ink-forge-gap-send .ink-forge-gap-arrow { color: #C05018; }
.ink-forge-gap-send .ink-forge-gap-label { color: #F0A050; }

.ink-forge-gap-publish i:nth-child(1) { background: #FF6B1A; }
.ink-forge-gap-publish i:nth-child(2) { background: #B0663F; }
.ink-forge-gap-publish i:nth-child(3) { background: #6B8CA8; }
.ink-forge-gap-publish .ink-forge-gap-arrow { color: #5B7F9E; }
.ink-forge-gap-publish .ink-forge-gap-label { color: #8FB4D4; }

/* A gap with nothing waiting is still drawn — it is a place on the line, and
   hiding it would make the strip change shape as work moves. It recedes instead. */
.ink-forge-gap-idle { opacity: 0.42; cursor: default; }

/* ── narrow ────────────────────────────────────────────────────────────── */

/* The strip is a diagram of a sequence, and a sequence that wraps stops being one.
   Below the width where seven columns hold, it becomes a single column: the piles
   and gaps keep their place in the order, so it reads top to bottom instead of
   left to right, and the furnace stops being 1.6× anything. */
@media (max-width: 1180px) {
  .ink-forge-strip { grid-template-columns: 1fr; gap: 14px; }
  .ink-forge-gap { padding-bottom: 0; flex-direction: row; gap: 10px; }
  .ink-forge-gap-label { text-align: start; }
  .ink-forge-gap-squares { transform: rotate(90deg); }
  .ink-forge-furnace { padding-top: 16px; }
  .ink-forge-furnace .ink-forge-name { font-size: 23px; }
}

/* The Forge and, on a station page, the tab bar under it — CR-331.

   Turn 82a had two renderings of the line and argued they were different objects: a picture that
   says "here is the line and you are on it", a tab bar that says "these are your choices and this
   is the one you made". Both are true on a station page, so it gets both — and the tab bar, freed
   from carrying the drawing, becomes an ordinary `.ink-tabs`. */
.ink-forge-tabs {
  margin-top: 14px;
  padding: 12px 18px 0;
  background: #fff;
  border-radius: 12px 12px 0 0;
}
/* No rule of its own. The page panel directly below opens with `border-t`, and that line is what
   the tabs sit on — drawing a second one here would double it at every width. */
.ink-forge-tabs .ink-tabs { border-bottom: none; }

/* Turn 37b — a long description folded after its opening paragraph. Hidden with CSS rather than by cutting the HTML:
   a cut left the grower's wrapping element unclosed and pulled the rest of the page inside it. */
.ink-fold-after-first-p p ~ * { display: none; }
