/* ═══════════════════════════════════════════════════════════════════════
   PICKER SHEET  (shared — ui/picker-sheet.js → AngelHubUI.openPickerSheet)
   ─────────────────────────────────────────────────────────────────────
   The ONE search-and-pick chooser used app-wide (KB doc/folder, Asset,
   Contractor, …). Bottom-sheet on mobile, centred dialog on desktop —
   modelled on the KB "Link to a doc or folder" picker the user singled
   out as the reference. z-index floor 9800 sits above module modals;
   ui/modal-stack.js may bump it higher when stacked.
   ═══════════════════════════════════════════════════════════════════════ */
.psheet-overlay {
  position: fixed; inset: 0; z-index: 9800;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  /* iOS paint-order fix — self-composite so this fixed body-child gets its own
     GPU layer and its z-index is honoured over the permanently-composited
     .app-shell (transform + will-change, css/02). backdrop-filter was ASSUMED to
     do this but doesn't reliably on iOS WebKit, so the sheet could paint UNDER a
     module surface until a re-render forced a recomposite — the "opens behind the
     view / only appears after switching tabs" bug. Matches the explicit fix on
     .callout-modal-overlay (css/12) and .tasks-modal-overlay (css/05). */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
  display: flex; align-items: flex-end; justify-content: center;
  opacity: 0;
  transition: opacity 0.22s ease;
  /* Reserve the on-screen keyboard's space (--keyboard-height, set by the
     visualViewport listener in index.html) so the bottom sheet rests ON TOP of
     the keyboard instead of running underneath it — otherwise the search results
     / staff list scroll away behind the keyboard and can't be reached. Paired
     with the matching max-height cut on .psheet below so the head stays on-screen.
     Desktop's centred dialog resets this via `padding: 16px` in the media query. */
  padding-bottom: var(--keyboard-height, 0px);
}
[data-theme="light"] .psheet-overlay { background: rgba(15, 23, 42, 0.38); }
.psheet-overlay.is-open { opacity: 1; }

.psheet {
  width: 100%; max-width: 560px; margin: 0 auto;
  /* Shrink by the keyboard height too, so the sheet fits in the space above the
     keyboard (the overlay's padding-bottom lifts it; this keeps the top — the
     search box + filters — from being pushed off-screen). With both, the head
     stays put and the list scrolls within whatever room is left. */
  max-height: calc(86vh - var(--keyboard-height, 0px));
  display: flex; flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-bottom: none;
  border-top-left-radius: 18px;
  border-top-right-radius: 18px;
  box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.35);
  transform: translateY(100%);
  transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
  /* Bottom safe-area clearance lives on .psheet-body (and on .psheet-foot when a
     footer is present) — NOT here. A padding-bottom on the sheet sat BELOW the
     footer and stacked with the footer's OWN safe-area, leaving the footer button
     hanging ~one home-indicator above the screen edge. (Radek 2026-06-30) */
  overflow: hidden;
}
.psheet-overlay.is-open .psheet { transform: translateY(0); }

/* ── Tall variant (opts.tall) — keeps the bottom-sheet chrome (handle, rounded
   top, slide-up) but ALWAYS opens to (near) full height instead of hugging its
   content. This is what stops an in-sheet dropdown (the Site/Department filters
   in the staff picker) from being cramped/clipped: a short, content-sized sheet
   leaves its filter menus nowhere to open, whereas a tall sheet gives them the
   whole list-body below to drop into. min-height matches the max-height, so the
   sheet is a steady ~86vh regardless of how many rows it holds. */
.psheet-overlay--tall .psheet { min-height: calc(86vh - var(--keyboard-height, 0px)); }

/* Bottom-sheet on phones + small tablets (the "slides up from the bottom" feel
   the user liked); only genuinely wide screens get the centred dialog. */
@media (min-width: 700px) {
  .psheet-overlay { align-items: center; padding: 16px; }
  .psheet {
    border-radius: var(--radius-lg, 16px);
    border-bottom: 1px solid var(--border);
    max-height: 80vh;
    transform: translateY(20px) scale(0.96);
  }
  .psheet-overlay--tall .psheet { min-height: 80vh; }
  .psheet-overlay.is-open .psheet { transform: translateY(0) scale(1); }
}

/* ── Full-screen variant (opts.fullscreen) — opted into by the asset picker ──
   A visual browse (galleries / folders / multi-site) needs the whole screen, not
   a half-height sheet that jumps with the keyboard. Mobile: fills from the
   safe-area top to the bottom, header (with X) pinned at top, body scrolls.
   Desktop: a large centred browser so the galleries breathe. Other pickers are
   untouched — they keep the compact bottom-sheet above. */
.psheet-overlay--full { align-items: stretch; padding-top: env(safe-area-inset-top); }
.psheet-overlay--full .psheet {
  width: 100%; max-width: 760px; margin: 0 auto;
  height: 100%; max-height: 100%;
  border: none; border-radius: 0;
  box-shadow: none;
}
.psheet-overlay--full .psheet-handle { display: none; }
@media (min-width: 700px) {
  /* Anchor to the top with a clear margin (NOT centred) so the window visibly
     clears the app top bar instead of butting up against it — a centred 90vh
     window left only a sliver of dark backdrop above it, reading as "bonded" to
     the bar. The window fills downward from there with a matching bottom gap. */
  .psheet-overlay--full { align-items: flex-start; padding: 0; }
  .psheet-overlay--full .psheet {
    width: 94vw; max-width: 1040px;
    margin-top: 88px; height: calc(100vh - 124px); max-height: calc(100vh - 124px);
    border: 1px solid var(--border); border-radius: var(--radius-lg, 16px);
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
    transform: translateY(16px) scale(0.97);
  }
  .psheet-overlay--full.is-open .psheet { transform: translateY(0) scale(1); }
}

/* ── Narrow full-screen (opts.overlayClass 'psheet-overlay--full-narrow') ──
   For a full-screen picker whose content is a simple LIST, not a gallery — the
   location / category tree picker (AngelHubTreePicker). Mobile keeps the calm
   full-screen browse (unchanged); desktop caps the width to the standard modal
   (matching the create-location .callout-modal, 560px) instead of the wide
   1040px gallery width, which looked stranded and over-wide for a row list.
   Two overlay classes → outweighs the base .psheet-overlay--full .psheet. */
@media (min-width: 700px) {
  .psheet-overlay--full.psheet-overlay--full-narrow .psheet { max-width: 560px; }
}

.psheet-handle {
  width: 36px; height: 4px; flex-shrink: 0;
  border-radius: var(--radius-pill, 999px);
  background: var(--border-strong, var(--border));
  margin: 10px auto 0;
}
@media (min-width: 600px) { .psheet-handle { display: none; } }

/* ── Header ── */
.psheet-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px 12px; flex-shrink: 0;
}
.psheet-title {
  font-family: var(--display, var(--body));
  font-size: var(--text-2xl, 1.25rem); font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text-primary);
}
.psheet-close {
  width: 32px; height: 32px; flex-shrink: 0;
  display: grid; place-items: center;
  border: none; border-radius: var(--radius-md, 10px);
  background: transparent; color: var(--text-muted);
  cursor: pointer; transition: background 0.15s, color 0.15s;
}
.psheet-close:hover { background: var(--bg-elevated); color: var(--text-primary); }
.psheet-close svg { width: 16px; height: 16px; stroke-width: 2.2; }

/* ── Search ── */
/* margin (not padding) for the gap below, so the absolutely-positioned icon's
   top:50% centres on the input itself rather than the padded wrapper. */
.psheet-search { position: relative; flex-shrink: 0; padding: 0 18px; margin-bottom: 12px; display: flex; align-items: center; }
.psheet-search > svg {
  position: absolute; left: 30px; top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: var(--text-muted); pointer-events: none;
}
.psheet-search-input {
  width: 100%; padding: 11px 12px 11px 38px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 10px);
  color: var(--text-primary);
  font-family: inherit;
  /* 16px is the iOS no-zoom threshold — keep at/above it. */
  font-size: var(--text-base, 1rem);
  outline: none;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.psheet-search-input::placeholder { color: var(--text-muted); }
.psheet-search-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ── Breadcrumbs ── */
.psheet-crumbs {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; flex-shrink: 0;
  padding: 0 18px 8px;
  font-size: var(--text-sm);
}
.psheet-crumbs[hidden] { display: none; }
/* Matches the KB main-browser breadcrumb (css/03 .kb-crumb + css/07 .kb-crumb-back)
   so folder/site navigation reads the SAME everywhere this picker appears. */
.psheet-crumb {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: none;
  padding: 5px 10px; border-radius: var(--radius-md, 8px);
  font-family: inherit; font-size: var(--text-sm); font-weight: 500;
  color: var(--text-secondary); cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.psheet-crumb svg { width: 13px; height: 13px; stroke-width: 2; flex-shrink: 0; }
.psheet-crumb:hover:not(:disabled) { background: var(--bg-elevated); color: var(--text-primary); }
.psheet-crumb.is-current, .psheet-crumb:disabled {
  color: var(--text-primary); font-weight: 600; background: var(--bg-elevated); cursor: default;
}
/* First crumb = the back target → a bordered pill with a ‹ chevron, exactly like
   KB's "‹ All folders" back chip. */
.psheet-crumb.is-back {
  padding: 6px 10px 6px 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  color: var(--text-primary); font-weight: 600;
}
.psheet-crumb.is-back svg { width: 14px; height: 14px; }
.psheet-crumb.is-back:hover {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border-strong));
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
}
.psheet-crumb-sep { color: var(--text-muted); font-size: var(--text-sm, 0.85rem); margin: 0 2px; }

/* ── Pinned action bar (create / link "function buttons") ──
   Sits between the breadcrumbs and the scrolling list. Reads as buttons, not
   rows: accent-tinted pills for create actions + a filled primary for the
   confirm. A bottom hairline separates them from the folder list below. */
.psheet-actions {
  flex-shrink: 0;
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 2px 14px 12px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.psheet-actions[hidden] { display: none; }
.psheet-act {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  flex: 1 1 auto; min-width: 0;
  height: 42px; padding: 0 14px;
  border-radius: var(--radius-md, 11px);
  font: 600 14px/1 var(--body); font-family: inherit;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s, transform 0.08s;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.psheet-act:active { transform: scale(0.98); }
.psheet-act > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.psheet-act-ico { display: grid; place-items: center; flex-shrink: 0; }
.psheet-act-ico svg { width: 17px; height: 17px; }
/* Full-width row — drops onto its own line below the pills */
.psheet-act-block { flex: 1 1 100%; }
/* Pill = secondary create action (accent text on a soft tint) */
.psheet-act-pill {
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
}
.psheet-act-pill:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); border-color: var(--accent); }
/* Primary = the main confirm (filled accent) */
.psheet-act-primary {
  color: var(--bg-base);
  background: var(--accent);
  border: 1px solid transparent;
  box-shadow: 0 2px 8px var(--accent-glow);
}
.psheet-act-primary:hover { box-shadow: 0 4px 12px var(--accent-glow); }

/* ── Staff-picker filter dropdowns (raw HTML in the pinned actions slot).
   Site + Department, stacked full-width, reusing the shared .tasks-priority-*
   custom dropdown so they match the Asset Register exactly. */
.psheet-actions .spick-filterbar { flex: 1 1 100%; display: flex; flex-direction: row; flex-wrap: wrap; gap: 8px; }
.spick-fdd { flex: 1 1 140px; min-width: 0; }                      /* Site + Dept side-by-side, wrap on very narrow */
.spick-fdd .tasks-priority-trigger { width: 100%; height: 40px; }
.spick-fdd .tasks-priority-trigger-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.spick-fdd .tasks-priority-menu { left: 0; right: 0; min-width: 0; max-height: 260px; overflow-y: auto; }

/* ── Selected-people strip (multi-select) — removable avatar chips, pinned above
   the list so you always see who you've picked while scrolling/filtering. ── */
.spick-selected { flex: 1 1 100%; display: flex; flex-direction: column; gap: 7px; margin-top: 2px; }
.spick-sel-head {
  font: 700 11px/1 var(--body); text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted);
}
.spick-sel-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.spick-sel-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 3px 5px 3px 3px;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-pill, 999px);
  color: var(--text-primary); font: 600 12.5px/1 var(--body);
}
.spick-sel-av {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: #fff; font: 700 10px/1 var(--body);
}
.spick-sel-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 110px; }
.spick-sel-x {
  flex-shrink: 0; width: 20px; height: 20px; padding: 0; border: 0;
  display: grid; place-items: center; cursor: pointer;
  background: transparent; color: var(--text-muted); border-radius: 50%;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.spick-sel-x:hover { color: var(--text-primary); background: var(--bg-hover, var(--bg-surface)); }
.spick-sel-x svg { width: 13px; height: 13px; }

/* ── Body / list ── */
.psheet-body { flex: 1; overflow-y: auto; padding: 0 14px calc(8px + env(safe-area-inset-bottom)); -webkit-overflow-scrolling: touch; }
.psheet-list { display: flex; flex-direction: column; gap: 6px; padding-bottom: 6px; }

/* ── Grouped sections (e.g. staff picker: site · department) ──
   A quiet section header above each group's rows; falsy label → no header. */
.psheet-group {
  padding: 12px 6px 6px;
  font: 700 11px/1 var(--body);
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted);
}
.psheet-body > .psheet-group:first-child { padding-top: 4px; }

/* ── Collapsible group (opt-in via setRows group.collapsed) ──
   The header reads as a foldable row (chevron + optional colour dot + count),
   NOT the quiet uppercase label. Rows hide via CSS when collapsed. Used by the
   Audits "start from a template" picker so it matches the collapsible category
   list. The two-class selector outweighs the base .psheet-group rule. */
.psheet-group-wrap + .psheet-group-wrap { margin-top: 2px; }
.psheet-group.psheet-group--toggle {
  display: flex; align-items: center; gap: 8px; width: 100%;
  margin: 0; padding: 11px 8px;
  background: none; border: none; border-radius: var(--radius-sm, 8px);
  cursor: pointer; font-family: inherit; text-align: left;
  text-transform: none; letter-spacing: 0;
  color: var(--text-primary); font-size: var(--text-sm); font-weight: 600;
  touch-action: manipulation;
}
.psheet-group.psheet-group--toggle:hover { background: var(--bg-elevated); }
.psheet-group-chev {
  width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0;
  transition: transform 0.18s; transform: rotate(0deg);
}
.psheet-group-wrap.is-collapsed .psheet-group-chev { transform: rotate(-90deg); }
.psheet-group-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.psheet-group-label { flex: 1; }
.psheet-group-count {
  font-size: 11px; font-weight: 600; color: var(--text-muted);
  background: var(--bg-surface); border: 1px solid var(--border);
  padding: 2px 8px; border-radius: var(--radius-md, 10px);
}
.psheet-group-wrap.is-collapsed .psheet-list { display: none; }

/* ── Header secondary actions (opts.headerActions) ──
   Small icon buttons (a "⋯" menu) left of the close X, for the rare actions a
   picker tucks away — e.g. the location picker's New location / Manage locations.
   Styled like .psheet-close so the header stays calm. */
.psheet-head-right { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.psheet-headact {
  width: 32px; height: 32px; flex-shrink: 0;
  display: grid; place-items: center;
  border: none; border-radius: var(--radius-md, 10px);
  background: transparent; color: var(--text-muted);
  cursor: pointer; transition: background 0.15s, color 0.15s;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.psheet-headact:hover { background: var(--bg-elevated); color: var(--text-primary); }
/* Match the X (.psheet-close) sitting beside it — both 16px so the two header
   icons read at the same size (the app's modal/sheet-header standard). */
.psheet-headact svg { width: 16px; height: 16px; }

/* ── Foldered accordion (location picker browse) ──
   Areas expand IN PLACE — tap the folder header to open/close (the chevron
   rotates, siblings stay in view, no drilling); tap a leaf row (.psheet-row) to
   pick. A faint ⋯ on each folder header holds the rare "Use the whole area" /
   "Add inside" actions. Reuses the row atoms + the collapse pattern; nested
   areas indent under their parent with a quiet guide line. */
.psheet-fold { display: flex; flex-direction: column; gap: 6px; }
/* One bordered pill holds the toggle AND the ⋯ inline (no gap, no separate box) —
   matches the Settings locations manager's folder header (.cl-cat-group-header). */
.psheet-fold-head {
  display: flex; align-items: stretch; gap: 0; overflow: hidden;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-md, 11px);
  transition: border-color 0.12s, background 0.12s, transform 0.06s;
}
.psheet-fold-head:hover { border-color: var(--accent); background: var(--bg-hover, var(--bg-surface)); }
.psheet-fold-head:active { transform: scale(0.992); }
.psheet-fold-head.is-current { border-color: color-mix(in srgb, var(--accent) 50%, transparent); background: var(--accent-soft); }
.psheet-fold-toggle {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 10px;
  padding: 11px 12px;
  background: transparent; border: 0;
  font-family: inherit; color: var(--text-primary); text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.psheet-fold-chev { width: 15px; height: 15px; flex-shrink: 0; color: var(--text-muted); transition: transform 0.18s; }
.psheet-fold.is-collapsed > .psheet-fold-head .psheet-fold-chev { transform: rotate(-90deg); }
.psheet-fold-name {
  flex: 1; min-width: 0;
  font-size: var(--text-md, 0.95rem); font-weight: 600; color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.psheet-fold-count {
  flex-shrink: 0; font-size: 11px; font-weight: 600; color: var(--text-muted);
  background: var(--bg-surface); border: 1px solid var(--border);
  padding: 2px 8px; border-radius: var(--radius-md, 10px);
}
.psheet-fold-more {
  flex-shrink: 0; width: 40px; align-self: stretch;
  display: grid; place-items: center;
  border: 0; background: transparent; color: var(--text-muted);
  cursor: pointer; transition: color 0.12s, background 0.12s;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.psheet-fold-more:hover { color: var(--text-primary); background: var(--bg-surface); }
.psheet-fold-more svg { width: 18px; height: 18px; }
.psheet-fold.is-collapsed > .psheet-list { display: none; }
/* Nested areas indent under their parent with a quiet guide line. */
.psheet-fold > .psheet-list { padding-left: 12px; margin-left: 11px; border-left: 1px solid var(--border); }

/* ── Picker filter chips (pinned actions slot) ──
   A wrap of toggle chips to narrow the list — e.g. the Audits picker's
   "All sites / <site>" filter. Mirrors the app's .order-filter-chip look. */
.psheet-filter-row {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.psheet-filter-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--body); font-size: var(--text-xs); font-weight: 600;
  color: var(--text-secondary); cursor: pointer; transition: all 120ms;
  touch-action: manipulation;
}
.psheet-filter-chip:hover { background: var(--bg-hover); color: var(--text-primary); }
.psheet-filter-chip.is-active {
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--accent);
}

/* ── Scope chip on a staff row (the site/department the person covers).
   Neutral chip body (the two-tier rule) with colour reserved for the icon. */
.psheet-scope-chip {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 5px;
  max-width: 150px;
  padding: 4px 9px; border-radius: var(--radius-sm, 8px);
  background: var(--bg-surface); border: 1px solid var(--border);
  color: var(--text-secondary); font: 600 var(--text-xs, 0.72rem)/1 var(--body);
}
.psheet-scope-chip > span:last-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.psheet-scope-ico { display: grid; place-items: center; flex-shrink: 0; color: var(--text-muted); }
.psheet-scope-ico svg { width: 13px; height: 13px; }

/* ── Initials avatar (staff picker lead slot) — accent circle, white initials,
   matching the Projects team card (.project-member-av). ── */
.psheet-row-avatar {
  flex-shrink: 0;
  width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: #fff;
  font: 700 12px/1 var(--body); letter-spacing: 0.02em;
}

/* ── Multi-select checkbox — empty square → filled accent check when the row is
   on. A clear, obvious tap target (replaces the easy-to-miss small ring). ── */
.psheet-pick {
  flex-shrink: 0; width: 24px; height: 24px; margin-left: 2px;
  display: grid; place-items: center;
  border: 2px solid var(--border-strong, var(--border)); border-radius: var(--radius-sm, 6px);
  color: transparent; background: transparent;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.psheet-pick svg { width: 15px; height: 15px; stroke-width: 3; }
.psheet-row.is-current .psheet-pick { background: var(--accent); border-color: var(--accent); color: #fff; }

.psheet-row {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 11px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 11px);
  font-family: inherit; color: var(--text-primary);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, transform 0.06s;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.psheet-row:hover { border-color: var(--accent); background: var(--bg-hover, var(--bg-surface)); }
.psheet-row:active { transform: scale(0.992); }
.psheet-row.is-current { border-color: color-mix(in srgb, var(--accent) 50%, transparent); background: var(--accent-soft); }

.psheet-row-icon {
  width: 24px; height: 24px; flex-shrink: 0;
  display: grid; place-items: center;
  color: var(--text-muted);
}
.psheet-row-icon svg { width: 18px; height: 18px; }
.psheet-row-icon.is-accent { color: var(--accent); }

.psheet-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.psheet-row-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.psheet-row-name {
  font-size: var(--text-md, 0.95rem); font-weight: 600; color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.psheet-row-sub {
  font-size: var(--text-sm, 0.8rem); color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Contact line inside a rich row body (mainHtml) — e.g. contractor rows. */
.psheet-row-contact {
  font: 500 12.5px/1.2 var(--body); color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.psheet-row-arrow { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-muted); }
.psheet-row-arrow svg { width: 14px; height: 14px; }

/* Inline "Current" pill on a row name */
.psheet-row-current {
  flex-shrink: 0;
  font: 600 10px/1 var(--body); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--accent); background: var(--accent-soft);
  padding: 3px 6px; border-radius: 5px;
}

/* Trade / tag chips inside a row sub-line (subHtml) */
.psheet-trades { display: flex; flex-wrap: wrap; gap: 4px; }
.psheet-trade {
  font: 500 11px/1 var(--body); color: var(--text-secondary);
  background: var(--bg-surface); border: 1px solid var(--border);
  padding: 3px 7px; border-radius: 5px;
}

/* Trailing status badge (badgeHtml) */
.psheet-status {
  flex-shrink: 0; font: 600 11px/1 var(--body);
  padding: 4px 8px; border-radius: 6px; text-transform: capitalize;
}
.psheet-status.is-active   { color: var(--success, #10b981); background: var(--success-soft, rgba(16,185,129,0.12)); }
.psheet-status.is-pending  { color: var(--warning, #d97706); background: var(--warning-soft, rgba(217,119,6,0.12)); }
.psheet-status.is-inactive { color: var(--text-muted); background: var(--bg-surface); }

/* ── Left status-bar row (barColor option) ──
   Lets a picker row mirror a list card with a coloured left bar — used by the
   contractor picker so its rows look identical to the Contractors list card.
   The row drops its own padding (the bar sits flush at the edge) and stretches
   so the bar spans full height; the body carries the card's own padding/gap. */
.psheet-row--bar { align-items: stretch; gap: 0; padding: 0; overflow: hidden; background: var(--bg-surface); }
.psheet-row-bar { width: 5px; flex-shrink: 0; align-self: stretch; }
.psheet-row--bar .psheet-row-main { padding: 14px 16px 12px; gap: 7px; }
/* Name hero + inline "Current" pill (mirrors the card name row) */
.ctr-pick-namerow { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; min-width: 0; }

/* ── Loading / empty ── */
.psheet-loading, .psheet-empty { padding: 36px 16px; text-align: center; color: var(--text-muted); }
.psheet-empty-title { font: 600 var(--text-base) / 1.3 var(--body); color: var(--text-secondary); margin-bottom: 4px; }
.psheet-empty-sub { font: 500 var(--text-sm) / 1.4 var(--body); color: var(--text-muted); }

/* ── Footer ── */
.psheet-foot {
  flex-shrink: 0; display: flex; gap: 10px; align-items: center;
  padding: 12px 18px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
}
.psheet-foot[hidden] { display: none; }
.psheet-foot-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 16px;
  border: 1px solid var(--border); border-radius: var(--radius-md, 11px);
  background: var(--bg-elevated); color: var(--text-primary);
  font: 600 14px/1 var(--body); cursor: pointer;
  transition: border-color 0.12s, background 0.12s, color 0.12s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
}
.psheet-foot-btn:active { transform: scale(0.97); }
.psheet-foot-btn svg { width: 17px; height: 17px; }
.psheet-foot-btn.is-grow { flex: 1; }
.psheet-foot-btn-dashed { border-style: dashed; border-color: var(--border-strong, var(--border)); background: var(--bg-surface); }
.psheet-foot-btn-dashed:hover { border-color: var(--accent); color: var(--accent); }
.psheet-foot-btn-ghost { background: transparent; color: var(--text-secondary); border-color: var(--border); }
.psheet-foot-btn-primary { background: var(--accent); color: var(--bg-base); border-color: transparent; box-shadow: 0 2px 8px var(--accent-glow); }
.psheet-foot-btn-primary:hover { box-shadow: 0 4px 12px var(--accent-glow); }
.psheet-foot-btn.is-danger { color: #dc2626; background: none; border-color: transparent; }
.psheet-foot-btn.is-danger:hover { background: rgba(220, 38, 38, 0.08); }

/* Location picker — optional "exact spot" footer (Tasks). The spot box (reuses
   .ah-locfield-detail, css/13) stacks above the action row inside the footer. */
.psheet-spot-foot { display: flex; flex-direction: column; gap: 10px; width: 100%; }
.psheet-spot-foot .psheet-spot-actions { display: flex; gap: 10px; }

/* ── Inline quick-add form (e.g. "Add new contractor") ── */
.psheet-form { display: flex; flex-direction: column; gap: 12px; padding: 6px 4px 12px; }
.psheet-form-field { display: flex; flex-direction: column; gap: 6px; }
.psheet-form-field > span { font: 600 11.5px/1 var(--body); color: var(--text-secondary); letter-spacing: 0.02em; }
.psheet-form-field > span em { color: var(--accent); font-style: normal; }
.psheet-form-field input {
  height: 42px; padding: 0 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong, var(--border)); border-radius: var(--radius-md, 10px);
  color: var(--text-primary); font: 500 var(--text-base, 1rem)/1 var(--body); outline: none;
}
.psheet-form-field input:focus { border-color: var(--accent); }
.psheet-form-row { display: flex; gap: 10px; }
.psheet-form-row .psheet-form-field { flex: 1; min-width: 0; }
.psheet-form-note { font: 500 12px/1.4 var(--body); color: var(--text-muted); margin: 0; }

/* ── Visual asset picker (ui/asset-picker.js) ─────────────────────────────
   View toggle · category chips · thumbnail rows. Gallery tiles reuse the
   register's .asset-gallery-* (css/13); tighten the grid for the narrow sheet. */
.apick-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; justify-content: flex-end; margin-bottom: 12px; }
/* Category + Site dropdowns sit on the LEFT (in order); the view toggle stays on
   the RIGHT (auto margin absorbs the gap, and it drops to its own line on wrap). */
.apick-toolbar .callout-view-toggle { margin-left: auto; }
/* Two-axis toolbar (Radek 2026-06-29): Browse (All/Folders/Locations) keeps the
   auto-margin so it sits right; the Display (List/Gallery) icon pair sits SNUG
   beside it (reset its own auto so it isn't pushed to a second gap). */
.apick-toolbar .apick-disp-toggle { margin-left: 0; }
.apick-disp-btn { padding: 7px 11px; display: inline-flex; align-items: center; justify-content: center; }
.apick-disp-btn svg { width: 16px; height: 16px; display: block; }
/* Location browse tree reuses the .psheet-fold (area) / .psheet-row (leaf) atoms
   wholesale — only the leaf's trailing count chip needs nudging off the edge. */
.apick-loctree { margin-top: 2px; }
.apick-loc-leaf .psheet-fold-count { margin-left: 8px; }
/* Open the menu down-LEFT (aligned to the trigger) and cap its height so a long
   list scrolls inside the menu instead of being clipped by the picker body
   (which is overflow-y:auto). */
.apick-cat-dd .tasks-priority-menu,
.apick-site-dd .tasks-priority-menu { left: 0; right: auto; max-height: 280px; overflow-y: auto; }
/* The dropdown opens DOWNWARD over the list; the .psheet body would clip it when
   the list is short. While the menu is OPEN, give the pane a floor so the sheet is
   tall enough to show it in full; closed, the sheet stays compact (no empty gap). */
.apick-pane.is-cat-open { min-height: 330px; }
.psheet .asset-gallery { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
/* Gallery tile caption stacks the asset name over its site (shown only when
   browsing All sites). Column wrapper so the name still ellipsizes. */
.apick-tile-meta { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
.apick-tile-site { font: 500 10.5px/1.2 var(--body); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.apick-cats { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.apick-cat {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--bg-surface); color: var(--text-secondary);
  font: 600 12.5px/1 var(--body); cursor: pointer;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.apick-cat:hover { border-color: var(--accent); }
.apick-cat.is-on { background: var(--accent); border-color: var(--accent); color: var(--bg-base); }
.apick-cat-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.apick-cat.is-on .apick-cat-dot { box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.6); }

.apick-rows { display: flex; flex-direction: column; gap: 6px; }
.apick-row {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 8px 10px; text-align: left;
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); cursor: pointer; font: inherit;
  transition: border-color 0.12s, background 0.12s;
}
.apick-row:hover { border-color: var(--accent); background: var(--bg-elevated); }
.apick-row:active { transform: scale(0.995); }
.apick-thumb {
  width: 46px; height: 46px; flex: none; border-radius: var(--radius-sm);
  overflow: hidden; background: var(--bg-elevated);
  display: flex; align-items: center; justify-content: center;
}
.apick-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.apick-thumb.is-ph svg, .apick-thumb.is-folder svg { width: 22px; height: 22px; opacity: 0.7; }
.apick-thumb.is-folder { color: var(--accent); }
.apick-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.apick-row-name { font: 600 14px/1.3 var(--body); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.apick-row-sub { font: 500 12px/1.3 var(--body); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.apick-row-go { flex: none; color: var(--text-muted); display: flex; }
.apick-row-go svg { width: 18px; height: 18px; }

/* "+ New category" as the last row in the category menu, then the inline
   name field + Create that appears when it's tapped. */
.apick-newcat-opt { border-top: 1px solid var(--border); margin-top: 2px; color: var(--accent); }
.apick-newcat { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.apick-newcat-input {
  flex: 1; min-width: 0; height: 38px; padding: 0 14px;
  background: var(--bg-elevated); border: 1px solid var(--border-strong, var(--border));
  border-radius: 999px; color: var(--text-primary); font: 500 13.5px/1 var(--body); outline: none;
}
.apick-newcat-input:focus { border-color: var(--accent); }
.apick-newcat-btn {
  flex: none; height: 38px; padding: 0 16px; border: none; border-radius: 999px;
  background: var(--accent); color: var(--bg-base); font: 600 13px/1 var(--body); cursor: pointer;
}
.apick-newcat-btn:disabled { opacity: 0.6; cursor: default; }
.apick-newcat-cancel {
  flex: none; height: 38px; padding: 0 12px; border: 1px solid var(--border);
  border-radius: 999px; background: var(--bg-surface); color: var(--text-secondary);
  font: 600 13px/1 var(--body); cursor: pointer;
}

/* 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) {
  .psheet-head    { padding: 14px 12px 10px; }
  .psheet-search  { padding: 0 12px; }
  .psheet-crumbs  { padding: 0 12px 6px; }
  .psheet-actions { padding: 2px 10px 10px; }
  .psheet-body    { padding: 0 10px calc(6px + env(safe-area-inset-bottom)); }
  .psheet-loading,
  .psheet-empty   { padding: 28px 12px; }
  .psheet-foot    { padding: 10px 12px calc(10px + env(safe-area-inset-bottom)); }
  .psheet-row--bar .psheet-row-main { padding: 12px 12px 10px; }
}

/* Dimmed (ruled-out) row — rowModel `dim: true`: a destination the caller
   has disabled, kept visible with the reason in its sub line (e.g. the KB
   move-folder picker's self/descendant/depth-blocked folders). No onClick
   is attached, so the row is inert; neutralise the hover/active cues that
   would suggest otherwise. */
.psheet-row.is-dim { opacity: 0.5; cursor: default; }
.psheet-row.is-dim:hover { border-color: var(--border); background: var(--bg-elevated); }
.psheet-row.is-dim:active { transform: none; }

/* ═══════════════════════════════════════════════════════════════════════
   SHARED PHOTO PICKER (ui/photo-picker.js) — the ONE "Add photo" chooser.
   Rides the psheet shell; the live strip inside is ui/photo-capture.js
   (.tasks-photo-thumb* from css/05). Both themes via tokens only.
   ═══════════════════════════════════════════════════════════════════════ */
.ahpp { display: flex; flex-direction: column; padding-top: 6px; }

/* Capture tiles — the two primary actions, side by side */
.ahpp-actions {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  margin-bottom: 12px;
}
.ahpp-action {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; min-height: 76px; padding: 14px 10px;
  background: var(--bg-elevated); border: 1px solid var(--border-strong, var(--border));
  border-radius: 14px; color: var(--text-primary);
  font: 600 var(--text-sm) var(--body); cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: background 0.12s, border-color 0.12s;
}
.ahpp-action svg { width: 22px; height: 22px; }
.ahpp-action:hover { border-color: var(--accent); }
.ahpp-action:active { opacity: 0.8; }
.ahpp-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ahpp-action-primary {
  background: var(--accent-soft); border-color: transparent; color: var(--accent);
}
.ahpp-action-primary:hover { border-color: var(--accent); }

/* Batch progress — "Uploading N of M" + slim bar */
.ahpp-progress { margin: 0 2px 10px; }
.ahpp-progress[hidden] { display: none; }
.ahpp-progress-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px; }
.ahpp-progress-label { font: 600 var(--text-xs) var(--body); color: var(--text-secondary); }
.ahpp-progress-track {
  height: 6px; border-radius: 999px; background: var(--bg-elevated); overflow: hidden;
}
.ahpp-progress-fill {
  height: 100%; width: 0; border-radius: 999px; background: var(--accent);
  transition: width 0.25s ease;
}
.ahpp-progress.is-failed .ahpp-progress-fill { background: var(--danger); }
.ahpp-progress.is-failed .ahpp-progress-label { color: var(--danger); }

/* The live strip: photo-capture engine, picker flavour.
   - Remove is hidden: once a photo lands, onPick has ALREADY inserted it —
     a remove button here would be a lie (uploading tiles are committed too).
   - A landed tile (not uploading/failed/queued) gets a success tick badge. */
.ahpp .ahpp-strip { min-height: 0; }
.ahpp .tasks-photo-thumb-remove { display: none; }
.ahpp .tasks-photo-thumb { position: relative; }
.ahpp .tasks-photo-thumb:not(.is-uploading):not(.is-failed):not(.is-queued)::after {
  content: ''; position: absolute; right: 4px; bottom: 4px;
  width: 20px; height: 20px; border-radius: 50%;
  background-color: var(--success);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-size: 12px 12px; background-position: center; background-repeat: no-repeat;
}

/* "Browse existing" sources — lazy accordion rows */
.ahpp-srcs { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 6px; }
.ahpp-src {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 52px; padding: 10px; margin: 2px 0;
  background: transparent; border: none; border-radius: 10px;
  color: var(--text-primary); text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: background 0.12s;
}
.ahpp-src:hover { background: var(--bg-elevated); }
.ahpp-src:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ahpp-src-icon { flex: none; display: flex; color: var(--text-secondary); }
.ahpp-src-icon svg { width: 20px; height: 20px; }
.ahpp-src-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ahpp-src-label { font: 600 var(--text-sm) var(--body); }
.ahpp-src-sub { font: 500 var(--text-xs) var(--body); color: var(--text-muted); }
.ahpp-src-chev { flex: none; width: 16px; height: 16px; color: var(--text-muted); transition: transform 0.15s; }
.ahpp-src.is-open .ahpp-src-chev { transform: rotate(180deg); }
.ahpp-src-panel { padding: 2px 2px 12px; }
.ahpp-src-panel[hidden] { display: none; }

/* Source panels: back link + heading (doc navigator), tile grid, states */
.ahpp-src-back {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
  padding: 6px 8px; margin-bottom: 2px; background: transparent; border: none;
  border-radius: 8px; color: var(--accent); font: 600 var(--text-xs) var(--body);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.ahpp-src-back svg { width: 15px; height: 15px; }
.ahpp-src-back:hover { background: var(--bg-elevated); }
.ahpp-src-head {
  font: 600 var(--text-sm) var(--body); color: var(--text-primary);
  margin: 0 2px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ahpp-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px;
}
.ahpp-tile-wrap { aspect-ratio: 1; }
.ahpp-tile {
  position: relative; width: 100%; height: 100%; padding: 0;
  border: 1px solid var(--border); border-radius: 10px; overflow: hidden;
  background: var(--bg-elevated); cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.ahpp-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ahpp-tile:active { opacity: 0.75; }
.ahpp-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ahpp-tile-overlay {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.4); color: #fff; opacity: 0; transition: opacity 0.12s;
}
.ahpp-tile-overlay svg { width: 26px; height: 26px; }
.ahpp-tile:hover .ahpp-tile-overlay { opacity: 1; }
.ahpp-skeleton {
  width: 100%; aspect-ratio: 1; border-radius: 10px;
  background: linear-gradient(90deg, var(--bg-elevated) 0%, var(--bg-surface) 50%, var(--bg-elevated) 100%);
  background-size: 200% 100%;
  animation: ahppShimmer 1.4s ease-in-out infinite;
}
@keyframes ahppShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.ahpp-empty {
  padding: 22px 12px; text-align: center;
  font: 500 var(--text-sm) var(--body); color: var(--text-secondary);
}
.ahpp-empty p { margin: 0 0 10px; }
.ahpp-retry {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 8px 16px;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 10px;
  color: var(--text-primary); font: 600 var(--text-sm) var(--body); cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.ahpp-retry:hover { background: var(--bg-surface); border-color: var(--border-strong, var(--border)); }

/* Mobile ≤599px — full-width law (§4): the psheet body is already trimmed;
   just tighten the picker's own gaps. Appended after all base rules. */
@media (max-width: 599px) {
  .ahpp-actions { gap: 8px; }
  .ahpp-grid { grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); }
}
