:root {
  --bg: #f4f6f5;
  --card: #ffffff;
  --ink: #1c2422;
  --muted: #5c6b66;
  --brand: #0b5d4e;
  --brand-ink: #ffffff;
  --line: #d9e0dd;
  --pass: #1c7c3c;
  --warn: #b8860b;
  --fail: #c0362c;
  --fail-bg: #fdecea;
  --radius: 12px;
  /* Operator reskin palette (used by the .operator shell). */
  --ink-900: #14202b;
  --paper: #f2f4f3;
  --pass-tint: #e2f2ea;
  --pass-line: #bcdfce;
  --fail-tint: #fbeae8;
  --fail-line: #efc5c0;
  --steel: #2c6e9b;
  --steel-tint: #e7f0f7;
  --amber: #a96f0e;
  --amber-tint: #faf1dc;
}

* { box-sizing: border-box; }

/* Dashboard summary tiles (QA review) */
.dashboard {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 10px;
  margin-bottom: 18px;
}
.stat {
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
  text-align: left;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 13px 14px;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.stat:hover:not(.stat-static) { border-color: var(--brand); box-shadow: 0 1px 5px rgba(11, 93, 78, 0.12); }
.stat:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.stat-static { cursor: default; }
.stat-num { font-size: 27px; font-weight: 700; line-height: 1.05; font-variant-numeric: tabular-nums; }
.stat-lbl { font-size: 12px; color: var(--muted); letter-spacing: 0.02em; }
.stat-alert { border-color: #f0c9c4; background: var(--fail-bg); }
.stat-alert .stat-num { color: var(--fail); }
.stat-alert:hover:not(.stat-static) { border-color: var(--fail); box-shadow: 0 1px 5px rgba(192, 54, 44, 0.15); }

body {
  margin: 0;
  font: 16px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  color: var(--ink);
  background: var(--bg);
}

/* THREE EQUAL-SIDED COLUMNS, not space-between.
   The nav has to sit in the same place on every section, and space-between put
   it wherever its two siblings left room - so it slid sideways as the brand
   sub-line changed width ("Operator records" / "QA review" / "Form builder") and
   as the clock appeared and disappeared. Equal side tracks centre the nav on the
   BAR instead of on its neighbours, so nothing a section puts in either slot can
   move it.
   `min-height` does the same job vertically: the bar keeps one height whatever
   the slots hold. */
.topbar {
  background: var(--brand);
  color: var(--brand-ink);
  padding: 12px 18px;
  display: grid;
  /* minmax(0, 1fr), not a bare 1fr: a bare `1fr` is minmax(AUTO, 1fr), so the
     track will not shrink below its content's minimum - and the brand block's
     minimum is wider than the clock's, which lets the side tracks go unequal
     once space is tight and puts the nav back off-centre. minmax(0, ...) makes
     them strictly equal at every width. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  min-height: 58px;
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar-main { grid-column: 1; grid-row: 1; justify-self: start; min-width: 0; }
.appnav { grid-column: 2; grid-row: 1; justify-self: center; }
.topbar-right { grid-column: 3; grid-row: 1; justify-self: end; min-width: 0; }
.brand { font-weight: 600; letter-spacing: 0.2px; }
.record-tag {
  font-size: 13px;
  background: rgba(255, 255, 255, 0.18);
  padding: 4px 10px;
  border-radius: 999px;
}

/* --- the header, shared by every section ---------------------------------- */
/* These three used to be scoped under .operator, because only the operator
   page had a two-line brand and a right-hand slot row. The shell now uses the
   same header on every section, so they are base rules and .operator only
   overrides the parts that differ. */
.topbar-main { display: flex; flex-direction: column; line-height: 1.15; }
.brand-sub {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.72;
}
.topbar-right { display: flex; align-items: center; gap: 10px; }

/* --- section nav ---------------------------------------------------------- */
/* Operator / QA review / Form builder, in the header on every screen. It sits
   on both the dark operator bar and the green QA bar, so it is painted from
   the bar's own ink at low opacity rather than any fixed palette colour. */
.appnav { display: flex; gap: 4px; flex-wrap: wrap; justify-content: center; }
.appnav-item {
  color: inherit;
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 999px;
  opacity: 0.7;
  white-space: nowrap;
}
.appnav-item:hover { opacity: 1; background: rgba(255, 255, 255, 0.1); }
.appnav-item.on { opacity: 1; background: rgba(255, 255, 255, 0.18); }
/* Touch target on a tablet: the nav is how an operator leaves a form, so it
   must not be a 13px sliver. */
@media (pointer: coarse) {
  .appnav-item { padding: 9px 14px; }
}
/* On a phone the brand sub-line is the first thing to go - the nav says which
   section you are in, so the sub-line is repeating itself. */
/* Below this width the brand, three section links and the status slot cannot
   share one row: the nav wrapped mid-list, orphaning "Form builder" under a
   brand that had itself wrapped to two lines. The nav gets its own row instead.
   NOT only a phone case - an iPad in Split View or Slide Over is handed a
   ~320-507pt window and fails identically, and portrait is the operator's
   designed orientation. */
@media (max-width: 620px) {
  .brand-sub { display: none; }
  .appnav-item { padding: 8px 10px; font-size: 12.5px; }

  /* Two rows: brand + status slot above, the nav across the full width below.
     Grid places all three explicitly, so the DOM order stays brand -> nav ->
     status for the keyboard and for screen readers while the nav renders last.
     (This replaces a flex `order: 3` trick; the grid version says where things
     go instead of reordering them after the fact.)
     The brand is one line - "La Casa Connect" wrapping mid-name read as a layout
     fault - and the status slot yields first, since a record tag may be absent. */
  .topbar {
    grid-template-columns: minmax(0, 1fr) auto;
    padding: 10px 12px;
    gap: 8px;
    row-gap: 8px;
    min-height: 0;
  }
  .brand { white-space: nowrap; }
  .topbar-main { grid-column: 1; grid-row: 1; justify-self: start; min-width: 0; }
  .topbar-right { grid-column: 2; grid-row: 1; justify-self: end; min-width: 0; flex-wrap: wrap; }

  /* The nav scrolls sideways rather than wrapping to a third row - three pills
     fit down to 320px, so the scroll is only a backstop. */
  .appnav {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-self: stretch;
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    scrollbar-width: none;            /* Firefox */
    -ms-overflow-style: none;         /* old Edge */
  }
  .appnav-item { flex: 0 0 auto; }
  .appnav::-webkit-scrollbar { display: none; }   /* Safari / Chrome */
}

.app { max-width: 760px; margin: 0 auto; padding: 18px; }
.loading { color: var(--muted); }

h1 { font-size: 20px; margin: 4px 0 16px; }
h2 { font-size: 17px; margin: 0; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 16px;
}

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}
.section-sub { color: var(--muted); font-size: 13px; }

.form-list button {
  width: 100%;
  text-align: left;
  margin-bottom: 10px;
}
.form-list .code { color: var(--muted); font-size: 13px; }

label { display: block; font-weight: 600; margin: 12px 0 4px; font-size: 14px; }
.target { font-weight: 400; color: var(--muted); }

input, select {
  width: 100%;
  padding: 12px;
  font-size: 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  color: var(--ink);
}
input:focus, select:focus { outline: 2px solid var(--brand); border-color: var(--brand); }

.row {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px;
  margin-bottom: 12px;
}
.row-head { font-size: 13px; color: var(--muted); margin-bottom: 4px; }

.field { margin-bottom: 6px; }
.field-flag {
  display: inline-block;
  margin-top: 6px;
  font-size: 13px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
}
.flag-pass { color: var(--pass); }
.flag-warn { color: var(--warn); }
.flag-fail { color: var(--fail); background: var(--fail-bg); }

.field-warn { margin-top: 6px; font-size: 13px; font-weight: 600; color: var(--warn); }

button {
  font: inherit;
  font-weight: 600;
  padding: 12px 16px;
  border: 1px solid var(--brand);
  border-radius: 10px;
  background: var(--brand);
  color: var(--brand-ink);
  cursor: pointer;
}
button.secondary { background: #fff; color: var(--brand); }
button.ghost { background: #fff; color: var(--muted); border-color: var(--line); }
button:disabled { opacity: 0.5; cursor: default; }

.actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.add-row { margin-top: 4px; }

.banner {
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 14px;
  font-size: 14px;
}
.banner-error { background: var(--fail-bg); color: var(--fail); border: 1px solid #f3c9c4; }
.banner-ok { background: #e8f5ec; color: var(--pass); border: 1px solid #bfe4c9; }
/* A caution, not a failure: a late record is still a valid record. Kept clearly
   distinct from banner-error so real out-of-spec failures keep their weight. */
.banner-warn { background: #fdf4e3; color: #8a5a00; border: 1px solid #f0d9a8; }
.banner ul { margin: 6px 0 0; padding-left: 18px; }

.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  background: #1c2422;
  color: #fff;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
}
.reference-note { color: var(--muted); font-size: 13px; }
.reference-note.hash { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* --- operator stepper ----------------------------------------------------- */
.stepper { margin-bottom: 16px; }
.stepper-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.stepper-title { font-size: 18px; font-weight: 600; }
.stepper-sub { color: var(--muted); font-size: 13px; margin-top: 6px; }
.progress { height: 8px; background: var(--line); border-radius: 999px; margin-top: 10px; overflow: hidden; }
.progress-fill { height: 100%; background: var(--brand); border-radius: 999px; transition: width 0.2s ease; }

/* Section tab strip - horizontally scrollable jump-to-section. */
.tabs {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
  scrollbar-width: thin;
}
.tab {
  flex: 0 0 auto;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 600;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--muted);
  white-space: nowrap;
}
.tab.on { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }

/* One-tap "mark remaining as Pass" control above a checklist section. */
.bulk-pass { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 12px; }
.bulk-pass .reference-note { flex: 1 1 200px; }

/* Submit-time operator sign-off. */
.attest { background: #f3f6f5; }
.attest-label { display: flex; align-items: flex-start; gap: 12px; margin: 0; font-weight: 500; line-height: 1.4; }
.attest-label input { width: auto; flex: 0 0 auto; margin-top: 3px; transform: scale(1.3); }

.navbar {
  position: sticky;
  bottom: 0;
  display: flex;
  gap: 10px;
  padding: 12px 0;
  margin-top: 8px;
  background: linear-gradient(to top, var(--bg) 70%, transparent);
}
.navbar button { flex: 1; }
.navbar button:first-child { flex: 0 0 auto; }

/* --- checklist items ------------------------------------------------------- */
.items > .item { padding: 14px 0; border-top: 1px solid var(--line); }
.items > .item:first-child { border-top: none; padding-top: 4px; }
.item-label { font-weight: 600; margin-bottom: 4px; line-height: 1.35; }
.item-instr { color: var(--muted); font-size: 13px; line-height: 1.35; margin-bottom: 10px; }

/* Section-level guidance under the title (e.g. the shared inspection check). */
.section-instr { color: var(--muted); font-size: 13px; line-height: 1.4; margin: -2px 0 14px; }

.segmented { display: flex; gap: 8px; }
.seg {
  flex: 1;
  padding: 14px 8px;
  font-size: 16px;
  font-weight: 600;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  color: var(--muted);
}
.seg.on.seg-pass { background: var(--pass); color: #fff; border-color: var(--pass); }
.seg.on.seg-fail { background: var(--fail); color: #fff; border-color: var(--fail); }
.seg.on.seg-na { background: var(--muted); color: #fff; border-color: var(--muted); }

/* Production-day picker: two big taps (Today / Yesterday) instead of a date
   field, because those are the only days the server will accept. */
.day-pick { display: flex; gap: 8px; }
.day-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 56px;
  padding: 10px 8px;
  border: 1.5px solid var(--line);
  border-radius: 12px;
  background: #fff;
  color: var(--muted);
  cursor: pointer;
}
.day-btn .day-label { font-size: 16px; font-weight: 700; }
.day-btn .day-sub { font-size: 12.5px; }
.day-btn.on { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }
.day-btn.on .day-sub { color: rgba(255, 255, 255, 0.85); }

.field.cond { padding: 10px 12px; margin-top: 10px; background: var(--fail-bg); border-radius: 10px; }
.field.cond .cond-label { margin-top: 0; color: var(--fail); }

/* Corrective action, revealed on a failed item: what to do, at the point of need. */
.corrective {
  display: flex; flex-direction: column; gap: 3px;
  margin-top: 10px; padding: 10px 12px;
  background: var(--fail-bg); border: 1px solid #f3c9c4;
  border-left: 4px solid var(--fail); border-radius: 10px;
}
/* `display: flex` above outranks the UA [hidden] rule, so restore hide-on-hidden. */
.corrective[hidden] { display: none; }
.corrective-tag { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--fail); }
.corrective-text { font-size: 13.5px; line-height: 1.4; color: var(--ink); }

/* Auto-tracked rotation hint (e.g. the next ATP swab point). */
.rotation-hint {
  margin: -2px 0 14px; padding: 10px 12px;
  background: #e8f1ee; border: 1px solid #bcd8cf; border-radius: 10px;
  font-size: 13px; line-height: 1.4; color: var(--brand);
}

.run { border: 1px solid var(--line); border-radius: 10px; padding: 12px; margin-bottom: 12px; }
.run-head { display: flex; align-items: center; justify-content: space-between; font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.ref-item { padding: 6px 0; border-top: 1px solid var(--line); font-size: 14px; color: var(--ink); }

/* --- review + confirmation ------------------------------------------------ */
.review-sections button.review-row {
  width: 100%; text-align: left; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 10px;
}
.review-row .code.ok { color: var(--pass); }
.review-row .code.todo { color: var(--fail); }
.review-stats { margin: 6px 0 0; padding-left: 18px; }
.review-stats .stat-fail { color: var(--fail); font-weight: 600; }
.review-stats .stat-ok { color: var(--pass); font-weight: 600; }

.confirm { text-align: center; }
.confirm-check {
  width: 64px; height: 64px; margin: 8px auto 4px; border-radius: 50%;
  background: var(--pass); color: #fff; font-size: 36px; line-height: 64px;
}

/* --- photo / evidence (operator entry) ------------------------------------ */
.photo-slot { margin-top: 8px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.photo-slot[hidden] { display: none; } /* author display:flex would otherwise override [hidden] */
.photo-slot[data-required="1"]::after {
  content: 'required if failed';
  font-size: 12px; color: var(--fail);
}
.photo-status { font-size: 13px; color: var(--muted); }

/* --- attachments (QA review) ---------------------------------------------- */
.attachments { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.attachment-img {
  max-width: 160px; max-height: 160px; border-radius: 8px;
  border: 1px solid var(--line); object-fit: cover; cursor: pointer; background: #f0f0f0;
}
.attachment-file { font-size: 13px; }

/* --- QA review front end --------------------------------------------------- */
.filter-bar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.filter-bar button { padding: 8px 12px; font-size: 14px; }

.search-panel {
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  padding: 10px 14px;
  margin-bottom: 16px;
}
.search-panel summary { cursor: pointer; font-weight: 600; font-size: 14px; }
.search-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 8px 14px;
  margin-top: 10px;
}
.search-grid label { margin: 6px 0 4px; }
.search-checks { display: flex; gap: 18px; flex-wrap: wrap; margin: 10px 0; }
.search-checks .check { display: flex; align-items: center; font-weight: 600; font-size: 14px; }
.search-checks .check input { width: auto; }

.queue button.queue-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  text-align: left;
  margin-bottom: 10px;
}
.queue-main { min-width: 0; }
.queue-badges { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

.pill {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--line);
  color: var(--ink);
  white-space: nowrap;
}
.pill-submitted { background: #fdf3da; color: #8a6d11; }
.pill-approved { background: #e8f5ec; color: var(--pass); }
.pill-draft { background: #eef1f0; color: var(--muted); }
.pill-voided { background: #eceeed; color: var(--muted); text-decoration: line-through; }
.pill-capa { background: #fdecea; color: var(--fail); }
.pill-fail { background: var(--fail-bg); color: var(--fail); }

/* A returned record is back to 'draft' but is still QA's outstanding item. */
.queue-reason { margin-top: 4px; font-size: 12.5px; color: var(--fail); }

.detail-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.detail-head button { padding: 8px 12px; font-size: 14px; }
.detail-head-right { display: flex; align-items: center; gap: 10px; }

.capa-row, .wf-row, .rev-row {
  display: flex;
  gap: 10px;
  align-items: baseline;
  flex-wrap: wrap;
  padding: 6px 0;
  border-top: 1px solid var(--line);
  font-size: 14px;
}
.capa-row:first-of-type, .wf-row:first-of-type { border-top: none; }
.wf-event { font-weight: 600; text-transform: capitalize; }

/* A corrective action worked in place: containment / investigation / root cause. */
.capa-case { border-top: 1px solid var(--line); padding: 4px 0 12px; }
.capa-case:first-of-type { border-top: none; }
.capa-case .capa-row { border-top: none; }
.capa-num { font-weight: 700; }
.capa-body { padding-left: 2px; }
.capa-body textarea {
  width: 100%;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  resize: vertical;
}
.capa-body textarea:focus { outline: 2px solid var(--brand); border-color: var(--brand); }
.capa-case.closed .capa-body { opacity: 0.7; }

.resp { padding: 10px 0; border-top: 1px solid var(--line); }
.resp:first-of-type { border-top: none; }
.resp-fail { border-left: 3px solid var(--fail); padding-left: 10px; margin-left: -10px; }
.resp-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.resp-name { font-weight: 600; }
.resp-value { display: flex; align-items: center; gap: 8px; text-align: right; }
.resp-value .field-flag { margin-top: 0; }

.revisions { margin-top: 6px; font-size: 13px; }
.revisions summary { color: var(--muted); cursor: pointer; }
.rev-num { font-weight: 600; }
.rev-reason { color: var(--fail); }

.correct { margin-top: 8px; }
.correct-form { margin-top: 8px; }
button.small { padding: 8px 12px; font-size: 14px; }

/* ===========================================================================
   Operator PWA reskin - scoped under body.operator so the QA review page is
   untouched. Industrial dark header, pill toggles, zone accordions, the span
   grid, instrument readout, and a stateful submit bar.
   ========================================================================= */
body.operator { background: var(--paper); }

/* Colour only. The padding override that used to live here made the operator bar
   4px shorter than the QA one, so the nav - and the whole page under it - jumped
   vertically every time you switched section. Geometry belongs to `.topbar`; a
   section may repaint the bar but must not resize it. */
.operator .topbar {
  background: var(--ink-900);
}
.operator .topbar-main { display: flex; flex-direction: column; line-height: 1.15; }
.operator .brand { font-size: 16px; font-weight: 700; letter-spacing: 0.01em; }
.operator .brand-sub {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: #9fb3c4;
}
.operator .topbar-right { display: flex; align-items: center; gap: 10px; }
.operator .record-tag { background: rgba(255, 255, 255, 0.14); }
.operator .clock { font-variant-numeric: tabular-nums; font-size: 13px; color: #c8d6e2; }

/* Date & time inputs: native date/time controls render very differently across
   browsers - on iOS Safari an empty one shows as a blank, oversized box with no
   placeholder or icon. Normalise the height to match the text fields and add a
   visible calendar/clock icon so it clearly reads as a tappable picker even when
   empty. `appearance: none` still opens the native picker on tap. */
.operator input[type="date"],
.operator input[type="time"] {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  min-height: 48px;
  padding-right: 42px;
  background-repeat: no-repeat;
  background-position: right 13px center;
  background-size: 20px 20px;
  color: var(--ink);
}
.operator input[type="date"]:invalid,
.operator input[type="time"]:invalid { color: var(--muted); }
.operator input[type="date"] {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236b7a85' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
}
.operator input[type="time"] {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236b7a85' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpolyline points='12 7 12 12 15 14'/%3E%3C/svg%3E");
}
/* Chrome/desktop draws its own picker indicator; hide it so only our icon shows. */
.operator input[type="date"]::-webkit-calendar-picker-indicator,
.operator input[type="time"]::-webkit-calendar-picker-indicator {
  opacity: 0;
  position: absolute;
  right: 0;
  width: 42px;
  height: 100%;
  cursor: pointer;
}

/* Big pill Pass / Fail / N-A toggles. */
.operator .seg { min-height: 48px; border-width: 1.5px; border-radius: 999px; }
.operator .seg.on.seg-pass { background: var(--pass); color: #fff; border-color: var(--pass); }
.operator .seg.on.seg-fail { background: var(--fail); color: #fff; border-color: var(--fail); }

/* Collapsible zone accordions inside a checklist section. */
.zones { display: block; }
.zone { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 12px; overflow: hidden; }
.zone-h {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 14px 16px; background: none; border: none; color: var(--ink); cursor: pointer;
}
.zone-h .zt { font-weight: 700; font-size: 15px; text-align: left; }
.zone-h .zs { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.zprog { font-variant-numeric: tabular-nums; font-size: 12.5px; color: var(--muted); }
.zprog.done { color: var(--pass); font-weight: 700; }
.chev { font-size: 11px; color: var(--muted); transition: transform 0.2s ease; }
.zone.open .chev { transform: rotate(180deg); }
.zone-body { display: none; border-top: 1px solid var(--line); padding: 0 16px; }
.zone.open .zone-body { display: block; }
.zone-body .items > .item:first-child { padding-top: 12px; }

/* Chamber tap grid (e.g. 16 checkweigher chambers). */
.grid-field { margin: 6px 0 4px; }
.chamber-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }
.chamber {
  aspect-ratio: 1; padding: 0; border: 1.5px solid var(--line); border-radius: 8px;
  background: #fff; color: var(--muted); font-weight: 700; font-size: 13px;
  font-variant-numeric: tabular-nums; cursor: pointer;
}
.chamber.p { background: var(--pass-tint); border-color: var(--pass); color: var(--pass); }
.chamber.f { background: var(--fail-tint); border-color: var(--fail); color: var(--fail); }
.grid-hint { font-size: 11.5px; color: var(--muted); margin: 8px 0 0; }

/* Derived verdict pill (span summary + ATP readout). */
.verdict { display: inline-block; margin-top: 8px; padding: 8px 12px; border-radius: 10px; font-weight: 700; font-size: 13.5px; }
.verdict.idle { background: var(--bg); color: var(--muted); border: 1px dashed var(--line); }
.verdict.pass { background: var(--pass-tint); color: var(--pass); border: 1px solid var(--pass-line); }
.verdict.fail { background: var(--fail-tint); color: var(--fail); border: 1px solid var(--fail-line); }
.verdict.warn { background: var(--amber-tint); color: var(--amber); border: 1px solid #e8d3a6; }

/* Instrument readout (ATP luminometer). */
.readout-field { margin-bottom: 8px; }
.readout-row { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
.lumin { flex: 1; display: flex; align-items: baseline; gap: 8px; background: var(--ink-900); border-radius: 10px; padding: 10px 14px; }
.readout-input {
  width: 100%; padding: 0; background: transparent; border: none; outline: none;
  color: #7de8a9; font-variant-numeric: tabular-nums; font-size: 26px; font-weight: 700;
}
.readout-input::placeholder { color: #3e5568; }
.readout-row .verdict { margin-top: 0; min-width: 88px; text-align: center; }

/* Stateful submit bar. */
.operator .submit-main { flex: 1; }
.operator .submit-main:disabled { background: #c7cfd4; color: #69777f; border-color: #c7cfd4; opacity: 1; }
.operator .submit-main.ready { background: var(--pass); border-color: var(--pass); color: #fff; }

/* Cleaning register - a card per area (frequency badge, collapsible sequence,
   Mark done / 2nd person verify). */
.section-plain { margin-bottom: 16px; }
.clean-list { display: block; }
.clean-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; margin-bottom: 11px; }
.clean-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.clean-name { font-weight: 600; font-size: 14.5px; line-height: 1.3; }
.freq-badge { flex-shrink: 0; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; color: var(--steel); background: var(--steel-tint); padding: 3px 9px; border-radius: 999px; }
.seq-toggle { display: inline-block; margin-top: 5px; padding: 0; border: none; background: none; color: var(--steel); font-size: 12.5px; font-weight: 600; cursor: pointer; }
.clean-seq { margin-top: 8px; padding: 9px 12px; background: var(--bg); border-radius: 9px; font-size: 12.5px; line-height: 1.5; color: var(--ink); }
.clean-seq[hidden] { display: none; }
.clean-actions { display: flex; gap: 8px; margin-top: 12px; }
.cbtn { flex: 1; padding: 12px 8px; border: 1.5px solid var(--line); border-radius: 10px; background: #fff; color: var(--muted); font-weight: 600; font-size: 13.5px; cursor: pointer; }
.cbtn.is-done { background: var(--pass-tint); border-color: var(--pass); color: var(--pass); }
.cbtn.is-verified { background: var(--steel-tint); border-color: var(--steel); color: var(--steel); }
.cbtn:disabled { opacity: 0.45; cursor: not-allowed; }
.link-btn { display: inline-block; margin-top: 10px; padding: 0; border: none; background: none; color: var(--fail); font-size: 12.5px; font-weight: 600; cursor: pointer; }
.link-btn[hidden] { display: none; }
.name-entry { margin-top: 10px; }
.name-entry[hidden] { display: none; }
.name-entry label { margin: 0 0 4px; }
.name-entry-row { display: flex; gap: 8px; align-items: center; }
.name-entry-row input { flex: 1; }
.name-entry-row button { flex: 0 0 auto; }

/* Running log - timestamped entries for high-frequency capture (weight /
   packaging check every 15 min). Older entries collapse to one line. */
.log { display: block; margin-top: 4px; }
.log-row { border: 1px solid var(--line); border-radius: 10px; margin-bottom: 8px; background: #fff; overflow: hidden; }
.log-row.open { border-color: var(--steel); box-shadow: 0 1px 6px rgba(11, 93, 78, 0.08); }
.log-head {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 14px; border: none; background: none; cursor: pointer; text-align: left;
}
.log-time { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 14.5px; color: var(--ink); flex: 0 0 auto; min-width: 44px; }
.log-summary { flex: 1; font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log-row.open .log-summary { color: var(--steel); }
.log-body { padding: 2px 14px 14px; border-top: 1px solid var(--line); }

.add-check {
  width: 100%; min-height: 52px; font-size: 15px; font-weight: 700;
  border-radius: 12px; letter-spacing: 0.01em;
}

/* A periodic check that is not due on this entry (sensory between the 30-min marks). */
.not-due {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; margin-bottom: 10px; border: 1px dashed var(--line);
  border-radius: 9px; background: var(--bg);
}
.nd-label { font-size: 13.5px; color: var(--muted); }
.nd-chip { font-size: 11.5px; font-weight: 600; color: var(--muted); background: #fff; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line); }

/* Form chooser: device scope bar + area/line grouping. */
.scope-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 14px;
  background: var(--card, #fff); border: 1px solid var(--line); border-radius: 10px;
}
.scope-loc { font-weight: 600; font-size: 14px; margin-right: auto; }
.scope-q { font-size: 15px; font-weight: 600; margin: 4px 0 12px; }
.group-h { font-size: 15px; font-weight: 700; margin: 20px 0 8px; letter-spacing: 0.01em; }
.group-line {
  font-size: 12px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--muted); margin: 10px 2px 6px;
}
.form-card { text-align: left; }

/* One card standing for a family of products (e.g. the nine packing forms). */
.group-card { border-left: 4px solid var(--line); }

/* "N more in progress on other lines" - present but not shouting. */
.elsewhere-row { margin: 6px 2px 2px; }

/* Search over every form - the reliable path on a tablet that moves around. */
.form-search { margin: 14px 0 4px; }
.form-search input {
  width: 100%;
  min-height: 48px;
  padding: 10px 14px;
  font: inherit;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #fff;
}
.form-search input:focus { outline: 2px solid var(--brand); border-color: var(--brand); }

/* Recents: a compact horizontal row, not another full-width stack. */
/* A swipeable strip on a tablet. The native horizontal scrollbar is desktop
   chrome - heavy, and on a touch screen it is not even the control you use -
   so it is hidden and replaced by snap points plus a soft right edge, which is
   what actually says "there is more this way". */
.recent-row {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;              /* Firefox */
  -ms-overflow-style: none;           /* old Edge */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.recent-row::-webkit-scrollbar { display: none; }   /* Safari / Chrome */
.recent-chip {
  flex: 0 0 auto;
  max-width: 60%;
  text-align: left;
  padding: 10px 14px;
  scroll-snap-align: start;
}
.recent-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A chip is exactly two lines: the name, then line + form code. The name was
   already clipped to one line but the meta line underneath wrapped freely, so
   at phone width a chip came out with an ellipsised title over three lines of
   code - taller than it was wide. Both lines clip now. */
.recent-chip .code { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 620px) {
  /* 60% of a ~354px content box is ~212px, which truncates almost every form
     name. The row already scrolls horizontally, so a wider chip costs nothing
     but a slightly shorter peek at the next one. */
  .recent-chip { max-width: 78%; }
}

/* "In progress": records already open on this line, so a shift picks up where
   the last one left off instead of starting a duplicate for the same day. */
.resume-card { border-left: 4px solid var(--brand); }
.resume-card.returned { border-left-color: var(--fail); }
.resume-card .pill { margin-left: 8px; vertical-align: middle; }
/* The line, next to the form name - the same form runs on several lines. */
.resume-line {
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: #eef1f0;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
  vertical-align: middle;
}
.pill-returned { background: var(--fail-bg); color: var(--fail); }
/* A draft whose production day has passed - started and never finished. */
.pill-stale { background: #fdf4e3; color: #8a5a00; }
/* Why a field is required, under the field rather than after a failed submit. */
.field-hint { margin: -4px 0 12px; font-size: 13px; color: var(--muted); }
.resume-reason { margin-top: 6px; font-size: 13px; color: var(--fail); }

/* Shown when more than one operator is on the open record. */
.shared-note {
  margin: 0 0 12px;
  padding: 8px 12px;
  border-radius: 8px;
  background: #eef1f0;
  color: var(--muted);
  font-size: 13px;
}

/* Print / save-as-PDF.
   Sticky elements land at their scroll position when a page is printed, so the
   header ends up painted over the middle of the content. Un-stick them, and
   drop the transient toast, so a saved PDF is an honest picture of the page
   (which is how these screens get reviewed when a browser is not to hand). */

/* --- QA record detail: exception-first layout ----------------------------- */
/* The reviewer's job is to find what is wrong, not to read every value. These
   rules give the verdict, the section summaries and the flags the weight, and
   push clean detail into a muted single line. */

.verdict {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 12px;
  background: var(--card);
}
.verdict-clean { border-left: 4px solid var(--pass); background: var(--pass-tint); }
.verdict-flagged { border-left: 4px solid var(--fail); background: var(--fail-tint); }

.verdict-head { display: flex; align-items: center; gap: 10px; }
.verdict-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-weight: 700;
  color: #fff;
  flex: none;
}
.verdict-clean .verdict-mark { background: var(--pass); }
.verdict-flagged .verdict-mark { background: var(--fail); }
.verdict-text { font-size: 17px; font-weight: 700; }

.verdict-facts { display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 8px 0 4px; }
.verdict-fact { font-size: 14px; color: var(--muted); }
.verdict-fact strong { font-size: 15px; }
.verdict-fact.is-pass strong { color: var(--pass); }
.verdict-fact.is-fail strong { color: var(--fail); }
.verdict-fact.is-warn strong { color: var(--warn); }
.verdict-fact.is-capa strong { color: var(--fail); }

.mode-note {
  margin-top: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--steel-tint);
  color: var(--ink);
  font-size: 13px;
}

.entries-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 18px 2px 8px;
}
.entries-label { font-size: 13px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }

/* A section is a button so the whole header row is the hit target - important on
   a tablet, where a small caret is a poor thing to aim at. */
.section-card { padding: 0; overflow: hidden; }
.section-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 14px 16px;
  background: none;
  border: none;
  border-radius: 0;
  text-align: left;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.section-toggle:hover { background: var(--paper); }
.section-toggle.open { border-bottom: 1px solid var(--line); }
.section-toggle .caret { color: var(--muted); font-size: 12px; flex: none; width: 12px; }
.section-title { font-weight: 700; font-size: 15px; }
.section-count { color: var(--muted); font-size: 13px; white-space: nowrap; }
.section-chips { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

.chip {
  font-size: 12px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.chip-pass { background: var(--pass-tint); color: var(--pass); border: 1px solid var(--pass-line); }
.chip-fail { background: var(--fail-tint); color: var(--fail); border: 1px solid var(--fail-line); }
.chip-warn { background: var(--amber-tint); color: var(--amber); border: 1px solid var(--amber); }
.chip-note { background: var(--steel-tint); color: var(--steel); border: 1px solid var(--steel-tint); }

.section-card .resp { padding: 10px 16px; }
.section-card .row-head { padding: 8px 16px 0; }

/* The satellite fields of one unit - who cleaned it, when, who verified - on one
   muted line instead of a row each. */
.unit-line {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-top: 4px;
  font-size: 13px;
}
.unit-bit { display: inline-flex; align-items: baseline; gap: 5px; }
.unit-key { color: var(--muted); }
.unit-val { color: var(--ink); font-weight: 600; }

/* A satellite promoted to its own row (flagged, or being corrected). */
.resp-sub {
  margin: 8px 0 0 14px;
  padding: 8px 0 0 12px;
  border-left: 2px solid var(--line);
}
.resp-sub-name { font-weight: 600; font-size: 13px; color: var(--muted); }

@media (max-width: 640px) {
  .section-chips { margin-left: 0; width: 100%; justify-content: flex-start; }
  .section-toggle { flex-wrap: wrap; }
}

@media print {
  .topbar,
  .navbar {
    position: static;
  }
  .toast {
    display: none;
  }
  body {
    background: #fff;
  }
}

/* --- QA search / filters -------------------------------------------------- */
.search-panel select {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
  color: var(--ink);
  font: inherit;
  min-height: 40px;
}

/* One-tap date windows above the explicit From/To pair. */
.range-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin: 10px 0 4px;
}
.range-label {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-right: 4px;
}
.chip-btn {
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  color: var(--ink);
  font-size: 13px;
  cursor: pointer;
}
.chip-btn:hover { background: var(--paper); }
.chip-btn.on {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-ink);
  font-weight: 600;
}

.result-line {
  margin: 4px 2px 10px;
  font-size: 14px;
  color: var(--muted);
}
/* A truncated result set is a correctness problem, not a detail - it gets the
   weight of a warning rather than a muted footnote. */
.result-line.truncated {
  color: var(--ink);
  font-weight: 600;
  background: var(--amber-tint);
  border-left: 3px solid var(--amber);
  padding: 7px 10px;
  border-radius: 0 8px 8px 0;
}
.result-line.truncated .reference-note { font-weight: 400; }

.empty-state {
  padding: 18px 16px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  text-align: center;
}
.empty-state p { margin: 0 0 6px; }
.empty-state .actions { justify-content: center; }

/* ==========================================================================
   Form builder (body.builder). Scoped so nothing here can reach the operator
   PWA or the QA review screen, which have their own visual language.
   ========================================================================== */
.builder .page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.builder .page-head h1 { margin: 0 0 2px; }
.builder .muted { color: var(--muted); }
.builder .hint {
  color: var(--muted);
  font-size: 0.86rem;
  margin: 4px 0 0;
}
.builder .banner-warn {
  background: var(--amber-tint);
  border-left: 4px solid var(--amber);
  padding: 10px 12px;
  border-radius: 0 8px 8px 0;
  margin: 10px 0;
}
.builder button.primary {
  background: var(--brand);
  color: var(--brand-ink);
  border-color: var(--brand);
}
.builder button.danger { color: var(--fail); }

/* Two-column layout that collapses on a narrow screen. Designers work on a
   laptop, but the QA office machines are not all wide. */
.builder .grid2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 16px;
}
.builder .grid2 > .span2 { grid-column: 1 / -1; }
@media (max-width: 720px) {
  .builder .grid2 { grid-template-columns: 1fr; }
}
.builder .sub {
  border-top: 1px solid var(--line);
  padding-top: 12px;
  margin-top: 4px;
}
.builder .sub h4 { margin: 0 0 4px; }
.builder .nested {
  margin: 8px 0 8px 24px;
  padding-left: 12px;
  border-left: 2px solid var(--line);
}
.builder label.check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-weight: 400;
  margin: 6px 0;
  cursor: pointer;
}
.builder label.check input { width: auto; margin-top: 3px; }

/* --- catalogue --- */
.builder .cat-area {
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin: 22px 0 8px;
}
.builder .cat-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.builder .cat-card.is-retired { opacity: 0.68; }
.builder .cat-card h3 { margin: 0 0 2px; }
.builder .cat-meta { color: var(--muted); font-size: 0.86rem; margin: 0 0 6px; }
.builder .cat-side { text-align: right; }
.builder .chips { display: flex; gap: 6px; flex-wrap: wrap; }
.builder .chip {
  display: inline-block;
  font-size: 0.76rem;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--muted);
}
.builder .chip-live { background: var(--pass-tint); border-color: var(--pass-line); color: var(--pass); }
.builder .chip-draft { background: var(--steel-tint); border-color: var(--steel); color: var(--steel); }
.builder .chip-retired { background: var(--paper); }
.builder .chip-bad { background: var(--fail-tint); border-color: var(--fail-line); color: var(--fail); }
.builder .chip-capa { background: var(--amber-tint); border-color: var(--amber); color: var(--amber); }

/* --- issues --- */
.builder .issue-panel.has-errors { border-left: 4px solid var(--fail); }
.builder .issue-panel h3 { margin: 10px 0 6px; font-size: 0.95rem; }
.builder ul.issues { list-style: none; padding: 0; margin: 0; }
.builder .issue {
  padding: 7px 10px;
  border-radius: 8px;
  margin-bottom: 4px;
  cursor: pointer;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.builder .issue:hover { outline: 2px solid var(--line); }
.builder .issue-error { background: var(--fail-tint); }
.builder .issue-warn { background: var(--amber-tint); }
.builder .issue-where { font-weight: 600; white-space: nowrap; }
.builder .inline-issue {
  margin: 6px 0 0;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 0.88rem;
}
.builder .inline-error { background: var(--fail-tint); color: var(--fail); }
.builder .inline-warning { background: var(--amber-tint); color: var(--amber); }

/* --- sections + fields --- */
.builder .sec-head {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  flex-wrap: wrap;
}
.builder .sec-title { font-weight: 600; font-size: 1.05rem; }
.builder .sec-caret { color: var(--muted); width: 1em; }
.builder .sec-body { margin-top: 14px; }
.builder .sec-body h3 { margin: 18px 0 8px; font-size: 0.95rem; }
.builder .sec.sec-bad { border-left: 4px solid var(--fail); }
.builder .field {
  border: 1px solid var(--line);
  border-radius: 10px;
  margin-bottom: 6px;
  background: var(--card);
}
.builder .field-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  cursor: pointer;
  flex-wrap: wrap;
}
.builder .field-head.field-bad { background: var(--fail-tint); border-radius: 10px; }
.builder .field-label { font-weight: 600; flex: 1 1 auto; min-width: 140px; }
.builder .field-body {
  padding: 4px 12px 12px;
  border-top: 1px solid var(--line);
}

/* --- preview --- */
.builder .overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 32, 43, 0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 24px 16px;
  overflow: auto;
  z-index: 50;
}
.builder .sheet {
  background: var(--bg);
  border-radius: var(--radius);
  padding: 18px;
  width: min(760px, 100%);
}
.builder .pv-field {
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.builder .pv-field:last-child { border-bottom: none; }
.builder .pv-label { font-weight: 600; margin-bottom: 6px; }
.builder .pv-label .req { color: var(--fail); }
.builder .pv-seg { display: flex; gap: 6px; }
.builder .pv-pill {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 16px;
  background: var(--card);
  color: var(--muted);
}
.builder .pv-input {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 10px;
  background: var(--card);
  color: var(--muted);
}
.builder .pv-fail {
  margin-top: 8px;
  padding: 6px 10px;
  background: var(--fail-tint);
  border-radius: 6px;
  font-size: 0.88rem;
}

/* --- builder: tabs ---------------------------------------------------------
   A tab card is a CONTAINER, never an accordion. `focusIssue` scrolls to a
   section or field by DOM id, so a collapsed tab would hide the node it is
   trying to reach; the section card inside stays the collapse unit. */
.builder .tabcard {
  border: 1px solid var(--line);
  border-left: 4px solid var(--steel);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 14px 0;
  background: var(--paper);
}
.builder .tabcard-bad { border-left-color: var(--fail); }
.builder .tab-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.builder .tab-title {
  font-weight: 600;
  font-size: 1.02rem;
  flex: 1 1 12rem;
  min-width: 0;
  padding: 6px 8px;
}
.builder .tab-head .actions { margin: 0; }
.builder .tab-sections { margin-top: 8px; }
.builder .move-to-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--muted);
}
.builder .move-to-tab select { width: auto; min-width: 8rem; }

/* The app's own Start / Review steps. Shown so the designer sees the whole
   operator sequence, greyed because they are not theirs to edit. */
.builder .step-fixed {
  border: 1px dashed var(--line);
  border-radius: 10px;
  padding: 10px 14px;
  margin: 14px 0;
  background: transparent;
  color: var(--muted);
}
.builder .step-fixed-title { font-weight: 600; }
.builder .step-fixed-hint { font-size: 0.85rem; }

/* The preview renders the REAL operator controls, so they have to be made inert
   - defence 3 of 3. Defences 1 and 2 (a cloned definition, no-op persist) are the
   ones that actually make it safe; this is what stops a designer typing into a
   preview and believing it meant something. */
.builder .pv-live { pointer-events: none; }
.builder .pv-live input,
.builder .pv-live select,
.builder .pv-live textarea,
.builder .pv-live button { pointer-events: none; }

/* Preview: the tab strip. These are real buttons - the preview steps through one
   tab at a time, the way the operator meets them. An earlier version drew the
   strip as inert spans over a single scrolling page, which both differed from the
   live screen and offered a control that looked clickable and was not. */
.builder .pv-strip {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin: 10px 0 14px;
}
.builder .pv-tab {
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.builder .pv-tab:hover { border-color: var(--brand); }
.builder .pv-tab.on { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }
/* Start / Review & submit belong to the app, not the form. */
.builder .pv-tab-fixed { color: var(--muted); border-style: dashed; font-weight: 500; }
.builder .pv-tab-fixed.on { background: var(--muted); border-color: var(--muted); color: var(--card); }
.builder .pv-appstep {
  border: 1px dashed var(--line);
  border-radius: 10px;
  padding: 16px;
  color: var(--muted);
}
.builder .pv-tabgroup { margin-top: 16px; }
.builder .pv-tabname {
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 6px;
}

/* --- builder catalogue: product families ----------------------------------
   Nine of the eleven forms are one packing workflow with a different product on
   it. They collapse behind a single card; each still keeps its own form code,
   version and content hash - only the LISTING is folded. */
.builder .cat-family { cursor: pointer; border-left: 4px solid var(--steel); }
.builder .cat-family:hover { border-color: var(--steel); }
.builder .cat-family h3 { letter-spacing: 0.01em; }
.builder .cat-family-open {
  border-left: 4px solid var(--steel);
  border-radius: 10px;
  padding-left: 10px;
  margin-bottom: 12px;
  background: var(--steel-tint);
}
.builder .cat-family-open .cat-family { border-left: none; background: transparent; }
.builder .cat-family-open .cat-card:not(.cat-family) { margin-left: 12px; }

/* A secondary action on a catalogue card - retire / reinstate sits beside Edit
   without competing with it. */
.builder .cat-side button.small { padding: 6px 12px; font-size: 0.85rem; }

/* Cleaning: the section-level defaults, above the areas they apply to. Filling
   these once is what every row then inherits. */
.operator .clean-defaults {
  border: 1px dashed var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 14px;
}
.operator .clean-defaults-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
