/* ═══════════════════════════════════════════════════════════════════════
   RAISE CALLOUT — Photo strip
   ─────────────────────────────────────────────────────────────────────
   Thumbnails match the 64×64 KB quick-entry thumb (the "notice card"
   shape the user wanted). Below the thumb, a small caption input
   styled like the KB note caption pills — bg-elevated, radius-sm,
   compact font. Annotate + remove are corner icon buttons on the thumb.
   ═══════════════════════════════════════════════════════════════════════ */
.callout-form-photos-hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin: -2px 0 8px;
  line-height: 1.4;
}
.callout-form-photos-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 10px;
}
.callout-form-photos-grid:empty { display: none; }

.callout-form-photo-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 86px;
}
.callout-form-photo-thumb-wrap {
  position: relative;
  width: 86px;
  height: 86px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
}
.callout-form-photo-thumb-wrap img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.callout-form-photo-btn {
  position: absolute;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, 0.65);
  border: none;
  color: #fff;
  border-radius: var(--radius-full);
  cursor: pointer;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s, transform 0.12s;
}
.callout-form-photo-btn:hover { background: rgba(0, 0, 0, 0.85); }
.callout-form-photo-btn:active { transform: scale(0.92); }
.callout-form-photo-btn svg { width: 12px; height: 12px; }
.callout-form-photo-annot  { top: 4px; left:  4px; }
.callout-form-photo-remove { top: 4px; right: 4px; }
/* annotation-count badge → shared .ah-annot-badge.is-thumb (Prompt 106) */

.callout-form-photo-caption {
  width: 100%;
  font-family: inherit;
  font-size: 11px;
  padding: 5px 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  transition: border-color 0.12s;
  min-width: 0;
}
.callout-form-photo-caption:focus {
  outline: none;
  border-color: var(--accent);
}
.callout-form-photo-caption::placeholder { color: var(--text-muted); }

.callout-form-photo-add {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 8px 12px;
  background: var(--bg-elevated);
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s;
  -webkit-tap-highlight-color: transparent;
}
.callout-form-photo-add:not(:disabled):hover {
  border-color: var(--accent);
  color: var(--accent);
}
.callout-form-photo-add:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.callout-form-photo-add svg { width: 14px; height: 14px; }

/* ═══════════════════════════════════════════════════════════════════════
   CALLOUT DETAIL — Quick-action chip row
   ─────────────────────────────────────────────────────────────────────
   Four compact entry points (Note / Photo / File / Cost) wedged between
   the header meta chips and the tab bar. Each chip jumps to its tab
   AND opens the matching composer in one tap — so field staff don't
   have to swipe through tabs hunting for the right button.
   ═══════════════════════════════════════════════════════════════════════ */
.callout-detail-quick-actions {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 6px;
  margin: 12px 0 6px;
}
/* Calm, neutral utility tiles (match the Projects "Add to plan" type buttons):
   they recede until needed — colour lives only on the icon as a signpost — so
   they never compete with the priority / status / SLA signals above. Five fit
   one row; works in both themes via neutral foundation vars. */
.callout-detail-quick-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 10px 3px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.15;
  text-align: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s, transform 0.1s;
  -webkit-tap-highlight-color: transparent;
  min-width: 0;
}
.callout-detail-quick-chip svg {
  width: 18px; height: 18px;
  stroke-width: 2;
  color: var(--accent);
}
.callout-detail-quick-chip:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
  color: var(--text-primary);
}
.callout-detail-quick-chip:active { transform: scale(0.96); }

/* Book-visit modal */
.callout-visit-hint {
  margin: 0 0 14px; font-size: 12.5px; line-height: 1.45; color: var(--text-secondary);
}
.callout-visit-fields {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px;
}
/* Style the field labels (a <span>) + date/time/textarea inputs, which the base
   .callout-form-field rules (css/12) don't cover for date/time types. Scoped to
   this modal so nothing else shifts. */
.callout-visit-modal .callout-form-field > span {
  font-size: var(--text-sm); font-weight: 600; color: var(--text-secondary);
}
.callout-visit-modal .callout-form-field > span em {
  font-weight: 500; font-style: normal; color: var(--text-muted);
}
.callout-visit-modal input,
.callout-visit-modal textarea {
  font-family: inherit; font-size: var(--text-base); color: var(--text-primary);
  width: 100%; box-sizing: border-box;
  padding: 10px 12px; background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  transition: border-color 0.12s, background 0.12s;
}
.callout-visit-modal input:focus,
.callout-visit-modal textarea:focus {
  outline: none; border-color: var(--accent); background: var(--bg-surface);
}

/* Booked-visits list on the callout detail (edit / cancel each one) */
.callout-detail-visits {
  margin: 12px 0 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  overflow: hidden;
}
.callout-detail-visits-head {
  font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--text-muted); padding: 10px 12px 6px;
}
.callout-visit-row {
  /* Two stacked zones: a top line (date/note + the small edit·cancel icons in
     the top-right corner) and a foot holding the primary Mark-attended button,
     right-aligned (Radek 2026-07-03). */
  display: flex; flex-direction: column; gap: 10px;
  padding: 9px 12px; border-top: 1px solid var(--border);
}
.callout-visit-row.is-past { opacity: 0.6; }
.callout-visit-row-top { display: flex; align-items: center; gap: 10px; }
.callout-visit-row-foot { display: flex; justify-content: flex-end; }
.callout-visit-row-icon { flex: 0 0 auto; display: inline-flex; color: var(--accent); }
.callout-visit-row-icon svg { width: 18px; height: 18px; }
.callout-visit-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.callout-visit-row-when { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); white-space: nowrap; }
.callout-visit-row-note {
  font-size: var(--text-xs); color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Edit + cancel icons — pinned to the top-right corner of the visit card
   (pushed there by margin-left:auto inside .callout-visit-row-top). */
.callout-visit-row-acts { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.callout-visit-row-act {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  background: transparent; border: 1px solid var(--border);
  border-radius: var(--radius-sm); color: var(--text-secondary);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.callout-visit-row-act svg { width: 15px; height: 15px; }
.callout-visit-row-act:hover { border-color: var(--accent); color: var(--accent); }
.callout-visit-row-act.is-danger:hover {
  border-color: var(--danger); color: var(--danger); background: var(--danger-soft);
}
.callout-visit-row-act.is-go:hover {
  border-color: #16a34a; color: #16a34a; background: rgba(22,163,74,0.08);
}
/* Attended (done) visit — green check + calm "Attended" tag, no actions. */
.callout-visit-row.is-attended .callout-visit-row-icon { color: #16a34a; }
.callout-visit-row.is-attended .callout-visit-row-when { color: var(--text-secondary); }
.callout-visit-attended-tag {
  flex: 0 0 auto; font-size: var(--text-xs); font-weight: 700;
  letter-spacing: 0.02em; text-transform: uppercase;
  color: #16a34a; background: rgba(22,163,74,0.10);
  border: 1px solid rgba(22,163,74,0.30);
  padding: 4px 9px; border-radius: 999px; white-space: nowrap;
}
/* Labelled attend toggle — replaces the old bare tick (unclear on its own).
   Styled as a compact FUNCTION button to match the timeline "Mark en route /
   Mark on site" CTA (.callout-detail-big-cta): accent-filled, radius-md, so it
   reads unmistakably as an action. Off = accent "Mark attended"; on = green
   "Attended" you can tap to undo an accidental mark. Same size in both states. */
.callout-visit-attend-btn {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: var(--radius-md);
  background: var(--accent); border: 1px solid var(--accent);
  color: #fff; font-size: var(--text-sm); font-weight: 600;
  white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: filter 0.12s, background 0.12s, border-color 0.12s;
}
.callout-visit-attend-btn svg { width: 15px; height: 15px; }
.callout-visit-attend-btn:hover { filter: brightness(1.08); }
.callout-visit-attend-btn.is-on {
  background: #16a34a; border-color: #16a34a; color: #fff;
}
.callout-visit-attend-btn.is-on:hover { filter: brightness(1.06); }

@media (max-width: 380px) {
  /* Five tiles on a narrow phone — trim the label + icon so they sit on one row. */
  .callout-detail-quick-chip { font-size: 10px; padding: 9px 2px; gap: 4px; }
  .callout-detail-quick-chip svg { width: 16px; height: 16px; }
}

/* ─── Asset detail tab bar + panels ─── */
/* Split primary-action row: [Add task] [Log service] */
.asset-primary-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 12px;
}
.asset-primary-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 12px 10px;
  border: none;
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 700;
  cursor: pointer;
  transition: filter 0.12s, transform 0.08s, border-color 0.12s, color 0.12s;
}
.asset-primary-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
.asset-primary-btn:hover  { filter: brightness(1.08); }
.asset-primary-btn:active { transform: scale(0.98); }
/* Add task — accent fill (everyday action for all staff) */
.asset-primary-btn--task {
  background: var(--accent);
  color: #001317;
}
/* Log service — outlined secondary (engineer-only action) */
.asset-primary-btn--service {
  background: var(--bg-elevated);
  color: var(--text-primary);
  border: 1.5px solid var(--border-strong);
  filter: none;
}
.asset-primary-btn--service:hover {
  border-color: var(--accent);
  color: var(--accent);
  filter: none;
}
/* If only one button is rendered, stretch it full-width */
.asset-primary-actions:has(:only-child) {
  grid-template-columns: 1fr;
}

.asset-tab-panel { padding: 0; }
.asset-tab-panel + .asset-tab-panel { margin-top: 0; }

/* Asset files grid in Documents tab */
.asset-files-section {
  margin-top: 20px;
}
.asset-files-title {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 10px;
}
/* File rows — chip-first row matching the Tasks/Callouts document lists
   (was a square gallery tile). Photos still use the gallery grid above. */
.asset-files-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.asset-file-tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  cursor: pointer;
  transition: border-color 0.12s;
}
.asset-file-tile:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.asset-file-tile .callout-doc-type { flex-shrink: 0; }
.asset-file-tile-name {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
}
.asset-file-del {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.asset-file-del:hover { background: var(--bg-elevated); color: #ef4444; }
.asset-file-del svg { width: 18px; height: 18px; }
.asset-file-tile.is-uploading { opacity: 0.55; cursor: default; pointer-events: none; }
.asset-file-tile-uploading { font-size: var(--text-xs); color: var(--text-muted); flex-shrink: 0; }

/* Asset cost lines in Costs tab */
.asset-costs-section { margin-bottom: 20px; }
.asset-costs-section-title {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 10px;
}
/* Cost entries that originate from a linked task / callout: clickable, with a
   source badge so it's obvious where the money came from. */
.callout-costs-row.is-clickable { cursor: pointer; transition: background 0.12s; }
.callout-costs-row.is-clickable:hover {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.asset-cost-source {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 7px 1px 5px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
  background: var(--accent-soft);
  color: var(--accent);
  white-space: nowrap;
}
.asset-cost-source svg { width: 11px; height: 11px; flex-shrink: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   CALLOUT DETAIL — additional polish
   ─────────────────────────────────────────────────────────────────────
   - Undo chevron next to the next-step button
   - Empty-contractor chip (clickable "Assign contractor")
   - Timeline composer photo strip + photo thumbnails in event rows
   ═══════════════════════════════════════════════════════════════════════ */
.callout-detail-undo {
  width: 36px; height: 36px;
  display: inline-grid; place-items: center;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  margin-right: 6px;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.12s, color 0.12s, background 0.12s, transform 0.1s;
}
.callout-detail-undo:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.callout-detail-undo:active { transform: scale(0.94); }
.callout-detail-undo svg { width: 18px; height: 18px; }

/* Timeline composer photo strip + thumbnails — same 86px size as the
   raise form so users learn one shape. */
.callout-timeline-composer-photos {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}
.callout-timeline-composer-photos:empty { display: none; }
.callout-timeline-photo-tile {
  position: relative;
  width: 64px; height: 64px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
}
.callout-timeline-photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.callout-timeline-photo-btn {
  position: absolute;
  width: 18px; height: 18px;
  display: grid; place-items: center;
  background: rgba(0,0,0,0.7);
  border: none;
  color: #fff;
  border-radius: var(--radius-full);
  cursor: pointer;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}
.callout-timeline-photo-btn:hover { background: rgba(0,0,0,0.9); }
.callout-timeline-photo-annot  { top: 3px; left: 3px; }
.callout-timeline-photo-remove { top: 3px; right: 3px; }
.callout-timeline-photo-badge {
  position: absolute;
  bottom: 3px; right: 3px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  background: var(--accent);
  border-radius: var(--radius-full);
  display: inline-flex; align-items: center; justify-content: center;
}

.callout-timeline-composer-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 8px;
}
.callout-timeline-composer-attach {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 7px 10px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.callout-timeline-composer-attach:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.callout-timeline-composer-attach svg { width: 14px; height: 14px; }

/* Photo thumb embedded in timeline event row — opens a viewer on click. */
.callout-event-photo {
  position: relative;
  display: inline-block;
  margin-top: 6px;
  width: 96px; height: 96px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  padding: 0;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.callout-event-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* annotation-count badge → shared .ah-annot-badge.is-thumb (Prompt 106) */

/* ═══════════════════════════════════════════════════════════════════════
   CALLOUT DETAIL — Meta row (contractor + asset cards)
   ─────────────────────────────────────────────────────────────────────
   Two half-width cards side by side. When empty they invite the user to
   fill them in (dashed border, icon + label). When set they collapse
   to the existing chip style. Mirrors the half-screen card pattern from
   the Raise Callout form.
   ═══════════════════════════════════════════════════════════════════════ */
.callout-detail-meta-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 10px 0 6px;
}
.callout-detail-meta-cell { min-width: 0; }
.callout-detail-meta-cell:empty { display: none; }
/* The contractor & asset cards now use the shared Tasks info-tile
   (.tasks-detail-info-tile) so they match the Tasks detail 1:1 — same icon,
   stacked label/value, pencil → Change/Remove modal. Make each tile fill its
   half-width grid cell and hold an even min-height across the row. */
.callout-detail-meta-cell > .tasks-detail-info-tile { width: 100%; min-height: 44px; }
/* Removed-asset name renders muted/italic even inside the accent-tinted
   is-active tile (override the active value colour). */
.callout-detail-meta-cell .tasks-detail-info-tile.is-active .tasks-detail-info-tile-value.is-stale {
  color: var(--text-muted);
  font-style: italic;
}
/* Slim contractor sub-line: tap-to-call phone and/or named contact, stacked
   under the contractor name inside the tile body. */
.callout-tile-phone,
.callout-tile-subline {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 3px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  font-weight: 600;
}
.callout-tile-phone { color: var(--accent); text-decoration: none; }
.callout-tile-phone svg { width: 12px; height: 12px; flex-shrink: 0; }
.callout-tile-phone span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.callout-tile-subline { color: var(--text-muted); font-weight: 500; }
/* (Free-text contractor static-body styling is now global in css/05-tasks.css
   — .tasks-detail-info-tile-click.is-static.) */

/* Watchers row — the few people kept in the loop. Small round avatar circles
   (like the chat on-duty strip) that overlap slightly, plus a dashed + to add.
   Milestone updates ping only these people; view-only users just see the faces. */
.callout-detail-watchers {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 4px 0 6px;
}
.callout-detail-watchers-label {
  font: 600 var(--text-xs)/1 var(--body);
  color: var(--text-secondary);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  flex-shrink: 0;
}
.callout-detail-watchers-avatars { display: flex; align-items: center; min-width: 0; }
.callout-watcher-av {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #fff;
  font: 700 11px/1 var(--body);
  background: var(--wav, var(--accent));
  border: 2px solid var(--bg-surface);
  margin-left: -8px;
  flex-shrink: 0;
  user-select: none;
}
.callout-watcher-av:first-child { margin-left: 0; }
.callout-watcher-av.is-removable { cursor: pointer; transition: transform 0.08s ease; }
.callout-watcher-av.is-removable:hover { transform: translateY(-1px); }
.callout-watcher-add {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  margin-left: 6px;
  flex-shrink: 0;
  background: var(--bg-elevated);
  border: 1px dashed var(--border);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.callout-watcher-add:first-child { margin-left: 0; }
.callout-watcher-add:hover { background: var(--bg-surface); color: var(--accent); border-color: var(--accent); }
.callout-watcher-add svg { width: 16px; height: 16px; }
.callout-watcher-empty {
  font: 500 var(--text-xs)/1.3 var(--body);
  color: var(--text-muted);
  margin-left: 8px;
}

/* Very tiny phones only: stack the cards vertically. iPhone SE / mini
   (375 wide) and up keep the side-by-side layout the user requested. */
@media (max-width: 320px) {
  .callout-detail-meta-row { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════════
   CALLOUT DETAIL — Lifecycle stepper + big CTA + visible Hold/Cancel
   ─────────────────────────────────────────────────────────────────────
   New header anatomy:
     Back · Ref · Priority · [Edit pencil] [More]
     Title
     [Stepper: 1 → 2 → 3 → 4 → 5]
     SLA · Xh Ym left              [Hold] [Cancel]
     [Contractor card] [Asset card]
     [Cost summary]
     [Note] [Photo] [File] [£ Cost]
     [ ↩ ]  [ ✓ Big Mark complete CTA ]
     ─── Tabs ───
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── Edit pencil icon — matches the Tasks .tasks-icon-btn look:
   32×32 square, transparent fill, delicate 1px border, muted glyph. ─── */
.callout-detail-edit {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s, color 0.12s, transform 0.12s;
}
.callout-detail-edit:hover { background: var(--bg-elevated); color: var(--text-primary); }
.callout-detail-edit:active { transform: scale(0.94); }
.callout-detail-edit svg { width: 20px; height: 20px; stroke-width: 2; }
/* Close button inside callout header matches the same 40×40 footprint */
.callout-detail-header .tasks-modal-close { width: 40px; height: 40px; }
.callout-detail-header .tasks-modal-close svg { width: 20px; height: 20px; }
/* Delete variant — same shape, red tint on hover to signal danger */
.callout-detail-delete:hover {
  background: color-mix(in srgb, #ef4444 8%, var(--bg-surface));
  color: #ef4444;
  border-color: color-mix(in srgb, #ef4444 40%, transparent);
}

/* ─── 5-step stepper ─── */
.callout-stepper {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0;
  margin: 14px 0 6px;
  padding: 0 4px;
}
.callout-stepper.is-muted { opacity: 0.45; }

.callout-stepper-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  min-width: 0;
}
.callout-stepper-dot {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  font-size: 12px;
  font-weight: 700;
  border-radius: var(--radius-full);
  background: var(--bg-elevated);
  border: 2px solid var(--border-strong);
  color: var(--text-muted);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.callout-stepper-label {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-muted);
  text-align: center;
  letter-spacing: 0.01em;
  line-height: 1.15;
  max-width: 60px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.callout-stepper-line {
  flex: 1;
  height: 2px;
  background: var(--border-strong);
  margin-top: 13px;
  min-width: 8px;
}

.callout-stepper-step.is-complete .callout-stepper-dot {
  background: rgb(22,163,74);
  border-color: rgb(22,163,74);
  color: #fff;
}
.callout-stepper-step.is-complete .callout-stepper-label {
  color: rgb(22,163,74);
}
.callout-stepper-step.is-active .callout-stepper-dot {
  background: var(--bg-base);
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.callout-stepper-step.is-active .callout-stepper-label {
  color: var(--accent);
  font-weight: 700;
}

.callout-stepper-banner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: var(--text-sm);
  pointer-events: none;
  border-radius: var(--radius-md);
}
.callout-stepper-banner.is-hold     { color: #b45309; background: rgba(180,83,9,0.10); }
.callout-stepper-banner.is-cancelled { color: #dc2626; background: rgba(220,38,38,0.10); }

/* ─── Footer row beneath the stepper (SLA · Hold/Cancel chips) ─── */
.callout-stepper-footer {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin-bottom: 8px;
  align-items: stretch;
}
.callout-stepper-footer-left {
  grid-column: 1 / 3;
  display: flex;
  align-items: center;
  min-width: 0;
}

.callout-stepper-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 9px 4px 8px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  min-width: 56px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.12s, color 0.12s, background 0.12s, transform 0.1s;
}
.callout-stepper-chip:active { transform: scale(0.96); }
.callout-stepper-chip svg { width: 18px; height: 18px; stroke-width: 2; }
.callout-stepper-chip.is-hold   { color: #ea580c; border-color: rgba(234,88,12,0.45); background: rgba(234,88,12,0.08); }
.callout-stepper-chip.is-hold:hover { border-color: #ea580c; background: rgba(234,88,12,0.15); }
.callout-stepper-chip.is-cancel { color: #dc2626; border-color: rgba(220,38,38,0.45); background: rgba(220,38,38,0.08); }
.callout-stepper-chip.is-cancel:hover { border-color: #dc2626; background: rgba(220,38,38,0.15); }
.callout-stepper-chip.is-resume        { border-color: rgb(22,163,74); color: rgb(22,163,74); }
.callout-stepper-chip.is-resume:hover  { background: rgba(22,163,74,0.10); }

/* ─── Big bottom-of-header CTA — mirrors .tasks-detail-complete-btn ─── */
.callout-detail-big-cta-row {
  display: flex;
  align-items: center;
  /* Tuck the advance/complete action to the RIGHT as a compact button — the
     same "action tucked right, not a full-width bar" pattern the Tasks detail
     adopted (css/05:1500, Radek 2026-06-29). The 5-dot stepper above already
     carries the progress story, so the button no longer needs to dominate. */
  justify-content: flex-end;
  gap: 8px;
  margin: 8px 0 12px;
}
.callout-detail-big-cta-row .callout-detail-undo {
  margin-right: 0;
  height: auto;
  align-self: center;
}
.callout-detail-big-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* Compact, auto-width — matches the Tasks compact complete button
     (.tasks-detail-chips .tasks-detail-complete-btn: text-sm/600, ~7-8px pad). */
  width: auto;
  padding: 8px 16px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  letter-spacing: 0;
  -webkit-tap-highlight-color: transparent;
  transition: filter 0.12s, transform 0.05s;
}
.callout-detail-big-cta:hover { filter: brightness(1.08); }
.callout-detail-big-cta:active { transform: scale(0.99); }
.callout-detail-big-cta svg { width: 16px; height: 16px; flex-shrink: 0; }

@media (max-width: 380px) {
  /* Narrow phones: tighten the stepper spacing so the 5 dots still fit. */
  .callout-stepper-label { font-size: 10px; max-width: 52px; }
  .callout-stepper-dot { width: 24px; height: 24px; font-size: 11px; }
  .callout-stepper-line { margin-top: 11px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   CALLOUT COSTS — Row hover affordance + detail modal styles
   ─────────────────────────────────────────────────────────────────────
   Rows are now interactive (whole-row tap opens the detail modal).
   Edit + Delete + Approve are inside the modal so the list view stays
   uncluttered.
   ═══════════════════════════════════════════════════════════════════════ */
.callout-costs-row {
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, transform 0.1s;
  -webkit-tap-highlight-color: transparent;
}
.callout-costs-row:hover {
  border-color: var(--accent);
}
.callout-costs-row:active { transform: scale(0.997); }
.callout-costs-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ─── Cost detail modal body ─── */
.callout-cost-view {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.callout-cost-view-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.callout-cost-view-desc {
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--text-primary);
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.callout-cost-view-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.callout-cost-view-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.callout-cost-view-label {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.callout-cost-view-value {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
  text-align: right;
}
.callout-cost-view-file {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--accent);
  font-size: var(--text-sm);
  text-decoration: none;
  font-weight: 600;
}
.callout-cost-view-file svg { width: 14px; height: 14px; }
.callout-cost-view-file:hover { text-decoration: underline; }

/* ─── Tappable completed stepper dots — revert path ─── */
button.callout-stepper-step {
  /* Reset button defaults so it behaves like the surrounding flex item. */
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.1s;
}
button.callout-stepper-step.is-tappable .callout-stepper-dot {
  cursor: pointer;
  transition: background 0.12s, transform 0.1s, box-shadow 0.15s;
}
button.callout-stepper-step.is-tappable:hover .callout-stepper-dot {
  box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.18);
}
button.callout-stepper-step.is-tappable:active .callout-stepper-dot { transform: scale(0.92); }

/* The CTA row no longer holds an undo chevron — drop the gap padding
   that was there for two children, and let the button fill the row. */
.callout-detail-big-cta-row .callout-detail-undo { display: none; }

/* ═══════════════════════════════════════════════════════════════════════
   PHOTO VIEWER — Shared lightbox styles
   ─────────────────────────────────────────────────────────────────────
   Full-screen black overlay with the image centred. Caption + actions
   in a footer bar. Honours iOS safe-areas so the close X is reachable
   and the actions row stays above the home indicator.
   ═══════════════════════════════════════════════════════════════════════ */
.photo-viewer-overlay {
  position: fixed;
  inset: 0;
  /* Above the callout / asset / engineer detail overlays (8500) so the
     lightbox renders ON TOP, not behind. Keep below the 9999 toast
     layer so toast notifications can still surface above. */
  z-index: 9000;
  background: rgba(0, 0, 0, 0.92);
  opacity: 0;
  transition: opacity 0.18s;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  touch-action: none;
}
.photo-viewer-overlay.is-open { opacity: 1; }
body.photo-viewer-open { overflow: hidden; }

/* ── Shared in-app DOC VIEWER (ui/doc-viewer.js) ──────────────────────
   PDF files open here, in-app, instead of an unreliable new browser tab.
   Images route to the photo viewer above; Office files use the download
   card (.doc-dl-*, built on the .callout-modal shell). */
.doc-viewer-overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;                 /* same layer as the photo viewer */
  background: rgba(0, 0, 0, 0.92);
  opacity: 0;
  transition: opacity 0.18s;
  display: flex;
  flex-direction: column;
}
.doc-viewer-overlay.is-open { opacity: 1; }
body.doc-viewer-open { overflow: hidden; }
.doc-viewer-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 10px 14px 18px;
  /* Full-screen doc viewer → clear the status bar robustly (see --safe-top). */
  padding-top: var(--safe-top);
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.doc-viewer-name {
  flex: 1;
  min-width: 0;
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-viewer-acts { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.doc-viewer-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}
.doc-viewer-btn:hover { background: var(--bg-elevated); color: var(--text-primary); }
.doc-viewer-btn svg { width: 22px; height: 22px; }
.doc-viewer-body { flex: 1; min-height: 0; }
.doc-viewer-frame { width: 100%; height: 100%; border: 0; background: #fff; }

/* Download card for non-previewable files (Word/Excel/CSV/…) */
.doc-dl-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.doc-dl-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
}
.doc-dl-ico svg { width: 24px; height: 24px; }
.doc-dl-meta { min-width: 0; }
.doc-dl-name {
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-dl-sub { font-size: var(--text-sm); color: var(--text-muted); margin-top: 2px; }
.doc-dl-note { font-size: var(--text-sm); color: var(--text-secondary); margin: 14px 0; }
.doc-dl-action {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 12px;
  background: var(--accent);
  color: var(--bg-base);
  border-radius: var(--radius-md);
  font-family: var(--body);
  font-weight: 600;
  text-decoration: none;
}
.doc-dl-action:hover { filter: brightness(1.05); }
.doc-dl-action svg { width: 18px; height: 18px; }

/* ── Photo viewer top bar — exact match of .kb-reader-header ── */
.pv-header {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 14px 10px 14px 18px;
  /* Full-screen photo viewer → clear the status bar robustly (see --safe-top). */
  padding-top: var(--safe-top);
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface);
  flex-shrink: 0;
  position: relative;
  z-index: 2;
}
.pv-header-counter {
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-secondary);
  margin-right: auto; /* pushes action icons to the right */
  padding-left: 4px;
}
/* Bump icon tap targets to Apple's 44pt minimum on mobile */
@media (max-width: 640px) {
  .pv-header { padding: 10px 6px 10px 14px; padding-top: var(--safe-top); }
  .pv-header .kb-reader-action { width: 44px; height: 44px; }
}

/* ── (legacy) floating glass buttons — kept for any remaining usages ── */
.pv-top-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  pointer-events: auto;
}
/* 40×40 rounded-square glass button — matches .kb-lightbox-close footprint */
.pv-top-btn {
  width: 40px; height: 40px;
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.10);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #fff;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.14s, color 0.14s, transform 0.1s, border-color 0.14s;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.pv-top-btn svg { width: 18px; height: 18px; stroke-width: 2.2; }
.pv-top-btn:hover {
  background: rgba(255, 255, 255, 0.22);
  border-color: rgba(255, 255, 255, 0.30);
}
.pv-top-btn:active { transform: scale(0.92); }
/* Delete button turns red on hover */
.pv-top-btn.danger:hover {
  background: rgba(220, 38, 38, 0.30);
  border-color: rgba(220, 38, 38, 0.50);
  color: #f87171;
}

.photo-viewer-stage {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding-bottom: env(safe-area-inset-bottom); /* keep image above home indicator */
}
.photo-viewer-stage.pv-loading::after {
  content: '';
  position: absolute;
  width: 32px; height: 32px;
  border: 3px solid rgba(255,255,255,0.2);
  border-top-color: rgba(255,255,255,0.8);
  border-radius: 50%;
  animation: pv-spin 0.7s linear infinite;
}
@keyframes pv-spin { to { transform: rotate(360deg); } }
.photo-viewer-img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
  transition: transform 0.18s cubic-bezier(0.32, 0.72, 0, 1);
  transform-origin: center center;
  will-change: transform;
}
.photo-viewer-annot-layer {
  position: absolute;
  /* Match the stage's bottom safe-area pad so this layer shares the IMAGE's
     box (and therefore its centre). The image is centred in the stage's
     CONTENT box — shrunk by padding-bottom: env(safe-area-inset-bottom) — so
     an inset:0 layer would centre ~safe-area/2 lower. With different centres,
     scaling the photo and this overlay by the same factor pivots them around
     different points and the annotations drift off the photo when zoomed on
     iOS. Sharing the bottom inset keeps both centres identical → zero drift.
     On desktop env() is 0, so this is identical to inset:0 (no behaviour change). */
  top: 0;
  left: 0;
  right: 0;
  bottom: env(safe-area-inset-bottom);
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.18s cubic-bezier(0.32, 0.72, 0, 1);
  transform-origin: center center;
}
.photo-viewer-annot-layer .kb-annot-svg-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ── Photo hero — shared photo-first banner at the top of a detail view
   (Asset register, Tasks, Call-outs). Big cover image; tap opens the shared
   swipeable photo viewer. Rendered only when there's a cover photo. Markup in
   ui/photo-hero.js (AngelHubUI.photoHero). */
.photo-hero {
  position: relative;
  display: block;
  width: 100%;
  margin: 0 0 14px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  background: var(--bg-elevated);
  aspect-ratio: 16 / 10;
  max-height: 360px;
}
.photo-hero:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Swipeable track — native horizontal scroll-snap (momentum on touch, trackpad
   on desktop). One slide per view; each photo crops to the same frame so the
   banner height never jumps. */
.photo-hero-track {
  position: absolute;
  inset: 0;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* No CSS scroll-behavior:smooth — finger-swipes stay native/instant; only the
     arrow/dot button-nav animates (wirePhotoHero passes behavior:'smooth'). */
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.photo-hero-track::-webkit-scrollbar { display: none; }
.photo-hero-slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  /* Anchor the per-slide annotation badge (Prompt 105) to THIS slide so it
     scrolls with the track — without it the abs badge escapes to .photo-hero
     and every slide's badge stacks at the hero's top-left. */
  position: relative;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  /* Neutral placeholder while a lazy slide (P32) loads — theme-aware, covered
     the instant the object-fit:cover image paints, so there's no layout jump. */
  background: var(--bg-elevated);
}
.photo-hero img,
.photo-hero-slide img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-hero-expand {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border-radius: 8px;
  pointer-events: none;
}
.photo-hero-expand svg { width: 18px; height: 18px; }
.photo-hero-count {
  position: absolute;
  left: 10px;
  bottom: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border-radius: 999px;
  font: 600 12px / 1 var(--body);
}
.photo-hero-count svg { width: 13px; height: 13px; }
/* Annotation-awareness badge (Prompt 105) — a calm top-left chip flagging that
   THIS slide's photo carries vector annotations (which draw only in the
   full-screen viewer). Same dark-scrim/white family as the rest of the hero
   chrome, so it reads as calm context in BOTH themes (§4), never an act-now
   signal. Icon + honest count; pointer-events:none so it never interferes with
   the swipe-vs-tap detection in wirePhotoHero. */
.ah-annot-badge {
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border-radius: 999px;
  font: 600 var(--text-xs) / 1 var(--body);
  pointer-events: none;
}
.ah-annot-badge svg { width: 13px; height: 13px; }
/* Compact variant for small photo TILES/DECKS (~60–96px) — the ONE annotation
   badge everywhere (Prompt 106): same calm dark-scrim/white chip + highlighter
   icon, trimmed so it never crowds a thumbnail. Default corner = bottom-right;
   `at-bl` / `at-tr` move it clear of a surface's own action buttons. Replaces
   the six retired per-module badges (tasks strip / photo-capture deck / callout
   + asset photo tiles / engineer-form deck / timeline row / engineer-visit
   fault tile) — one visual truth, no parallel styles (§3). */
.ah-annot-badge.is-thumb {
  left: auto; top: auto;
  right: 5px; bottom: 5px;
  gap: 3px;
  padding: 2px 6px;
  border-radius: var(--radius-md);
}
.ah-annot-badge.is-thumb svg { width: 11px; height: 11px; }
.ah-annot-badge.is-thumb.at-bl { right: auto; left: 5px; }
.ah-annot-badge.is-thumb.at-tr { bottom: auto; top: 5px; }
/* Dot indicators (≤8 photos) — active dot stretches to a pill. */
.photo-hero-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 10px;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: 6px;
  pointer-events: none;
}
.photo-hero-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.55);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  pointer-events: auto;
  transition: width 0.2s ease, background 0.2s ease;
}
.photo-hero-dot.is-active { width: 18px; background: #fff; }
/* "1 / N" counter when there are too many photos for dots. */
.photo-hero-counter {
  position: absolute;
  left: 10px;
  bottom: 10px;
  z-index: 2;
  padding: 4px 9px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border-radius: 999px;
  font: 600 12px / 1 var(--body);
}
/* Prev / next arrows — desktop hover affordance (touch uses the swipe). */
.photo-hero-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.photo-hero-arrow:hover { background: rgba(0, 0, 0, 0.7); }
.photo-hero-arrow svg { width: 20px; height: 20px; }
.photo-hero-prev { left: 10px; }
.photo-hero-next { right: 10px; }
.photo-hero-arrow.is-hidden { opacity: 0 !important; pointer-events: none !important; }
@media (hover: hover) {
  .photo-hero:hover .photo-hero-arrow,
  .photo-hero:focus-within .photo-hero-arrow { opacity: 1; pointer-events: auto; }
}

.photo-viewer-close,
.photo-viewer-prev,
.photo-viewer-next {
  position: absolute;
  background: rgba(0, 0, 0, 0.55);
  border: none;
  color: #fff;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--radius-full);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s, transform 0.1s;
  z-index: 2;
}
.photo-viewer-close:hover,
.photo-viewer-prev:hover,
.photo-viewer-next:hover { background: rgba(0, 0, 0, 0.85); }
.photo-viewer-close:active,
.photo-viewer-prev:active,
.photo-viewer-next:active { transform: scale(0.94); }
.photo-viewer-prev:disabled,
.photo-viewer-next:disabled { opacity: 0.35; cursor: not-allowed; }

.photo-viewer-close {
  /* Full-screen photo viewer → clear the status bar robustly (see --safe-top). */
  top: var(--safe-top);
  right: 14px;
}
.photo-viewer-prev { left:  14px; top: 50%; transform: translateY(-50%); }
.photo-viewer-next { right: 14px; top: 50%; transform: translateY(-50%); }
.photo-viewer-prev:active { transform: translateY(-50%) scale(0.94); }
.photo-viewer-next:active { transform: translateY(-50%) scale(0.94); }
/* Prev / next arrows show on every viewport, mobile included (swipe still
   works alongside) — tappable arrows are clearer than swipe-only on phones. */

.photo-viewer-footer {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: 48px 16px max(16px, calc(env(safe-area-inset-bottom) + 12px));
  background: linear-gradient(to top, rgba(0, 0, 0, 0.75), transparent);
  z-index: 2;
  pointer-events: none; /* caption is read-only; taps fall through to the stage */
}
.photo-viewer-caption {
  color: #fff;
  font-size: var(--text-sm);
  font-weight: 500;
  text-align: center;
  line-height: 1.4;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}
.photo-viewer-actions {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.photo-viewer-zoom-btn {
  width: 36px; height: 36px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.25);
  color: #fff;
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: 18px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s, transform 0.1s;
}
.photo-viewer-zoom-btn:hover { background: rgba(255, 255, 255, 0.22); }
.photo-viewer-zoom-btn:active { transform: scale(0.94); }
.photo-viewer-annotate {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 8px 14px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: filter 0.12s, transform 0.1s;
}
.photo-viewer-annotate:hover { filter: brightness(1.1); }
.photo-viewer-annotate:active { transform: scale(0.96); }

/* ─── Shared photo viewer adopts the KB capture-lightbox header style ───
   Same look across every full-screen photo view in the app (Callouts,
   Assets, Tasks etc.). Mirrors the unscoped .kb-lightbox-action rules
   so the buttons feel native to the photo-viewer-overlay surface too. */
.photo-viewer-overlay .kb-lightbox-actions {
  display: inline-flex;
  gap: 8px;
  pointer-events: auto;
  margin-left: auto;
  margin-right: 10px;
}
.photo-viewer-overlay .kb-lightbox-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px 8px 11px;
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--radius-md);
  color: #fff;
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
  -webkit-tap-highlight-color: transparent;
}
.photo-viewer-overlay .kb-lightbox-action:hover { background: rgba(255,255,255,0.18); }
.photo-viewer-overlay .kb-lightbox-action:active { transform: scale(0.96); }
.photo-viewer-overlay .kb-lightbox-action svg { width: 14px; height: 14px; flex-shrink: 0; stroke-width: 2.2; }
@media (max-width: 480px) {
  .photo-viewer-overlay .kb-lightbox-action span { display: none; }
  .photo-viewer-overlay .kb-lightbox-action {
    padding: 0;
    width: 40px; height: 40px;
    justify-content: center;
  }
  .photo-viewer-overlay .kb-lightbox-action svg { width: 18px; height: 18px; }
}

/* Share button — same chip shape as Annotate but neutral, so the
   primary annotate action stays visually dominant. Hidden once the
   user starts zooming in (see applyTransform_ in photo-viewer.js). */
.photo-viewer-share {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 8px 14px;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: var(--radius-md);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s, transform 0.1s;
}
.photo-viewer-share:hover { background: rgba(255, 255, 255, 0.22); }
.photo-viewer-share:active { transform: scale(0.96); }

/* ═══════════════════════════════════════════════════════════════════════
   CALLOUTS — Split-pane layout (desktop only)
   ─────────────────────────────────────────────────────────────────────
   Mirrors the Tasks two-pane shape: list on the left, detail mounts
   inline on the right. Mobile keeps the existing single-column list +
   fullscreen overlay behaviour — the right pane is hidden under
   max-width: 959px so the list fills the viewport like before.
   ═══════════════════════════════════════════════════════════════════════ */
.callout-split {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  min-height: calc(100vh - 100px);
  margin-top: 12px;
}
.callout-list-pane {
  flex: 0 0 360px;
  min-width: 0;
  position: relative;
  padding-bottom: 96px;
}
.callout-list-pane .callout-list-wrap { margin-top: 0; }

.callout-detail-pane {
  flex: 1 1 auto;
  min-width: 0;
  align-self: stretch;
  position: sticky;
  top: 0;
  max-height: calc(100vh - 94px);
  overflow-y: auto;
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  scroll-behavior: smooth;
}
.callout-detail-pane:empty,
.callout-detail-pane .callout-detail-pane-empty {
  background: transparent;
}
.callout-detail-pane-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 100%;
  min-height: 320px;
  color: var(--text-muted);
  padding: 40px 20px;
  text-align: center;
}
.callout-detail-pane-empty-title {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-secondary);
  margin-top: 8px;
}
.callout-detail-pane-empty-sub {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* When the pane has a mounted detail, drop the surrounding card chrome
   so the detail header (with its own dividers) reads cleanly. The shell
   provides its own padding. */
.callout-detail-pane.is-mounted { padding: 0; }
.callout-detail-pane.is-mounted .callout-detail-shell { padding: 18px 22px 24px; }
/* (The shell + header are now white --bg-surface in the base rule for EVERY mode,
   so the old pane-only background override was removed — 2026-07-01. See
   css/12 .callout-detail-shell.) */
/* The Back chevron in pane mode acts as a "deselect" / close. */
.callout-detail-pane.is-mounted .callout-detail-back { color: var(--text-muted); }

/* Highlight the selected card in the list when its detail is showing.
   Matches the Tasks card selection style for cross-module consistency. */
.callout-list-pane .callout-card.is-selected {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-surface));
}

/* Mobile fallback — hide the right pane, list fills width, clicks
   open the existing fullscreen overlay. */
@media (max-width: 959px) {
  .callout-split { display: block; min-height: 0; margin-top: 0; }
  .callout-list-pane { padding-bottom: 0; }
  .callout-detail-pane { display: none; }
}

/* Narrow laptops (960–1100) — shrink the list pane a touch so the
   detail stays usable. */
@media (max-width: 1100px) and (min-width: 960px) {
  .callout-list-pane { flex-basis: 320px; }
  .callout-detail-pane.is-mounted .callout-detail-shell { padding: 16px 18px 20px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   OFFLINE UPLOAD QUEUE — pending photo tile styles
   ─────────────────────────────────────────────────────────────────────
   .callout-photo-tile--pending  dimmed tile with uploading spinner
   .photo-pending-overlay        centred spinner overlay
   .pending-spin                 CSS rotation animation
   ═══════════════════════════════════════════════════════════════════════ */

@keyframes pending-spin { to { transform: rotate(360deg); } }

.callout-photo-tile--pending {
  position: relative;
  cursor: default;
  pointer-events: none;
}
.callout-photo-tile--pending img {
  filter: brightness(0.55) saturate(0.6);
  object-fit: cover;
  width: 100%;
  height: 100%;
  display: block;
}
.photo-pending-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.28);
  border-radius: inherit;
}
.pending-spin {
  animation: pending-spin 1s linear infinite;
  opacity: 0.92;
}

/* ═══════════════════════════════════════════════════════════════════════
   COST ENTRY WIDGET  (modules/assets/cost-entry.js)
   Multi-line cost entry modal shared across Assets, Callouts, Services.
   ═══════════════════════════════════════════════════════════════════════ */

body.ce-open { overflow: hidden; }

/* ── Overlay backdrop ─────────────────────────────────────────────── */
.ce-overlay {
  /* 9600 sits ABOVE the task modal (.tasks-modal-overlay 9000) and an
     elevated callout (9500) so "Add cost" opened from inside a task/callout
     detail layers on top — not behind it. Stays BELOW popovers (9999) and
     the widget's own SKU popup (.ce-sku-popup-overlay 99999). */
  position: fixed; inset: 0; z-index: 9600;
  background: rgba(0, 0, 0, 0.72);
  display: flex;
  align-items: flex-end;          /* sheet from bottom on mobile */
  opacity: 0;
  transition: opacity 0.22s ease;
}
.ce-overlay.is-open { opacity: 1; }
@media (min-width: 640px) {
  .ce-overlay { align-items: center; justify-content: center; padding: 16px; }
}

/* ── Dialog shell ─────────────────────────────────────────────────── */
.ce-shell {
  width: 100%;
  max-width: 960px;
  max-height: calc(92vh - var(--keyboard-height, 0px));
  background: var(--bg-card, #12151c);
  border-radius: 16px 16px 0 0;
  display: flex;
  flex-direction: column;
  transform: translateY(32px);
  opacity: 0;
  transition: transform 0.22s ease, opacity 0.22s ease;
  overflow: hidden;
}
.ce-overlay.is-open .ce-shell { transform: translateY(0); opacity: 1; }
@media (min-width: 640px) {
  .ce-shell {
    border-radius: 16px;
    max-height: calc(88vh - var(--keyboard-height, 0px));
    width: calc(100% - 32px);
  }
}

/* ── Header ───────────────────────────────────────────────────────── */
.ce-header {
  padding: 16px 16px 12px;
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
  flex-shrink: 0;
}
.ce-header-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.ce-header-title {
  font: 600 18px / 1.2 var(--font-display, 'Syne', sans-serif);
  color: var(--text-primary, #f1f5f9);
}
.ce-close {
  width: 42px; height: 42px;
  border: 1px solid transparent;
  border-radius: var(--radius-md, 10px);
  background: transparent;
  cursor: pointer;
  display: grid; place-items: center;
  color: var(--text-secondary);
  transition: background 0.12s, color 0.12s, transform 0.08s;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.ce-close:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.ce-close:active { transform: scale(0.94); }
.ce-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ce-close svg { width: 22px; height: 22px; stroke-width: 2; }

.ce-header-meta { display: flex; align-items: center; gap: 16px; }

.ce-date-label {
  display: flex; align-items: center; gap: 6px;
  font: 500 13px / 1 var(--body);
  color: var(--text-secondary, #94a3b8);
  cursor: pointer;
  user-select: none;
}
.ce-date-label svg { width: 14px; height: 14px; flex-shrink: 0; }
.ce-date-label span { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; }
.ce-date-input {
  background: var(--bg-input, rgba(255,255,255,0.06));
  border: 1px solid var(--border-input, rgba(255,255,255,0.10));
  border-radius: 8px;
  color: var(--text-primary, #f1f5f9);
  font: 500 13px / 1 var(--body);
  padding: 5px 9px;
  outline: none;
  transition: border-color 0.15s;
  -webkit-appearance: none;
  color-scheme: light dark;
}
.ce-date-input:focus { border-color: var(--accent, #22d3ee); }

/* ── Scroll area + table ──────────────────────────────────────────── */
.ce-scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: auto;
  padding: 14px 16px 10px;
  padding-bottom: calc(10px + var(--keyboard-height, 0px));
  -webkit-overflow-scrolling: touch;
}

.ce-table-wrap { min-width: 680px; }

/* Number-input spinners — kill the up/down arrow buttons that
   browsers stick on type="number". They crowd small inputs (price,
   qty) and look unprofessional. Applied globally inside cost-entry
   so neither desktop nor mobile shows them. */
.ce-input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}
.ce-input[type="number"]::-webkit-outer-spin-button,
.ce-input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* (Mobile cost-entry media query lives AFTER the base rules — see
   below near the end of the cost-entry section. Placed there to win
   the cascade naturally without !important.) */

/* Column grid — shared between header and rows */
.ce-table-head,
.ce-row {
  display: grid;
  /* cat | sku | desc | qty | price | vat | total | del */
  grid-template-columns: 96px 100px 1fr 52px 96px 72px 74px 44px;
  column-gap: 6px;
  align-items: center;
}

/* ── Column headers ───────────────────────────────────────────────── */
.ce-table-head {
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.07));
  margin-bottom: 4px;
}
.ce-th {
  font: 600 11px / 1 var(--body);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-muted, #64748b);
  white-space: nowrap;
}
.ce-th-qty,
.ce-th-price,
.ce-th-total { text-align: right; }

/* ── Line rows ────────────────────────────────────────────────────── */
.ce-row {
  padding: 4px 0;
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.04));
}
.ce-row:last-child { border-bottom: none; }

.ce-cell { display: flex; align-items: center; min-width: 0; }

/* Category cell — colour dot + compact select */
.ce-cell-cat { gap: 5px; }
.ce-cat-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  transition: background 0.15s;
}
/* Truncate the displayed category name — dropdown options still show in full */
.ce-cell-cat .ce-select {
  font-size: 12px;
  padding-left: 6px;
  padding-right: 20px;   /* room for the chevron only */
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

/* Price cell — £ prefix */
.ce-cell-price .ce-price-wrap {
  position: relative;
  width: 100%;
}
.ce-cell-price .ce-price-sym {
  position: absolute;
  left: 9px; top: 50%;
  transform: translateY(-50%);
  font: 400 13px / 1 var(--body);
  color: var(--text-muted, #64748b);
  pointer-events: none;
  z-index: 1;
}
.ce-cell-price .ce-price-inp { padding-left: 20px; }

/* ── Shared input / select styles ─────────────────────────────────── */
.ce-input,
.ce-select {
  width: 100%;
  height: 34px;
  padding: 0 8px;
  background: var(--bg-input, rgba(255,255,255,0.05));
  border: 1px solid transparent;
  border-radius: 8px;
  color: var(--text-primary, #f1f5f9);
  font: 400 13px / 1 var(--body);
  outline: none;
  transition: border-color 0.15s, background 0.15s;
  -webkit-appearance: none;
  min-width: 0;
}
.ce-input:focus,
.ce-select:focus {
  border-color: var(--accent, #22d3ee);
  background: var(--accent-soft);
}
.ce-input::placeholder { color: var(--text-muted, #64748b); }

/* Right-align number inputs */
.ce-qty-inp  { text-align: right; padding: 0 6px; }

/* Select — custom chevron */
.ce-select {
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 14px;
  padding-right: 24px;
  cursor: pointer;
}

/* ── Line total ───────────────────────────────────────────────────── */
.ce-cell-total { justify-content: flex-end; }
.ce-line-total {
  font: 500 13px / 1 var(--body);
  color: var(--text-secondary, #94a3b8);
  text-align: right;
  white-space: nowrap;
}

/* ── Delete button ────────────────────────────────────────────────── */
.ce-cell-del { justify-content: center; }
.ce-del-btn {
  width: 42px; height: 42px;
  border: 1px solid transparent;
  border-radius: var(--radius-md, 10px);
  background: transparent;
  cursor: pointer;
  display: grid; place-items: center;
  color: var(--text-muted, #64748b);
  transition: background 0.12s, border-color 0.12s, color 0.12s, transform 0.08s;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.ce-del-btn:hover {
  background: rgba(220, 38, 38, 0.10);
  border-color: rgba(220, 38, 38, 0.30);
  color: #ef4444;
}
.ce-del-btn:active { transform: scale(0.94); }
.ce-del-btn svg { width: 22px; height: 22px; stroke-width: 2; }

/* ── Add another item button ──────────────────────────────────────── */
.ce-add-line-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 10px;
  padding: 0 16px;
  height: 38px;
  background: var(--accent, #22d3ee);
  border: none;
  border-radius: var(--radius-md, 10px);
  cursor: pointer;
  color: #07090d;
  font: 600 13px / 1 var(--body);
  transition: opacity 0.12s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
  flex-shrink: 0;
}
.ce-add-line-btn:hover  { opacity: 0.88; }
.ce-add-line-btn:active { transform: scale(0.96); }
.ce-add-line-btn svg { width: 15px; height: 15px; flex-shrink: 0; }

/* ── Action row: "Add another item" + "Add photo / file" ──────────── */
.ce-actions-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.ce-actions-row .ce-add-line-btn { margin-top: 0; }

/* Secondary / outline style so it reads as a companion to the primary
   "Add another item" without two filled buttons competing. */
.ce-add-file-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 14px;
  height: 38px;
  background: var(--bg-surface);
  border: 1px solid var(--border-strong, var(--border));
  border-radius: var(--radius-md, 10px);
  cursor: pointer;
  color: var(--text-primary);
  font: 600 13px / 1 var(--body);
  transition: background 0.12s, border-color 0.12s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
  flex-shrink: 0;
}
.ce-add-file-btn:hover  { background: var(--bg-hover, var(--bg-elevated)); border-color: var(--accent); }
.ce-add-file-btn:active { transform: scale(0.96); }
.ce-add-file-btn svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--accent); }

/* ── Pending-attachment thumbnail strip (inside the widget) ───────── */
.ce-attach-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin-top: 12px;
}
.ce-attach-thumb {
  position: relative;
  width: 66px;
  height: 66px;
  border-radius: 10px;
  border: 1px solid var(--border);
  overflow: hidden;
  background: var(--bg-elevated);
  flex-shrink: 0;
}
.ce-attach-thumb.is-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ce-attach-thumb.is-doc {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px;
  text-align: center;
}
.ce-attach-thumb.is-doc svg { width: 22px; height: 22px; color: var(--text-secondary); flex-shrink: 0; }
.ce-attach-thumb-name {
  font: 500 9.5px / 1.15 var(--body);
  color: var(--text-secondary);
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ce-attach-thumb-x {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: rgba(8, 10, 14, 0.72);
  color: #fff;
  cursor: pointer;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}
.ce-attach-thumb-x:hover { background: var(--danger, #ef4444); }
.ce-attach-thumb-x svg { width: 12px; height: 12px; }

/* ── 3-way capture chooser (Camera / Photo library / File) ────────── */
.ce-attach-chooser-overlay {
  position: fixed;
  inset: 0;
  z-index: 99999;            /* above the cost-entry overlay (9600) */
  background: rgba(0, 0, 0, 0.62);
  display: flex;
  align-items: flex-end;     /* bottom sheet on mobile */
  opacity: 0;
  transition: opacity 0.18s ease;
}
.ce-attach-chooser-overlay.is-open { opacity: 1; }
@media (min-width: 640px) {
  .ce-attach-chooser-overlay { align-items: center; justify-content: center; padding: 16px; }
}
.ce-attach-chooser {
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
  background: var(--bg-elevated, #161a22);
  border: 1px solid var(--border);
  border-radius: 18px 18px 0 0;
  padding: 18px 18px calc(18px + env(safe-area-inset-bottom));
  transform: translateY(24px);
  opacity: 0;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.ce-attach-chooser-overlay.is-open .ce-attach-chooser { transform: translateY(0); opacity: 1; }
@media (min-width: 640px) {
  .ce-attach-chooser { border-radius: 16px; padding: 18px; }
}
.ce-attach-chooser-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.ce-attach-chooser-head span { font: 700 16px / 1.2 var(--display, var(--body)); color: var(--text-primary); }
.ce-attach-chooser-close {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--text-secondary);
  cursor: pointer; flex-shrink: 0;
}
.ce-attach-chooser-close:hover { background: var(--bg-elevated); color: var(--text-primary); }
.ce-attach-chooser-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ce-attach-chooser-close svg { width: 18px; height: 18px; }
.ce-attach-chooser-opts { display: flex; flex-direction: column; gap: 10px; }
.ce-attach-opt {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 16px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  color: var(--text-primary);
  font: 600 14.5px / 1 var(--body);
  text-align: left;
  transition: background 0.12s, border-color 0.12s, transform 0.06s;
  -webkit-tap-highlight-color: transparent;
}
.ce-attach-opt:hover  { background: var(--bg-hover, var(--bg-elevated)); border-color: var(--accent); }
.ce-attach-opt:active { transform: scale(0.985); }
.ce-attach-opt svg {
  width: 24px; height: 24px; flex-shrink: 0;
  color: var(--accent);
}

/* ── Saved-cost attachments strip (shown in cost rows everywhere) ──── */
.cost-attach-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 7px;
}
.cost-attach-item {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  flex-shrink: 0;
}
.cost-attach-item.is-img {
  width: 42px;
  height: 42px;
  border-radius: 7px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}
.cost-attach-item.is-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cost-attach-item.is-img:hover { border-color: var(--accent); }
.cost-attach-item.is-doc {
  gap: 5px;
  max-width: 170px;
  padding: 5px 9px;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  color: var(--text-secondary);
  font: 500 11.5px / 1 var(--body);
}
.cost-attach-item.is-doc:hover { border-color: var(--accent); color: var(--text-primary); }
.cost-attach-item.is-doc svg { width: 13px; height: 13px; flex-shrink: 0; }
.cost-attach-item.is-doc span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Footer ───────────────────────────────────────────────────────── */
.ce-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
  flex-shrink: 0;
}
.ce-footer-total {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.ce-footer-total-label {
  font: 400 12px / 1 var(--body);
  color: var(--text-secondary, #94a3b8);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.ce-grand-total {
  font: 700 22px / 1 var(--font-display, 'Syne', sans-serif);
  color: var(--text-primary, #f1f5f9);
}
.ce-vat-note {
  font: 400 12px / 1 var(--body);
  color: var(--text-muted, #64748b);
}
.ce-footer-actions { display: flex; gap: 8px; flex-shrink: 0; }

/* ─── VAT mode toggle (header) ──────────────────────────────────────
   Small segmented control next to the Date label. Lets the user say
   whether they're entering prices that already include VAT (matching
   a receipt) or excluding VAT (matching a trade supplier quote).
   Stored data stays canonical ex-VAT; the toggle just changes how
   the user types + how the price field is displayed back to them. */
.ce-vat-mode {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
  margin-left: auto;
}
.ce-vat-mode-btn {
  padding: 5px 12px;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font: 600 12px / 1 var(--body);
  border-radius: var(--radius-sm, 4px);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.ce-vat-mode-btn:hover { color: var(--text-primary); }
.ce-vat-mode-btn.is-on {
  background: var(--accent);
  color: var(--bg-base);
}

/* Make ce-header-meta wrap on narrow screens so the toggle drops below
   the date label gracefully */
.ce-header-meta {
  flex-wrap: wrap;
  gap: 12px;
  width: 100%;
}

/* Per-entry supplier pill in the cost-entry header (optional) — opens the
   shared AngelHubSupplierPicker; dashed when empty, filled once a supplier is set. */
.ce-supplier {
  display: inline-flex; align-items: center; gap: 7px;
  height: 34px; padding: 0 12px;
  background: var(--bg-input, rgba(255,255,255,0.05));
  border: 1px dashed var(--border);
  border-radius: 8px;
  color: var(--text-muted);
  font: 500 13px / 1 var(--body);
  cursor: pointer;
  max-width: 230px;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.ce-supplier svg { width: 15px; height: 15px; flex-shrink: 0; }
.ce-supplier .ce-supplier-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ce-supplier:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
  color: var(--accent);
}
.ce-supplier.has-value {
  border-style: solid; border-color: transparent;
  background: var(--bg-elevated); color: var(--text-primary);
}
.ce-supplier.has-value:hover { color: var(--accent); }

/* ─── SKU button + popup ────────────────────────────────────────────
   The SKU cell renders as a small button. Empty = dashed "+ SKU"
   hint. With value = solid button showing the SKU. Click → opens a
   centred popup with a large input for comfortable typing. */
.ce-sku-btn {
  width: 100%;
  height: 34px;
  padding: 0 6px;
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: 8px;
  color: var(--text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.ce-sku-btn svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}
.ce-sku-btn:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
/* When a SKU value is present, button is "filled" and shows the code */
.ce-sku-btn.has-value {
  background: var(--bg-elevated);
  border: 1px solid transparent;
  color: var(--text-primary);
  font: 500 12px / 1 var(--body);
  letter-spacing: 0;
  justify-content: flex-start;
  padding: 0 8px;
}
.ce-sku-btn.has-value:hover {
  background: var(--bg-hover);
  color: var(--accent);
}

/* Desktop: SKU is an inline input you type straight into (we have the width);
   the + button → popup is hidden here and restored on mobile (≤900px block). */
.ce-cell-sku .ce-sku-inp { letter-spacing: 0.02em; }
.ce-cell-sku .ce-sku-btn { display: none; }

/* ─── SKU popup ──────────────────────────────────────────────────── */
.ce-sku-popup-overlay {
  position: fixed; inset: 0;
  z-index: 99999;
  background: rgba(0,0,0,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.ce-sku-popup-overlay.is-open { opacity: 1; }
.ce-sku-popup {
  width: 100%;
  max-width: 360px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  transform: translateY(8px);
  transition: transform 0.2s ease;
}
.ce-sku-popup-overlay.is-open .ce-sku-popup { transform: translateY(0); }
.ce-sku-popup-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px 12px;
  border-bottom: 1px solid var(--border);
}
.ce-sku-popup-title {
  flex: 1;
  font: 600 var(--text-xl) / 1.2 var(--display);
  color: var(--text-primary);
}
.ce-sku-popup-close {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.ce-sku-popup-close:hover { background: var(--bg-elevated); color: var(--text-primary); }
.ce-sku-popup-close svg { width: 18px; height: 18px; }
.ce-sku-popup-body {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ce-sku-popup-label {
  font: 600 var(--text-sm) / 1 var(--body);
  color: var(--text-secondary);
}
.ce-sku-popup-input {
  width: 100%;
  height: 44px;          /* comfortable touch target */
  padding: 0 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font: 500 16px / 1 var(--body);
  letter-spacing: 0.02em;
  outline: none;
  transition: border-color 0.15s, background 0.15s;
}
.ce-sku-popup-input:focus {
  border-color: var(--accent);
  background: var(--bg-surface);
}
.ce-sku-popup-input::placeholder { color: var(--text-muted); }
.ce-sku-popup-hint {
  font: 400 var(--text-xs) / 1.4 var(--body);
  color: var(--text-muted);
}
.ce-sku-popup-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px 16px;
  border-top: 1px solid var(--border);
}
.ce-sku-popup-clear {
  padding: 8px 12px;
  background: transparent;
  border: 1px solid color-mix(in srgb, #dc2626 35%, var(--border));
  color: #dc2626;
  border-radius: var(--radius-md);
  font: 600 var(--text-sm) / 1 var(--body);
  cursor: pointer;
  transition: background 0.12s;
}
.ce-sku-popup-clear:hover {
  background: color-mix(in srgb, #dc2626 8%, transparent);
}

/* ═══════════════════════════════════════════════════════════════════════
   Mobile cost-entry (≤900px) — placed AFTER all base .ce-* rules so it
   wins the cascade without needing !important. This is the location
   that the column widths, padding, border + display rules ACTUALLY
   take effect. (Earlier attempt was before the base rules → got
   overridden by them, which is why nothing visibly changed.)

   Three structural differences vs desktop:
     1. Category lifted onto its own row above the inline row
     2. Column headers hidden entirely (they overlap on narrow widths)
     3. Per-line Total hidden — the grand "TOTAL EX-VAT" at the bottom
        of the form sums everything; dropping it frees 74px of horizontal
        space for Description.

   Aggressive column trimming so Description gets dominant inline width.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  /* Drop the forced horizontal-scroll min-width */
  .ce-table-wrap { min-width: 0; }

  /* HIDE column headers entirely */
  .ce-table-head { display: none; }

  /* Hide per-line Total — grand total still in footer */
  .ce-cell-total { display: none; }

  /* Hide per-line VAT on mobile — 99% of UK maintenance costs are 20%
     standard rate. Default vat_code='standard' is set by the data
     layer; the footer shows the computed VAT total ("+£X.XX VAT") so
     the user still sees what they're paying. Power users can override
     individual VAT on desktop (≥900px) where the column is visible. */
  .ce-cell-vat { display: none; }

  /* Inline row: Category above, everything else inline.
     Six columns visible (sku/desc/qty/price/del) — that gives
     Description a much bigger 1fr share. */
  .ce-row {
    grid-template-columns: 38px minmax(0, 1fr) 32px 92px 28px;
    grid-template-areas:
      "cat cat  cat cat   cat"
      "sku desc qty price del";
    column-gap: 5px;
    row-gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
  }
  .ce-row:last-child { border-bottom: none; }
  .ce-cell-cat   { grid-area: cat; }
  .ce-cell-sku   { grid-area: sku; }
  .ce-cell-desc  { grid-area: desc; }
  .ce-cell-qty   { grid-area: qty; }
  .ce-cell-price { grid-area: price; }
  .ce-cell-del   { grid-area: del; }

  /* Category gets full width on its own row */
  .ce-cell-cat .ce-select { width: 100%; }

  /* Smaller delete button so it doesn't eat horizontal space.
     Bin SVG scales inside the button. */
  .ce-cell-del .ce-del-btn { width: 26px; height: 26px; padding: 0; }
  .ce-cell-del .ce-del-btn svg { width: 14px; height: 14px; }

  /* ─── Legibility ────────────────────────────────────────────────
     "Everything dark / hard to read" — fix by brightening placeholder,
     lifting input background contrast, bumping font weight on values. */
  .ce-input {
    background: var(--bg-hover);            /* a touch more contrast than the default fill */
    color: var(--text-primary);
    font-size: 13px;
  }
  .ce-input::placeholder {
    color: var(--text-secondary);
    opacity: 1;                            /* override iOS/Safari dimming */
  }
  .ce-select {
    background-color: var(--bg-hover);
    color: var(--text-primary);
    font-weight: 500;
    font-size: 13px;
  }

  /* Trim input padding to fit tighter columns */
  .ce-input,
  .ce-select { padding-left: 6px; padding-right: 6px; }
  /* Price — readable amount with £ tucked tight */
  .ce-cell-price .ce-price-inp {
    padding-left: 14px;
    padding-right: 4px;
    font-weight: 500;
  }
  .ce-cell-price .ce-price-sym { left: 5px; font-size: 12px; }
  /* Qty — narrow centred. (VAT column hidden — see above) */
  .ce-cell-qty .ce-input { padding: 0 2px; text-align: center; }
  /* SKU reverts to the compact + button → popup on mobile (no room to type inline) */
  .ce-cell-sku .ce-sku-inp { display: none; }
  .ce-cell-sku .ce-sku-btn { display: flex; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Cost Ledger — the shared READ-ONLY cost line-item table (AngelHubCostLedger).
   Mirrors the .ce-* entry table look so adding and viewing costs feel identical;
   replaces the old one-card-per-cost display. Used by Tasks first, then
   call-outs / assets / budgets. Totals reuse .callout-costs-totals (css/12).
   ═══════════════════════════════════════════════════════════════════════ */
.clg-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin: 16px 0 6px;
}
.clg-heading {
  margin: 0;
  font: 600 12px / 1 var(--body);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted);
}
.clg-add { padding: 7px 12px; }              /* uses .callout-btn .callout-btn-primary */
.clg-add svg { width: 15px; height: 15px; margin-right: 2px; }

.clg-table { display: flex; flex-direction: column; }

.clg-row {
  display: grid;
  /* cat | sku | desc | qty | unit | vat | total | act */
  grid-template-columns: 92px 70px minmax(0,1fr) 38px 72px 44px 88px 30px;
  column-gap: 8px;
  align-items: start;
  padding: 9px 4px;
  border-bottom: 1px solid var(--border-subtle, rgba(255,255,255,0.05));
}
.clg-row:last-child { border-bottom: none; }

.clg-head {
  align-items: center;
  padding-top: 2px; padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  font: 600 11px / 1 var(--body);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted);
}

.clg-cell { min-width: 0; font: 400 13px / 1.4 var(--body); color: var(--text-secondary); }

.clg-cell-cat { display: flex; align-items: center; gap: 7px; color: var(--text-primary); font-weight: 500; }
.clg-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.clg-cat-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.clg-cell-sku {
  font-size: 12px; color: var(--text-secondary); letter-spacing: 0.02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.clg-empty { color: var(--text-muted); }

.clg-cell-desc { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.clg-desc { color: var(--text-primary); font-weight: 500; line-height: 1.35; }
.clg-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font-size: 11px; color: var(--text-muted);
}
.clg-qu { display: none; }                   /* qty × unit shown only on mobile (cols hidden there) */
.clg-src {
  padding: 2px 7px; border: 1px solid var(--border); border-radius: 6px;
  background: var(--bg-elevated); color: var(--text-secondary);
  font-weight: 600; font-size: 10px;
}
.clg-supplier { color: var(--text-secondary); font-weight: 500; }

.clg-cell-qty   { text-align: right; color: var(--text-primary); }
.clg-cell-unit  { text-align: right; }
.clg-cell-vat   { text-align: right; }
.clg-cell-total { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.clg-total-ex   { font-weight: 600; color: var(--text-primary); white-space: nowrap; }
.clg-total-inc  { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.clg-cell-act   { display: flex; justify-content: flex-end; }

.clg-row.is-click { cursor: pointer; border-radius: 8px; transition: background 0.12s; }
.clg-row.is-click:hover { background: var(--bg-hover); }
.clg-row.is-linked { opacity: 0.9; }

.clg-del {
  width: 30px; height: 30px; display: grid; place-items: center;
  border: 0; background: transparent; border-radius: 8px;
  color: var(--text-muted); cursor: pointer; flex-shrink: 0;
  transition: background 0.12s, color 0.12s;
}
.clg-del:hover { background: color-mix(in srgb, #dc2626 10%, transparent); color: #dc2626; }
.clg-del svg { width: 15px; height: 15px; }

.clg-quote-actions { display: flex; gap: 6px; margin-top: 2px; }
.clg-qbtn {
  padding: 3px 10px; border-radius: 6px; cursor: pointer;
  font: 600 11px / 1 var(--body); border: 1px solid transparent;
}
.clg-qbtn-approve {
  background: color-mix(in srgb, var(--success, #16a34a) 12%, transparent);
  color: var(--success, #16a34a);
  border-color: color-mix(in srgb, var(--success, #16a34a) 35%, transparent);
}
.clg-qbtn-reject { background: transparent; color: var(--text-secondary); border-color: var(--border); }

.clg-cell-desc .cost-attach-strip { margin-top: 2px; }

/* Mobile — condensed: drop the qty/unit/vat columns; category + description +
   total stack. qty × unit folds into the description meta line so nothing is
   lost. (Per the agreed standard: mobile may show a restricted view.) */
@media (max-width: 599px) {
  .clg-row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "cat   total"
      "desc  desc"
      "act   act";
    column-gap: 10px; row-gap: 6px;
    padding: 10px 2px;
  }
  .clg-head { display: none; }
  .clg-cell-cat   { grid-area: cat; }
  .clg-cell-total { grid-area: total; }
  .clg-cell-desc  { grid-area: desc; }
  .clg-cell-act   { grid-area: act; justify-content: flex-start; }
  .clg-cell-sku, .clg-cell-qty, .clg-cell-unit, .clg-cell-vat { display: none; }
  .clg-qu { display: inline; }
  .clg-cell-act:empty { display: none; }
}

/* Compact ledger (inline contexts like the budget drill-in expand): always use
   the stacked layout regardless of viewport — the container is narrow even on a
   wide screen, so the desktop grid would overlap. Mirrors the mobile reflow. */
.clg-table.clg-stack .clg-row {
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "cat   total"
    "desc  desc"
    "act   act";
  column-gap: 10px; row-gap: 6px;
  padding: 9px 2px;
}
.clg-table.clg-stack .clg-head { display: none; }
.clg-table.clg-stack .clg-cell-cat   { grid-area: cat; }
.clg-table.clg-stack .clg-cell-total { grid-area: total; }
.clg-table.clg-stack .clg-cell-desc  { grid-area: desc; }
.clg-table.clg-stack .clg-cell-act   { grid-area: act; justify-content: flex-start; }
.clg-table.clg-stack .clg-cell-sku,
.clg-table.clg-stack .clg-cell-qty,
.clg-table.clg-stack .clg-cell-unit,
.clg-table.clg-stack .clg-cell-vat { display: none; }
.clg-table.clg-stack .clg-qu { display: inline; }
.clg-table.clg-stack .clg-cell-act:empty { display: none; }

/* ── Updated cost line display (in asset Costs tab) ──────────────── */
.callout-costs-row-sku {
  font: 500 11px / 1 var(--body);
  color: var(--text-muted, #64748b);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.callout-costs-row-qty {
  font: 400 12px / 1 var(--body);
  color: var(--text-secondary, #94a3b8);
}
.callout-costs-row-unit {
  font: 400 12px / 1 var(--body);
  color: var(--text-muted, #64748b);
}

/* ═══════════════════════════════════════════════════════════════════════
   CONTRACTORS MODULE  (ctr-*)
   ─────────────────────────────────────────────────────────────────────
   Org-wide contractor register with rate cards, SLA commitments, and
   combined callout + service history. Uses shared structural classes
   from callouts (.callout-kpi-card, .callout-view-toggle, .asset-list,
   .asset-empty, .callout-detail-header, .callout-detail-tab*) so only
   contractor-specific overrides are declared here.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── LIST CARDS ─────────────────────────────────────────────────────── */
.ctr-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Contractor list — individual cards stand on their own with a gap
   between them. Previous design had them flush-stacked with shared
   borders which made the list look flat and admin-form-y. The new
   pattern matches the rest of the app (Tasks / Callouts / KB) which
   uses gap-separated cards with subtle elevation. */
.ctr-card-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ctr-card {
  display: flex;
  align-items: stretch;
  width: 100%;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  padding: 0;
  cursor: pointer;
  text-align: left;
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: background 0.16s, border-color 0.16s, transform 0.12s, box-shadow 0.16s;
}
.ctr-card:hover {
  background: var(--bg-hover);
  border-color: var(--border-strong);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 8%, transparent);
}
.ctr-card:active {
  background: var(--bg-elevated);
  transform: translateY(0);
  box-shadow: none;
}

/* Selected state — canonical accent treatment (50% border + 6% tint) */
.ctr-card.is-selected {
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-surface));
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
}

/* Left colour bar — status indicator. Widened from 4px → 5px for
   more visual presence at glance distance, and the rounded corners
   simplified since the card now has its own border-radius. */
.ctr-card-bar {
  display: block;
  width: 5px;
  flex-shrink: 0;
  background: #94a3b8;
}

.ctr-card-main {
  flex: 1;
  min-width: 0;
  padding: 14px 16px 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* One calm chip row under the name — status (loud) + neutral trade chips +
   contract warning. Replaces the old split top-strip/signals rows so the card
   reads as a clean profile: name, then its chips. */
.ctr-card-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

.ctr-card-top {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

/* Ref chip — monospace accent pill, matches .callout-card-ref exactly so
   ref IDs read the same across Callouts / Contractors. */
.ctr-card-ref {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 3px 7px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  flex-shrink: 0;
}

/* Trade category chip — NEUTRAL (two-tier rule), trade colour on the dot only. */
.ctr-card-trade {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: 600 var(--text-xs, 11px) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm, 5px);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  white-space: nowrap;
}
.ctr-card-trade-dot { width: 7px; height: 7px; border-radius: var(--radius-full); flex-shrink: 0; }
/* Loud signal row under the name — status + contract-expiry warning. */
.ctr-card-signals { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }

/* Status chip — colour-coded via data-status attribute */
/* CALM (2026-06-29) — neutral chip + colour on the dot (matches .ctr-detail-status). */
.ctr-card-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 500 var(--text-xs, 11px) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm, 5px);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-primary);
  flex-shrink: 0;
}
.ctr-card-status::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-muted); flex-shrink: 0;
}
.ctr-card-status[data-status="active"]::before   { background: #16a34a; }
.ctr-card-status[data-status="pending"]::before  { background: #ca8a04; }
.ctr-card-status[data-status="inactive"]::before { background: #94a3b8; }

/* Detail status chip — CALM (neutral chip + colour kept on the dot), matching the
   Tasks/Call-out detail. The loud .ctr-card-status above stays loud for list
   scanning (two-tier card rule). (Radek 2026-06-29) */
.ctr-detail-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 500 var(--text-xs, 11px) / 1 var(--body);
  padding: 5px 9px;
  border-radius: var(--radius-sm, 5px);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-primary);
}
.ctr-detail-status::before {
  content: '';
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--text-muted);
  flex-shrink: 0;
}
.ctr-detail-status[data-status="active"]::before { background: #16a34a; }
.ctr-detail-status[data-status="pending"]::before { background: #ca8a04; }
.ctr-detail-status[data-status="inactive"]::before { background: #94a3b8; }

/* Contract expiry warning chip */
.ctr-card-contract-warn {
  display: inline-flex;
  align-items: center;
  font: 600 var(--text-xs, 11px) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm, 5px);
  border: 1px solid transparent;
}
.ctr-card-contract-warn.is-expired {
  color: #dc2626;
  background: rgba(220,38,38,0.10);
  border-color: rgba(220,38,38,0.45);
}
.ctr-card-contract-warn.is-expiring {
  color: #ea580c;
  background: rgba(234,88,12,0.10);
  border-color: rgba(234,88,12,0.45);
}

/* Name is the card hero — match the Callouts/Tasks card title (--text-lg,
   wraps rather than truncating) so contractor cards read the same as the rest. */
.ctr-card-name {
  font: 600 var(--text-lg) / 1.35 var(--body);
  color: var(--text-primary, #0f172a);
  word-wrap: break-word;
}

.ctr-card-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.ctr-card-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font: 400 12px / 1 var(--body);
  color: var(--text-secondary, #64748b);
}
.ctr-card-meta-item svg { width: 12px; height: 12px; flex-shrink: 0; }
.ctr-card-meta-more {
  font: 500 11px / 1 var(--body);
  color: var(--text-muted, #94a3b8);
}

/* ── DETAIL OVERLAY ─────────────────────────────────────────────────── */
.ctr-overlay {
  position: fixed;
  inset: 0;
  z-index: 1200;
  background: var(--bg-base);
  display: flex;
  flex-direction: column;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  overflow: hidden;
}
.ctr-overlay.is-open {
  opacity: 1;
  transform: none;
}
.ctr-overlay-inner {
  /* Match the asset/callout detail: a centred, contained 980px column rather
     than sprawling full-width, so the contractor detail looks consistent. */
  width: 100%;
  max-width: 980px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

/* Header inherits .callout-detail-header styles. Three stacked rows — ref+actions,
   name, chips — all aligned to the header's 18px left edge (rows carry vertical
   padding only, so nothing is over-indented vs the ref chip). */
.ctr-detail-header {
  padding: 12px 18px 14px;
}
.ctr-detail-header .callout-detail-header-top {
  gap: 6px;
}
.ctr-detail-name-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0 0;
  flex-wrap: wrap;
}
.ctr-detail-name-row .callout-detail-title {
  margin: 0;
  flex: 1;
  min-width: 0;
}

/* Calm chip row under the name — status + contract warning (loud signals)
   followed by the neutral trade + site context chips. One chip language with
   the list card; nothing competes with the name for attention. */
.ctr-detail-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 10px 0 0;
}
.ctr-detail-phone,
.ctr-detail-emerg-phone {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 600 13px / 1 var(--body);
  text-decoration: none;
  padding: 5px 12px;
  border-radius: var(--radius-sm, 5px);
  flex-shrink: 0;
}
.ctr-detail-phone {
  color: var(--accent, #6366f1);
  background: var(--accent-soft, rgba(99,102,241,0.08));
  border: 1px solid color-mix(in srgb, var(--accent, #6366f1) 45%, transparent);
}
.ctr-detail-emerg-phone {
  color: #dc2626;
  background: rgba(220,38,38,0.08);
  border: 1px solid rgba(220,38,38,0.40);
}
.ctr-detail-phone svg,
.ctr-detail-emerg-phone svg {
  width: 14px; height: 14px; flex-shrink: 0;
}

/* Tab body — fills remaining height and scrolls */
.ctr-tab-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

/* Peek host (collection-browser split pane, ≥1280px): the SAME detail content
   mounted in-page — structure mirrors .ctr-overlay-inner (header + tab bar
   pinned, .ctr-tab-body scrolls inside the pane), just without the fixed
   overlay wrapper. Desktop-only by construction (the pane exists ≥1280px). */
.ctr-peek {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.ctr-peek .ctr-detail-header,
.ctr-peek .callout-detail-tab-bar { flex-shrink: 0; }

/* ── PANEL BODY ─────────────────────────────────────────────────────── */
.ctr-panel-body {
  padding: 20px 20px 40px;
  display: flex;
  flex-direction: column;
  gap: 28px;
  max-width: 760px;
}

.ctr-info-section {}

.ctr-info-section-title {
  font: 700 11px / 1 var(--body);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary, #64748b);
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.ctr-form-section-sub,
.ctr-info-section-title .ctr-form-section-sub {
  font: 400 11px / 1 var(--body);
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-muted, #94a3b8);
}

.ctr-info-grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ctr-info-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
}
.ctr-info-label {
  font: 500 12px / 1.4 var(--body);
  color: var(--text-secondary, #64748b);
  min-width: 120px;
  flex-shrink: 0;
}
.ctr-info-row span,
.ctr-info-row a {
  font: 400 13px / 1.4 var(--body);
  color: var(--text-primary, #0f172a);
}
.ctr-info-link {
  color: var(--accent, #6366f1) !important;
  text-decoration: none;
}
.ctr-info-link:hover { text-decoration: underline; }
.ctr-info-empty {
  font: 400 13px / 1.5 var(--body);
  color: var(--text-muted, #94a3b8);
  margin: 0;
}
.ctr-notes-body {
  font: 400 14px / 1.6 var(--body);
  color: var(--text-primary, #0f172a);
  margin: 0;
  white-space: pre-wrap;
}

/* Subtle creation/update stamp at the foot of the Overview tab. */
.ctr-overview-stamp {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px solid var(--border-faint, var(--border));
  font: 400 12px / 1.4 var(--body);
  color: var(--text-muted);
}
.ctr-overview-stamp svg { width: 13px; height: 13px; flex-shrink: 0; }

/* ── RATES — grouped label→value list ───────────────────────────────── */
.ctr-rate-group + .ctr-rate-group { margin-top: 18px; }
.ctr-rate-group-head {
  font: 700 11px / 1 var(--body);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 6px;
}
.ctr-rate-list { display: flex; flex-direction: column; }
.ctr-rate-list-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border-faint, #f1f5f9);
}
.ctr-rate-list-row:last-child { border-bottom: none; }
.ctr-rate-list-label { font: 400 13px / 1.4 var(--body); color: var(--text-secondary); }
.ctr-rate-list-val {
  font: 600 14px / 1.2 var(--body);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* With-contract vs without-contract headline tiles */
.ctr-rate-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 4px;
}
.ctr-rate-compare-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}
.ctr-rate-compare-tile.is-contract {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: var(--accent-soft);
}
.ctr-rate-compare-label {
  font: 600 11px / 1 var(--body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.ctr-rate-compare-tile.is-contract .ctr-rate-compare-label { color: var(--accent); }
.ctr-rate-compare-val {
  font: 700 22px / 1 var(--display);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.ctr-rate-compare-unit { font: 600 12px / 1 var(--body); color: var(--text-muted); margin-left: 2px; }
.ctr-rate-compare-save {
  margin: 6px 0 2px;
  font: 500 12px / 1.4 var(--body);
  color: #16a34a;
}

/* ── SLA — per-priority cards ───────────────────────────────────────── */
.ctr-sla-cards { display: flex; flex-direction: column; gap: 8px; }
.ctr-sla-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.ctr-sla-card-vals { display: flex; gap: 22px; margin-left: auto; }
.ctr-sla-card-val { display: flex; flex-direction: column; gap: 3px; align-items: flex-end; }
.ctr-sla-card-k {
  font: 600 10px / 1 var(--body);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.ctr-sla-card-v {
  font: 600 14px / 1 var(--body);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.ctr-sla-note {
  margin: 10px 0 0;
  font: 400 12px / 1.4 var(--body);
  color: var(--text-muted);
}
/* Priority pill — shared by the SLA cards (and the form). One chip size. */
.ctr-sla-table-priority {
  display: inline-flex;
  align-items: center;
  font: 600 var(--text-xs, 11px) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm, 5px);
  border: 1px solid transparent;
  white-space: nowrap;
}

/* ── CONTRACT — featured annual value + term ────────────────────────── */
.ctr-contract-value {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 14px 16px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: var(--radius-md);
  margin-bottom: 14px;
}
.ctr-contract-value-label {
  font: 600 11px / 1 var(--body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
}
.ctr-contract-value-num {
  font: 700 24px / 1 var(--display);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.ctr-contract-value-unit { font: 600 12px / 1 var(--body); color: var(--text-muted); margin-left: 4px; }
.ctr-contract-days-chip {
  display: inline-flex;
  align-items: center;
  font: 600 11px / 1 var(--body);
  padding: 3px 8px;
  margin-left: 8px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  white-space: nowrap;
}

/* ── CONTRACT BANNERS ───────────────────────────────────────────────── */
.ctr-contract-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--radius-md, 10px);
  font: 500 13px / 1.4 var(--body);
  border: 1px solid transparent;
}
.ctr-contract-banner svg { width: 18px; height: 18px; flex-shrink: 0; }
.ctr-contract-banner.is-expired {
  color: #dc2626;
  background: rgba(220,38,38,0.08);
  border-color: rgba(220,38,38,0.35);
}
.ctr-contract-banner.is-expiring {
  color: #ea580c;
  background: rgba(234,88,12,0.08);
  border-color: rgba(234,88,12,0.35);
}

/* ── FORM ───────────────────────────────────────────────────────────── */
.ctr-form-modal { max-width: 720px; }

.ctr-form-body {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* 3-column grid for compact rate inputs (Call-out / Min hrs / Travel) */
.ctr-form-row-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px;
}
@media (max-width: 520px) {
  .ctr-form-row-3 { grid-template-columns: 1fr; }
}

/* ── TRADE CHIPS ────────────────────────────────────────────────────── */
.ctr-trade-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.ctr-trade-label-row label {
  margin: 0;
}
.ctr-manage-trades-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.ctr-manage-trades-btn:hover {
  background: var(--bg-elevated);
  color: var(--accent);
  border-color: var(--accent);
}
.ctr-manage-trades-btn svg {
  width: 12px;
  height: 12px;
}

.ctr-trade-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
/* Override the base .callout-costs-cat-option for our chip-with-dot style */
.ctr-trade-chip {
  padding: 6px 10px 6px 8px !important;
  gap: 6px;
  font-size: var(--text-sm);
}
.ctr-trade-chip-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-block;
}
.ctr-trade-chip.is-selected .ctr-trade-chip-dot {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--cat-colour) 30%, transparent);
}

/* ── STATUS / BILLING CHIPS (segmented control) ─────────────────────── */
.ctr-status-grid {
  grid-template-columns: repeat(3, 1fr) !important;
}
.ctr-billing-grid {
  grid-template-columns: repeat(4, 1fr) !important;
}
@media (max-width: 520px) {
  .ctr-billing-grid { grid-template-columns: repeat(2, 1fr) !important; }
}
.ctr-status-chip {
  gap: 6px;
  padding: 9px 8px !important;
}
.ctr-status-chip.is-selected {
  border-color: var(--s-colour) !important;
  background: var(--s-soft) !important;
  color: var(--s-colour) !important;
}
.ctr-status-chip-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-block;
}

/* ── SLA GRID ───────────────────────────────────────────────────────── */
.ctr-sla-grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ctr-sla-row {
  display: grid;
  grid-template-columns: 130px 1fr 1fr;
  align-items: end;
  gap: 12px;
}
.ctr-sla-priority-label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: 600 var(--text-xs) / 1 var(--body);
  padding: 9px 10px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  white-space: nowrap;
  height: 41px;
}
.ctr-sla-field { gap: 4px !important; }
.ctr-sla-field label {
  font-size: 11px !important;
  font-weight: 500 !important;
  color: var(--text-muted) !important;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
@media (max-width: 520px) {
  .ctr-sla-row {
    grid-template-columns: 1fr;
    padding: 10px;
    background: var(--bg-base);
    border-radius: var(--radius-md);
  }
  .ctr-sla-priority-label {
    justify-content: flex-start;
    width: fit-content;
  }
}

/* ── CONTRACT DOCUMENTS UPLOAD ──────────────────────────────────────── */
.ctr-doc-zone {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ctr-doc-zone-cta {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 16px;
  background: var(--bg-base);
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
  font-family: inherit;
  text-align: left;
  color: inherit;
}
.ctr-doc-zone-cta:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}
.ctr-doc-zone-cta:active { transform: scale(0.997); }
.ctr-doc-zone-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  background: var(--accent);
  color: #001317;
  border-radius: var(--radius-md);
  flex-shrink: 0;
}
.ctr-doc-zone-icon svg { width: 20px; height: 20px; }
.ctr-doc-zone-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.ctr-doc-zone-title {
  font: 600 var(--text-base) / 1.2 var(--body);
  color: var(--text-primary);
}
.ctr-doc-zone-sub {
  font: 400 var(--text-xs) / 1.4 var(--body);
  color: var(--text-muted);
}
.ctr-doc-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ctr-doc-list:empty { display: none; }
.ctr-doc-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.ctr-doc-icon {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft, rgba(0,216,230,0.10));
  color: var(--accent);
  flex-shrink: 0;
}
.ctr-doc-icon svg { width: 14px; height: 14px; }
.ctr-doc-info {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
  min-width: 0;
}
.ctr-doc-name {
  font: 500 var(--text-sm) / 1.3 var(--body);
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ctr-doc-meta {
  font: 400 var(--text-xs) / 1 var(--body);
  color: var(--text-muted);
}
.ctr-doc-remove {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
  flex-shrink: 0;
}
.ctr-doc-remove:hover {
  background: rgba(220,38,38,0.10);
  color: #dc2626;
}
.ctr-doc-remove svg { width: 14px; height: 14px; }

/* ── COMPLIANCE TAB (insurance / certs with expiry) ─────────────────── */
.ctr-doc-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}
.ctr-doc-panel-head .ctr-info-section-title { margin: 0; }
.ctr-doc-add { flex: 0 0 auto; }
.ctr-doc-add svg { width: 16px; height: 16px; }

.ctr-doc-cards {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* One doc = a card. A left colour rail signals its expiry state at a glance
   (red expired · amber expiring · green valid · neutral undated). */
.ctr-doc-card {
  display: flex;
  align-items: stretch;
  gap: 8px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.ctr-doc-card.is-expired  { border-left-color: var(--rag-fail); }
.ctr-doc-card.is-expiring { border-left-color: var(--rag-warn); }
.ctr-doc-card.is-ok       { border-left-color: var(--rag-pass); }
.ctr-doc-card-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 12px 14px;
  background: none;
  border: 0;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.ctr-doc-card-main[disabled] { cursor: default; }
.ctr-doc-card-main:not([disabled]):hover { background: var(--bg-elevated); }
.ctr-doc-card-main:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Neutral type chip (two-tier rule — colour reserved for the expiry signal). */
.ctr-doc-type-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  font: 600 var(--text-xs, 11px) / 1 var(--body);
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 5px);
}
.ctr-doc-type-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-muted);
  flex: 0 0 auto;
}
.ctr-doc-card-name {
  font: 600 var(--text-base) / 1.3 var(--body);
  color: var(--text-primary);
  word-break: break-word;
}
.ctr-doc-card-dates {
  font: 500 var(--text-xs) / 1.3 var(--body);
  color: var(--text-muted);
}
.ctr-doc-card-signals { display: flex; flex-wrap: wrap; gap: 6px; }
/* Loud expiry chip — same language as the contract-expiry warning. */
.ctr-doc-expiry {
  display: inline-flex;
  align-items: center;
  font: 600 var(--text-xs, 11px) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm, 5px);
  border: 1px solid transparent;
}
.ctr-doc-expiry.is-expired {
  color: var(--rag-fail);
  background: color-mix(in srgb, var(--rag-fail-fill) 12%, transparent);
  border-color: color-mix(in srgb, var(--rag-fail-fill) 45%, transparent);
}
.ctr-doc-expiry.is-expiring {
  color: var(--rag-warn);
  background: color-mix(in srgb, var(--rag-warn-fill) 14%, transparent);
  border-color: color-mix(in srgb, var(--rag-warn-fill) 45%, transparent);
}
.ctr-doc-expiry.is-ok {
  color: var(--rag-pass);
  background: color-mix(in srgb, var(--rag-pass-fill) 12%, transparent);
  border-color: color-mix(in srgb, var(--rag-pass-fill) 45%, transparent);
}
.ctr-doc-expiry.is-none {
  color: var(--text-muted);
  background: var(--bg-elevated);
  border-color: var(--border);
}
.ctr-doc-card-actions {
  display: flex;
  align-items: center;
  padding: 6px 8px 6px 0;
  flex: 0 0 auto;
}
.ctr-doc-act { width: 34px; height: 34px; }
.ctr-doc-act svg { width: 17px; height: 17px; }

/* Type picker in the add/edit modal — single-select chip grid (the cycle-chip
   idiom, never a native <select>). */
.ctr-doctype-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.ctr-doctype-chip {
  padding: 7px 12px;
  font: 600 var(--text-sm) / 1 var(--body);
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.ctr-doctype-chip:hover { border-color: var(--border-strong, var(--border)); }
.ctr-doctype-chip.is-active {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
.ctr-doctype-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ctr-doc-zone-cta.has-file { border-style: solid; border-color: var(--accent); }

/* ── TRADE MANAGER MODAL ────────────────────────────────────────────── */
.ctr-trade-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ctr-trade-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.ctr-trade-row-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px 5px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font: 600 var(--text-sm) / 1 var(--body);
}
.ctr-trade-row-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.ctr-trade-row-builtin {
  font: 500 11px / 1 var(--body);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 3px 7px;
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  border: 1px solid var(--border);
}
.ctr-trade-row-actions {
  margin-left: auto;
  display: flex;
  gap: 4px;
}
.ctr-trade-row-btn {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.ctr-trade-row-btn:hover {
  background: var(--bg-base);
  color: var(--accent);
  border-color: var(--accent);
}
.ctr-trade-row-btn svg { width: 14px; height: 14px; }
.ctr-trade-row-btn-danger:hover {
  background: rgba(220,38,38,0.10);
  color: #dc2626;
  border-color: rgba(220,38,38,0.45);
}

/* ── HISTORY TAB ────────────────────────────────────────────────────── */
.ctr-history-panel {
  padding: 0;
}

/* Spend summary row */
.ctr-history-summary {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border, #e2e8f0);
}
.ctr-history-summary-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 16px 12px;
  border-right: 1px solid var(--border, #e2e8f0);
}
.ctr-history-summary-item:last-child { border-right: none; }
.ctr-history-summary-label {
  font: 500 11px / 1 var(--body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-secondary, #64748b);
}
.ctr-history-summary-value {
  font: 700 20px / 1 var(--font-display, 'Syne', sans-serif);
  color: var(--text-primary, #0f172a);
  font-variant-numeric: tabular-nums;
}

/* Feed — gap-separated cards (matches the contractor list / app card style)
   rather than a flush bordered feed, so each callout/service reads as its own
   entry. */
.ctr-history-feed {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
}
.ctr-history-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
/* Clickable rows (button variant) — reset native button chrome, full width,
   left-aligned, and give a calm hover/press + focus affordance so a history
   row reads as tappable (opens the linked call-out / asset). */
button.ctr-history-item {
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: background 0.12s ease, border-color 0.12s ease, transform 0.06s ease;
}
button.ctr-history-item:hover {
  background: var(--bg-elevated);
  border-color: var(--border-strong, var(--border));
}
button.ctr-history-item:active { transform: scale(0.995); }
button.ctr-history-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* "Open me" chevron — muted, nudges right on hover. */
.ctr-history-chev {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  align-self: center;
  color: var(--text-muted, #94a3b8);
  transition: transform 0.12s ease, color 0.12s ease;
}
button.ctr-history-item:hover .ctr-history-chev {
  color: var(--text-secondary);
  transform: translateX(2px);
}

/* Icon column */
.ctr-history-item-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm, 5px);
  flex-shrink: 0;
  margin-top: 2px;
}
.ctr-history-item-icon svg { width: 16px; height: 16px; }
.ctr-history-item-icon.is-callout {
  background: rgba(234,88,12,0.10);
  color: #ea580c;
  border: 1px solid rgba(234,88,12,0.30);
}
.ctr-history-item-icon.is-service {
  background: rgba(59,130,246,0.10);
  color: #3b82f6;
  border: 1px solid rgba(59,130,246,0.30);
}

.ctr-history-item-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ctr-history-item-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px;
}
/* Ref chip within history — NEUTRAL monospace (calm context, two-tier rule);
   colour is reserved for the status/priority signals beside it. */
.ctr-history-ref {
  display: inline-flex;
  align-items: center;
  font: 600 var(--text-xs, 11px) / 1 var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  padding: 4px 9px;
  border-radius: var(--radius-sm, 5px);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  background: var(--bg-elevated);
  letter-spacing: 0.02em;
}
/* Generic chip within history (status, type badge, etc.) — CALM: neutral chip +
   colour on the dot, matching the detail standard. One chip size. */
.ctr-history-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 500 var(--text-xs, 11px) / 1 var(--body);
  padding: 5px 9px;
  border-radius: var(--radius-sm, 5px);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-primary);
  white-space: nowrap;
}
.ctr-history-cdot {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
/* Subtle label to differentiate callout vs service in the feed */
.ctr-history-type-label {
  font: 500 var(--text-xs, 11px) / 1 var(--body);
  color: var(--text-muted, #94a3b8);
  margin-left: auto;
  flex-shrink: 0;
}
.ctr-history-item-title {
  font: 500 13px / 1.4 var(--body);
  color: var(--text-primary, #0f172a);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.ctr-history-item-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.ctr-history-asset {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font: 400 12px / 1 var(--body);
  color: var(--text-secondary, #64748b);
}
.ctr-history-asset svg { width: 11px; height: 11px; }
.ctr-history-time {
  font: 400 12px / 1 var(--body);
  color: var(--text-muted, #94a3b8);
}
.ctr-history-cost {
  display: inline-flex;
  align-items: center;
  font: 600 12px / 1 var(--body);
  color: #16a34a;
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

/* ═══════════════════════════════════════════════════════════════════════
   CHECKLISTS MODULE  (cl-*)
   ─────────────────────────────────────────────────────────────────────
   Three-tab list (Active / History / Templates) → template builder
   modal → runner overlay. Reuses callout-* form classes for consistency.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── CARD GRID ──────────────────────────────────────────────────────── */
.cl-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 12px;
}
@media (max-width: 720px) {
  .cl-card-grid { grid-template-columns: 1fr; }
}

.cl-card {
  display: flex;
  align-items: stretch;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.12s, box-shadow 0.12s, transform 0.06s;
  overflow: hidden;
  position: relative;
}
.cl-card:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
  box-shadow: 0 4px 14px color-mix(in srgb, var(--text-primary) 8%, transparent);
}
.cl-card:active { transform: scale(0.997); }
.cl-card-bar {
  display: block;
  width: 3px;
  flex-shrink: 0;
  background: #94a3b8;
  /* Category is calm context — its colour rides on .cl-card-cat-dot. The inline
     per-card background here is desaturated + dimmed so the left edge reads as a
     quiet accent, not a loud full-colour stripe (calm pass, Radek 2026-06-30). */
  filter: saturate(0.45);
  opacity: 0.5;
}
.cl-card-main {
  flex: 1;
  min-width: 0;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.cl-card-top {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

/* Card chips */
.cl-card-cat,
.cl-card-cycle,
.cl-card-due,
.cl-card-status,
.cl-card-auto-chip {
  display: inline-flex;
  align-items: center;
  font: 600 var(--text-xs) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
}
.cl-card-cycle,
.cl-card-cat {
  background: var(--bg-elevated);
  color: var(--text-secondary);
  border-color: var(--border);
}
.cl-card-cat { gap: 5px; line-height: 1.2; }  /* match the location chip height (23px), like the asset category chip */
.cl-card-cat-dot { width: 7px; height: 7px; border-radius: var(--radius-full); flex-shrink: 0; }
/* Loud signal row under the title — status + due (was crammed in the calm top). */
.cl-card-signals { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
/* CALM (calm pass 2026-06-30) — "Auto" is pure context, not an act-now signal,
   so it reads as a neutral chip with the accent confined to a leading dot. */
.cl-card-auto-chip {
  gap: 5px;
  background: var(--bg-elevated);
  color: var(--text-secondary);
  border-color: var(--border);
}
.cl-card-auto-chip::before {
  content: ''; width: 6px; height: 6px; border-radius: var(--radius-full);
  background: var(--accent); flex-shrink: 0;
}
/* "Due in X" (plenty of time) is calm context — neutral chip, green on the dot
   only — so it doesn't compete with the genuine amber/red deadline alarms below,
   which STAY loud (act-now). (calm pass 2026-06-30) */
.cl-card-due.is-safe    { gap: 6px; color: var(--text-primary); background: var(--bg-elevated); border-color: var(--border); font-weight: 500; }
.cl-card-due.is-safe::before { content: ''; width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--rag-pass-fill); flex-shrink: 0; }
.cl-card-due.is-warning { color: var(--rag-warn); background: color-mix(in srgb, var(--rag-warn-fill) 12%, transparent);  border-color: color-mix(in srgb, var(--rag-warn-fill) 45%, transparent); }
.cl-card-due.is-breach  { color: var(--rag-fail); background: color-mix(in srgb, var(--rag-fail-fill) 12%, transparent);  border-color: color-mix(in srgb, var(--rag-fail-fill) 45%, transparent); }

/* CALM (2026-06-29) — status reads neutral + colour on the dot; the due chip
   above stays LOUD (deadline alarm). */
.cl-card-status {
  gap: 6px;
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text-primary);
  font-weight: 500;
}
.cl-card-status::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-muted); flex-shrink: 0;
}
.cl-card-status[data-status="open"]::before        { background: #3b82f6; }
.cl-card-status[data-status="in_progress"]::before  { background: var(--rag-warn-fill); }
.cl-card-status[data-status="completed"]::before    { background: var(--rag-pass-fill); }
.cl-card-status[data-status="missed"]::before       { background: var(--rag-fail-fill); }

.cl-card-title {
  font: 600 var(--text-base) / 1.3 var(--body);
  color: var(--text-primary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cl-card-desc {
  font: 400 var(--text-sm) / 1.4 var(--body);
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cl-card-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.cl-card-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font: 500 var(--text-xs) / 1 var(--body);
  color: var(--text-secondary);
}
.cl-card-meta-item svg { width: 12px; height: 12px; flex-shrink: 0; }
.cl-card-meta-time {
  font: 400 var(--text-xs) / 1 var(--body);
  color: var(--text-muted);
  margin-left: auto;
}

.cl-card-progress {
  display: flex;
  align-items: center;
  gap: 8px;
}
.cl-card-progress-track {
  flex: 1;
  height: 5px;
  background: var(--bg-elevated);
  border-radius: 3px;
  overflow: hidden;
  display: flex;   /* segments sit side by side (2026-07-05) */
}
.cl-card-progress-fill {
  height: 100%;
  background: var(--accent);
  transition: width 0.2s;
  flex-shrink: 0;
}
/* Segmented card bar (2026-07-05) — same verdict-in-proportion semantics as
   the runner bars above. */
.cl-card-progress-fill.is-seg-pass  { background: var(--rag-pass-fill); }
.cl-card-progress-fill.is-seg-warn  { background: var(--rag-warn-fill); }
.cl-card-progress-fill.is-seg-fail  { background: var(--rag-fail-fill); }
.cl-card-progress-fill.is-seg-other { background: var(--accent); }
.cl-card-progress-label {
  font: 600 var(--text-xs) / 1 var(--body);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.cl-card-actions {
  display: flex;
  gap: 6px;
  margin-top: 4px;
}
.cl-card-start-btn,
.cl-card-open-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 600 var(--text-sm) / 1 var(--body);
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.cl-card-start-btn {
  background: var(--accent);
  color: #001317;
}
.cl-card-start-btn:hover { filter: brightness(1.08); }
.cl-card-start-btn svg { width: 14px; height: 14px; }
.cl-card-open-btn {
  background: transparent;
  color: var(--text-secondary);
  border-color: var(--border);
}
.cl-card-open-btn:hover { color: var(--text-primary); border-color: var(--text-secondary); }
/* Copy-to-another-site icon button — secondary, icon-only square, matches the
   .cl-card-open-btn chrome. Manager-gated (checklists.manage). Opens the
   Site→Department copy picker (modules/checklists/copy.js). */
.cl-card-copy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  padding: 8px;
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.cl-card-copy-btn:hover { color: var(--text-primary); border-color: var(--text-secondary); }
.cl-card-copy-btn svg { width: 16px; height: 16px; }

/* Copy picker — one-line hint above the Site/Department pickers. The picker
   itself reuses the Tasks "Move to department" modal (.tasks-modal-deptpick),
   so it needs no modal CSS of its own. */
.cl-copy-hint {
  margin: 0 0 4px;
  font: 400 var(--text-sm) / 1.5 var(--body);
  color: var(--text-secondary);
}

/* ── TEMPLATE BUILDER MODAL ─────────────────────────────────────────── */
.cl-form-modal-wide { max-width: 760px; }

/* Compact footer so the action bar doesn't crowd the editing area, and so the
   Archive / Save buttons NEVER wrap onto a second line on a narrow phone (the
   long "Archive template" label used to wrap, ballooning the footer to ~81px).
   (Header is compacted via the shared rule above.) */
.cl-form-modal .callout-modal-foot { padding: 10px 14px; gap: 8px;
  /* The footer is pinned to the bottom of this full-height editor sheet, so on
     a notched iPhone the Save/Archive buttons sat inside the home-indicator
     strip — iOS swallowed the taps there and Save "did nothing" (a desktop
     click, which ignores position, worked). Lift the footer above the home
     indicator with the bottom safe-area inset. Longhand, after the shorthand,
     so it overrides padding-bottom (and Safari doesn't drop a max()/calc()
     placed in the shorthand's first slot). */
  padding-bottom: max(10px, calc(env(safe-area-inset-bottom) + 10px)); }
.cl-form-modal .callout-modal-foot .callout-btn {
  white-space: nowrap;
  min-width: 0;
}

/* Header "Preview" pill — opens the runner on the current draft (sandbox). */
.cl-form-preview-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 6px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font: 600 var(--text-sm) / 1 var(--body);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s;
}
.cl-form-preview-btn:hover { border-color: var(--accent); color: var(--accent); }
.cl-form-preview-btn svg { width: 15px; height: 15px; }

/* Basic-info section has no section header — promote its field labels (Name /
   Description / Category) to the SAME font as a section head (.callout-form-
   section-head: display font, base size, primary colour) so they read clearly
   instead of as faint secondary labels. */
.cl-basic-section .callout-form-field > label {
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}

/* ── Template builder: clearly-defined input fields (Radek 2026-06-30; polarity
   flip 2026-07-05). The builders now sit on the RUNNER polarity — grey modal
   body, WHITE .callout-form-section panels and WHITE check/section cards (see
   the "BUILDERS → runner polarity" block at the end of css/15). Every type-in
   control therefore takes the canonical Tasks treatment: a GREY --bg-elevated
   fill on the white panel/card (the .tasks-field pattern), a real --border-input
   outline and an accent focus ring, so each one reads as a distinct, tappable
   box. background-COLOR (not the shorthand) so native select chevrons /
   appearances survive. Scoped to .cl-form-modal, shared by the checklist AND
   audit template builders (identical twins); the rest of the app keeps today's
   treatment until a deliberate app-wide roll-out. */
.cl-form-modal .callout-form-field input[type="text"],
.cl-form-modal .callout-form-field input[type="tel"],
.cl-form-modal .callout-form-field input[type="email"],
.cl-form-modal .callout-form-field input[type="number"],
.cl-form-modal .callout-form-field input[type="date"],
.cl-form-modal .callout-form-field textarea,
.cl-form-modal .callout-form-field-textarea,
.cl-form-modal .callout-form-field select,
.cl-form-modal .tasks-priority-trigger,
.cl-form-modal .ah-locfield {
  background-color: var(--bg-elevated);
  border: 1px solid var(--border-input);
}
.cl-form-modal .tasks-priority-trigger:hover,
.cl-form-modal .ah-locfield:hover { border-color: var(--accent); }
.cl-form-modal .callout-form-field input[type="text"]:focus,
.cl-form-modal .callout-form-field input[type="tel"]:focus,
.cl-form-modal .callout-form-field input[type="email"]:focus,
.cl-form-modal .callout-form-field input[type="number"]:focus,
.cl-form-modal .callout-form-field input[type="date"]:focus,
.cl-form-modal .callout-form-field textarea:focus,
.cl-form-modal .callout-form-field-textarea:focus,
.cl-form-modal .callout-form-field select:focus,
.cl-form-modal .tasks-priority-trigger[aria-expanded="true"],
.cl-form-modal .ah-locfield:focus {
  border-color: var(--accent);
  background-color: var(--bg-elevated);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}

/* ── …and EVERY control inside the check cards too (Radek 2026-06-30; polarity
   flip 2026-07-05). The check cards are WHITE now (runner polarity), so every
   type-in field inside them takes the grey --bg-elevated fill — grey pills on a
   white card, exactly like the runner's answer buttons and fail controls. The
   --border-input outline + accent focus ring stay. Same .cl-form-modal scope
   (checklist + audit twins). background-COLOR / border-COLOR longhand so the
   cards' other borders (e.g. the section's accent left bar, the Delete button's
   red edge) and native select chevrons all survive. */
.cl-form-modal .cl-item-label,
.cl-form-modal .cl-item-followup,
.cl-form-modal .cl-item-unit-custom,
.cl-form-modal .cl-item-unit-select,
.cl-form-modal .cl-item-energy-meter {
  background-color: var(--bg-elevated);
  border-color: var(--border-input);
}
.cl-form-modal .cl-item-label:focus,
.cl-form-modal .cl-item-followup:focus,
.cl-form-modal .cl-item-unit-custom:focus,
.cl-form-modal .cl-item-unit-select:focus,
.cl-form-modal .cl-item-energy-meter:focus {
  border-color: var(--accent);
  background-color: var(--bg-elevated);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Reading safe-range numbers join the grey-field treatment; the section title
   input keeps its white fill (it sits on the tinted section HEAD, not the card). */
.cl-form-modal .cl-zone-input {
  background-color: var(--bg-elevated);
  border-color: var(--border-input);
}
.cl-form-modal .cl-section-title-input { border-color: var(--border-input); }
.cl-form-modal .cl-zone-input:focus,
.cl-form-modal .cl-section-title-input:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Buttons / tiles / icons: the "On fail" chip, the action-row icons and the
   Add-check tiles ("add to checklist" icons). Grey pills on the white card
   (runner polarity, 2026-07-05); the accent glyphs stay. The red Delete keeps
   its red edge. */
.cl-form-modal .cl-item-fail-btn,
.cl-form-modal .cl-item-btn,
.cl-form-modal .cl-add-item-btn { background-color: var(--bg-elevated); }
.cl-form-modal .cl-item-fail-btn,
.cl-form-modal .cl-item-btn:not(.cl-item-btn-danger),
.cl-form-modal .cl-add-item-btn { border-color: var(--border-input); }
.cl-form-modal .cl-item-fail-btn:hover,
.cl-form-modal .cl-item-btn:not(.cl-item-btn-danger):hover,
.cl-form-modal .cl-add-item-btn:hover { border-color: var(--accent); }
.cl-form-modal .cl-add-item-btn:hover {
  background-color: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
  color: var(--text-primary);
}

/* The shared photo + Info buttons (ui/step-block.js, KB-instruction classes) in
   the check's action row take the same grey-pill treatment as the location pin
   (white cards, 2026-07-05). The "Info added" signal
   (.kb-instr-edit-step-info-active) keeps its accent tint — it's a deliberate
   filled state, left untouched. */
.cl-form-modal .kb-instr-edit-photo-add,
.cl-form-modal .kb-instr-edit-step-info-add {
  background-color: var(--bg-elevated);
  border-color: var(--border-input);
}
.cl-form-modal .kb-instr-edit-photo-add:hover,
.cl-form-modal .kb-instr-edit-photo-add:active,
.cl-form-modal .kb-instr-edit-step-info-add:hover,
.cl-form-modal .kb-instr-edit-step-info-add:active {
  border-color: var(--accent);
  background-color: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
  color: var(--text-primary);
}

/* Containers: the cards themselves are WHITE on the grey canvas (runner
   polarity — the background flips live at the end of css/15); here we keep the
   firm edges so cards read against the white section wells too (the accent left
   bar + Delete's red edge are left untouched). */
.cl-form-modal .cl-item { border-color: var(--border-input); }
.cl-form-modal .cl-section-card {
  border-top-color: var(--border-input);
  border-right-color: var(--border-input);
  border-bottom-color: var(--border-input);
}

/* Schedule: the recurring-only block flows with its section instead of reading
   as a sub-card, so One-off and Recurring look the same (Radek). The section
   panel is WHITE now (polarity flip 2026-07-05), so "flow" means transparent —
   the grey recurrence fields pop on the white panel exactly like the One-off /
   duration rows around them. .cl-form-modal scope leaves Compliance's block
   untouched. */
.cl-form-modal .cl-recurring-block {
  background-color: transparent;
  border-color: transparent;
}

/* Audit builder: the question / option / follow-up / dept-select fields use
   .audit-input (css/15), whose grey --bg-elevated base is exactly right on the
   now-WHITE cards (polarity flip 2026-07-05) — this rule just firms the edge and
   keeps the focus ring. background-COLOR (not the shorthand) so the
   .audit-select dropdown chevron survives; my .cl-form-modal .audit-input
   (0,2,0) beats the css/15 base (.audit-input, 0,1,0) regardless of file order.
   The audit RUNNER's .audit-input (a different surface) is untouched. */
.cl-form-modal .audit-input {
  background-color: var(--bg-elevated);
  border-color: var(--border-input);
}
.cl-form-modal .audit-input:focus {
  border-color: var(--accent);
  background-color: var(--bg-elevated);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.cl-form-body {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* Category chip tweaks — make the dot prominent */
.cl-cat-chip { padding: 6px 10px 6px 8px !important; gap: 6px; font-size: var(--text-sm); }
.cl-cat-chip-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-block;
}
.cl-cat-grid { gap: 6px; }

/* Cycle segmented control — 2 options (One-off / Recurring) */
.cl-cycle-grid {
  grid-template-columns: 1fr 1fr !important;
}

/* Recurring-only fields — show only when "Recurring" is selected */
.cl-recurring-block {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-top: -4px;
}
.cl-recurring-block[hidden] { display: none; }

.cl-recurrence-input-row {
  display: flex;
  gap: 8px;
}
.cl-recurrence-interval {
  width: 90px !important;
  flex-shrink: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.cl-recurrence-unit {
  flex: 1;
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.cl-recurrence-unit:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
}

/* Duration field — number + Days/Hours segmented toggle. Used by Time to
   complete + Amber warning. Day-first reads clearer than raw hours; Hours is
   one tap away for short checks. */
.cl-dur-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.cl-dur-input {
  width: 88px !important;
  flex-shrink: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.cl-dur-units {
  display: inline-flex;
  flex: 1;
  gap: 3px;
  padding: 3px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.cl-dur-unit-btn {
  flex: 1;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font: 600 var(--text-sm) / 1 var(--body);
  padding: 8px 10px;
  border-radius: calc(var(--radius-md) - 3px);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.cl-dur-unit-btn:hover { color: var(--text-primary); }
.cl-dur-unit-btn.is-active {
  background: var(--accent);
  color: #fff;
}

/* Toggle (custom switch style) */
.cl-toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
}
.cl-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.cl-toggle-slider {
  position: relative;
  width: 36px;
  height: 20px;
  background: var(--border);
  border-radius: 999px;
  transition: background 0.15s;
  flex-shrink: 0;
}
.cl-toggle-slider::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 16px; height: 16px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.15s;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}
.cl-toggle input:checked + .cl-toggle-slider {
  background: var(--accent);
}
.cl-toggle input:checked + .cl-toggle-slider::after {
  transform: translateX(16px);
}
.cl-toggle-label {
  font: 500 var(--text-sm) / 1.3 var(--body);
  color: var(--text-primary);
}

/* ── ITEM EDITOR (within template builder) ──────────────────────────── */
.cl-items-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Non-tick check rows (Yes/No, Reading, Info) adopt the Tick check's
   KB step-block shape: [round badge] [main content column] [vertical
   action column], top-aligned, so every check type reads identically. */
.cl-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.cl-item:focus-within { border-color: var(--accent); }
/* Click-to-select: the active check the ↑/↓ arrows will move. A clear accent
   ring so it's always obvious which card is selected during navigation. */
.cl-item.is-selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 32%, transparent);
}
.cl-item-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Round number badge — matches the Tick check's KB step-block badge
   (.kb-instr-edit-step-num) so every check type reads identically. */
.cl-item-num {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  background: var(--accent);
  color: var(--bg-base);
  font: 700 var(--text-base) / 1 var(--display, var(--body));
  border-radius: var(--radius-full);
  flex-shrink: 0;
}
.cl-item-type-pill {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;   /* content-width pill — don't stretch in the flex column */
  font: 600 var(--text-xs) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
}
.cl-item-type-pill.is-tick    { background: rgba(22,163,74,0.10);  color: #16a34a; border-color: rgba(22,163,74,0.45); }
.cl-item-type-pill.is-yesno   { background: rgba(59,130,246,0.10); color: #3b82f6; border-color: rgba(59,130,246,0.45); }
.cl-item-type-pill.is-reading { background: rgba(234,88,12,0.10);  color: #ea580c; border-color: rgba(234,88,12,0.45); }
.cl-item-type-pill.is-info    { background: rgba(99,102,241,0.10); color: #6366f1; border-color: rgba(99,102,241,0.45); }
/* Notice pill stays neutral — the callout's identity colour is shown by the
   pre-coloured Warning/Important/Tip/Info picker below, so the pill doesn't
   compete with it. */
.cl-item-type-pill.is-notice  { background: var(--bg-elevated); color: var(--text-secondary); border-color: var(--border); }

/* The per-check location now lives on the card itself — a shared `.card-loc-chip`
   (own / `--ghost` "from section" when inherited) + the compact `.cl-item-btn` pin
   in the action row (audit parity, Radek 2026-06-30). No bespoke button style. */
.callout-form-help-inline { font-weight: 400; font-size: var(--text-xs); color: var(--text-muted); }

.cl-item-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}
/* Move / remove buttons — mirror the Tick check's KB step-block actions
   (.kb-block-action-btn) so the chrome matches across check types:
   38×38 tap target, 20px icons, delete red by default. */
.cl-item-btn {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s, transform 0.06s;
  flex-shrink: 0;
}
.cl-item-btn:hover {
  background: var(--bg-surface);
  color: var(--text-primary);
  border-color: var(--border-strong, var(--text-muted));
}
.cl-item-btn:active { transform: scale(0.96); }
.cl-item-btn svg { width: 18px; height: 18px; stroke-width: 2.2; }
/* Delete variant — red icon + tinted border by default (not just on hover). */
.cl-item-btn-danger {
  color: #dc2626;
  border-color: color-mix(in srgb, #dc2626 25%, var(--border));
}
.cl-item-btn-danger:hover {
  background: color-mix(in srgb, #dc2626 10%, transparent);
  color: #dc2626;
  border-color: color-mix(in srgb, #dc2626 50%, transparent);
}

.cl-item-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cl-item-label,
.cl-item-followup,
.cl-item-unit-custom {
  font: 400 var(--text-base) / 1 var(--body);
  color: var(--text-primary);
  padding: 9px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: border-color 0.12s, background 0.12s;
  font-family: inherit;
  width: 100%;
}
.cl-item-label:focus,
.cl-item-followup:focus,
.cl-item-unit-custom:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
}
.cl-yesno-task-toggle {
  display: flex !important;
  align-items: flex-end !important;
}

/* Action row — the compact photo/info chips + the "create task" toggle on
   one line. The toggle is pushed to the right to use the space the slimmer
   chips freed up; on a narrow phone the row wraps instead of colliding. */
.cl-item-action-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
}
.cl-item-action-row .kb-doc-block-bottom-row { margin-top: 0; flex: 0 0 auto; }
.cl-action-toggle {
  margin-left: auto;
  flex-shrink: 0;
}
/* Empty state (no photo yet): "On fail" chip on the LEFT, the photo icon + the
   labelled "Info" chip pushed RIGHT — all on ONE line (Radek 2026-06-26). The
   photo uses its base 34px icon; Info keeps its label. On a narrow phone the row
   wraps gracefully (.cl-item-action-row is flex-wrap). A placed photo is a big
   block, so it renders ABOVE the action row and "On fail" sits below it. */
.cl-item-v2 .cl-item-action-row .kb-doc-block-bottom-row { margin-left: auto; }

/* ── v2 CHECK CARD (Tick first, 2026-06-25) ───────────────────────────
   Header strip (number + type pill + up/down/delete on the right, like a
   section header) → full-width body. Reclaims the whole card width the old
   side action column used to steal. Opt-in via .cl-item-v2 so the other check
   types keep their layout until this is rolled over to them. */
.cl-item-v2 {
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}
.cl-item-head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.cl-item-head .cl-item-type-pill { align-self: center; }
.cl-item-actions-head {
  flex-direction: row;        /* override the column side-stack */
  margin-left: auto;          /* push reorder/remove to the right */
}
.cl-item-v2 .cl-item-body { gap: 12px; }

/* On-fail disclosure chip — the canonical calm function chip + a chevron. The
   flag icon is accent (like the photo/info icons); .is-active (create-task-on-
   fail ON) tints the chip so it reads as armed without opening it. */
.cl-item-fail-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  min-height: 38px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font: 600 var(--text-sm) / 1 var(--body);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
  flex-shrink: 0;
}
.cl-item-fail-btn svg:not(.cl-fail-chev) { width: 18px; height: 18px; color: var(--accent); flex-shrink: 0; }
.cl-item-fail-btn .cl-fail-chev { width: 13px; height: 13px; opacity: 0.65; transition: transform 0.15s; flex-shrink: 0; }
.cl-item-fail-btn.is-open .cl-fail-chev { transform: rotate(180deg); }
.cl-item-fail-btn:hover {
  border-color: var(--accent);
  color: var(--text-primary);
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
}
/* "On fail" stays the NEUTRAL chip so it reads as one set with the photo/info
   icon buttons (Radek 2026-06-25 — the old .is-active accent border/tint was
   removed). The flag icon stays accent, exactly like the photo/info icons. */

/* The folded "on Fail" config (unfolds under the action row) */
.cl-item-fail-config {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.cl-item-fail-config[hidden] { display: none; }
.cl-fail-config-toggle { align-self: flex-start; }

/* ── Reading CARD: one Location + many measurements (2026-07-01) ─────────
   A reading check is a card whose body stacks one row per measurement
   (What's-measured + Unit + its Options fold). Rows sit on the card surface,
   separated by a calm dashed divider — no nested grey box, so the inputs keep
   their existing contrast. The card's Location (pin + chip) + photo/info live
   in the card action row, exactly like Pass/Fail. */
.cl-reading-measures { display: flex; flex-direction: column; }
.cl-reading-measure {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 0 2px;
}
.cl-reading-measure:first-child { padding-top: 2px; }
.cl-reading-measure + .cl-reading-measure { border-top: 1px dashed var(--border); }
/* Name (flexible) + Unit (natural width) + a Remove button, aligned to the
   input baseline; wraps on a narrow phone. */
.cl-reading-measure-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px 12px;
}
.cl-reading-measure-fields > .callout-form-field { margin: 0; }
.cl-reading-measure-name { flex: 1 1 150px; min-width: 0; }
.cl-reading-measure-remove { flex: 0 0 auto; margin-bottom: 1px; }
/* "Options" chip on the LEFT; the card-level Location pin + photo/info pushed
   RIGHT (only on the first measurement) so the pin sits in line with Options and
   we drop the old standalone card action row (Radek 2026-07-01). */
.cl-reading-measure-action-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cl-reading-card-controls { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; }
/* ONE 38px toolbar (Radek 2026-07-16): inside any builder check card (.cl-item —
   checklist AND audit builders), the shared KB photo + "Info" chips rise from
   their 34px KB-editor metrics to the row's 38px rhythm (.cl-item-btn pin,
   "On fail"/"Options" chips, and the filled Info icon are all 38px already —
   the Info button used to JUMP 34→38 when info was added). Icons match the
   pin's 18px. KB's own editor keeps its 34px canonical chip untouched. */
.cl-item .kb-instr-edit-photo-add-inline {
  width: 38px;
  min-width: 38px;
  min-height: 38px;
}
.cl-item .kb-instr-edit-photo-add-inline svg { width: 18px; height: 18px; }
.cl-item .kb-instr-edit-step-info-add { min-height: 38px; }
.cl-item .kb-instr-edit-step-info-add svg { width: 18px; height: 18px; }
/* The Reading row's card controls wrap the KB bottom-row too — zero its 8px
   top margin (the tick/yes-no action row already does this above) so the pin,
   photo and Info sit on ONE baseline instead of the pair hanging 8px low. */
.cl-reading-card-controls .kb-doc-block-bottom-row { margin-top: 0; align-items: center; }

/* ── Times of day (multi-daily slots, 2026-07-16) ─────────────────────────
   The schedule section's optional slot editor: chips of added times + an
   add row. The explicit [hidden] rule is REQUIRED — .callout-form-field sets
   display:flex, which silently beats the UA [hidden] rule (§6). */
.cl-times-field[hidden] { display: none; }
.cl-times-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cl-item-fail-btn.cl-time-chip svg { width: 13px; height: 13px; color: currentColor; opacity: 0.75; }
.cl-times-add-row { display: flex; align-items: center; gap: 8px; }
/* type="time" is missing from the form's generic input-type lists (css/12 +
   the .cl-form-modal overrides above only name text/number/date/…), so the
   UA default white box leaks through in dark mode — style it to match the
   date input exactly, scoped to this row. */
.cl-times-add-row input[type="time"] {
  max-width: 150px;
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  padding: 8px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
}
.cl-times-add-row input[type="time"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}
/* "+ Add measurement" — a calm dashed ghost button, full width. */
.cl-reading-add-measure {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  margin-top: 10px;
  padding: 9px 12px;
  background: transparent;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font: 600 var(--text-sm) / 1 var(--body);
  cursor: pointer;
}
.cl-reading-add-measure:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--bg-hover);
}
.cl-reading-add-measure svg { width: 15px; height: 15px; }

/* Tick Pass/Fail config in the template editor — sits under the tick step
   block, set off with a subtle top divider so it reads as the check's
   run-time behaviour (mirrors the Yes/No follow-up + toggle row). */
.cl-tick-fail-config {
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px dashed var(--border);
}
.cl-tick-fail-config-hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-bottom: 10px;
}

/* ── STEP-STYLE TICK ITEM (mirrors KB step block UX) ─────────────── */
.cl-item-body-step {
  padding: 12px !important;
  gap: 8px !important;
}
.cl-step-text {
  font: 400 var(--text-base) / 1.4 var(--body);
  color: var(--text-primary);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: border-color 0.12s, background 0.12s;
  font-family: inherit;
  width: 100%;
  resize: none;        /* auto-grow handles size */
  overflow: hidden;    /* hide scrollbar while growing */
  min-height: 40px;
}
.cl-step-text:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
}
.cl-step-bottom-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.cl-step-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font: 500 var(--text-xs) / 1 var(--body);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
  font-family: inherit;
}
.cl-step-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  border-style: solid;
}
.cl-step-btn svg { width: 13px; height: 13px; flex-shrink: 0; }
.cl-step-btn.is-active {
  border-style: solid;
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: var(--accent-soft, rgba(0,216,230,0.08));
  color: var(--accent);
}
.cl-step-btn-photo.is-active { background: rgba(99,102,241,0.10); color: #6366f1; border-color: rgba(99,102,241,0.45); }
.cl-step-btn-info.is-active  { background: rgba(245,158,11,0.10); color: #d97706; border-color: rgba(245,158,11,0.45); }

/* When a KB modal opens on top of a callout/checklist modal (e.g. tick item
   "+ Info" invokes KB's Step Info editor as a nested overlay), it needs to
   render above. callout-modal-overlay is z-index 9000 and KB modals default
   to 300 — bump them above when stacked. */
body.callout-modal-open .kb-modal-overlay { z-index: 9500; }
body.callout-modal-open .kb-modal-overlay.open { z-index: 9500; }

/* Shared textarea base — used by the Info check's instruction body and
   any callout-style textarea inside the builder. */
.cl-item-info-text,
.callout-form-field-textarea {
  font: 400 var(--text-sm) / 1.5 var(--body);
  color: var(--text-primary);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  resize: vertical;
  width: 100%;
  font-family: inherit;
}

/* "Add photo" / "+ Info" check actions now inherit the SHARED canonical
   function-chip (css/03 .kb-instr-edit-photo-add / -step-info-add) — calm
   neutral tile, accent icon, matching the Tasks + add-check chips. The old
   loud-accent checklist override was removed (2026-06-25, app-wide
   consistency pass) so KB + Checklists share one button look. */
.cl-item-info-text:focus,
.callout-form-field-textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
}

/* ── ZONE EDITOR (reading item) ─────────────────────────────────────── */
.cl-zone-intro { margin: 4px 0 10px; }

/* Safe-range DESIGNER (Radek 2026-07-01): labels ABOVE the traffic-light bar
   (Critical · Good range · Critical) and the number inputs BELOW it, every column
   aligned to its own zone — so the control reads like the bar it configures. The
   green band is the widest column (it's the target). Three sibling grids share one
   template so labels, segments and inputs line up vertically. Replaces the old bar
   + two-row ladder; far shorter and self-explaining. */
.cl-zband { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }
.cl-zband-labels,
.cl-zband .cl-zone-bar,
.cl-zband-inputs {
  display: grid;
  grid-template-columns:
    minmax(0, 1fr) minmax(0, 0.5fr) minmax(0, 2.2fr) minmax(0, 0.5fr) minmax(0, 1fr);
  gap: 6px;
  align-items: center;
  margin: 0;
}
.cl-zband-lab {
  font: 700 var(--text-xs) / 1.1 var(--body);
  text-align: center;
  white-space: nowrap;
}
.cl-zband-lab.is-crit  { color: var(--rag-fail); }
.cl-zband-lab.is-green { color: var(--rag-pass); }
.cl-zband-inputs { align-items: start; }
.cl-zband-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 0;
}
.cl-zband-crit { flex-direction: column; gap: 4px; }
.cl-zband-cap {
  font: 600 var(--text-xs) / 1 var(--body);
  color: var(--text-muted);
}
.cl-zband-good .cl-zone-input { width: 100%; max-width: 78px; }
.cl-zband-crit .cl-zone-input { width: 100%; max-width: 66px; }

.cl-zone-bar-seg { height: 8px; border-radius: 999px; }
.cl-zone-bar-seg.is-crit  { background: var(--rag-fail-fill); }
.cl-zone-bar-seg.is-amber { background: var(--rag-warn-fill); }
.cl-zone-bar-seg.is-green { background: var(--rag-pass-fill); }

/* The colour dot — still used by the per-zone auto-task toggles below. */
.cl-zone-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  flex-shrink: 0;
}
.cl-zone-dot.is-crit  { background: var(--rag-fail-fill); }
.cl-zone-dot.is-amber { background: var(--rag-warn-fill); }
.cl-zone-dot.is-green { background: var(--rag-pass-fill); }
/* The "to" between the good-band inputs. */
.cl-zone-sep {
  font: 500 var(--text-xs) / 1 var(--body);
  color: var(--text-muted);
  flex-shrink: 0;
}
.cl-zone-input {
  width: 60px;
  flex-shrink: 0;
  padding: 7px 6px;
  text-align: center;
  font: 600 var(--text-sm) / 1 var(--body);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  font-family: inherit;
}
.cl-zone-input:focus {
  outline: none;
  border-color: var(--accent);
}

/* Unit control — native select of curated units + a "Custom…" text field.
   Matches the schedule's cycle-unit select for consistency. */
.cl-item-unit-select,
.cl-item-energy-meter {
  width: 100%;
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.cl-item-unit-select:focus,
.cl-item-energy-meter:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
}
.cl-item-energy-meter:disabled { opacity: .6; cursor: default; }
.cl-item-unit-custom { margin-top: 8px; }

/* Reading → Energy meter feed — rarely used, so it folds behind a quiet
   disclosure (reuses the shared .cl-item-fail-btn chip; Radek 2026-07-01). The
   toggle is a full-width summary row with the chevron pushed to the right; the
   <select> lives in the body and only shows when opened (default: only if a meter
   is already linked). */
.cl-reading-energy-feed {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--border);
}
.cl-energy-toggle { width: 100%; justify-content: flex-start; }
.cl-energy-toggle .cl-fail-chev { margin-left: auto; }
.cl-reading-energy-body { margin-top: 10px; }
.cl-reading-energy-body[hidden] { display: none; }
.cl-opt { font-weight: 500; color: var(--text-muted); font-size: var(--text-xs); }

/* Per-zone auto-task toggles — Amber / Critical, mirrors the Yes/No toggle. */
.cl-reading-task-config {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--border);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cl-reading-task-config-hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.cl-reading-task-toggle .cl-toggle-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.cl-reading-task-toggle .cl-zone-dot { width: 10px; height: 10px; }

/* ── ADD-ITEM PICKER ────────────────────────────────────────────────── */
.cl-add-item-row {
  margin-top: 4px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cl-add-item-label {
  font: 600 var(--text-xs) / 1 var(--body);
  color: var(--text-muted);
}
/* Compact "add a check" picker — reuses the Tasks quick-action chip look
   (.callout-detail-quick-chip): calm neutral tiles that recede until needed,
   colour lives only on the icon, and all five check types fit one row. Same
   dimensions so the builder's add buttons match the rest of the app instead
   of being the chunky 4-up grid they were. */
.cl-add-item-buttons {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
}
/* Bottom picker carries a 5th "Add section" tile → 5 across (matches the Tasks
   5-up quick-action grid). The section tile is the same chip, just a different
   action (data-cl-add-section, not data-add-type). */
.cl-add-item-buttons.has-section {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.cl-add-item-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 10px 3px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font: 600 11px / 1.15 var(--body);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s, transform 0.1s;
  -webkit-tap-highlight-color: transparent;
  font-family: inherit;
  min-width: 0;
}
.cl-add-item-btn:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
  color: var(--text-primary);
}
.cl-add-item-btn:active { transform: scale(0.96); }
.cl-add-item-btn-icon {
  display: grid;
  place-items: center;
}
.cl-add-item-btn-icon svg { width: 18px; height: 18px; stroke-width: 2; color: var(--accent); }

/* ════════════════════════════════════════════════════════════════════
   CHECKLIST SECTIONS — collapsible room-by-room / area grouping.
   Builder cards (template editor) + run-mode cards (with per-section RAG
   status bars). Mirrors the KB document-section collapse language
   (chevron + aria-expanded + display:none) with checklist `cl-` classes.
   ════════════════════════════════════════════════════════════════════ */

/* ── Builder: bottom add-row (ungrouped picker + Add section) ──────── */
.cl-checks-add-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* (.cl-add-section-btn removed 2026-06-25 — "Add section" is now a tile in the
   add-check row, styled by .cl-add-item-btn.) */

/* ── Builder: one collapsible section card ─────────────────────────── */
.cl-section-card {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  overflow: hidden;
}
.cl-section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: color-mix(in srgb, var(--accent) 7%, var(--bg-elevated));
  border-bottom: 1px solid var(--border);
}
.cl-section-card.is-collapsed .cl-section-head { border-bottom-color: transparent; }
.cl-section-collapse {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
}
.cl-section-collapse:hover { background: var(--bg-surface); color: var(--text-primary); }
.cl-section-chevron { width: 18px; height: 18px; transition: transform 0.15s; }
.cl-section-collapse[aria-expanded="false"] .cl-section-chevron { transform: rotate(-90deg); }
.cl-section-title-input {
  flex: 1;
  min-width: 0;
  font: 700 var(--text-base) / 1.2 var(--display);
  color: var(--text-primary);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 7px 10px;
}
.cl-section-title-input:focus { outline: none; border-color: var(--accent); }
.cl-section-title-input::placeholder { color: var(--text-muted); font-weight: 600; }
.cl-section-head-actions { display: inline-flex; gap: 4px; flex-shrink: 0; }
.cl-section-head-actions .cl-item-btn:disabled { opacity: 0.3; pointer-events: none; }
.cl-section-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px;
}
.cl-section-card.is-collapsed .cl-section-body { display: none; }
.cl-section-body .cl-add-item-row { margin-top: 0; }
.cl-section-empty {
  font: 500 var(--text-sm) / 1.4 var(--body);
  color: var(--text-muted);
  padding: 4px 2px;
}

/* (.cl-item-section-move dropdown removed 2026-06-25 — checks move between
   sections via the ↑/↓ arrows now, KB-style.) */

/* ── Run mode: collapsible section with its own RAG status bar ─────── */
.cl-run-section {
  border: 1px solid var(--border);
  border-left: 4px solid var(--text-muted);   /* RAG, recoloured by state below */
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  overflow: hidden;
}
.cl-run-section.is-green   { border-left-color: var(--rag-pass-fill); }
.cl-run-section.is-amber   { border-left-color: var(--rag-warn-fill); }
.cl-run-section.is-red     { border-left-color: var(--rag-fail-fill); }
.cl-run-section.is-neutral { border-left-color: var(--text-muted); }
.cl-run-section-header {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 14px;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
}
.cl-run-section.is-green   .cl-run-section-header { background: color-mix(in srgb, var(--rag-pass-fill) 8%, transparent); }
.cl-run-section.is-amber   .cl-run-section-header { background: color-mix(in srgb, var(--rag-warn-fill) 8%, transparent); }
.cl-run-section.is-red     .cl-run-section-header { background: color-mix(in srgb, var(--rag-fail-fill) 8%, transparent); }
.cl-run-section-title {
  font: 700 var(--text-base) / 1.2 var(--display);
  color: var(--text-primary);
  flex-shrink: 0;
  max-width: 42%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cl-run-section-bar { flex: 1; min-width: 0; }
.cl-run-section-chevron {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--text-secondary);
  transition: transform 0.15s;
}
.cl-run-section-header[aria-expanded="false"] .cl-run-section-chevron { transform: rotate(-90deg); }
.cl-run-section-header[aria-expanded="false"] + .cl-run-section-body { display: none; }
.cl-run-section-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 14px;
}
/* Compact variant of the progress bar for the section header — no panel chrome,
   just the count + chips + track. Reuses every .cl-runner-progress-* inner rule. */
.cl-runner-progress--section {
  padding: 0;
  background: none;
  border: none;
}
.cl-runner-progress--section .cl-runner-progress-stats { margin-bottom: 4px; gap: 8px; }
.cl-runner-progress--section .cl-runner-progress-count { font-size: var(--text-sm); }

/* ── Active list card: "Continue where you left off" resume cue ─────── */
.cl-card-resume {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-top: 8px;
  font: 600 var(--text-xs) / 1 var(--body);
  color: var(--accent);
}
.cl-card-resume svg { width: 14px; height: 14px; }

.cl-form-delete-btn {
  margin-right: auto;
  color: #dc2626 !important;
  border-color: rgba(220,38,38,0.45) !important;
}
.cl-form-delete-btn:hover {
  background: rgba(220,38,38,0.08) !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   CHECKLISTS RUNNER (overlay)
   ═══════════════════════════════════════════════════════════════════════ */
.cl-runner-overlay {
  position: fixed;
  inset: 0;
  z-index: 1200;
  background: var(--bg-base);
  display: flex;
  flex-direction: column;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  overflow: hidden;
}
.cl-runner-overlay.is-open {
  opacity: 1;
  transform: none;
}
.cl-runner-inner {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

/* ── Runner as a CENTRED MODAL on desktop (matches the Audit "Start audit"
      runner shell) ────────────────────────────────────────────────────────
   The checklist runner opens as a popup card with a dimmed backdrop instead of
   a full-viewport takeover — the same shape as the audit runner modal, so the
   app has ONE runner layout (Radek 2026-07-17). Scoped to the .cl-runner-modal
   modifier the CHECKLIST runner adds in buildOverlay_, so the inventory count
   runner — which also reuses .cl-runner-overlay — stays full-screen (unchanged).
   Full-bleed takeover on phones; a centred 800px card at ≥800px (the SAME
   breakpoint + max-width + radius the audit runner uses). z-index stays 1200 so
   a linked-task modal still stacks ON TOP of the runner (the Esc/close guard
   relies on that). The existing body.callout-modal-open scroll-lock + is-open
   fade already ship with the runner — this only reshapes the shell. */
.cl-runner-overlay.cl-runner-modal {
  background: rgba(0, 0, 0, 0.5);
}
.cl-runner-overlay.cl-runner-modal > .cl-runner-inner {
  background: var(--bg-base);
  width: 100%;
}
@media (min-width: 800px) {
  .cl-runner-overlay.cl-runner-modal {
    align-items: center;
    justify-content: center;
    padding: var(--space-3);
  }
  .cl-runner-overlay.cl-runner-modal > .cl-runner-inner {
    max-width: 800px;
    height: auto;
    max-height: 96vh;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
  }
}

.cl-runner-header {
  flex-shrink: 0;
}
.cl-runner-cat,
.cl-runner-status,
.cl-runner-due {
  display: inline-flex;
  align-items: center;
  font: 600 var(--text-xs) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
}
/* Runner header status — CALM (neutral chip + colour on the dot). The due/SLA
   chips below stay LOUD (act-now). (Radek 2026-06-29) */
.cl-runner-status {
  gap: 6px;
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text-primary);
  font-weight: 500;
}
.cl-runner-status::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-muted); flex-shrink: 0;
}
.cl-runner-status[data-status="open"]::before        { background: #3b82f6; }
.cl-runner-status[data-status="in_progress"]::before  { background: var(--rag-warn-fill); }
.cl-runner-status[data-status="completed"]::before    { background: var(--rag-pass-fill); }
.cl-runner-status[data-status="missed"]::before       { background: var(--rag-fail-fill); }
/* Runner header category — CALM (neutral chip + colour on the dot), matching the
   already-calmed .cl-runner-status beside it. The colour is set on the dot inline
   from runner.js; the loud bg/border tint there was removed. (calm pass 2026-06-30) */
.cl-runner-cat {
  gap: 6px;
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text-secondary);
  font-weight: 500;
}
.cl-runner-cat-dot { width: 7px; height: 7px; border-radius: var(--radius-full); flex-shrink: 0; }
.cl-runner-due.is-safe    { color: var(--rag-pass); background: color-mix(in srgb, var(--rag-pass-fill) 12%, transparent); border-color: color-mix(in srgb, var(--rag-pass-fill) 45%, transparent); }
.cl-runner-due.is-warning { color: var(--rag-warn); background: color-mix(in srgb, var(--rag-warn-fill) 12%, transparent); border-color: color-mix(in srgb, var(--rag-warn-fill) 45%, transparent); }
.cl-runner-due.is-breach  { color: var(--rag-fail); background: color-mix(in srgb, var(--rag-fail-fill) 12%, transparent); border-color: color-mix(in srgb, var(--rag-fail-fill) 45%, transparent); }

.cl-runner-title-row { padding: 8px 16px 0; }
.cl-runner-desc {
  padding: 4px 16px 12px;
  font: 400 var(--text-sm) / 1.5 var(--body);
  color: var(--text-secondary);
}

/* Progress bar */
.cl-runner-progress {
  padding: 12px 16px;
  /* White so the status bar reads as part of the top chrome (with the header)
     and sits CLEARLY above the grey scroll body — it used to be grey too and
     blended into it (Radek 2026-07-03). The bottom hairline draws the divide. */
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.cl-runner-progress-stats {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.cl-runner-progress-count {
  font: 700 var(--text-base) / 1 var(--body);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.cl-runner-progress-summary {
  display: inline-flex;
  gap: 6px;
  margin-left: auto;
}
/* RAG tally chips ("3 pass" / "1 fail") — CALM (calm pass 2026-06-30): a results
   readout, not a deadline alarm, so neutral chip with the RAG colour on a leading
   dot, standardised to the app chip size (4px 9px). */
.cl-runner-progress-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 500 var(--text-xs) / 1 var(--body);
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.cl-runner-progress-chip::before {
  content: ''; width: 6px; height: 6px; border-radius: var(--radius-full); flex-shrink: 0;
}
.cl-runner-progress-chip.is-pass::before { background: var(--rag-pass-fill); }
.cl-runner-progress-chip.is-warn::before { background: var(--rag-warn-fill); }
.cl-runner-progress-chip.is-fail::before { background: var(--rag-fail-fill); }
.cl-runner-progress-track {
  height: 6px;
  background: var(--bg-base);
  border-radius: 3px;
  overflow: hidden;
  /* Segments sit side by side (2026-07-05) — a legacy single fill still lays
     out identically as the lone flex child. */
  display: flex;
}
.cl-runner-progress-fill {
  height: 100%;
  transition: width 0.2s;
  flex-shrink: 0;
}
/* SEGMENTED fill (2026-07-05, audit + checklist runners): colour tells the
   verdict, total filled width tells the progress — one fail reads as its true
   share of the bar, never a full-width red flood. .is-seg-other = answered but
   not pass/fail graded (audit text/photo questions). */
.cl-runner-progress-fill.is-seg-pass  { background: var(--rag-pass-fill); }
.cl-runner-progress-fill.is-seg-warn  { background: var(--rag-warn-fill); }
.cl-runner-progress-fill.is-seg-fail  { background: var(--rag-fail-fill); }
.cl-runner-progress-fill.is-seg-other { background: var(--accent); }

/* Items area — scrollable */
.cl-runner-items {
  flex: 1;
  /* min-height:0 lets this flex child shrink below its content height inside the
     column-flex .cl-runner-inner, so overflow-y actually scrolls (without it some
     browsers give the item its full content height → the list can't scroll and the
     overflow is clipped). Belt-and-braces for the "can't scroll on desktop" report. */
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  /* Extra bottom room so the LAST check's revealed Fail follow-up (reason box +
     Create task) has space and isn't flush against the footer. */
  padding: 16px 16px 28px;
  max-width: 800px;
  width: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Every direct child of the scroll column (section card, check row, tick list,
   notice) must keep its natural height — flexbox must NEVER shrink it to fit.
   A flex item with `overflow: hidden` (e.g. .cl-run-section, .cl-runner-tick-list)
   gets an automatic min-size of 0, so when the list is taller than the pane
   flexbox crushes that child toward zero and `overflow: hidden` clips its content.
   That collapsed a whole section to a ~2px sliver, hiding all its checks and
   making the list look unscrollable. flex-shrink:0 keeps every child full-height
   and the pane scrolls instead. (The tick list sets this on itself too — this
   covers the section cards and any future row type as well.) */
.cl-runner-items > * { flex-shrink: 0; }
/* When a Fail/No/out-of-zone follow-up is scrolled into view, leave a gap below
   it (revealFollowup_ uses scrollIntoView). */
.cl-run-yesno-followup,
.cl-run-reading-followup { scroll-margin-bottom: 20px; }

.cl-run-item {
  display: grid;
  /* Row 1: [number] [label + status badge]. Row 2: a FULL-WIDTH content row
     (grid-column 1/-1) so the answer controls — reading input, Yes/No buttons,
     "what was wrong" box — use the whole card, not a cramped middle column. */
  grid-template-columns: 32px 1fr;
  align-items: start;
  gap: 8px 12px;
  padding: 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: border-color 0.12s;
}
.cl-run-item.is-info {
  background: color-mix(in srgb, #6366f1 6%, var(--bg-surface));
  border-color: color-mix(in srgb, #6366f1 30%, var(--border));
}
/* Round accent number badge — SAME for every check type (Tick / Yes-No /
   Reading), and it NEVER changes on completion (the pass/fail signal is the
   right-side .cl-run-item-status-badge ✓/✕). Matches the builder's .cl-item-num.
   (Radek 2026-06-26 — unified the runner badges + stopped the Tick number→check
   swap.) */
.cl-run-item-num {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  background: var(--accent);
  color: var(--bg-base);
  font: 700 var(--text-sm) / 1 var(--body);
  border-radius: var(--radius-full);
}
.cl-run-item.is-info .cl-run-item-num {
  background: color-mix(in srgb, #6366f1 14%, transparent);
  color: #6366f1;
}
.cl-run-item-content {
  grid-column: 1 / -1;   /* span the whole card width (row 2) */
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.cl-run-item-label {
  font: 600 var(--text-base) / 1.3 var(--body);
  color: var(--text-primary);
}
.cl-run-item-label.is-info { color: #6366f1; }
/* Label + (i) info icon row — the icon appears when a Yes/No or Reading
   check has KB info attached (same info the Tick check shows). */
.cl-run-item-head {
  grid-column: 2;        /* row 1, beside the number */
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.cl-run-item-head .cl-run-item-label { flex: 1; min-width: 0; }
.cl-run-item-info-btn {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: var(--accent-soft, color-mix(in srgb, var(--accent) 12%, transparent));
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: var(--radius-full);
  color: var(--accent);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.cl-run-item-info-btn:hover {
  background: color-mix(in srgb, var(--accent) 22%, var(--bg-base));
  border-color: var(--accent);
}
.cl-run-item-info-btn svg { width: 16px; height: 16px; }
.cl-run-item-status {
  display: grid;
  place-items: center;
  flex-shrink: 0;        /* sits at the end of the header row */
}
.cl-run-item-status-badge {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font: 700 13px / 1 var(--body);
  border: 1px solid transparent;
}
.cl-run-item-status-badge.is-pass { background: color-mix(in srgb, var(--rag-pass-fill) 14%, transparent);  color: var(--rag-pass); border-color: color-mix(in srgb, var(--rag-pass-fill) 45%, transparent); }
.cl-run-item-status-badge.is-warn { background: color-mix(in srgb, var(--rag-warn-fill) 14%, transparent);  color: var(--rag-warn); border-color: color-mix(in srgb, var(--rag-warn-fill) 45%, transparent); }
.cl-run-item-status-badge.is-fail { background: color-mix(in srgb, var(--rag-fail-fill) 14%, transparent);  color: var(--rag-fail); border-color: color-mix(in srgb, var(--rag-fail-fill) 45%, transparent); }

/* Inline info box inside item body */
.cl-run-info-box {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px;
  background: color-mix(in srgb, #6366f1 8%, transparent);
  border: 1px solid color-mix(in srgb, #6366f1 30%, transparent);
  border-radius: var(--radius-md);
}
.cl-run-info-box svg {
  width: 16px;
  height: 16px;
  color: #6366f1;
  flex-shrink: 0;
  margin-top: 1px;
}
.cl-run-info-text {
  font: 400 var(--text-sm) / 1.5 var(--body);
  color: var(--text-primary);
  white-space: pre-wrap;
}
.cl-run-info-panel {
  padding: 4px 0;
}
.cl-run-info-panel-text {
  font: 400 var(--text-sm) / 1.6 var(--body);
  color: var(--text-primary);
  white-space: pre-wrap;
}

/* ── TICK ITEM ──────────────────────────────────────────────────────── */
.cl-run-tick {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  transition: background 0.12s, border-color 0.12s;
}
.cl-run-tick:hover { border-color: var(--accent); }
.cl-run-tick.is-readonly { cursor: default; }
.cl-run-tick input { position: absolute; opacity: 0; pointer-events: none; }
.cl-run-tick-box {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  background: var(--bg-surface);
  border: 2px solid var(--border);
  border-radius: 6px;
  transition: background 0.12s, border-color 0.12s;
  flex-shrink: 0;
}
.cl-run-tick-box svg {
  width: 16px;
  height: 16px;
  color: #fff;
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.15s, transform 0.15s;
}
.cl-run-tick.is-ticked .cl-run-tick-box {
  background: var(--rag-pass-fill);
  border-color: var(--rag-pass-fill);
}
.cl-run-tick.is-ticked .cl-run-tick-box svg {
  opacity: 1;
  transform: scale(1);
}
.cl-run-tick.is-ticked {
  background: color-mix(in srgb, var(--rag-pass-fill) 8%, transparent);
  border-color: color-mix(in srgb, var(--rag-pass-fill) 45%, transparent);
}
.cl-run-tick-label {
  font: 500 var(--text-base) / 1.3 var(--body);
  color: var(--text-primary);
  flex: 1;
}

/* Tick item with photo — fallback if KB step block isn't loaded.
   New path uses KB's .kb-instr-step rendering inside .cl-runner-tick-list. */
.cl-run-tick-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ── History tab: collapsible monthly groups ───────────────────────
   Mirrors the Tasks completed-view pattern so users navigate one
   consistent affordance across the app. The most recent month is open
   by default; older months fold away on first visit. Each group has
   a clickable header with chevron + month label + count chip. */
/* The same collapsible-group visual is shared by History's month buckets AND
   the category groups on the Audits + Checklists template lists — one accordion
   look across the app (.cl-cat-group* are the generic category-group aliases). */
.cl-history-month,
.cl-cat-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cl-history-month + .cl-history-month,
.cl-cat-group + .cl-cat-group { margin-top: 6px; }
.cl-history-month-header,
.cl-cat-group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: border-color 0.12s, background 0.12s;
  touch-action: manipulation;
  color: var(--text-primary);
}
.cl-history-month-header:hover,
.cl-cat-group-header:hover {
  border-color: var(--accent);
  background: var(--bg-surface);
}
.cl-history-month-chevron,
.cl-cat-group-chevron {
  width: 16px;
  height: 16px;
  color: var(--text-muted);
  flex-shrink: 0;
  transition: transform 0.18s;
  transform: rotate(-90deg);
}
.cl-history-month.is-open .cl-history-month-chevron,
.cl-cat-group.is-open .cl-cat-group-chevron { transform: rotate(0deg); }
.cl-history-month-label,
.cl-cat-group-label {
  flex: 1;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}
.cl-history-month-count,
.cl-cat-group-count {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-muted);
  background: var(--bg-surface);
  padding: 2px 8px;
  border-radius: var(--radius-md);
}
/* A small category-colour dot in the group header — ties the header to the
   category colour, mirroring the card's category chip. Category groups only. */
.cl-cat-group-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* ── Pass / Fail buttons under each tick item ──────────────────────
   Below the KB step block, two big tap targets. Pass marks the check
   green; Fail opens the Tasks create modal with the check's context
   pre-filled. Matches the visual language of the Yes/No buttons used
   elsewhere in the runner so users learn one pattern. */
.cl-tick-runner-wrap {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
}
.cl-tick-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.cl-tick-pass-btn,
.cl-tick-fail-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  font: 600 var(--text-base) / 1 var(--body);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  font-family: inherit;
}
.cl-tick-pass-btn svg,
.cl-tick-fail-btn svg { width: 18px; height: 18px; }
/* Hover tint ONLY on real pointers. On touch, :hover STICKS after a tap, so a
   Pass/Fail button stayed green/red (looking selected) even after the choice was
   cleared — the data was un-checked but the visual wasn't. Gate it so touch
   relies purely on .is-selected (the true state). */
@media (hover: hover) {
  .cl-tick-pass-btn:hover { border-color: var(--rag-pass-fill); color: var(--rag-pass); }
  .cl-tick-fail-btn:hover { border-color: var(--rag-fail-fill); color: var(--rag-fail); }
}
.cl-tick-pass-btn.is-selected {
  background: color-mix(in srgb, var(--rag-pass-fill) 12%, transparent);
  border-color: var(--rag-pass-fill);
  color: var(--rag-pass);
}
.cl-tick-fail-btn.is-selected {
  background: color-mix(in srgb, var(--rag-fail-fill) 12%, transparent);
  border-color: var(--rag-fail-fill);
  color: var(--rag-fail);
}

/* Task-linked indicator — shown when Fail has been recorded + task created */
.cl-tick-task-linked {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: rgba(245,158,11,0.08);
  border: 1px solid rgba(245,158,11,0.40);
  border-radius: var(--radius-md);
  font: 500 var(--text-sm) / 1.4 var(--body);
  color: #d97706;
}
.cl-tick-task-linked svg { width: 16px; height: 16px; flex-shrink: 0; }

/* Auto-resolved indicator — shown in read-only (history) mode when a
   Fail was auto-passed because its linked task was completed. Sits
   directly under the check it resolved so the user can trace cause →
   effect without hunting through the footer. Green to mirror the
   pass-state styling on the check above it. */
.cl-tick-task-resolved {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  margin-top: 8px;
  background: color-mix(in srgb, var(--rag-pass-fill) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--rag-pass-fill) 40%, transparent);
  border-radius: var(--radius-md);
  font: 500 var(--text-sm) / 1.4 var(--body);
  color: var(--rag-pass);
}
.cl-tick-task-resolved svg { width: 16px; height: 16px; flex-shrink: 0; }
.cl-tick-task-resolved-text {
  flex: 1 1 auto;
  min-width: 0;
}
/* Task-ref chip — opens the completed task that resolved this check.
   Sits flush right inside the resolved note. Green to match the note
   colour scheme; tap-feedback via active scale. */
.cl-tick-task-resolved-chip {
  flex: 0 0 auto;
  margin-left: 4px;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--rag-pass-fill) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--rag-pass-fill) 45%, transparent);
  color: var(--rag-pass);
  font: 600 var(--text-xs) / 1 var(--body);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background 0.12s ease, transform 0.06s ease;
  white-space: nowrap;
}
.cl-tick-task-resolved-chip:hover {
  background: color-mix(in srgb, var(--rag-pass-fill) 22%, transparent);
}
.cl-tick-task-resolved-chip:active {
  transform: scale(0.96);
}

/* Failed-state styling on the KB step block — red number circle with X
   instead of the green check used for is-completed. KB's CSS already
   has hooks for is-completed; we add a parallel state for is-failed. */
.kb-instr-step.is-failed .kb-instr-step-num {
  background: #dc2626;
  border-color: #dc2626;
  color: #fff;
}
.kb-instr-step.is-failed .kb-instr-step-num-text { display: none; }
.kb-instr-step.is-failed .kb-instr-step-num::after {
  content: '✕';
  font: 700 16px/1 var(--body);
  color: #fff;
}
/* Passed check — green circle + check. The runner adds .is-completed on a Pass,
   but nothing styled it (KB's done-state class is .is-done), so a pass kept the
   default accent number and was indistinguishable from an un-actioned step.
   Mirror the .is-failed treatment so pass = green ✓, fail = red ✕. */
.kb-instr-step.is-completed .kb-instr-step-num {
  background: var(--success, #16a34a);
  border-color: var(--success, #16a34a);
  color: #fff;
}
.kb-instr-step.is-completed .kb-instr-step-num-text { display: none; }
.kb-instr-step.is-completed .kb-instr-step-num::after {
  content: '✓';
  font: 700 17px/1 var(--body);
  color: #fff;
}
/* Un-actioned check in a COMPLETED run — muted neutral circle so it reads as
   "not checked", clearly distinct from a pending (accent) step. */
.kb-instr-step.is-unactioned .kb-instr-step-num {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

/* ── Read-only "what happened" panel under a FAILED check (history view) ──
   The reason recorded + a tappable follow-up-task / asset tile so a reviewer
   can open the work and sort it out. Left red accent = the problem area;
   flips green once the linked task resolved the check. */
.cl-fail-detail {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 10px 4px 2px;
  padding: 12px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--rag-fail-fill);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}
.cl-fail-detail.is-resolved {
  border-color: var(--border);
  border-left-color: var(--rag-pass-fill);
  background: var(--bg-surface);
}
.cl-fail-reason { display: flex; flex-direction: column; gap: 4px; }
.cl-fail-reason-label {
  font: 700 var(--text-xs) / 1 var(--body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.cl-fail-reason-text {
  margin: 0;
  font: 400 var(--text-sm) / 1.5 var(--body);
  color: var(--text-primary);
  white-space: pre-wrap;
}
.cl-fail-task-sub {
  margin-top: 2px;
  font: 600 var(--text-xs) / 1.3 var(--body);
  color: #dc2626;
}
.cl-fail-task-sub.is-resolved { color: var(--rag-pass); }

/* When checklist runner uses KB's step block read mode, wrap the <li>
   in a borderless ul so the existing .kb-instr-step styling applies
   without competing with our cl-run-item grid layout. */
.cl-runner-tick-list {
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  padding: 4px 8px;
  /* Each step is a flex child of the .cl-runner-items column. Without this
     the steps shrink below their content when the list is taller than the
     pane, and `overflow: hidden` then CLIPS the bottom of the Pass/Fail
     buttons. flex-shrink:0 keeps every step at full height; the list pane
     scrolls instead. */
  flex-shrink: 0;
}
.cl-runner-tick-list .kb-instr-step {
  margin: 0 !important;
  padding: 10px 4px !important;
  border: none !important;
  background: transparent !important;
}
/* Force the photo thumb to a tidy size when used in the checklist runner */
.cl-runner-tick-list .kb-instr-step-photo-thumb-wrap { flex-shrink: 0; }
.cl-runner-tick-list .kb-instr-step-photo-thumb {
  width: 64px;
  height: 64px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg-elevated);
}

/* Info viewer modal — read-only display of step info.
   Compact, professional header (scoped to this viewer only — the shared
   .callout-modal-head used by callouts etc. is untouched). The default head is
   tall (16/20 padding, xl title, 36px close, + an env(safe-area)+8 top pad on
   mobile); for a read-only popup that reads as bulky, so we trim it. */
/* Compact modal header — shared by the read-only Step Info viewer AND the
   template builder (both want a shorter, tidier bar than the default
   .callout-modal-head; the builder also wants the reclaimed height for editing). */
.cl-info-viewer .callout-modal-head,
.cl-form-modal .callout-modal-head {
  padding: 10px 14px 10px 16px;
  gap: 10px;
}
.cl-info-viewer .callout-modal-head h2,
.cl-form-modal .callout-modal-head h2 {
  font-size: var(--text-lg);
  letter-spacing: -0.01em;
  /* Let the title shrink/ellipsis so header actions (e.g. Preview) + close
     always stay on-screen on a narrow phone. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cl-info-viewer .callout-modal-close,
.cl-form-modal .callout-modal-close { width: 30px; height: 30px; }
@media (max-width: 599px) {
  /* These are bottom-sheets that rarely reach the notch, so they don't need the
     shared sheet's larger safe-area top pad — keep just a small guard. */
  .cl-info-viewer .callout-modal-head,
  .cl-form-modal .callout-modal-head {
    padding-top: max(10px, calc(env(safe-area-inset-top) + 2px));
  }
  /* Mobile: tighten the section→check nesting + vertical gaps so the check content
     uses the width (pairs with the app-wide modal/form trim in css/12). Desktop
     keeps the roomier 10px. */
  .cl-items-list   { gap: 8px; }
  .cl-section-body { padding: 6px; gap: 8px; }
  .cl-item         { padding: 8px; gap: 8px; }
}
.cl-run-info-viewer-text {
  font: 400 var(--text-base) / 1.6 var(--body);
  color: var(--text-primary);
  margin: 0 0 12px;
  white-space: pre-wrap;
}
.cl-run-info-viewer-photos {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cl-run-info-viewer-photo img {
  width: 100%;
  border-radius: var(--radius-md);
  display: block;
}

/* ── YES/NO ITEM ────────────────────────────────────────────────────── */
.cl-run-yesno {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.cl-run-yesno-buttons {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.cl-run-yesno-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  font: 600 var(--text-base) / 1 var(--body);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  font-family: inherit;
}
.cl-run-yesno-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.cl-run-yesno-btn svg { width: 18px; height: 18px; }
@media (hover: hover) {
  .cl-run-yesno-btn.is-yes:hover:not(:disabled) { border-color: var(--rag-pass-fill); color: var(--rag-pass); }
  .cl-run-yesno-btn.is-no:hover:not(:disabled)  { border-color: var(--rag-fail-fill); color: var(--rag-fail); }
}
.cl-run-yesno-btn.is-yes.is-selected { background: color-mix(in srgb, var(--rag-pass-fill) 12%, transparent); border-color: var(--rag-pass-fill); color: var(--rag-pass); }
.cl-run-yesno-btn.is-no.is-selected  { background: color-mix(in srgb, var(--rag-fail-fill) 12%, transparent); border-color: var(--rag-fail-fill); color: var(--rag-fail); }

/* The Fail / "No" follow-up ("What was wrong?") is a CALM neutral panel
   (Radek 2026-06-26: the all-red box was too loud — the red is reserved for the
   act-now signals, i.e. the No/Fail button + the right-side ✕ status badge). The
   numeric Reading out-of-range variants below re-assert amber/red, since a reading
   outside its safe range is a real alert. */
.cl-run-yesno-followup {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  animation: cl-fade-in 0.15s ease-out;
}
/* Tick (Pass/Fail) fail follow-up sits in .cl-run-tick-body, which has no
   column gap — so give it the SAME 12px gap below the buttons that Yes/No
   gets for free from .cl-run-yesno { gap:12px } (Radek 2026-06-26). */
.cl-tick-fail-followup { margin-top: 12px; }
@keyframes cl-fade-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
.cl-run-followup-label {
  font: 600 var(--text-sm) / 1 var(--body);
  color: var(--text-secondary);
}
.cl-run-followup-input {
  background: var(--bg-surface);
  border-color: var(--border);
}
.cl-run-create-task-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  padding: 8px 14px;
  background: var(--accent);
  color: #001317;
  border: none;
  border-radius: var(--radius-sm);
  font: 600 var(--text-sm) / 1 var(--body);
  cursor: pointer;
  font-family: inherit;
  transition: filter 0.12s;
}
.cl-run-create-task-btn:hover { filter: brightness(1.08); }
.cl-run-create-task-btn svg { width: 14px; height: 14px; }
.cl-run-task-linked {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  padding: 6px 10px;
  background: rgba(22,163,74,0.10);
  color: #16a34a;
  border: 1px solid rgba(22,163,74,0.45);
  border-radius: var(--radius-sm);
  font: 600 var(--text-sm) / 1 var(--body);
}
.cl-run-task-linked svg { width: 14px; height: 14px; }

/* ── READING ITEM ──────────────────────────────────────────────────── */
.cl-run-reading {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* One reading card can hold several measurements (Water temp, Chlorine, pH…).
   Each is a stacked block with its own name label, input, unit + zone chip and
   follow-up; separated by a calm dashed divider. A single-measurement card
   shows no name (the card header already names it). */
.cl-run-reading-measure {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cl-run-reading-measure + .cl-run-reading-measure {
  padding-top: 10px;
  border-top: 1px dashed var(--border);
}
.cl-run-reading-measure-name {
  font: 600 var(--text-sm) / 1.2 var(--body);
  color: var(--text-secondary);
}
.cl-run-reading-input-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  /* One line, always — [compact input] [unit] [status]. Was flex-wrap:wrap,
     which on mobile pushed the status chip onto its own row (and the flex:1
     input grew huge). Matches the tidy desktop layout on every width. */
  flex-wrap: nowrap;
}
.cl-run-reading-input {
  /* Compact — a reading is at most a few digits, so the input doesn't need to
     fill the row (was flex:1 / min-width:140px → grew very wide and wrapped). */
  flex: 0 1 96px;
  min-width: 70px;
  padding: 10px 12px;
  font: 600 var(--text-lg, 18px) / 1 var(--body);
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  font-family: inherit;
}
.cl-run-reading-input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
}
.cl-run-reading-unit {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  padding: 0 14px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  font: 600 var(--text-base) / 1 var(--body);
  color: var(--text-secondary);
  white-space: nowrap;
}
.cl-run-reading-zone {
  display: inline-flex;
  align-items: center;
  /* Fills the rest of the line so the status reads in full — the content row is
     now the full card width, so on mobile it gets ~160px (was ~73px in the old
     cramped column, which clipped "Awaiting reading"). Capped so it doesn't
     sprawl into one giant pill on a wide desktop card. */
  flex: 1 1 auto;
  min-width: 0;
  max-width: 260px;
  padding: 0 14px;
  border-radius: var(--radius-md);
  font: 700 var(--text-sm) / 1 var(--body);
  border: 1.5px solid transparent;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  justify-content: center;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

/* Reading follow-up (per-zone auto-task). Reuses the shared follow-up panel
   (.cl-run-yesno-followup), which is now NEUTRAL — so a reading outside its safe
   range re-asserts its zone colour here: Amber for a warning, Red for Critical.
   These stay coloured on purpose (a numeric safety alert), unlike the calm
   generic Yes/No / Tick "what was wrong" box. */
.cl-run-reading-followup.is-amber {
  background: rgba(234,88,12,0.05);
  border-color: rgba(234,88,12,0.25);
}
.cl-run-reading-followup.is-amber .cl-run-followup-label { color: var(--rag-warn); }
.cl-run-reading-followup.is-amber .cl-run-followup-input { border-color: color-mix(in srgb, var(--rag-warn-fill) 30%, transparent); }
.cl-run-reading-followup.is-red {
  background: rgba(220,38,38,0.05);
  border-color: rgba(220,38,38,0.25);
}
.cl-run-reading-followup.is-red .cl-run-followup-label { color: var(--rag-fail); }
.cl-run-reading-followup.is-red .cl-run-followup-input { border-color: color-mix(in srgb, var(--rag-fail-fill) 30%, transparent); }

/* ── RUNNER FOOTER ──────────────────────────────────────────────────── */
.cl-runner-footer {
  flex-shrink: 0;
  padding: 14px 16px;
  background: var(--bg-surface);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 800px;
  width: 100%;
  margin: 0 auto;
}
.cl-runner-notes-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.cl-runner-notes-field label {
  font: 600 var(--text-sm) / 1 var(--body);
  color: var(--text-secondary);
}
.cl-runner-notes-field textarea {
  font: 400 var(--text-sm) / 1.4 var(--body);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  resize: vertical;
  font-family: inherit;
  color: var(--text-primary);
}
.cl-runner-footer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.cl-runner-footer.is-readonly {
  background: var(--bg-elevated);
}
.cl-runner-notes-readonly {
  font: 400 var(--text-sm) / 1.5 var(--body);
  color: var(--text-primary);
}
.cl-runner-notes-readonly p { margin: 4px 0 0; }
.cl-runner-notes-label {
  font: 600 var(--text-xs) / 1 var(--body);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.cl-runner-completed-by {
  font: 500 var(--text-sm) / 1 var(--body);
  color: var(--text-secondary);
}

/* PREVIEW (sandbox) mode — the template editor opens the runner to test a draft.
   Accent-tinted banner + footer so it's unmistakably NOT a live run, and the
   footer carries a "nothing is saved" note + a single Close preview button. */
.cl-runner-preview-banner {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-surface));
  color: var(--accent);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  font: 600 var(--text-sm) / 1.3 var(--body);
}
.cl-runner-preview-banner svg { width: 16px; height: 16px; flex-shrink: 0; }
.cl-runner-footer-preview {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.cl-runner-preview-note {
  font: 500 var(--text-sm) / 1.3 var(--body);
  color: var(--text-secondary);
}

/* ═══════════════════════════════════════════════════════════════════════
   SYNC INDICATOR — floating chip showing offline-queue status
   ─────────────────────────────────────────────────────────────────────
   Sits bottom-right above the conflict banner (when both visible).
   Hidden by default; only appears when there's something to communicate.
   ═══════════════════════════════════════════════════════════════════════ */
.sync-indicator {
  position: fixed;
  bottom: 16px;
  right: 16px;
  z-index: 9400;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.32);
  font: 600 var(--text-sm) / 1 var(--body);
  color: var(--text-primary);
  transition: opacity 0.2s, transform 0.2s;
  animation: sync-indicator-in 0.25s ease-out;
}
@keyframes sync-indicator-in {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: none;            opacity: 1; }
}
.sync-indicator[hidden] { display: none; }
/* State icon (replaces the old colour dot) — makes "what's happening" obvious. */
.sync-indicator-icon { width: 15px; height: 15px; flex-shrink: 0; display: block; }
/* Online + actively syncing — accent, spinning sync arrows. */
.sync-indicator.is-syncing {
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  background: color-mix(in srgb, var(--accent) 9%, var(--bg-surface));
  color: var(--accent);
}
.sync-indicator.is-syncing .sync-indicator-icon {
  animation: sync-indicator-spin 0.9s linear infinite;
  transform-origin: 50% 50%;
}
@keyframes sync-indicator-spin { to { transform: rotate(360deg); } }
/* Offline / waiting — amber cloud (saved on device, queued to upload). */
.sync-indicator.is-waiting {
  border-color: rgba(245, 158, 11, 0.45);
  background: color-mix(in srgb, #f59e0b 12%, var(--bg-surface));
  color: #f59e0b;
}
/* Briefly shown after the queue drains — green check, "All synced". */
.sync-indicator.is-done {
  border-color: rgba(22, 163, 74, 0.45);
  background: color-mix(in srgb, #16a34a 12%, var(--bg-surface));
  color: #16a34a;
}
/* Photos that gave up retrying — dead-lettered, needs the user. The whole
   chip is a button; tapping opens Retry all / Discard (shared action sheet). */
.sync-indicator.is-attention {
  padding: 0;                                   /* the inner button owns the padding */
  border-color: rgba(245, 158, 11, 0.55);
  background: color-mix(in srgb, #f59e0b 15%, var(--bg-surface));
  color: #f59e0b;
}
.sync-indicator-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;                             /* ≥44px tap target (§4) */
  padding: 8px 14px;
  background: none;
  border: 0;
  border-radius: inherit;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.sync-indicator-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* On mobile, sit just above the conflict banner (when present) so
   they don't overlap at the bottom of the screen. */
@media (max-width: 768px) {
  .sync-indicator {
    /* Sit above the centred toast band (the toast is ~28px from the bottom
       and can span nearly the full width on mobile) so the two never overlap. */
    bottom: calc(env(safe-area-inset-bottom, 0px) + 76px);
    right: 12px;
    font-size: var(--text-xs);
    padding: 7px 12px;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   CONFLICT BANNER + MODAL  (write-queue conflict resolution UI)
   ─────────────────────────────────────────────────────────────────────
   Fixed amber banner that appears at the bottom of the screen when the
   write-queue has unresolved sync conflicts. Tapping it opens a modal
   listing each conflict with Keep mine / Discard mine choices.
   ═══════════════════════════════════════════════════════════════════════ */

.conflict-banner {
  position: fixed;
  left: 12px; right: 12px;
  bottom: max(12px, env(safe-area-inset-bottom, 0));
  z-index: 9500;
  display: flex;
  align-items: center;
  gap: 12px;
  width: auto;
  max-width: 520px;
  margin: 0 auto;
  padding: 12px 16px;
  background: #fef3c7;
  border: 1px solid #f59e0b;
  border-radius: var(--radius-md);
  color: #78350f;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
  transition: transform 0.12s, opacity 0.18s;
  animation: conflict-banner-in 0.25s ease-out;
}
@keyframes conflict-banner-in {
  from { transform: translateY(20px); opacity: 0; }
  to   { transform: none;             opacity: 1; }
}
.conflict-banner[hidden] { display: none; }
.conflict-banner:hover  { transform: translateY(-1px); }
.conflict-banner:active { transform: scale(0.99); }
.conflict-banner-icon {
  width: 24px; height: 24px;
  flex-shrink: 0;
  color: #d97706;
}
.conflict-banner-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.conflict-banner-title {
  font: 700 var(--text-sm) / 1.3 var(--body);
}
.conflict-banner-sub {
  font: 500 var(--text-xs) / 1 var(--body);
  color: #92400e;
  opacity: 0.85;
}
.conflict-banner-dismiss {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  flex-shrink: 0;
  font: 700 22px / 1 var(--body);
  color: #92400e;
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.12s;
}
.conflict-banner-dismiss:hover {
  background: rgba(217, 119, 6, 0.15);
}

/* ── Modal ─────────────────────────────────────────────────────────── */
.conflict-modal-intro {
  font: 400 var(--text-sm) / 1.5 var(--body);
  color: var(--text-secondary);
  margin: 0 0 14px;
}
.conflict-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.conflict-row {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.conflict-row-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.conflict-row-icon {
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  flex-shrink: 0;
  background: rgba(245, 158, 11, 0.12);
  border: 1px solid rgba(245, 158, 11, 0.45);
  color: #d97706;
  border-radius: var(--radius-sm);
}
.conflict-row-icon svg { width: 16px; height: 16px; }
.conflict-row-meta {
  flex: 1;
  min-width: 0;
}
.conflict-row-title {
  font: 600 var(--text-base) / 1.3 var(--body);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.conflict-row-sub {
  font: 500 var(--text-xs) / 1 var(--body);
  color: var(--text-muted);
  margin-top: 2px;
}
.conflict-row-versions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 8px 10px;
  background: var(--bg-base);
  border-radius: var(--radius-sm);
}
@media (max-width: 480px) {
  .conflict-row-versions { grid-template-columns: 1fr; }
}
.conflict-row-version-label {
  font: 600 var(--text-xs) / 1 var(--body);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.conflict-row-version-time {
  font: 400 var(--text-xs) / 1.3 var(--body);
  color: var(--text-muted);
  margin-top: 2px;
}
.conflict-row-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.conflict-row-actions .callout-btn { padding: 8px 14px; }

/* ═══════════════════════════════════════════════════════════════════════
   OFFLINE BANNER
   ═══════════════════════════════════════════════════════════════════════ */
#offlineBanner {
  background: #1c2533;
  color: #e2e8f0;
  text-align: center;
  font-size: 12px;
  font-weight: 500;
  /* The banner sits at the very top, so it must clear the iOS status bar /
     notch itself — robustly, even when iOS reports a 0 inset (see --safe-top).
     Longhand top padding — Safari drops a `padding` shorthand when max()/env()
     appears in the first slot. */
  padding-top: var(--safe-top);
  padding-bottom: 7px;
  padding-left: 16px;
  padding-right: 16px;
  line-height: 1.35;
  letter-spacing: 0.01em;
  position: relative;
  z-index: 9990;
  flex-shrink: 0;
}
/* While the banner owns the top, the app-bar must NOT also add its notch
   inset (that produced an empty gap below the banner). */
body.is-offline .app-bar { padding-top: 14px; }

/* ── NOTICE check — read-only coloured callout (info/tip/important/warning) ──
   The chip itself reuses the shared KB callout styling (.kb-doc-callout-*,
   css/03). These rules only cover the builder's segmented colour picker +
   live preview, and the runner's full-width wrapper. */
.cl-notice-style-row { display: flex; flex-wrap: wrap; gap: 6px; }
/* Pre-coloured segmented picker (Radek 2026-06-26): every option always carries
   its OWN semantic colour — coloured icon + text + soft tinted fill + border — so
   Warning / Important / Tip / Info read apart at a glance, not just when selected.
   --nc / --nc-rgb set each variant's colour ONCE; the shared rules below consume
   them (no per-variant repetition). Colours match the KB callouts + the live
   preview chip, so the picker and the rendered notice never disagree. */
.cl-notice-style-btn.cl-notice-style-warning   { --nc: #dc2626; --nc-rgb: 220,38,38; }
.cl-notice-style-btn.cl-notice-style-important { --nc: #d97706; --nc-rgb: 217,119,6; }
.cl-notice-style-btn.cl-notice-style-tip       { --nc: #16a34a; --nc-rgb: 22,163,74; }
.cl-notice-style-btn.cl-notice-style-info      { --nc: #2563eb; --nc-rgb: 37,99,235; }
.cl-notice-style-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 11px;
  color: var(--nc, var(--text-secondary));
  background: rgba(var(--nc-rgb, 148,163,184), 0.07);
  border: 1.5px solid rgba(var(--nc-rgb, 148,163,184), 0.32);
  border-radius: var(--radius-md);
  font: 600 var(--text-sm) / 1 var(--body);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s;
  font-family: inherit;
}
.cl-notice-style-btn .cl-notice-style-ico { display: inline-flex; }
.cl-notice-style-btn .cl-notice-style-ico svg { width: 15px; height: 15px; }
.cl-notice-style-btn:hover { background: rgba(var(--nc-rgb, 148,163,184), 0.13); }
/* Selected = highlighted: full-strength border in the variant colour + a soft
   ring + a stronger fill, so the chosen style is unmistakable. */
.cl-notice-style-btn.is-on {
  border-color: var(--nc);
  background: rgba(var(--nc-rgb), 0.15);
  box-shadow: 0 0 0 3px rgba(var(--nc-rgb), 0.18);
}
.cl-notice-preview { margin-top: 4px; }
.cl-notice-preview:empty { display: none; }

/* Runner: the notice callout spans the full width between checks and must
   not be compressed by the flex column (same guard as .cl-runner-tick-list). */
.cl-run-notice { flex-shrink: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   READINGS TABLE — month-by-month grid (modules/checklists/readings.js)
   Rows = Location, columns = Measurement; cells coloured by the SAME
   evaluateZone() logic as the runner. Reuses .cl-card / .kb-reader-action /
   .asset-empty; these are the readings-specific extras only.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Readings card (Readings tab) — extends the shared .cl-card ── */
.cl-card-readings-count {
  display: inline-flex; align-items: center;
  font: 600 var(--text-xs) / 1 var(--body);
  padding: 4px 9px; border-radius: var(--radius-sm);
  background: var(--bg-elevated); border: 1px solid var(--border);
  color: var(--text-secondary);
}
.cl-card-readings-cta {
  display: inline-flex; align-items: center; gap: 3px;
  margin-left: auto;
  font: 600 var(--text-xs) / 1 var(--body);
  color: var(--accent);
}
.cl-card-readings-cta svg { width: 14px; height: 14px; }

/* ── Full-viewport overlay — same recipe as .cl-runner-overlay, but offset
      below the impersonation banner (never hide it). ── */
.cl-readings-overlay {
  position: fixed; left: 0; right: 0; bottom: 0; top: var(--banner-h, 0);
  z-index: 1200; background: var(--bg-base);
  display: flex; flex-direction: column;
  opacity: 0; transform: translateY(24px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  overflow: hidden;
}
.cl-readings-overlay.is-open { opacity: 1; transform: none; }
.cl-rd-inner { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.cl-rd-header { flex-shrink: 0; }
.cl-rd-readings-chip {
  display: inline-flex; align-items: center;
  font: 600 var(--text-xs) / 1 var(--body);
  padding: 4px 9px; border-radius: var(--radius-sm);
  background: var(--bg-elevated); border: 1px solid var(--border);
  color: var(--text-secondary);
}
.cl-rd-subtitle {
  padding: 2px 16px 0; color: var(--text-muted);
  font: 400 var(--text-sm) / 1.3 var(--body);
}

/* ── Month switcher ── */
.cl-rd-monthbar {
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; gap: 14px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.cl-rd-month-nav {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--radius-md);
  background: var(--bg-elevated); border: 1px solid var(--border);
  color: var(--text-primary); cursor: pointer;
  transition: border-color 0.12s, opacity 0.12s;
}
.cl-rd-month-nav svg { width: 20px; height: 20px; }
.cl-rd-month-nav:hover:not(:disabled) { border-color: var(--accent); }
.cl-rd-month-nav:disabled { opacity: 0.35; cursor: default; }
.cl-rd-month-center { text-align: center; min-width: 150px; }
.cl-rd-month-label { display: block; font: 600 var(--text-lg) / 1.2 var(--display); color: var(--text-primary); }
.cl-rd-month-pos { display: block; font: 400 var(--text-xs) / 1 var(--body); color: var(--text-muted); margin-top: 2px; }

/* ── Grid body ── */
.cl-rd-body { flex: 1; overflow: auto; padding: 16px; }
.cl-rd-table-wrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border); border-radius: var(--radius-md);
}
.cl-rd-table { border-collapse: separate; border-spacing: 0; width: 100%; }
.cl-rd-table th, .cl-rd-table td {
  padding: 10px 12px; text-align: center; white-space: nowrap;
  border-bottom: 1px solid var(--border); border-right: 1px solid var(--border);
}
.cl-rd-table th:last-child, .cl-rd-table td:last-child { border-right: none; }
.cl-rd-table tbody tr:last-child th, .cl-rd-table tbody tr:last-child td { border-bottom: none; }
.cl-rd-table thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--bg-elevated); color: var(--text-secondary);
  font: 600 var(--text-xs) / 1.2 var(--body);
  text-transform: uppercase; letter-spacing: 0.03em;
}
/* Sticky first column (row headers + corner) so labels stay visible on scroll */
.cl-rd-corner, .cl-rd-rowhead {
  position: sticky; left: 0; z-index: 1;
  background: var(--bg-elevated); text-align: left !important;
  font: 600 var(--text-sm) / 1.2 var(--body); color: var(--text-primary);
}
.cl-rd-corner { z-index: 3; color: var(--text-secondary); }
.cl-rd-cell { font: 600 var(--text-base) / 1.1 var(--body); position: relative; }
.cl-rd-cell.is-empty { background: var(--bg-base); }
.cl-rd-cell.is-blank { color: var(--text-muted); font-weight: 400; }
.cl-rd-val { display: inline-flex; align-items: baseline; gap: 2px; }
.cl-rd-unit { font: 400 var(--text-xs) / 1 var(--body); opacity: 0.8; }
.cl-rd-multi {
  position: absolute; top: 3px; right: 4px;
  font: 600 9px / 1 var(--body); opacity: 0.7;
}
/* Value cells are tappable → that reading's trend (Step 3) */
.cl-rd-cell[data-item-id] { cursor: pointer; transition: filter 0.12s; }
.cl-rd-cell[data-item-id]:hover { filter: brightness(1.15); }

/* ── Trend drill-down ── */
.cl-rd-trendbar {
  flex-shrink: 0;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}
.cl-rd-back {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 11px 6px 8px; border-radius: var(--radius-md);
  background: var(--bg-elevated); border: 1px solid var(--border);
  color: var(--text-primary); cursor: pointer;
  font: 600 var(--text-sm) / 1 var(--body); flex-shrink: 0;
  transition: border-color 0.12s;
}
.cl-rd-back:hover { border-color: var(--accent); }
.cl-rd-back svg { width: 18px; height: 18px; }
.cl-rd-trend-title {
  font: 600 var(--text-base) / 1.2 var(--body); color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1;
}
.cl-rd-trend-safe {
  flex-shrink: 0;
  font: 600 var(--text-xs) / 1 var(--body);
  color: #16a34a; background: rgba(22,163,74,0.12);
  border: 1px solid rgba(22,163,74,0.35);
  padding: 4px 9px; border-radius: var(--radius-sm);
}
.cl-rd-trend { padding: 16px; }
.cl-rd-chart-wrap { max-width: 520px; margin: 0 auto; }
.cl-rd-chart { width: 100%; height: auto; display: block; }

/* Hero — latest value + status, the at-a-glance answer above the chart. */
.cl-rd-hero { max-width: 520px; margin: 0 auto 14px; }
.cl-rd-hero-main { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cl-rd-hero-val {
  font: 600 var(--text-3xl) / 1 var(--display); color: var(--text-primary);
  letter-spacing: -0.02em; display: inline-flex; align-items: baseline;
}
.cl-rd-hero-unit { font-size: var(--text-lg); color: var(--text-secondary); margin-left: 2px; }
.cl-rd-hero-pill {
  font: 600 var(--text-xs) / 1 var(--body); padding: 4px 9px;
  border-radius: var(--radius-sm); border: 1px solid;
}
.cl-rd-hero-sub {
  margin-top: 6px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font: 400 var(--text-sm) / 1.3 var(--body); color: var(--text-muted);
}
.cl-rd-hero-delta { font-weight: 600; color: var(--text-secondary); }
.cl-rd-hero-delta.is-flat { font-weight: 400; }
.cl-rd-hero-dot { color: var(--text-muted); }

/* Trend line chart — professional monitoring look: green/amber/red zone bands
   behind the line, subtle grid, labelled safe-window edges, units on the axis.
   All band/limit colours ride the RAG tokens so both themes stay correct. */
.cl-rd-band { stroke: none; }
.cl-rd-band-green { fill: color-mix(in srgb, var(--rag-pass-fill) 15%, transparent); }
.cl-rd-band-amber { fill: color-mix(in srgb, var(--rag-warn-fill) 15%, transparent); }
.cl-rd-band-red   { fill: color-mix(in srgb, var(--rag-fail-fill) 13%, transparent); }
.cl-rd-grid { stroke: var(--border); stroke-width: 1; opacity: 0.35; }
.cl-rd-limit { stroke: var(--rag-warn); stroke-width: 1.3; stroke-dasharray: 4 3; opacity: 0.85; }
.cl-rd-limit-lab { fill: var(--rag-warn); font: 600 10px / 1 var(--body); }
.cl-rd-area { fill: color-mix(in srgb, var(--accent) 9%, transparent); stroke: none; }
.cl-rd-trend-line { fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.cl-rd-axis { fill: var(--text-muted); font: 400 10px / 1 var(--body); }
.cl-rd-axis-unit { fill: var(--text-secondary); font: 600 9px / 1 var(--body); letter-spacing: 0.02em; }

/* Gauge (1–3 readings) — same zone bands on a rounded track. */
.cl-rd-gauge-track { fill: var(--bg-elevated); }
.cl-rd-gauge-mark { stroke-width: 2; }
.cl-rd-viz-hint {
  max-width: 520px; margin: 8px auto 0; text-align: center;
  font: 400 var(--text-xs) / 1.4 var(--body); color: var(--text-muted);
}

.cl-rd-legend {
  display: flex; flex-wrap: wrap; gap: 14px; justify-content: center;
  margin-top: 12px; font: 400 var(--text-xs) / 1 var(--body); color: var(--text-secondary);
}
.cl-rd-legend span { display: inline-flex; align-items: center; gap: 5px; }
.cl-rd-key { width: 14px; height: 10px; border-radius: 3px; border: 1px solid; }
.cl-rd-key-green { background: color-mix(in srgb, var(--rag-pass-fill) 22%, transparent); border-color: color-mix(in srgb, var(--rag-pass-fill) 55%, transparent); }
.cl-rd-key-amber { background: color-mix(in srgb, var(--rag-warn-fill) 22%, transparent); border-color: color-mix(in srgb, var(--rag-warn-fill) 55%, transparent); }
.cl-rd-key-red   { background: color-mix(in srgb, var(--rag-fail-fill) 20%, transparent); border-color: color-mix(in srgb, var(--rag-fail-fill) 55%, transparent); }
.cl-rd-line-key  { width: 16px; height: 0; border-top: 2px solid var(--accent); border-radius: 2px; }
.cl-rd-strip-label {
  margin: 16px 0 6px; font: 400 var(--text-xs) / 1 var(--body); color: var(--text-muted);
}
.cl-rd-strip {
  display: flex; gap: 8px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding-bottom: 4px;
}
.cl-rd-strip::-webkit-scrollbar { display: none; }
.cl-rd-strip-item { flex: 0 0 auto; text-align: center; }
.cl-rd-strip-val {
  font: 600 var(--text-base) / 1 var(--body);
  padding: 7px 10px; border-radius: var(--radius-md); min-width: 44px;
}
.cl-rd-strip-date { font: 400 var(--text-xs) / 1 var(--body); color: var(--text-muted); margin-top: 4px; }
/* A flagged check that raised a task — the whole chip taps through to it. */
button.cl-rd-strip-item.is-task {
  appearance: none; -webkit-appearance: none; background: none; border: 0;
  margin: 0; padding: 2px; cursor: pointer; font: inherit;
  border-radius: var(--radius-md); transition: background .12s ease;
}
button.cl-rd-strip-item.is-task:hover { background: var(--bg-elevated); }
button.cl-rd-strip-item.is-task:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cl-rd-strip-task {
  display: inline-flex; align-items: center; gap: 3px; margin-top: 5px;
  font: 600 var(--text-xs) / 1 var(--body); color: var(--accent);
}
.cl-rd-strip-task svg { width: 12px; height: 12px; }

/* Mobile width pass (2026-06-25): tighten horizontal padding on mobile so content
   uses the screen width. Appended at end-of-file so it beats the base rules AND any
   wider-breakpoint (600/640/767px) blocks at equal specificity (later source wins).
   Desktop (>=600px) untouched. */
@media (max-width: 599px) {
  /* Full-screen detail takeover at the physical top → clear the status bar /
     notch robustly (see --safe-top), exactly like .callout-detail-header. Sides
     trim to align the ref chip with the panel body's 12px edge. Without this the
     ref + Edit/⋯/Close row hid under the notch on iPhone. */
  .ctr-detail-header { padding: var(--safe-top) 12px 12px; }
  .ctr-panel-body { padding: 16px 12px 40px; }
  .ctr-history-feed { padding: 12px; }
  .cl-runner-items { padding: 12px 12px 28px; }
  .cl-runner-footer { padding: 14px 12px; }
}

/* ─────────────────────────────────────────────────────────────────────────
   FULL-SCREEN VIEWER HEADERS — DESKTOP SLIM (2026-07-12)
   Both full-screen viewers reserve --safe-top (54px floor) at the top of their
   header to clear the iPhone notch — a tall, wasted band on a desktop that has
   no notch, so each header reads far taller than it should. Slim them to match
   the annotation editor's desktop header (2026-07-12, css/04): reclaim the
   notch gap and use a compact 8px top/bottom so each bar is ~56px instead of
   ~108px; the content auto-fills the freed space (both stages are flex:1 —
   .photo-viewer-img is max-height:100%, the doc frame flex-grows — nothing to
   retune). Covers:
     • .pv-header       — the shared PHOTO viewer (tap a photo to inspect it)
     • .doc-viewer-bar  — the in-app PDF / document viewer (ui/doc-viewer.js)
   LONGHAND top/bottom only, so each base header's asymmetric horizontal padding
   (10px right / 18px left) is preserved (§4 CSS trap). Desktop-only — same query
   the editor uses; mobile/touch tablets keep their 44px targets + safe-top.
   Appended at end-of-file so it beats the base rules on source order; the
   max-width:640 block is mutually exclusive so order is moot there. Each header
   stays a themed surface (var(--bg-surface)) — light in light, dark in dark. */
@media (min-width: 1024px) and (pointer: fine) {
  .pv-header,
  .doc-viewer-bar { padding-top: 8px; padding-bottom: 8px; }
}

/* ═════════════════════════════════════════════════════════════════════════
   CHECKLISTS — Performance tab (Prompt 112, the compliance heatmap)
   ─────────────────────────────────────────────────────────────────────
   The on-time / late / missed month view. The month stepper reuses the
   readings .cl-rd-monthbar; the matrix reuses .cl-rd-table / .cl-rd-table-wrap
   (sticky first column + horizontal scroll). All colours are the shared
   --rag-* tokens — ZERO new colour values, both themes by construction.
   Rendered desktop-matrix + mobile-cards; the @media at the end reveals one.
   ═════════════════════════════════════════════════════════════════════════ */
.cl-perf { display: block; }
.cl-perf-monthbar { margin-bottom: 14px; }

/* Headline — big on-time %, then the On time / Late / Missed counters. */
.cl-perf-headline {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 16px; margin-bottom: 12px;
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--bg-surface);
}
.cl-perf-rate { font: 700 clamp(28px, 7vw, 40px) / 1 var(--display); color: var(--text-primary); }
.cl-perf-rate-unit { font: 500 var(--text-base) / 1 var(--body); color: var(--text-muted); }
.cl-perf-rate-sub { font: 500 var(--text-sm) / 1.2 var(--body); color: var(--text-muted); margin-top: 4px; }
.cl-perf-counts { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }
.cl-perf-count {
  display: inline-flex; flex-direction: column; align-items: center;
  padding: 8px 14px; border-radius: var(--radius-md);
  background: var(--bg-elevated); border: 1px solid var(--border);
}
.cl-perf-count-n { font: 700 var(--text-lg) / 1 var(--display); color: var(--text-primary); }
.cl-perf-count-l { font: 500 var(--text-xs) / 1 var(--body); color: var(--text-muted); margin-top: 4px; }
/* Amber tone on the Missed counter ONLY when missed > 0 (§4 loud = act-now). */
.cl-perf-count.is-flag {
  background: color-mix(in srgb, var(--rag-warn-fill) 12%, transparent);
  border-color: color-mix(in srgb, var(--rag-warn-fill) 40%, transparent);
}
.cl-perf-count.is-flag .cl-perf-count-n { color: var(--rag-warn); }

.cl-perf-adhoc { font: 500 var(--text-xs) / 1.4 var(--body); color: var(--text-muted); margin: -4px 0 12px; }
.cl-perf-floornote {
  display: flex; align-items: center; gap: 6px; margin: -2px 0 12px;
  font: 500 var(--text-xs) / 1.4 var(--body); color: var(--text-muted);
}
.cl-perf-floornote svg { width: 14px; height: 14px; flex-shrink: 0; opacity: 0.8; }

/* Legend — the dot vocabulary spelled out. */
.cl-perf-legend {
  display: flex; gap: 14px; flex-wrap: wrap; margin: 0 0 12px;
  font: 500 var(--text-xs) / 1 var(--body); color: var(--text-secondary);
}
.cl-perf-legend-item { display: inline-flex; align-items: center; gap: 6px; }

/* The dot — colour is the outcome axis, fill/outline the effort axis. */
.cl-perf-dot { display: inline-block; width: 12px; height: 12px; border-radius: 50%; position: relative; vertical-align: middle; }
.cl-perf-dot.is-on-time     { background: var(--rag-pass-fill); }
.cl-perf-dot.is-late        { background: var(--rag-warn-fill); }
.cl-perf-dot.is-missed      { background: var(--rag-fail-fill); }
.cl-perf-dot.is-missed-part { background: transparent; box-shadow: inset 0 0 0 2px var(--rag-fail-fill); }
.cl-perf-dot.is-pending     { background: transparent; box-shadow: inset 0 0 0 1.5px var(--text-muted); }
.cl-perf-dot.is-prefloor    { background: var(--bg-elevated); box-shadow: inset 0 0 0 1px var(--border); }
.cl-perf-dot.is-none        { background: transparent; }
/* Multi-slot day count — a tiny badge riding the dot's top-right. */
.cl-perf-cnt {
  position: absolute; top: -7px; right: -8px;
  font: 700 9px / 1 var(--body); color: var(--text-secondary);
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 1px 3px; min-width: 12px; text-align: center;
}

/* Desktop matrix — reuses .cl-rd-table (sticky first col + header). */
.cl-perf-matrix th, .cl-perf-matrix td { padding: 5px 3px; text-align: center; min-width: 24px; }
.cl-perf-matrix .cl-rd-corner, .cl-perf-matrix .cl-rd-rowhead { text-align: left; min-width: 148px; padding: 5px 10px; }
.cl-perf-dayhead { font: 600 var(--text-xs) / 1 var(--body); color: var(--text-secondary); }
.cl-perf-dayhead.is-today, .cl-perf-cell.is-today { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.cl-perf-cell { vertical-align: middle; }
.cl-perf-sumhead { text-align: right !important; min-width: 78px; padding-right: 10px !important; font: 600 var(--text-xs) / 1 var(--body); color: var(--text-secondary); }
.cl-perf-rowsum { text-align: right; white-space: nowrap; padding-right: 10px !important; font: 600 var(--text-sm) / 1.2 var(--body); color: var(--text-primary); }
.cl-perf-rowsum-miss { font: 500 var(--text-xs) / 1 var(--body); color: var(--rag-warn); }
.cl-perf-name {
  appearance: none; -webkit-appearance: none; background: none; border: 0; margin: 0; padding: 0;
  font: 600 var(--text-sm) / 1.2 var(--display); color: var(--text-primary);
  text-align: left; cursor: pointer; width: 100%;
}
.cl-perf-name:hover { color: var(--accent); }
.cl-perf-name:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }

/* Mobile cards + the shared mini month grid (also used by the drill-in). */
.cl-perf-cards { display: none; }   /* revealed <1024px by the @media below */
.cl-perf-card {
  display: block; width: 100%; text-align: left; padding: 12px;
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--bg-surface); cursor: pointer; margin-bottom: 10px;
}
.cl-perf-card:hover { border-color: var(--accent); }
.cl-perf-card-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.cl-perf-card-name { font: 600 var(--text-base) / 1.2 var(--display); color: var(--text-primary); }
.cl-perf-card-rate { font: 700 var(--text-base) / 1 var(--display); color: var(--rag-pass); white-space: nowrap; }
.cl-perf-card-rate-u { font: 500 var(--text-xs) / 1 var(--body); color: var(--text-muted); }
.cl-perf-card-sub { font: 500 var(--text-xs) / 1 var(--body); color: var(--text-muted); margin: 4px 0 10px; }
.cl-perf-mini { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cl-perf-mini-cell { aspect-ratio: 1; border-radius: 4px; background: var(--bg-elevated); }
.cl-perf-mini-cell.is-on-time     { background: var(--rag-pass-fill); }
.cl-perf-mini-cell.is-late        { background: var(--rag-warn-fill); }
.cl-perf-mini-cell.is-missed      { background: var(--rag-fail-fill); }
.cl-perf-mini-cell.is-missed-part { background: transparent; box-shadow: inset 0 0 0 2px var(--rag-fail-fill); }
.cl-perf-mini-cell.is-pending     { background: transparent; box-shadow: inset 0 0 0 1.5px var(--text-muted); }
.cl-perf-mini-cell.is-prefloor    { background: transparent; box-shadow: inset 0 0 0 1px var(--border); }
.cl-perf-mini-cell.is-none        { background: var(--bg-elevated); }
.cl-perf-mini-cell.is-blank       { background: transparent; }

/* Drill-in (one template). */
.cl-perf-drill-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.cl-perf-drill-title { font: 600 var(--text-lg) / 1.2 var(--display); color: var(--text-primary); }
.cl-perf-drill-rate { margin-left: auto; font: 600 var(--text-sm) / 1 var(--body); color: var(--text-secondary); white-space: nowrap; }
.cl-perf-drill-grid { max-width: 340px; margin: 0 0 14px; }
.cl-perf-drill-grid .cl-perf-mini-cell { border-radius: 5px; }
.cl-perf-occ-list { display: flex; flex-direction: column; gap: 8px; }
.cl-perf-occ {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--bg-surface); cursor: pointer;
}
.cl-perf-occ:hover { border-color: var(--accent); }
.cl-perf-occ:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cl-perf-occ-date { font: 600 var(--text-sm) / 1.2 var(--body); color: var(--text-primary); min-width: 108px; }
.cl-perf-occ-slot { font: 600 var(--text-xs) / 1 var(--body); color: var(--text-secondary); }
.cl-perf-occ-by { font: 500 var(--text-xs) / 1 var(--body); color: var(--text-muted); }
.cl-perf-occ-fu {
  font: 600 var(--text-xs) / 1 var(--body); color: var(--rag-warn);
  padding: 3px 8px; border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--rag-warn-fill) 12%, transparent);
}
.cl-perf-occ-chip { margin-left: auto; padding: 4px 9px; border-radius: var(--radius-sm); font: 600 var(--text-xs) / 1 var(--body); white-space: nowrap; }
.cl-perf-occ-chip.is-on-time { color: var(--rag-pass); background: color-mix(in srgb, var(--rag-pass-fill) 12%, transparent); }
.cl-perf-occ-chip.is-late    { color: var(--rag-warn); background: color-mix(in srgb, var(--rag-warn-fill) 14%, transparent); }
.cl-perf-occ-chip.is-missed  { color: var(--rag-fail); background: color-mix(in srgb, var(--rag-fail-fill) 12%, transparent); }
.cl-perf-occ-chip.is-neutral { color: var(--text-secondary); background: var(--bg-elevated); }

/* Show the matrix on desktop, the cards below it (append AFTER the base rules so
   the media query wins at equal specificity — §4). */
@media (max-width: 1023px) {
  .cl-perf-matrix-wrap { display: none; }
  .cl-perf-cards { display: block; }
}
@media (max-width: 599px) {
  .cl-perf-headline { padding: 14px 12px; gap: 12px; }
  .cl-perf-counts { margin-left: 0; }
  .cl-perf-occ-date { min-width: 92px; }
}

.cl-perf-matrix-wrap .cl-rd-table-wrap { max-height: min(70vh, 860px); overflow-y: auto; }

/* ─── Call-out engineer-visit controls — the §4 44px tap floor (2026-07-26) ───
   The visits card now sits directly under the contractor tile (§11), which made
   these the first controls a manager reaches for on a phone — and all four
   missed the floor: the foot button computed 33px (padding-driven, it declares
   no height) and the two corner icons were a hard 30x30.
   PHONE ONLY, deliberately. Desktop is pointer-fine and runs the css/01
   zoom:0.88, where the compact sizes are correct and a 44px bordered box around
   a 15px glyph reads as empty chrome.
   The glyph steps 15->17px because a 15px icon in a 44px box looks unintentional.
   Appended at FILE END so the media query beats the base rules at equal
   specificity (§4 source order — a media query adds none). */
@media (max-width: 599px) {
  .callout-visit-attend-btn { min-height: 44px; }
  .callout-visit-row-act { width: 44px; height: 44px; }
  .callout-visit-row-act svg { width: 17px; height: 17px; }
}
