/* ═══════════════════════════════════════════════════════════════════════
   CALL OUTS MODULE
   ─────────────────────────────────────────────────────────────────────
   Cross-department maintenance jobs. Visually consistent with tasks and
   KB — same surfaces, same shadows, same shapes. Distinctive bits:
     - Priority badge (P1–P4) coloured by severity
     - SLA traffic-light chip on every active card
     - Status pill follows the lifecycle name verbatim
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── List view ───────────────────────────────────────────────────── */
.callout-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.callout-loading {
  padding: 40px 24px;
  text-align: center;
  font-size: var(--text-base);
  color: var(--text-muted);
}

/* Empty state — sits in the centre of the list area when there's nothing
   to show, matches the visual language used by other empty states. */
.callout-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 60px 24px;
  text-align: center;
  color: var(--text-muted);
}
.callout-empty-icon {
  width: 56px; height: 56px;
  display: grid; place-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  color: var(--text-secondary);
}
.callout-empty-icon svg { width: 28px; height: 28px; }
.callout-empty-title {
  font-family: var(--display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}
.callout-empty-sub {
  font-size: var(--text-base);
  color: var(--text-muted);
  max-width: 340px;
}

/* Card — matches tasks-card layout for cross-module visual consistency:
   left priority colour bar (4px), padded main content area, rectangular
   chips on top row, dot+text priority indicator in the meta row. */
.callout-card {
  display: flex;
  align-items: stretch;
  gap: 0;
  width: 100%;
  padding: 0;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.12s, transform 0.05s, box-shadow 0.12s;
  touch-action: manipulation;
  position: relative;
}
.callout-card:hover {
  border-color: var(--accent);
  box-shadow: 0 2px 10px rgba(0,0,0,0.07);
}
[data-theme="dark"] .callout-card:hover { box-shadow: 0 1px 8px rgba(0,0,0,0.4); }
.callout-card:active { transform: scale(0.997); }

.callout-card-priority-bar {
  width: 4px;
  flex-shrink: 0;
  align-self: stretch;
}
.callout-card-main {
  flex: 1;
  min-width: 0;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.callout-card-top {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.callout-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;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  padding: 3px 7px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.callout-card-time {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-left: auto;
}
.callout-card-title {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.35;
  word-wrap: break-word;
}
/* Bottom signal row — priority + status + SLA (when firing) + contractor.
   Tighter gap than the old meta row since it now leads with chips. */
.callout-card-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: 2px;
}
/* Priority chip — same shape as the ref pill so the two read as a
   matched pair across the top of the card. Colour palette comes from
   the priority itself via inline CSS vars (--pri-color, --pri-soft).
   The old dot+text rendering was too quiet against the dark surface;
   a proper chip with tinted background + coloured border pulls the
   eye to it just like the ref pill does. */
/* CALM (2026-06-29) — neutral chip + colour on the dot, matching the cards/detail. */
.callout-card-priority {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.callout-card-priority-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--pri-color, var(--text-muted)); flex-shrink: 0;
}
/* Contractor on the card — a neutral CHIP (like the location/status/priority
   chips), with the colour kept on the wrench icon. (Radek 2026-06-29) */
.callout-card-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-primary);
  font-size: var(--text-xs);
  font-weight: 500;
}
.callout-card-meta-item svg { width: 13px; height: 13px; flex-shrink: 0; color: var(--accent); }
/* No contractor yet — a calm dashed "ghost" chip (mirrors .card-loc-chip--ghost). */
.callout-card-meta-empty {
  background: transparent;
  border-style: dashed;
  color: var(--text-muted);
  font-style: normal;
}
.callout-card-meta-empty svg { color: var(--text-muted); }

/* Status chip — rectangular (radius-sm), matches the ref-chip family.
   Default (fallback) is a muted neutral; each status gets its own tint. */
/* CALM (2026-06-29) — neutral chip + colour on the dot, matching the detail. The
   card's left bar + SLA chip carry the act-now signal. */
.callout-card-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-primary);
  letter-spacing: 0.01em;
}
.callout-card-status::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-muted); flex-shrink: 0;
}
.callout-card-status[data-status="raised"]::before,
.callout-card-status[data-status="quote_received"]::before { background: #f59e0b; }
.callout-card-status[data-status="assigned"]::before,
.callout-card-status[data-status="attended"]::before,
.callout-card-status[data-status="in_progress"]::before,
.callout-card-status[data-status="quote_approved"]::before { background: #3b82f6; }
.callout-card-status[data-status="awaiting_quote"]::before,
.callout-card-status[data-status="awaiting_parts"]::before { background: #ea580c; }
.callout-card-status[data-status="completed"]::before,
.callout-card-status[data-status="signed_off"]::before,
.callout-card-status[data-status="closed"]::before { background: #16a34a; }
.callout-card-status[data-status="on_hold"]::before { background: #ea580c; }
.callout-card-status[data-status="cancelled"] {
  color: var(--text-muted);
  text-decoration: line-through;
}
.callout-card-status[data-status="cancelled"]::before { background: var(--text-muted); }

/* SLA chip — rectangular traffic-light indicator on active cards.
   safe = subtle, warning = amber, breach = red */
.callout-card-sla {
  display: inline-flex;
  align-items: center;
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.01em;
}
.callout-card-sla.is-safe    { color: #16a34a; background: rgba(22,163,74,0.10);  border: 1px solid rgba(22,163,74,0.45); }
.callout-card-sla.is-warning { color: #ea580c; background: rgba(234,88,12,0.12);  border: 1px solid rgba(234,88,12,0.45); }
.callout-card-sla.is-breach  { color: #dc2626; background: rgba(220,38,38,0.12);  border: 1px solid rgba(220,38,38,0.45); }

/* ─── Raise callout modal ────────────────────────────────────────── */
.callout-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 9000;
  /* iOS paint-order fix: self-composite so this fixed overlay gets its own
     GPU layer and its z-index is honoured against the permanently-composited
     .app-shell (transform + will-change in css/02). Without a compositing
     trigger, iOS WebKit can paint a fixed body-child UNDER the shell despite a
     higher z-index — the "modal opens behind the view" bug. (Picker sheets get
     the SAME explicit fix in css/16 — backdrop-filter alone doesn't do it
     reliably on iOS, despite an earlier comment here that claimed it did.) */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
  opacity: 0;
  transition: opacity 0.18s ease;
  padding-bottom: var(--keyboard-height, 0px);
}
.callout-modal-overlay.is-open { opacity: 1; }
@media (min-width: 600px) {
  .callout-modal-overlay { align-items: center; padding: 16px; }
}
body.callout-modal-open { overflow: hidden; }

.callout-modal {
  width: 100%;
  max-width: 560px;
  max-height: 92vh;
  background: var(--bg-surface);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  display: flex;
  flex-direction: column;
  transform: translateY(20px);
  transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
  overflow: hidden;
}
.callout-modal-overlay.is-open .callout-modal { transform: translateY(0); }
@media (min-width: 600px) {
  .callout-modal { border-radius: var(--radius-lg); }
}
@media (max-width: 599px) {
  .callout-modal { max-height: calc(92vh - var(--keyboard-height, 0px)); }
  /* iOS safe area: keep close + title clear of the notch/clock when
     the modal expands to fill most of the screen. */
  .callout-modal .callout-modal-head {
    padding-top: max(14px, calc(env(safe-area-inset-top) + 8px));
  }
}
.callout-modal-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.callout-modal-head h2 {
  flex: 1;
  margin: 0;
  font-family: var(--display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.015em;
}
.callout-modal-close {
  width: 36px; height: 36px;
  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;
}
.callout-modal-close:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.callout-modal-close svg { width: 18px; height: 18px; }
.callout-modal-body {
  padding: 16px 20px;
  overflow-y: auto;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.callout-modal-foot {
  display: flex;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  justify-content: flex-end;
}
/* While the keyboard is up you're filling fields, not submitting — hide the
   Cancel / Raise-callout footer so the form reclaims the space above the
   keyboard. It reappears when the keyboard closes (the natural moment to submit).
   Same pattern as the Tasks sheet. Radek 2026-06-27. */
body.kb-open .callout-modal-foot { display: none; }

/* Banner shown at the top of the raise form — purple link banner when
   raising from a task, neutral info banner when raising standalone. */
.callout-form-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--accent-soft, rgba(0, 216, 230, 0.08));
  color: var(--accent);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  line-height: 1.4;
}
.callout-form-banner svg { width: 16px; height: 16px; flex-shrink: 0; }
.callout-form-banner-info {
  background: var(--bg-elevated);
  color: var(--text-secondary);
}

/* Form field — consistent across all callout inputs */
.callout-form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.callout-form-field label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
}
.callout-form-required {
  color: #dc2626;
  font-weight: 700;
}
/* Shared form fields — DEFINED everywhere (app-wide legibility, Radek 2026-06-30,
   promoted from the checklist/audit builder pilot). The fields fill --bg-elevated
   and many forms (call-outs, tasks) render them DIRECTLY on the white --bg-surface
   modal body, where that grey fill pops (the cost-entry look). The faint --border
   was the problem: on a grey .callout-form-section panel the field melted into the
   panel. Strengthen the resting border to --border-input + add an accent focus ring
   so every field reads as a distinct box on BOTH a white body AND a grey panel —
   without flipping the fill to white (which would go white-on-white on the bare
   modal body). The builders keep their scoped white fill (it pops on their grey
   panels); everywhere else stays grey-on-white. */
.callout-form-field input[type="text"],
.callout-form-field input[type="tel"],
.callout-form-field input[type="email"],
.callout-form-field textarea {
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
  resize: vertical;
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s;
}
.callout-form-field input:focus,
.callout-form-field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* App-muted placeholder (like .tasks-field / .tasks-search) so callout-form
   inputs (Location, Contractor, …) match the KB-style Title/Description instead
   of falling back to the browser default grey. */
.callout-form-field input::placeholder,
.callout-form-field textarea::placeholder { color: var(--text-muted); }

/* Container-aware fill (app-wide legibility, Radek 2026-06-30). A control sitting
   DIRECTLY on the white modal body keeps the grey --bg-elevated fill (it pops on
   white — the cost-entry look; handled by the base rules above). But the same
   control INSIDE a grey .callout-form-section panel was grey-on-grey and blended
   (Projects, Contractors, the builders…). So: inside a section, flip the fill to
   white so it pops off the grey panel. .callout-form-section is always
   --bg-elevated (no white override exists in any css), so this never goes
   white-on-white. background-COLOR only — borders + accent focus rings are left to
   the base/focus rules, so this never clobbers a focus state. Covers the shared
   controls: form fields, the .tasks-priority-trigger dropdowns, .ah-locfield
   pickers (location / budget pot) and the .budget-amount-input £ wrapper. */
.callout-form-section .callout-form-field input[type="text"],
.callout-form-section .callout-form-field input[type="tel"],
.callout-form-section .callout-form-field input[type="email"],
.callout-form-section .callout-form-field input[type="number"],
.callout-form-section .callout-form-field input[type="date"],
.callout-form-section .callout-form-field textarea,
.callout-form-section .callout-form-field-textarea,
.callout-form-section .callout-form-field select,
.callout-form-section .tasks-priority-trigger,
.callout-form-section .ah-locfield,
.callout-form-section .budget-amount-input,
/* + the segmented choice chips, inventory pickers and the compliance recurrence
   select (adversarial-review gaps): all fill --bg-elevated too and would otherwise
   stay grey beside their now-white siblings. Their `.is-selected` rules sit later
   in source, so the accent selected state still wins — no clobber. */
.callout-form-section .callout-costs-cat-option,
.callout-form-section .callout-costs-quote-status-option,
.callout-form-section .inv-chip-pick,
.callout-form-section .inv-supplier-pick-btn,
/* + the .ctree-lt segmented pills (safety doc-type / read-mode / persons /
   routes, compliance + projects link-type pickers): same --bg-elevated fill,
   same grey-on-grey blend inside a section (Radek 2026-07-16). Their .is-on /
   :hover accent rules live later in source (css/15), so selected/hover states
   still win — no clobber. */
.callout-form-section .ctree-lt,
.callout-form-section .cl-recurrence-unit {
  background-color: var(--bg-surface);
}
/* The pills' resting hairline also melted on the grey panel — firm it to the
   input border (the 2026-06-30 field law). css/15's .is-on/:hover accent
   border-colors still win (equal specificity, later file). */
.callout-form-section .ctree-lt { border-color: var(--border-input); }
.callout-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 480px) {
  .callout-form-row { grid-template-columns: 1fr; }
}
.callout-form-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
}
/* Mobile: reclaim the side margins. Desktop keeps the roomier 20/14px, but on a
   phone the nested modal→form padding wastes ~30% of the width (CLAUDE.md mobile-
   first). Trim the SHARED modal shell + form panel so every form gets wider.
   NOTE: must sit AFTER the base rules above — equal specificity, so source order
   decides (a media query adds no specificity). */
@media (max-width: 599px) {
  .callout-modal-body   { padding: 14px 12px; gap: 12px; }
  .callout-form-section { padding: 10px; }
}
.callout-form-section-head {
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-form-section-sub {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: -6px;
}
/* Small uppercase label to group related fields inside one form section
   (e.g. Hourly labour / Charges within the contractor Rate card). */
.callout-form-subhead {
  font: 700 11px / 1 var(--body);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 4px 0 -2px;
}

/* Priority grid — 2x2 visual selector for P1–P4. Each option is a
   tappable card with the badge, label and one-line description. */
.callout-priority-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
@media (max-width: 420px) {
  .callout-priority-grid { grid-template-columns: 1fr; }
}
.callout-priority-option {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 10px;
  row-gap: 2px;
  align-items: center;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.callout-priority-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.callout-priority-option-badge {
  grid-row: 1 / span 2;
  display: grid; place-items: center;
  width: 36px; height: 36px;
  background: var(--p-soft);
  color: var(--p-colour);
  border-radius: var(--radius-md);
  font-weight: 700;
  font-size: var(--text-base);
  letter-spacing: 0.04em;
}
.callout-priority-option-label {
  font-weight: 600;
  font-size: var(--text-base);
  color: var(--text-primary);
}
.callout-priority-option-desc {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.callout-priority-option.is-selected {
  border-color: var(--p-colour);
  background: var(--bg-surface);
}

/* Buttons — primary calls action verbs in accent, secondary cancels in muted */
.callout-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 18px;
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, transform 0.06s;
  touch-action: manipulation;
  border: 1px solid transparent;
}
.callout-btn:active:not(:disabled) { transform: scale(0.98); }
.callout-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.callout-btn-primary {
  background: var(--accent);
  color: #001317;
  border-color: var(--accent);
}
.callout-btn-primary:hover:not(:disabled) {
  filter: brightness(1.08);
}
.callout-btn-secondary {
  background: transparent;
  color: var(--text-secondary);
  border-color: var(--border);
}
.callout-btn-secondary:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
/* Destructive actions (Delete / Remove / Clear) — tinted red, matching the
   app's existing danger affordances (.kb-folder-action.danger etc.). Used in
   ~18 places that previously had no .callout-btn-danger rule at all, so every
   destructive button across the app now reads as red. */
.callout-btn-danger {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 35%, transparent);
}
.callout-btn-danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--danger) 20%, transparent);
  border-color: color-mix(in srgb, var(--danger) 55%, transparent);
}

/* ─── Detail view (fullscreen overlay) ──────────────────────────── */
.callout-detail-overlay {
  position: fixed;
  inset: 0;
  z-index: 8500;
  background: var(--bg-base);
  opacity: 0;
  transition: opacity 0.2s ease;
  display: flex;
  align-items: stretch;
  overflow: hidden;
}
.callout-detail-overlay.is-open { opacity: 1; }
body.callout-detail-open { overflow: hidden; }

/* ── Desktop master-detail (opt-in via .is-inset) ─────────────────────
   On desktop (≥1024px, where the drawer is a permanent left rail) an inset
   detail opens WITHIN the content area — right of the rail, below the app
   bar — so the nav rail + top bar stay visible and usable instead of being
   covered by a full-screen takeover. Opt-in per module by adding .is-inset
   (Assets adopts it first; add the class elsewhere to follow, app-wide).
   The rail width is var(--drawer-width) and collapses to 0 under
   body.rail-collapsed, so the inset tracks it live. --ah-detail-top is set
   by the opener to the app bar's measured bottom (respects the impersonation
   banner + safe-area). Below 1024px (rail is a slide-out drawer) it stays
   full-screen; the login-less engineer QR portal never adds .is-inset, so it
   stays full-screen too. */
@media (min-width: 1024px) {
  .callout-detail-overlay.is-inset {
    left: var(--drawer-width);
    top: var(--ah-detail-top, 64px);
  }
  body.rail-collapsed .callout-detail-overlay.is-inset { left: 0; }

  /* In the inset desktop detail, scroll the WHOLE thing as one unit — the
     header (ref/name/icons) and the service-status zone scroll away with the
     body instead of staying pinned, so they don't eat fixed vertical space and
     the user gets full height to read. The shell becomes the single scroller;
     the inner .callout-detail-scroll drops to natural height so there's no
     nested scroll. The tab bar (.callout-detail-tabs, position:sticky top:0)
     still re-pins to the top once the header has scrolled past, so the
     Activity / Costs / Documents tabs stay reachable. Mobile / full-screen
     keep the pinned header (unchanged). */
  .callout-detail-overlay.is-inset .callout-detail-shell {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .callout-detail-overlay.is-inset .callout-detail-scroll {
    flex: 0 0 auto;
    overflow-y: visible;
  }
}

.callout-detail-shell {
  width: 100%;
  height: 100%;
  max-width: 980px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  /* White in EVERY mode (desktop pane AND full-screen / mobile overlay) so the
     detail always reads as a clean white card with the same contrast as the
     Tasks detail — the grey inner tiles (contractor / asset / quick-actions /
     engineer visits) pop against it. Radek prefers this over the old grey
     full-screen look (2026-07-01). */
  background: var(--bg-surface);
  overflow: hidden;
}

/* Slim sticky top bar — always visible. Only holds ref + priority + icons. */
.callout-detail-header {
  flex-shrink: 0;
  padding: 10px 18px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
}
/* Scroll container — everything below the top bar scrolls as one unit.
   Deliberately a PLAIN BLOCK (not display:flex), mirroring the Tasks detail
   scroller (.tasks-modal-body). iOS Safari silently breaks position:sticky for
   children of a flex scroll container, so a flex container here stopped the
   Activity/Costs/Documents tab bar from staying pinned on iPhone — while Tasks
   (a block scroller) worked. Keeping this a block makes the sticky tab bar pin
   reliably across browsers. */
.callout-detail-scroll {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
/* Title, stepper, actions, quick chips — inside the scroll container. */
.callout-detail-header-body {
  padding: 16px 18px 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.callout-detail-header-top {
  display: flex;
  align-items: center;
  gap: 6px;
  /* Allow chips + action icons to wrap when the asset/callout ref is
     long enough that they would overflow on a single line. Previously
     this was nowrap, which pushed the rightmost icons (including the
     critical X close button) off-screen on narrow viewports. With wrap
     + the actions row's margin-left:auto, the icons stay flush-right
     on whatever row they end up on. */
  flex-wrap: wrap;
  row-gap: 8px;
}
.callout-detail-header-actions {
  /* When the row wraps, the actions block goes to a new line on its
     own. Without flex-basis here the auto margin-left only kicks in
     if there's leftover width, which means a single very wide chip
     would still strand the actions to the left of the next row. */
  flex-shrink: 0;
}
.callout-detail-back {
  width: 36px; height: 36px;
  display: grid; place-items: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.callout-detail-back:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.callout-detail-back svg { width: 18px; height: 18px; }

.callout-detail-ref {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Detail status + priority read CALM — neutral chip, colour kept only on the dot
   (matches the Tasks detail + the pickers). The SLA chip stays loud (act-now).
   List cards keep the loud tinted signal for scanning. (Radek 2026-06-29) */
.callout-detail-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-primary);
  letter-spacing: 0.01em;
}
.callout-detail-status::before {
  content: '';
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--text-muted);
  flex-shrink: 0;
}
.callout-detail-status[data-status="raised"]::before,
.callout-detail-status[data-status="quote_received"]::before { background: #f59e0b; }
.callout-detail-status[data-status="assigned"]::before,
.callout-detail-status[data-status="attended"]::before,
.callout-detail-status[data-status="in_progress"]::before,
.callout-detail-status[data-status="quote_approved"]::before { background: #3b82f6; }
.callout-detail-status[data-status="awaiting_quote"]::before,
.callout-detail-status[data-status="awaiting_parts"]::before { background: #ea580c; }
.callout-detail-status[data-status="completed"]::before,
.callout-detail-status[data-status="signed_off"]::before,
.callout-detail-status[data-status="closed"]::before { background: #16a34a; }
.callout-detail-status[data-status="on_hold"]::before { background: #ea580c; }
.callout-detail-status[data-status="cancelled"] {
  color: var(--text-muted);
  text-decoration: line-through;
}
.callout-detail-status[data-status="cancelled"]::before { background: var(--text-muted); }

/* Priority chip in the detail header — neutral chip + coloured dot. */
.callout-detail-priority {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.01em;
  white-space: nowrap;
  flex-shrink: 0;
}
.callout-detail-cdot {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.callout-detail-sla {
  display: inline-flex;
  align-items: center;
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.01em;
}
.callout-detail-sla.is-safe    { color: #16a34a; background: rgba(22,163,74,0.10);  border: 1px solid rgba(22,163,74,0.45); }
.callout-detail-sla.is-warning { color: #ea580c; background: rgba(234,88,12,0.12);  border: 1px solid rgba(234,88,12,0.45); }
.callout-detail-sla.is-breach  { color: #dc2626; background: rgba(220,38,38,0.12);  border: 1px solid rgba(220,38,38,0.45); }

.callout-detail-header-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}
.callout-detail-nextstep {
  padding: 8px 14px;
  font-size: var(--text-sm);
}
.callout-detail-more {
  width: 36px; height: 36px;
  display: grid; place-items: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.callout-detail-more:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.callout-detail-more svg { width: 18px; height: 18px; }
.callout-detail-more.is-danger { color: #dc2626; }
.callout-detail-more.is-danger:hover { background: rgba(220,38,38,0.1); color: #dc2626; }

.asset-detail-title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-top: 12px;
}
.asset-detail-title-row .callout-detail-title { margin-top: 0; }
/* Category chip sits inline next to the title; never let it squish. */
.asset-detail-title-row .asset-detail-cat { flex-shrink: 0; }

/* Meta row — sits below the title, holds category + priority + location
   (+ warranty / service chips when present). Wraps to multiple lines on
   narrow viewports so no chip ever gets pushed off-screen. Replaces the
   old layout where these chips sat on the top row next to the ref ID
   and could push the X close button off the right edge. */
.asset-detail-meta-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

/* Re-skin the location chip so it reads as a neutral pill (matching the
   detail chip padding / border / weight). It rides inline AFTER the title
   in the title row; default .callout-detail-location is a plain text+icon
   line used in callouts elsewhere, so we scope this override to the asset
   title row to avoid leaking. Muted-neutral colours keep it visually softer
   than the category (coloured) chip — it's informational, not categorical.
   flex-shrink:0 stops it squishing next to a long title. */
.asset-detail-title-row .callout-detail-location {
  flex-shrink: 0;
  padding: 4px 9px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: 600 var(--text-xs) / 1 var(--body);
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  gap: 5px;
}
.asset-detail-title-row .callout-detail-location svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  color: var(--text-muted);
}
/* Warranty / service chips inherit .callout-card-sla which is a bit
   chunkier than the other detail chips by default — bring them in line
   when they sit in the asset meta row so the rhythm stays even. */
.asset-detail-meta-row .callout-card-sla {
  padding: 4px 9px;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
  border-radius: var(--radius-sm);
}
.callout-detail-title {
  margin: 4px 0 0;
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.02em;
  line-height: 1.25;
}
.callout-detail-location {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.callout-detail-location svg { width: 14px; height: 14px; }
.callout-detail-description {
  margin: 0;
  font-size: var(--text-base);
  color: var(--text-secondary);
  line-height: 1.5;
  white-space: pre-wrap;
}

/* Cost summary strip — three small cells, only visible to roles with
   the callouts.view-costs permission. */
.callout-detail-cost-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.callout-detail-cost-cell {
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-right: 1px solid var(--border);
}
.callout-detail-cost-cell:last-child { border-right: 0; }
.callout-detail-cost-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.callout-detail-cost-value {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}

/* ═══════════════════════════════════════════════════════════════════════
   SEGMENTED TABS — canonical reusable component
   ─────────────────────────────────────────────────────────────────────
   Pill container with full accent-fill on the active tab. Use for
   2-4 tab view-mode switches (Activity/Costs/Documents, Active/History
   etc.). For 5+ tabs use underline tabs instead — segmented gets
   cramped at that count.

   Two variants:
     .segmented-tabs            — inline-block, sizes to content
     .segmented-tabs.is-stretch — full-width, each tab flex:1
   ═══════════════════════════════════════════════════════════════════════ */
.segmented-tabs {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.segmented-tabs.is-stretch {
  display: flex;
  width: 100%;
}
.segmented-tab {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  white-space: nowrap;
}
.segmented-tab:hover  { color: var(--text-primary); }
.segmented-tab.is-on,
.segmented-tab.is-active {
  background: var(--accent);
  color: var(--bg-base);
}
.segmented-tab svg { width: 14px; height: 14px; flex-shrink: 0; }

/* Callouts detail tab bar — adopts the canonical segmented look.
   Sticky beneath the header so the user can switch view-modes
   without scrolling back. Stretched to fill the modal width because
   it lives in a focused detail view; in narrower contexts (e.g.,
   inline blocks) prefer the inline default. */
.callout-detail-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 12px 18px 4px;
  padding: 3px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  position: sticky;
  top: 0;
  z-index: 4;
}
.callout-detail-tab {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 12px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  white-space: nowrap;
}
.callout-detail-tab:hover { color: var(--text-primary); }
.callout-detail-tab.is-active {
  background: var(--accent);
  color: var(--bg-base);
}
.callout-detail-tab svg { width: 14px; height: 14px; flex-shrink: 0; }

/* Body — scrollable area beneath the sticky header */
.callout-detail-body {
  flex: 1;
  padding: 16px 18px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.callout-detail-body-stub { justify-content: center; }

/* More-menu — small floating menu anchored beneath the kebab button */
.callout-detail-more-menu {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 4px 16px rgba(0,0,0,0.12);
  padding: 4px;
  min-width: 180px;
  z-index: 9000;
}
.callout-detail-more-item {
  display: block;
  width: 100%;
  padding: 8px 12px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.callout-detail-more-item:hover { background: var(--bg-elevated); }
.callout-detail-more-item.is-destructive { color: #dc2626; }
.callout-detail-more-item.is-destructive:hover { background: rgba(220,38,38,0.08); }
.callout-detail-more-item.is-active { color: var(--accent); }
.callout-detail-more-item { display: flex; align-items: center; gap: 8px; }
.callout-detail-more-empty {
  padding: 8px 12px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* ─── Timeline tab ─────────────────────────────────────────────── */
.callout-timeline-composer {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.callout-timeline-composer-input {
  flex: 1;
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  padding: 8px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  resize: vertical;
  min-height: 44px;
}
.callout-timeline-composer-input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-surface);
}
.callout-timeline-composer-send {
  flex-shrink: 0;
  padding: 9px 14px;
  font-size: var(--text-sm);
}

/* Event feed — vertical timeline with icon column on the left */
.callout-event-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.callout-event {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 12px;
  padding: 10px 0;
  position: relative;
}
/* Vertical connector line between event icons — drawn from each icon's
   bottom edge through to the next icon's top. Last item is trimmed in JS
   via the :last-child pseudo. */
.callout-event:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 15px;
  top: 36px;
  bottom: -6px;
  width: 2px;
  background: var(--border);
}
.callout-event-icon {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  z-index: 1;
}
.callout-event-icon svg { width: 14px; height: 14px; }
.callout-event[data-event-type="raised"] .callout-event-icon {
  color: var(--accent);
  border-color: rgba(0,216,230,0.4);
  background: rgba(0,216,230,0.08);
}
.callout-event[data-event-type="status_change"] .callout-event-icon {
  color: #6366f1;
  border-color: rgba(99,102,241,0.4);
  background: rgba(99,102,241,0.08);
}
.callout-event[data-event-type="note"] .callout-event-icon {
  color: var(--text-secondary);
}
.callout-event-body {
  min-width: 0;
  padding-top: 4px;
}
.callout-event-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: var(--text-xs);
}
.callout-event-actor {
  font-weight: 600;
  color: var(--text-primary);
}
.callout-event-time {
  color: var(--text-muted);
}
.callout-event-text {
  margin-top: 2px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* On mobile the detail overlay claims the full screen with no inset.
   Tablet/desktop allow some breathing room around the shell. */
@media (max-width: 600px) {
  .callout-detail-shell {
    border-radius: 0;
  }
  .callout-detail-header {
    /* Mobile = full-screen takeover at the physical top → clear the status bar
       robustly (see --safe-top). Desktop .is-inset pane is unaffected (it uses
       the base rule below the app bar). */
    padding: var(--safe-top) 14px 10px;
  }
  .callout-detail-header-body {
    padding: 14px 14px 0;
  }
  .callout-detail-tabs {
    margin: 10px 14px 4px;
  }
  .callout-detail-body {
    padding: 12px 14px 24px;
  }
  .callout-detail-title { font-size: var(--text-xl); }
  .callout-detail-cost-strip {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ─── Costs tab ──────────────────────────────────────────────────── */
.callout-costs-totals {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.callout-costs-total-cell {
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-right: 1px solid var(--border);
}
.callout-costs-total-cell:last-child { border-right: 0; }
.callout-costs-total-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.callout-costs-total-value {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-costs-total-value.is-over  { color: #dc2626; }
.callout-costs-total-value.is-under { color: #16a34a; }
.callout-costs-total-sub {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* Section header above the list */
.callout-costs-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 6px;
}
.callout-costs-heading {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-costs-add {
  padding: 7px 12px;
  font-size: var(--text-sm);
  gap: 4px;
}
.callout-costs-add svg { width: 14px; height: 14px; }

/* Cost row — category chip, body, amount column, actions */
.callout-costs-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.callout-costs-row {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.callout-costs-cat {
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  letter-spacing: 0.02em;
}
.callout-costs-row-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.callout-costs-row-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.callout-costs-row-desc {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
  word-wrap: break-word;
}
.callout-costs-row-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.callout-costs-row-date { color: var(--text-muted); }
.callout-costs-file {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--accent);
  text-decoration: none;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  background: rgba(0,216,230,0.08);
  transition: background 0.12s;
}
.callout-costs-file:hover { background: rgba(0,216,230,0.16); }
.callout-costs-file svg { width: 12px; height: 12px; }
.callout-costs-row-amount {
  text-align: right;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.callout-costs-row-amount-ex {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-costs-row-amount-inc {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.callout-costs-row-actions {
  display: flex;
  gap: 4px;
}
.callout-costs-row-btn {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.callout-costs-row-btn:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.callout-costs-row-btn svg { width: 14px; height: 14px; }
.callout-costs-row-btn-danger:hover {
  background: rgba(220,38,38,0.10);
  color: #dc2626;
}

/* Quote status badge — pending/approved/rejected */
.callout-costs-quote-status {
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  text-transform: capitalize;
}
.callout-costs-quote-status.is-pending  { background: rgba(202,138,4,0.12);  color: #ca8a04; }
.callout-costs-quote-status.is-approved { background: rgba(22,163,74,0.10);  color: #16a34a; }
.callout-costs-quote-status.is-rejected { background: rgba(220,38,38,0.10);  color: #dc2626; }

/* Category & quote-status pickers in the modal */
.callout-costs-cat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}
@media (max-width: 420px) {
  .callout-costs-cat-grid { grid-template-columns: 1fr; }
}
.callout-costs-cat-option {
  position: relative;
  display: flex;
  align-items: center;
  padding: 8px 10px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
  transition: border-color 0.12s, background 0.12s;
}
.callout-costs-cat-option input { position: absolute; opacity: 0; pointer-events: none; }
.callout-costs-cat-option.is-selected {
  border-color: var(--cat-colour);
  background: var(--cat-soft);
  color: var(--cat-colour);
}
.callout-costs-quote-status-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.callout-costs-quote-status-option {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.callout-costs-quote-status-option input { position: absolute; opacity: 0; pointer-events: none; }
.callout-costs-quote-status-option.is-selected {
  border-color: var(--accent);
  background: var(--bg-surface);
  color: var(--text-primary);
}

.callout-form-field select {
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
}
.callout-form-field input[type="number"],
.callout-form-field input[type="date"] {
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
}
.callout-form-field input[type="file"] {
  font-family: inherit;
  font-size: var(--text-sm);
  padding: 8px;
  background: var(--bg-elevated);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
}
.callout-form-help {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-top: 2px;
}

/* ─── Documents tab ──────────────────────────────────────────────── */
.callout-docs-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}
.callout-docs-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.callout-docs-section-title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-docs-add {
  padding: 7px 12px;
  font-size: var(--text-sm);
  gap: 4px;
  cursor: pointer;
}
.callout-docs-add svg { width: 14px; height: 14px; }
.callout-docs-empty {
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-align: center;
}

/* Photo grid — square thumbnails with overlay action buttons */
.callout-photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px;
}
/* Callout detail: pin the Documents photo thumbnails to the same fixed
   96×96 size used by the Activity-timeline photo thumbnails
   (.callout-event-photo) so the two reads consistently instead of the
   stretchy 120px+ grid tiles. Desktop only — the <600px rule below keeps
   the 88px phone size. */
@media (min-width: 600px) {
  .callout-detail-body .callout-photo-grid {
    grid-template-columns: repeat(auto-fill, 96px);
    justify-content: start;
  }
  .callout-detail-body .callout-photo-tile {
    width: 96px;
    height: 96px;
    aspect-ratio: auto;
  }
}
/* Unified mobile thumbnail size for both Asset Register and Callouts —
   88×88 sits between the KB inline-step thumb (64) and the original
   callout grid (120+). Big enough to read a model plate at arm's
   length, small enough that 3-4 fit on a phone row. */
@media (max-width: 599px) {
  .asset-detail-body .callout-photo-grid,
  .callout-detail-body .callout-photo-grid {
    grid-template-columns: repeat(auto-fill, 88px);
    justify-content: start;
    gap: 8px;
  }
  .asset-detail-body .callout-photo-tile,
  .callout-detail-body .callout-photo-tile {
    width: 88px;
    height: 88px;
    aspect-ratio: auto;
  }
  .asset-detail-body .callout-photo-btn,
  .callout-detail-body .callout-photo-btn {
    width: 24px; height: 24px;
  }
  .asset-detail-body .callout-photo-btn svg,
  .callout-detail-body .callout-photo-btn svg { width: 12px; height: 12px; }
  .asset-detail-body .callout-photo-tile-actions,
  .callout-detail-body .callout-photo-tile-actions {
    top: 4px; right: 4px;
    gap: 3px;
  }
}
.callout-photo-tile {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--bg-elevated);
  /* Stronger 1.5px border so each photo reads as a distinct card
     against the light tab background. Soft shadow gives the same
     lift the timeline/cost cards have. */
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.callout-photo-tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.callout-photo-tile-actions {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.12s;
}
.callout-photo-tile:hover .callout-photo-tile-actions,
.callout-photo-tile:focus-within .callout-photo-tile-actions {
  opacity: 1;
}
@media (hover: none) {
  .callout-photo-tile-actions { opacity: 1; }
}
.callout-photo-btn {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  background: rgba(0,0,0,0.6);
  border: 0;
  border-radius: var(--radius-sm);
  color: #fff;
  cursor: pointer;
}
.callout-photo-btn:hover { background: rgba(0,0,0,0.8); }
.callout-photo-btn svg { width: 14px; height: 14px; }
.callout-photo-btn-danger:hover { background: #dc2626; }
/* annotation-count badge → shared .ah-annot-badge.is-thumb.at-bl (Prompt 106) */

/* File list — rows with type chip, name+meta link, delete */
.callout-doc-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.callout-doc-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  background: var(--bg-surface);
  /* Match the photo tile — stronger 1.5px border + soft shadow so the
     file row reads as a distinct card. */
  border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.callout-doc-type {
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  letter-spacing: 0.02em;
}
.callout-doc-link {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  color: var(--text-primary);
  text-decoration: none;
}
.callout-doc-name {
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.callout-doc-link:hover .callout-doc-name { color: var(--accent); }
.callout-doc-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.callout-doc-btn {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.callout-doc-btn:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.callout-doc-btn svg { width: 14px; height: 14px; }
.callout-doc-btn-danger:hover {
  background: rgba(220,38,38,0.10);
  color: #dc2626;
}

/* Document-type picker modal (the "What type of file?" chooser) */
.callout-modal-narrow { max-width: 420px; }
.callout-doc-type-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
@media (max-width: 420px) {
  .callout-doc-type-grid { grid-template-columns: 1fr; }
}
.callout-doc-type-option {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.12s, background 0.12s;
}
.callout-doc-type-option:hover {
  border-color: var(--type-colour);
  background: var(--type-soft);
}
.callout-doc-type-chip {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
  padding: 6px 12px;
  background: var(--type-soft);
  color: var(--type-colour);
  border-radius: var(--radius-sm);
}

/* ─── List wrap, view toggle, KPI cards ─────────────────────────── */
/* No explicit max-width — defer to .main so the module gets the same
   responsive width budget as KB and Rooms (720 → 1200 → 1280 → 1440px).
   This keeps cards visually consistent across modules. The small top
   padding restores breathing room below the sticky app-bar. */
.callout-list-wrap {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 0 0;
}
.callout-list-wrap .callout-list { padding: 0; max-width: none; margin: 0; }

/* Shared filter-pill toggle — used by Callouts list (All/Open/Done),
   Asset Register filters (All/Due/Overdue), and any other inline
   pill-filter surface. Adopts the canonical segmented-tabs visual
   treatment so the active state is unambiguous in dark mode.
   (Previously the active fill was bg-surface which was barely
   visible against the bg-elevated container — looked broken on
   dark themes.) */
.callout-view-toggle {
  display: inline-flex;
  align-self: flex-start;
  max-width: 100%;                   /* cap to the row so overflow can scroll  */
  overflow-x: auto;                  /* too many tabs to fit → swipe left/right */
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch; /* momentum scroll on iOS                 */
  scrollbar-width: none;             /* no visible scrollbar — just swipe       */
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 3px;
  gap: 2px;
}
.callout-view-toggle::-webkit-scrollbar { display: none; }
.callout-view-toggle-btn {
  padding: 6px 14px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  white-space: nowrap;
  flex-shrink: 0;                    /* keep full size → overflow scrolls, no squash */
}
.callout-view-toggle-btn:hover { color: var(--text-primary); }
.callout-view-toggle-btn.is-active {
  background: var(--accent);
  color: var(--bg-base);
}

/* Shared, opt-in discoverability cue for horizontally scrolling tab bars.
   ui/horizontal-scroll-fade.js adds an edge only while more content is hidden
   in that direction, so the cue never lies at either scroll boundary. */
.hscroll-fade {
  --hscroll-fade-bg: var(--bg-elevated);
  --hscroll-fade-size: 30px;
  position: relative;
  display: inline-block;
  align-self: flex-start;
  max-width: 100%;
  min-width: 0;
  border-radius: var(--radius-md);
}
.hscroll-fade > .callout-view-toggle {
  display: flex;
  align-self: auto;
}
.hscroll-fade-cue {
  position: absolute;
  z-index: 2;
  top: 1px;
  bottom: 1px;
  width: var(--hscroll-fade-size);
  display: flex;
  align-items: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s ease;
  color: var(--text-primary);
}
.hscroll-fade-cue.is-before {
  left: 1px;
  justify-content: flex-start;
  padding-left: 4px;
  border-radius: calc(var(--radius-md) - 1px) 0 0 calc(var(--radius-md) - 1px);
  background: linear-gradient(
    to right,
    var(--hscroll-fade-bg) 28%,
    color-mix(in srgb, var(--hscroll-fade-bg) 88%, transparent) 62%,
    transparent
  );
}
.hscroll-fade-cue.is-after {
  right: 1px;
  justify-content: flex-end;
  padding-right: 4px;
  border-radius: 0 calc(var(--radius-md) - 1px) calc(var(--radius-md) - 1px) 0;
  background: linear-gradient(
    to left,
    var(--hscroll-fade-bg) 28%,
    color-mix(in srgb, var(--hscroll-fade-bg) 88%, transparent) 62%,
    transparent
  );
}
.hscroll-fade-cue svg {
  width: 14px;
  height: 14px;
  flex: none;
}
.hscroll-fade.can-scroll-before .hscroll-fade-cue.is-before,
.hscroll-fade.can-scroll-after .hscroll-fade-cue.is-after { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .hscroll-fade-cue { transition: none; }
}

/* KPI cards — 4 small rectangular cards sitting above the list. Each
   highlights threshold values (P1/P2 > 0, SLA breach > 0) with a
   tinted background so what needs attention is visible without reading. */
.callout-kpi-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
@media (max-width: 640px) {
  .callout-kpi-row { grid-template-columns: repeat(2, 1fr); }
}
.callout-kpi-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
/* Button-flavoured KPI cards (Asset Register filter shortcuts).
   Same visual shape, but with hover + press + focus behavior that
   communicates clickability. Static divs (Callouts list KPIs) stay
   silent. Pattern matches the Checklists module's cl-kpi-card.

   The button reset is scoped to button.callout-kpi-card so we don't
   inadvertently style static <div class="callout-kpi-card"> elsewhere. */
button.callout-kpi-card {
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.12s ease, transform 0.06s ease, border-color 0.12s ease;
}
button.callout-kpi-card:hover {
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-surface));
  border-color: color-mix(in srgb, var(--accent) 32%, var(--border));
}
button.callout-kpi-card.is-warning:hover {
  background: rgba(202,138,4,0.14);
  border-color: rgba(202,138,4,0.50);
}
button.callout-kpi-card.is-breach:hover {
  background: rgba(220,38,38,0.16);
  border-color: rgba(220,38,38,0.55);
}
button.callout-kpi-card.is-alert:hover {
  background: rgba(234,88,12,0.14);
  border-color: rgba(234,88,12,0.50);
}
button.callout-kpi-card:active { transform: scale(0.98); }
button.callout-kpi-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Active filter — card matches the current filter mode. Accent
   border so the user sees which KPI is "selected" alongside its
   matching filter pill. Only applies to button variant. */
button.callout-kpi-card.is-active {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
}
.callout-kpi-card.is-alert {
  background: rgba(234,88,12,0.08);
  border-color: rgba(234,88,12,0.32);
}
.callout-kpi-card.is-warning {
  background: rgba(202,138,4,0.08);
  border-color: rgba(202,138,4,0.32);
}
.callout-kpi-card.is-breach {
  background: rgba(220,38,38,0.10);
  border-color: rgba(220,38,38,0.40);
}
.callout-kpi-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.callout-kpi-value {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-kpi-card.is-alert  .callout-kpi-value { color: #ea580c; }
.callout-kpi-card.is-warning .callout-kpi-value { color: #ca8a04; }
.callout-kpi-card.is-breach .callout-kpi-value { color: #dc2626; }

/* ─── Clickable KPI cards (Checklists module) ───────────────────────
   Make the KPI cards behave as shortcut buttons. Each card switches to
   a target tab (and optionally applies a sub-filter on Active for
   Due Soon / Overdue). Subtle hover + press feedback so the user knows
   they're tappable; ↗ chevron in the top-right reinforces it. */
.cl-kpi-card {
  position: relative;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.12s ease, transform 0.06s ease, border-color 0.12s ease;
}
.cl-kpi-card:hover {
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-surface));
  border-color: color-mix(in srgb, var(--accent) 32%, var(--border));
}
.cl-kpi-card.is-warning:hover {
  background: rgba(202,138,4,0.14);
  border-color: rgba(202,138,4,0.50);
}
.cl-kpi-card.is-breach:hover {
  background: rgba(220,38,38,0.16);
  border-color: rgba(220,38,38,0.55);
}
.cl-kpi-card.is-alert:hover {
  background: rgba(234,88,12,0.14);
  border-color: rgba(234,88,12,0.50);
}
.cl-kpi-card:active { transform: scale(0.98); }
.cl-kpi-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Chevron — small ↗ glyph hinting "tap to drill in". Faint by default,
   sharpens on hover so the card reads as interactive without shouting. */
.cl-kpi-chev {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 12px;
  height: 12px;
  color: var(--text-muted);
  opacity: 0.5;
  transition: opacity 0.12s ease, transform 0.12s ease;
}
.cl-kpi-card:hover .cl-kpi-chev {
  opacity: 1;
  transform: translate(2px, -2px);
}

/* ─── Follow-ups tab — small amber dot when count > 0 ───────────── */
.cl-tab-bar .callout-view-toggle-btn.has-followups {
  position: relative;
}
.cl-tab-bar .callout-view-toggle-btn.has-followups::before {
  content: '';
  position: absolute;
  top: 8px;
  right: 6px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ea580c;
  box-shadow: 0 0 0 2px var(--bg-surface);
}

/* ─── Mobile: scroll the tab strip instead of overflowing off-screen ───
   Inventory carries 7 tabs (Lists/Stock/Items/Locations/Suppliers/
   Movements/Counts) — more than fit across a phone. As an inline-flex
   pill the row simply ran past the right edge and the last tab got
   clipped with no way to reach it. On narrow screens make the bar a
   full-width horizontally-scrollable strip so every tab is swipeable. */
@media (max-width: 768px) {
  .cl-tab-bar {
    display: flex;
    align-self: stretch;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;            /* Firefox */
  }
  .cl-tab-bar::-webkit-scrollbar { display: none; }   /* WebKit */
  .cl-tab-bar .callout-view-toggle-btn { flex: 0 0 auto; }

  /* Tab bars with a handful of short tabs (Checklists: Active/Follow/History/
     Readings/Templates · Projects: All/Active/Planning/On hold/Completed) —
     size the tabs to SHARE the width so every one is fully visible without
     horizontal scrolling. Self-contained (sets its own flex container) so it
     works on any .callout-view-toggle, with or without .cl-tab-bar. Inventory
     keeps the scroll fallback above — it has 7 longer tabs that can't all fit. */
  .view-toggle-fit {
    display: flex;
    width: 100%;
    max-width: 100%;
    align-self: stretch;
    overflow-x: hidden;
  }
  .view-toggle-fit .callout-view-toggle-btn {
    flex: 1 1 0;
    min-width: 0;
    padding-left: 3px;
    padding-right: 3px;
    font-size: var(--text-xs);   /* so the longest label fits its share */
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ─── Sub-filter banner ─────────────────────────────────────────────
   Shown between the tab bar and the card grid when the user has tapped
   the Due Soon / Overdue KPI to focus on a subset. Lets them clear
   without hunting through tabs. */
.cl-subfilter-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px;
  margin: 8px 0 4px;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-surface));
  border: 1px solid color-mix(in srgb, var(--accent) 32%, var(--border));
  border-radius: var(--radius-md);
  font: 600 var(--text-sm) / 1.2 var(--body);
}
.cl-subfilter-banner-label { color: var(--text-primary); }
.cl-subfilter-clear {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: var(--radius-sm);
  color: var(--accent);
  font: 600 var(--text-xs) / 1 var(--body);
  cursor: pointer;
  transition: background 0.12s ease;
}
.cl-subfilter-clear:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cl-subfilter-clear svg { width: 12px; height: 12px; }

/* ─── KPI grid — 4 cards (Active / Due soon / Overdue / Follow-ups) ──
   Four across on desktop/tablet, a clean 2×2 on phones (no stranded card).
   Scoped via :has() to the checklist KPI row only — the other modules
   (assets, callouts) keep their default 4-column layout. */
.asset-stats-row:has(.cl-kpi-card) {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
@media (max-width: 640px) {
  .asset-stats-row:has(.cl-kpi-card) { grid-template-columns: repeat(2, 1fr); }
}

/* ─── History view ─────────────────────────────────────────────── */
.callout-history {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.callout-history-month {
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow: visible;
}
.callout-history-month-head {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  cursor: pointer;
  text-align: left;
  position: sticky;
  /* .main already starts below the app bar and the whole shell is shifted by
     --banner-h while impersonating, so 0 respects both without a double gap. */
  top: 0;
  z-index: 2;
  min-height: 44px;
  box-sizing: border-box;
}
.callout-history-month-head:hover {
  border-color: var(--accent);
  background: var(--bg-surface);
}
.callout-history-month-caret {
  width: 16px; height: 16px;
  color: var(--text-muted);
  transition: transform 0.18s ease;
  flex-shrink: 0;
}
.callout-history-month.is-collapsed .callout-history-month-caret {
  transform: rotate(-90deg);
}
.callout-history-month-label {
  font-weight: 600;
  flex-shrink: 0;
}
.callout-history-month-count {
  margin-left: auto;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.callout-history-month-body {
  display: flex;
  flex-direction: column;
}
.callout-history-month.is-collapsed .callout-history-month-body {
  display: none;
}

/* History rows consume the shared .colb-* kit. Only the reference keeps a
   local skin because its monospace identifier is Call-out-specific content. */
.callout-history-row-ref {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-muted);
  background: var(--bg-elevated);
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* ─── Settings modal sections ──────────────────────────────────── */
.callout-settings-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.callout-settings-section-head { display: flex; flex-direction: column; gap: 4px; }
.callout-settings-section-title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-settings-section-sub {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.45;
}
.callout-settings-dept-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.callout-settings-dept-option {
  position: relative;
  display: flex;
  align-items: center;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.callout-settings-dept-option input { position: absolute; opacity: 0; pointer-events: none; }
.callout-settings-dept-option.is-selected {
  border-color: var(--accent);
  background: var(--bg-surface);
}
.callout-settings-dept-name {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
}
.callout-settings-dept-clear { color: var(--text-muted); font-style: italic; }

/* ── Engineer visit card (timeline) ─────────────────────────────────────
   One rich card bundling an engineer's whole callout visit: outcome,
   notes, before/after photos, and a cost summary. */
.callout-event-visit .callout-event-icon { color: var(--accent); }
.callout-visit-outcome {
  display: inline-flex;
  align-items: center;
  margin: 4px 0 2px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--oc);
  background: color-mix(in srgb, var(--oc) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--oc) 40%, transparent);
}
.callout-visit-detail {
  margin-top: 6px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.45;
}
.callout-visit-photogroup { margin-top: 8px; }
.callout-visit-photogroup-label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.callout-visit-photos { display: flex; flex-wrap: wrap; gap: 6px; }
.callout-visit-costs {
  margin-top: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.callout-visit-cost-line,
.callout-visit-cost-total {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 10px;
  font-size: var(--text-sm);
}
.callout-visit-cost-line { color: var(--text-secondary); border-bottom: 1px solid var(--border); }
.callout-visit-cost-total { font-weight: 700; color: var(--text-primary); background: var(--bg-elevated); }

/* 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) {
  .callout-modal-head { padding-left: 12px; padding-right: 12px; }
  .callout-modal-foot { padding-left: 12px; padding-right: 12px; }
  .callout-detail-body   { padding-left: 12px; padding-right: 12px; }
  .callout-detail-header { padding-left: 12px; padding-right: 12px; }
  .callout-loading { padding-left: 14px; padding-right: 14px; }
  .callout-empty   { padding-left: 14px; padding-right: 14px; }
}
