    :root {
      --bg: #07070f;
      --surface: #0d0d1a;
      --surface2: #121224;
      --surface3: #181830;
      --border: #1e1e38;
      --border2: #2a2a48;
      --accent: #f0a500;
      --accent-dim: rgba(240,165,0,0.12);
      --accent-glow: rgba(240,165,0,0.25);
      --blue: #4a9eff;
      --blue-dim: rgba(74,158,255,0.12);
      --danger: #e74c3c;
      --danger-dim: rgba(231,76,60,0.12);
      --success: #27ae60;
      --success-dim: rgba(39,174,96,0.12);
      --warning: #f39c12;
      --text: #ececf6;
      /* Readability pass (TKT-108 review-UX batch): Craig reviews on an iPad in the shop;
         the old --text2/--text3 greys (#9898b0 / #5a5a72) were genuinely hard to read at
         distance. Brightened materially — these are shared tokens, so the lift applies to
         meta lines, descriptions, and body text across every tab. */
      --text2: #c2c2d6;
      --text3: #9a9ab4;
      --radius: 6px;
      --font-display: 'Barlow Condensed', sans-serif;
      --font-body: 'Barlow', sans-serif;
      --font-mono: 'IBM Plex Mono', monospace;
    }

    * { box-sizing: border-box; margin: 0; padding: 0; }

    body {
      background: var(--bg);
      color: var(--text);
      font-family: var(--font-body);
      font-size: 14px;
      min-height: 100vh;
      min-height: 100dvh;   /* dvh excludes the iOS Safari toolbar; vh fallback above */
      overflow-x: hidden;
      -webkit-text-size-adjust: 100%;
    }

    /* ── HEADER ── */
    .header {
      position: sticky;
      top: 0;
      z-index: 100;
      background: rgba(7,7,15,0.97);
      backdrop-filter: blur(12px);
      border-bottom: 1px solid var(--border);
      padding: 0 20px;
      /* keep the header clear of the notch in landscape / on cutout displays */
      padding-left: max(20px, env(safe-area-inset-left));
      padding-right: max(20px, env(safe-area-inset-right));
      /* min-height + wrap, not a fixed 52px (2026-09-25): on an iPad in portrait the right-hand cluster needs ~630px beside a ~230px left one, and a fixed-height nowrap row ran it off the screen edge (the page scrolled sideways). Where it fits this is the same single 52px row; where it does not, the header grows a row, and whatever pins under it follows its measured height (--hub-header-h). */
      min-height: 52px;
      flex-wrap: wrap;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 6px 16px;
    }

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

    .logo {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 18px;
      letter-spacing: 0.12em;
      text-transform: uppercase;
      color: var(--accent);
    }

    .logo span { color: var(--text3); font-weight: 300; }

    .domain-switcher {
      display: flex;
      align-items: center;
      gap: 6px;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 5px 10px;
      cursor: pointer;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 13px;
      letter-spacing: 0.08em;
      color: var(--blue);
      transition: border-color 0.2s;
      user-select: none;
    }

    .domain-switcher:hover { border-color: var(--border2); }

    .domain-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--blue); }

    .header-right { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }

    /* Version + freshness chip (#13): always visible, including on mobile. Compact monospace pill
       filled by hub-core.js with "v<HUB_VERSION> · <load time>" so a mid-session build swap shows. */
    .fresh-chip {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text3);
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: 999px;
      padding: 2px 8px;
      white-space: nowrap;
    }

    .status-indicator {
      display: flex;
      align-items: center;
      gap: 6px;
      font-family: var(--font-mono);
      font-size: 11px;
      color: var(--text3);
    }

    .status-dot {
      width: 7px; height: 7px;
      border-radius: 50%;
      background: var(--success);
      animation: pulse 2s infinite;
    }

    .status-dot.connecting { background: var(--warning); }
    .status-dot.error { background: var(--danger); animation: none; }

    @keyframes pulse {
      0%,100% { opacity: 1; } 50% { opacity: 0.35; }
    }

    .icon-btn {
      width: 32px; height: 32px;
      border-radius: var(--radius);
      border: 1px solid var(--border);
      background: var(--surface2);
      color: var(--text2);
      cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      font-size: 15px;
      transition: all 0.2s;
    }

    .icon-btn:hover { border-color: var(--border2); color: var(--text); }

    /* TIME CLOCK header badge (TKT-534). Permanent chrome; the COLOUR is the status, so the state
       must read at a glance across a shop floor — hence a filled dot plus a tinted border/background
       rather than colour on text alone. Tabular figures stop the width jittering as it ticks. */
    .tc-badge {
      /* ALWAYS the last item in the header cluster, whatever the DOM says (TKT-534). DOM order
         cannot win this on its own: the gateway appends its auth-gated 🩺 and ⏻ buttons at
         DOMContentLoaded (hub_gateway/server.js headerKit), so anything placed in index.html is
         necessarily before them. `order` decides the VISUAL sequence instead, so the badge — the
         widest item and the newest arrival — takes the overflow slot itself rather than pushing an
         established control onto a row of its own. */
      order: 1;
      height: 32px;
      display: flex; align-items: center; gap: 6px;
      padding: 0 10px;
      border-radius: var(--radius);
      border: 1px solid var(--border);
      background: var(--surface2);
      color: var(--text2);
      cursor: pointer;
      font-family: var(--font-mono);
      font-size: 12px;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      /* Transition ONLY the properties that carry meaning. `transition: all` would also animate
         height/padding/font-size when the responsive rules kick in at a viewport change — a layout
         animation nobody asked for, and one that makes the badge measure mid-flight during QA. */
      transition: color 0.2s, border-color 0.2s, background-color 0.2s;
    }
    .tc-badge:hover { filter: brightness(1.18); }
    .tc-badge-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: 0 0 8px; }
    /* GREEN = clocked in · BLUE = clocked out · YELLOW = on break. */
    .tc-badge-in    { color: var(--success); border-color: var(--success); background: var(--success-dim); }
    .tc-badge-out   { color: var(--blue);    border-color: var(--blue);    background: var(--blue-dim); }
    .tc-badge-break { color: var(--warning); border-color: var(--warning); background: rgba(243,156,18,0.12); }
    /* Clocked out prints words where there is room and 00:00 where there is not — a CSS swap, so no
       width maths in JS. Only one of the pair is ever rendered. */
    .tc-badge-short { display: none; }
    @media (max-width: 720px) {
      .tc-badge-long { display: none; }
      .tc-badge-short { display: inline; }
      .tc-badge { padding: 0 8px; font-size: 11px; }
    }

    /* ── DOMAIN MENU ── */
    .domain-menu {
      position: fixed;
      top: var(--hub-header-h, 52px);
      left: 20px;
      background: var(--surface);
      border: 1px solid var(--border2);
      border-radius: var(--radius);
      overflow: hidden;
      z-index: 200;
      min-width: 160px;
      display: none;
      box-shadow: 0 8px 24px rgba(0,0,0,0.4);
    }

    .domain-menu.open { display: block; }

    .domain-option {
      padding: 10px 16px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 13px;
      letter-spacing: 0.08em;
      cursor: pointer;
      transition: background 0.15s;
      display: flex; align-items: center; gap: 8px;
      color: var(--text2);
    }

    .domain-option:hover { background: var(--surface2); color: var(--text); }
    .domain-option.active { color: var(--accent); }

    /* ── MAIN ── */
    .main {
      max-width: 1200px;
      margin: 0 auto;
      padding: 20px 20px 60px;
      /* respect notch / home-indicator insets (viewport-fit=cover) */
      padding-left: max(20px, env(safe-area-inset-left));
      padding-right: max(20px, env(safe-area-inset-right));
      padding-bottom: max(60px, calc(40px + env(safe-area-inset-bottom)));
      display: flex;
      flex-direction: column;
      gap: 20px;
    }

    /* ── STATS BAR ── */
    .stats-bar { display: flex; gap: 10px; flex-wrap: wrap; }

    .stat-pill {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 20px;
      padding: 5px 14px;
      display: flex; align-items: center; gap: 8px;
    }

    .stat-label { color: var(--text2); font-size: 11px; }

    .stat-value {
      font-family: var(--font-mono);
      font-weight: 500;
      font-size: 12px;
      color: var(--text);
    }

    .stat-value.alert { color: var(--danger); }
    .stat-value.warn { color: var(--warning); }
    .stat-value.ok { color: var(--success); }

    /* ── HOT ZONE ── */
    .hot-zone {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
    }

    .hot-zone-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 10px 16px;
      border-bottom: 1px solid var(--border);
      background: rgba(231,76,60,0.05);
    }

    .hot-zone-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 12px;
      letter-spacing: 0.15em;
      text-transform: uppercase;
      color: var(--danger);
      display: flex; align-items: center; gap: 8px;
    }

    .hot-zone-title::before {
      content: '';
      width: 7px; height: 7px;
      border-radius: 50%;
      background: var(--danger);
      animation: pulse 1.5s infinite;
    }

    .hot-item {
      display: flex; align-items: center; gap: 12px;
      padding: 11px 16px;
      border-bottom: 1px solid var(--border);
      cursor: pointer;
      transition: background 0.15s;
    }

    .hot-item:last-child { border-bottom: none; }
    .hot-item:hover { background: var(--surface2); }
    /* Blocked tasks can appear in the Hot Zone only when there isn't enough ready work to
       fill it — dim them and flag the blocker so the ready items read as actionable. */
    .hot-item-blocked .hot-item-name { color: var(--text2); }
    .hot-item-blocked-tag { font-size: 11px; color: var(--danger); flex-shrink: 0; }

    /* TKT-681: the row's citable OT-<n> id (Row_ID) — monospace so it reads as an identifier */
    .hot-item-otid {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text2);
      flex-shrink: 0;
    }

    .hot-item-priority {
      font-family: var(--font-mono);
      font-size: 10px;
      font-weight: 500;
      padding: 2px 6px;
      border-radius: 3px;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      flex-shrink: 0;
    }

    .priority-high { background: var(--danger-dim); color: var(--danger); }
    .priority-medium { background: rgba(243,156,18,0.12); color: var(--warning); }

    .hot-item-name {
      flex: 1;
      font-size: 13px;
      color: var(--text);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .hot-item-category {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text3);
      flex-shrink: 0;
    }

    .hot-done-btn {
      flex-shrink: 0;
      width: 20px; height: 20px;
      border-radius: 4px;
      border: 1px solid var(--border2);
      background: transparent;
      color: var(--text3);
      cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      font-size: 11px;
      transition: all 0.15s;
    }
    /* Guard the green "hover" state behind a real hover-capable pointer. On touch (Craig's
       iPad) a tap leaves a STICKY :hover at the tapped screen point; after the Hot Zone
       re-renders on mark-done, the row that rolls up into that slot inherits the stuck green
       state and reads as "checked" though it isn't. (hover:hover)+(pointer:fine) means touch
       taps never paint the hover state, so nothing sticks. Root cause of the bug, not a patch. */
    @media (hover: hover) and (pointer: fine) {
      .hot-done-btn:hover { border-color: var(--success); color: var(--success); background: var(--success-dim); }
    }

    .hot-zone-empty {
      padding: 18px 16px;
      text-align: center;
      color: var(--text3);
      font-size: 13px;
    }

    /* ── MODULES ── */
    .section-label {
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 11px;
      letter-spacing: 0.15em;
      text-transform: uppercase;
      color: var(--text3);
      margin-bottom: -8px;
    }

    .module-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 12px;
    }

    /* Module cards: 3 (desktop >1100) → 2 (tablet) → 1 (phone, set in the phone block). */
    @media (max-width: 1100px) {
      .module-grid { grid-template-columns: repeat(2, 1fr); }
    }

    @media (max-width: 640px) {
      .lv-date    { width: 110px; }
      .lv-select  { min-width: 90px; }
    }

    .module-card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 10px 12px;
      cursor: pointer;
      transition: all 0.2s;
      position: relative;
      overflow: hidden;
      text-decoration: none;
      display: block;
    }

    .module-card::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 2px;
      background: var(--border);
      transition: background 0.2s;
    }

    .module-card.live::before { background: var(--success); }

    .module-card:hover:not(.disabled) {
      border-color: var(--border2);
      background: var(--surface2);
      transform: translateY(-1px);
    }

    .module-card.disabled { opacity: 0.45; cursor: default; }

    .module-header {
      display: flex; align-items: flex-start; justify-content: space-between;
      margin-bottom: 6px;
    }

    .module-icon { font-size: 16px; line-height: 1; }

    .module-badge {
      font-family: var(--font-mono);
      font-size: 11px;
      font-weight: 500;
      padding: 2px 7px;
      border-radius: 10px;
      min-width: 24px;
      text-align: center;
    }

    .badge-orange { background: var(--accent-dim); color: var(--accent); }
    .badge-blue { background: var(--blue-dim); color: var(--blue); }
    .badge-red { background: var(--danger-dim); color: var(--danger); }
    .badge-gray { background: var(--surface3); color: var(--text3); }

    .module-name {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 13px;
      letter-spacing: 0.05em;
      text-transform: uppercase;
      color: var(--text);
      margin-bottom: 2px;
    }

    .module-desc { font-size: 12.5px; color: var(--text2); line-height: 1.35; }

    .module-status {
      margin-top: 6px;
      font-family: var(--font-mono);
      font-size: 10px;
      letter-spacing: 0.08em;
    }

    .status-live { color: var(--success); }
    .status-soon { color: var(--text3); }

    /* ── LOG VIEWER PANEL ── */
    .log-viewer-panel {
      position: fixed;
      inset: 0;
      z-index: 300;
      background: var(--bg);
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    .log-viewer-header {
      display: flex; align-items: center; gap: 10px;
      padding: 0 14px;
      padding-left: max(14px, env(safe-area-inset-left));
      padding-right: max(14px, env(safe-area-inset-right));
      height: 52px;
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
      background: rgba(7,7,15,0.97);
      backdrop-filter: blur(12px);
    }

    .lv-back-btn {
      display: flex; align-items: center; gap: 5px;
      background: none;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      color: var(--text2);
      font-family: var(--font-display);
      font-size: 13px;
      font-weight: 600;
      letter-spacing: 0.05em;
      padding: 5px 10px;
      cursor: pointer;
      white-space: nowrap;
      transition: all 0.15s;
      flex-shrink: 0;
    }
    .lv-back-btn:hover { border-color: var(--border2); color: var(--text); }

    .log-viewer-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 15px;
      letter-spacing: 0.12em;
      text-transform: uppercase;
      color: var(--accent);
      flex: 1;
    }

    .log-viewer-controls { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; overflow-x: auto; flex-shrink: 0; }

    .log-viewer-filters {
      display: flex; align-items: center; gap: 8px;
      padding: 8px 14px;
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
      flex-wrap: wrap;
    }

    .log-viewer-ai {
      display: flex; align-items: center; gap: 8px;
      padding: 8px 14px;
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
      flex-wrap: wrap;
    }

    .lv-input {
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: 4px;
      color: var(--text);
      font-family: var(--font-body);
      font-size: 12px;
      padding: 5px 8px;
      outline: none;
    }

    .lv-input:focus { border-color: var(--accent); }
    .lv-date { width: 140px; }
    .lv-select { min-width: 120px; cursor: pointer; }
    .lv-search { flex: 1; }
    .lv-ai-input { flex: 1; }
    .lv-count { font-family: var(--font-mono); font-size: 11px; color: var(--text3); white-space: nowrap; }

    .lv-btn {
      background: var(--surface3);
      border: 1px solid var(--border2);
      border-radius: 4px;
      color: var(--text2);
      font-family: var(--font-display);
      font-size: 12px;
      font-weight: 600;
      letter-spacing: 0.06em;
      padding: 5px 12px;
      cursor: pointer;
      text-transform: uppercase;
      transition: all 0.15s;
      white-space: nowrap;
    }

    .lv-btn:hover { background: var(--surface2); color: var(--text); border-color: var(--accent); }
    .lv-btn-close { padding: 5px 8px; }
    .lv-btn-ai { background: var(--blue-dim); color: var(--blue); border-color: rgba(74,158,255,0.3); }
    .lv-btn-ai:hover { background: rgba(74,158,255,0.2); }

    .lv-ai-response {
      margin: 0 14px 0;
      padding: 10px 12px;
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: 4px;
      font-size: 12px;
      color: var(--text2);
      line-height: 1.5;
      white-space: pre-wrap;
      max-height: 160px;
      overflow-y: auto;
      flex-shrink: 0;
      margin-bottom: 8px;
    }

    .log-viewer-body {
      flex: 1;
      overflow-y: auto;
      -webkit-overflow-scrolling: touch;
      padding: 8px 0;
      padding-bottom: max(8px, env(safe-area-inset-bottom));
      min-height: 0;
    }

    .lv-empty {
      padding: 32px;
      text-align: center;
      color: var(--text3);
      font-size: 12px;
    }

    /* Log-Scope config screen (intake-observability-event-logging) — registry-driven toggles. */
    .lv-scope-panel {
      border: 1px solid var(--border);
      border-radius: 6px;
      background: var(--surface2);
      padding: 10px 12px;
      margin: 6px 0 4px;
      max-height: 42vh;
      overflow-y: auto;
    }
    .lv-scope-intro { color: var(--text3); font-size: 11px; margin-bottom: 8px; }
    .lv-scope-subsystem {
      font-family: var(--font-mono);
      font-size: 11px;
      font-weight: 600;
      color: var(--accent, var(--text));
      text-transform: uppercase;
      letter-spacing: 0.04em;
      margin: 10px 0 4px;
    }
    .lv-subsystem-badge {
      font-family: var(--font-mono);
      font-size: 9px;
      color: var(--text3);
      border: 1px solid var(--border);
      border-radius: 3px;
      padding: 0 4px;
      text-transform: uppercase;
      letter-spacing: 0.03em;
    }
    .lv-scope-group { margin-bottom: 10px; }
    .lv-scope-group-title {
      font-family: var(--font-condensed, inherit);
      text-transform: uppercase;
      letter-spacing: 0.06em;
      font-size: 10px;
      color: var(--text3);
      border-bottom: 1px solid var(--border);
      padding-bottom: 3px;
      margin-bottom: 6px;
    }
    .lv-scope-row {
      display: flex;
      align-items: flex-start;
      gap: 8px;
      padding: 5px 2px;
      cursor: pointer;
    }
    .lv-scope-row:hover { background: var(--surface); }
    .lv-scope-row input[type="checkbox"] { margin-top: 2px; flex: none; }
    .lv-scope-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
    .lv-scope-label { color: var(--text); font-size: 12px; font-weight: 500; }
    .lv-scope-event { color: var(--text3); font-size: 10px; font-family: var(--font-mono); }
    .lv-scope-desc { color: var(--text2); font-size: 11px; line-height: 1.35; }

    .lv-card {
      padding: 7px 14px;
      border-bottom: 1px solid var(--border);
      font-size: 12px;
      line-height: 1.4;
    }

    .lv-card:hover { background: var(--surface2); }

    .lv-card-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px; }

    .lv-ts {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text3);
      flex-shrink: 0;
    }

    .lv-event-badge {
      font-family: var(--font-mono);
      font-size: 10px;
      font-weight: 500;
      padding: 1px 6px;
      border-radius: 3px;
      flex-shrink: 0;
    }

    .lv-ev-EMAIL_RECEIVED    { background: var(--blue-dim); color: var(--blue); }
    .lv-ev-AI_CLASSIFIED     { background: var(--success-dim); color: var(--success); }
    .lv-ev-TASK_CREATED      { background: var(--accent-dim); color: var(--accent); }
    .lv-ev-CASE_CREATED      { background: var(--accent-dim); color: var(--accent); }
    .lv-ev-CASE_LINKED       { background: var(--accent-dim); color: var(--accent); }
    .lv-ev-COMPANY_MATCHED   { background: rgba(74,158,255,0.08); color: #7ab8ff; }
    .lv-ev-BLACKLISTED       { background: var(--danger-dim); color: var(--danger); }
    .lv-ev-RULE_HIT          { background: var(--danger-dim); color: var(--danger); }
    .lv-ev-SKIPPED           { background: var(--surface3); color: var(--text3); }
    .lv-ev-ERROR             { background: var(--danger-dim); color: var(--danger); font-weight: 700; }
    .lv-ev-TASK_CLOSED       { background: var(--surface3); color: var(--text3); }
    .lv-ev-TASK_ASSIGNED     { background: var(--success-dim); color: var(--success); }
    .lv-ev-CASE_STAGE_ADVANCED { background: var(--accent-dim); color: var(--accent); }
    .lv-ev-BACKFILL_START    { background: var(--surface3); color: var(--text2); }
    .lv-ev-BACKFILL_END      { background: var(--surface3); color: var(--text2); }
    .lv-ev-default           { background: var(--surface3); color: var(--text2); }

    .lv-card-summary { color: var(--text2); font-size: 11px; }
    .lv-card-detail  { color: var(--text3); font-size: 12px; font-family: var(--font-mono); margin-top: 2px; }

    /* ── AGENT PANEL ── */
    .agent-panel {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      display: flex;
      flex-direction: column;
      height: 500px;
    }

    .agent-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 12px 16px;
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
    }

    .agent-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 13px;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--accent);
      display: flex; align-items: center; gap: 8px;
    }

    .agent-title::before { content: '◆'; font-size: 10px; }

    /* TKT-1316 — the draft-or-act switch row at the top of the chat (also shown in the dock). */
    .agent-write-mode {
      display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
      padding: 8px 16px;
      border-bottom: 1px solid var(--border);
      font-size: 12px; color: var(--text2);
      cursor: pointer; flex-shrink: 0;
    }
    .agent-write-mode input { width: 16px; height: 16px; margin: 0; cursor: pointer; }
    .agent-write-mode-name { font-weight: 600; color: var(--text); }
    .agent-write-mode-state { color: var(--text3); }
    .agent-undo-btn {
      margin-left: 8px; padding: 2px 10px;
      font-size: 11px; border-radius: 4px; cursor: pointer;
      border: 1px solid var(--accent); background: transparent; color: var(--accent);
    }
    .agent-undo-btn:disabled { opacity: .6; cursor: default; }

    .agent-msgs {
      flex: 1;
      overflow-y: auto;
      padding: 16px;
      display: flex;
      flex-direction: column;
      gap: 14px;
      scroll-behavior: smooth;
    }

    .agent-msgs::-webkit-scrollbar { width: 4px; }
    .agent-msgs::-webkit-scrollbar-track { background: transparent; }
    .agent-msgs::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }

    .msg { display: flex; flex-direction: column; gap: 4px; max-width: 92%; }
    .msg.user { align-self: flex-end; align-items: flex-end; }
    .msg.agent { align-self: flex-start; align-items: flex-start; }
    .msg.system { align-self: center; max-width: 100%; }

    .msg-role {
      font-family: var(--font-mono);
      font-size: 10px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .msg.agent .msg-role { color: var(--accent); }
    .msg.user .msg-role { color: var(--blue); }

    .msg-bubble {
      padding: 10px 14px;
      border-radius: var(--radius);
      font-size: 13px;
      line-height: 1.65;
    }

    .msg.agent .msg-bubble {
      background: var(--surface2);
      border: 1px solid var(--border);
      color: var(--text);
    }

    .msg.user .msg-bubble {
      background: var(--blue-dim);
      border: 1px solid rgba(74,158,255,0.2);
      color: var(--text);
    }

    .msg.system .msg-bubble {
      background: transparent;
      border: none;
      color: var(--text3);
      font-family: var(--font-mono);
      font-size: 11px;
      padding: 2px 0;
      text-align: center;
    }

    /* Markdown rendered inside a Control Agent bubble (TKT-613). The assistant already emits
       tables and lists; before this they reached the operator as literal | pipes and ** asterisks.
       Scoped to .md-body so nothing here can affect the rest of the Hub. */
    /* Load-bearing, and NOT obvious: .msg sets align-items:flex-start, so a bubble sizes to its
       CONTENT on the horizontal axis and will happily overflow its parent. Measured in the browser
       at a 380px dock: without this the bubble rendered 637px wide inside a 350px .msg and the
       table's overflow-x never engaged — it just pushed the panel. With it the bubble is 348px and
       the table scrolls inside its wrapper. overflow-x on .md-table-wrap is useless on its own. */
    .md-body { max-width: 100%; }
    .md-body > :first-child { margin-top: 0; }
    .md-body > :last-child { margin-bottom: 0; }
    .md-body p { margin: 0 0 8px; }
    .md-body .md-h {
      margin: 12px 0 6px;
      font-size: 12px;
      font-weight: 600;
      letter-spacing: 0.02em;
      color: var(--text);
    }
    .md-body .md-list { margin: 0 0 8px; padding-left: 20px; }
    .md-body .md-list li { margin: 2px 0; }
    .md-body .md-quote {
      margin: 0 0 8px;
      padding: 2px 0 2px 10px;
      border-left: 2px solid var(--border);
      color: var(--text2);
    }
    .md-body .md-hr { border: none; border-top: 1px solid var(--border); margin: 10px 0; }
    .md-body code {
      font-family: var(--font-mono);
      font-size: 11.5px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 3px;
      padding: 1px 4px;
    }
    .md-body .md-pre {
      margin: 0 0 8px;
      padding: 8px 10px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow-x: auto;
    }
    /* A pre already has the frame — don't double-box the code inside it. */
    .md-body .md-pre code { background: none; border: none; padding: 0; }

    /* The dock is narrow, so a wide table scrolls INSIDE its own wrapper. Without this a
       QB aging table with six columns blows the bubble past the panel edge. */
    .md-body .md-table-wrap { overflow-x: auto; margin: 0 0 8px; }
    .md-body .md-table {
      border-collapse: collapse;
      width: 100%;
      font-size: 12px;
      font-variant-numeric: tabular-nums;
    }
    .md-body .md-table th,
    .md-body .md-table td {
      border: 1px solid var(--border);
      padding: 4px 8px;
      text-align: left;
      white-space: nowrap;
    }
    .md-body .md-table th {
      background: var(--surface);
      font-weight: 600;
      color: var(--text);
    }
    .md-body .md-table tbody tr:nth-child(even) td { background: rgba(255,255,255,0.02); }

    .typing {
      display: flex; gap: 4px; align-items: center;
      padding: 10px 14px;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
    }

    .typing span {
      width: 6px; height: 6px;
      border-radius: 50%;
      background: var(--accent);
      animation: typingBounce 1.2s infinite;
    }

    .typing span:nth-child(2) { animation-delay: 0.2s; }
    .typing span:nth-child(3) { animation-delay: 0.4s; }

    @keyframes typingBounce {
      0%,60%,100% { transform: translateY(0); opacity: 0.4; }
      30% { transform: translateY(-4px); opacity: 1; }
    }

    .agent-input-area {
      padding: 12px 16px;
      border-top: 1px solid var(--border);
      display: flex; gap: 10px;
      flex-shrink: 0;
    }

    .agent-input {
      flex: 1;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 9px 12px;
      color: var(--text);
      font-family: var(--font-body);
      font-size: 13px;
      outline: none;
      transition: border-color 0.2s;
      /* TKT-606. Was `resize:none; height:38px; overflow:hidden`, which made every textarea
         carrying this class about 1.5 lines tall with no usable way through a longer message.
         Craig: "only two lines tall, preventing comfortable editing and scrollback".
         Precisely what `overflow:hidden` cost, since it is easy to overstate: the content was
         never truly unreachable — the caret still drags the view along as you arrow through it,
         and scrollTop still responds programmatically (measured: 547 with the old rule applied).
         What it removed was the SCROLLBAR and wheel/drag scrolling, so there was no visible
         affordance and no way to skim back — you navigated a 30-line message blind, through a
         1.5-line window, with `resize:none` blocking the obvious workaround.
         The fixed height also silently overrode the `rows` attribute on the OTHER two textareas
         using this class — the voice relay asks for rows="3" and group chat for rows="2", and both
         were squashed to 38px. Dropping the height restores each element's declared intent.
         line-height is pinned so `rows` maps to a predictable pixel height. */
      resize: vertical;        /* drag it to whatever suits the message being written */
      min-height: 38px;        /* the old height becomes the FLOOR, not the ceiling */
      max-height: 45vh;        /* never let it eat the conversation above it */
      overflow-y: auto;        /* the scrollback that `overflow:hidden` was denying */
      line-height: 1.45;
    }

    .agent-input:focus { border-color: var(--border2); }
    .agent-input::placeholder { color: var(--text3); }

    .send-btn {
      background: var(--accent);
      border: none;
      border-radius: var(--radius);
      padding: 0 16px;
      color: #000;
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 13px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      cursor: pointer;
      transition: opacity 0.2s;
      height: 38px;
      white-space: nowrap;
    }

    .send-btn:hover { opacity: 0.85; }
    .send-btn:disabled { opacity: 0.35; cursor: default; }

    /* ── SETTINGS ── */
    .settings-overlay {
      display: none;
      position: fixed; inset: 0;
      background: rgba(0,0,0,0.75);
      z-index: 300;
      align-items: center; justify-content: center;
    }

    .settings-overlay.open { display: flex; }

    .settings-panel {
      background: var(--surface);
      border: 1px solid var(--border2);
      border-radius: 8px;
      padding: 24px;
      width: 380px;
      max-width: calc(100vw - 40px);
      max-height: calc(100dvh - 32px);   /* scroll instead of overflowing a short viewport */
      overflow-y: auto;
      box-shadow: 0 20px 60px rgba(0,0,0,0.5);
    }

    .settings-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 15px;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--text);
      margin-bottom: 20px;
    }

    .settings-field { margin-bottom: 14px; }

    .settings-label {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text2);
      letter-spacing: 0.1em;
      text-transform: uppercase;
      margin-bottom: 6px;
    }

    .settings-input {
      width: 100%;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 8px 12px;
      color: var(--text);
      font-family: var(--font-mono);
      font-size: 12px;
      outline: none;
    }

    .settings-input:focus { border-color: var(--border2); }

    .settings-actions {
      display: flex; justify-content: flex-end; gap: 10px;
      margin-top: 20px;
    }

    .btn {
      padding: 8px 18px;
      border-radius: var(--radius);
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 13px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      cursor: pointer;
      border: none;
      transition: opacity 0.2s;
    }

    .btn-primary { background: var(--accent); color: #000; }
    .btn-ghost { background: var(--surface2); color: var(--text2); border: 1px solid var(--border); }
    .btn:hover { opacity: 0.85; }

    /* scrollbar */
    ::-webkit-scrollbar { width: 5px; height: 5px; }
    ::-webkit-scrollbar-track { background: transparent; }
    ::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }

    /* ── TASKS PANEL ── */
    .tasks-panel {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
    }

    .tasks-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 10px 16px;
      border-bottom: 1px solid var(--border);
      flex-wrap: wrap;
      gap: 8px;
    }

    .tasks-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 12px;
      letter-spacing: 0.15em;
      text-transform: uppercase;
      color: var(--accent);
    }

    .tasks-tabs { display: flex; gap: 4px; }

    .tasks-tab {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 4px 12px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 11px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--text2);
      cursor: pointer;
      transition: all 0.15s;
    }

    .tasks-tab:hover { border-color: var(--border2); color: var(--text); }
    .tasks-tab.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }

    .tasks-row {
      display: flex; align-items: center; gap: 10px;
      padding: 9px 16px;
      border-bottom: 1px solid var(--border);
      transition: background 0.15s;
      cursor: pointer;
    }

    .tasks-row:last-child { border-bottom: none; }
    .tasks-row:hover { background: var(--surface2); }

    /* Two-line card — replaces flat .tasks-row for all three tabs */
    .tasks-card {
      padding: 9px 16px;
      border-bottom: 1px solid var(--border);
      cursor: pointer;
      transition: background 0.15s;
    }
    .tasks-card:last-child { border-bottom: none; }
    .tasks-card:hover { background: var(--surface2); }

    /* Blocked task state — left accent + dimmed, badge in the card top row */
    .tasks-card.blocked { border-left: 3px solid var(--danger); background: var(--danger-dim); }
    .tasks-card.blocked .tasks-card-name { color: var(--text2); }
    .tasks-blocked-badge {
      font-family: var(--font-display);
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      color: var(--danger);
      background: var(--danger-dim);
      border: 1px solid var(--danger);
      border-radius: 4px;
      padding: 1px 6px;
      flex-shrink: 0;
      white-space: nowrap;
    }
    .tasks-ticket-link { font-size: 13px; }

    /* Working-status chip on a task card (TKT-110) — In Progress (started) / Delayed
       (started but stuck). Distinct colours so an in-flight row reads at a glance. */
    .task-status-chip {
      font-family: var(--font-display);
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      border-radius: 4px;
      padding: 1px 6px;
      flex-shrink: 0;
      white-space: nowrap;
    }
    .task-status-chip.status-inprogress { color: var(--blue); background: var(--blue-dim); border: 1px solid var(--blue); }
    .task-status-chip.status-delayed { color: var(--warning); background: rgba(243,156,18,0.12); border: 1px solid var(--warning); }

    /* Status control in the task detail panel. */
    .task-status-select {
      width: 100%;
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: var(--radius);
      color: var(--text);
      font-family: var(--font-body);
      font-size: 13px;
      padding: 6px 8px;
      margin-top: 2px;
    }
    .task-status-hint { font-size: 12px; color: var(--text3); margin-top: 5px; line-height: 1.4; }

    /* Category filter chips — wrap on narrow screens, no off-screen overflow */
    .task-chips {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      padding: 10px 16px;
      border-bottom: 1px solid var(--border);
    }
    .task-chip {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: 999px;
      padding: 3px 11px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 10px;
      letter-spacing: 0.05em;
      color: var(--text2);
      cursor: pointer;
      transition: all 0.15s;
      white-space: nowrap;
    }
    .task-chip:hover { border-color: var(--border2); color: var(--text); }
    .task-chip.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }

    /* ── Craig's Tasks: view filter (Available / All / Blocked) ── */
    .task-views {
      display: flex; flex-wrap: wrap; gap: 6px;
      padding: 10px 16px 0;
    }
    .task-view-chip {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 5px 12px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 11px;
      letter-spacing: 0.05em;
      text-transform: uppercase;
      color: var(--text2);
      cursor: pointer;
      transition: all 0.15s;
      white-space: nowrap;
    }
    .task-view-chip:hover { border-color: var(--border2); color: var(--text); }
    .task-view-chip.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
    .task-view-chip .tvc-n {
      font-family: var(--font-mono);
      font-size: 10px;
      opacity: 0.8;
      margin-left: 2px;
    }

    /* ── Craig's Tasks: sort control ── */
    .task-sortbar {
      display: flex; align-items: center; gap: 8px;
      padding: 10px 16px 0;
    }
    .task-sort-label {
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--text3);
    }
    .task-sort-select {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      color: var(--text);
      font-size: 12px;
      padding: 4px 8px;
      cursor: pointer;
    }
    .task-sort-dir {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      color: var(--text2);
      font-family: var(--font-mono);
      font-size: 11px;
      padding: 4px 10px;
      cursor: pointer;
      transition: all 0.15s;
    }
    .task-sort-dir:hover { border-color: var(--border2); color: var(--text); }

    /* ── Related-task chips (Blocked By / Blocks / linked tasks ↔ tickets) ── */
    .task-rel-chips { display: flex; flex-wrap: wrap; gap: 6px; }
    .task-rel-chip {
      display: inline-flex; align-items: center; gap: 4px;
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: 999px;
      padding: 3px 10px;
      font-size: 12px;
      color: var(--text);
      cursor: pointer;
      text-decoration: none;
      transition: all 0.15s;
      max-width: 100%;
    }
    .task-rel-chip:hover { border-color: var(--accent); color: var(--accent); }
    .task-rel-chip.rel-done { color: var(--text3); border-color: var(--border); }
    .task-rel-chip.rel-done:hover { color: var(--success); border-color: var(--success); }
    .task-rel-chip.rel-ticket { border-color: var(--accent); color: var(--accent); }
    .rel-open-count {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--danger);
      font-weight: 400;
      margin-left: 4px;
    }

    /* ── Done-verification cascade modal ── */
    .tdc-overlay {
      position: fixed; inset: 0;
      background: rgba(0,0,0,0.6);
      z-index: 600;
      display: flex; align-items: center; justify-content: center;
      padding: 20px;
    }
    .tdc-card {
      background: var(--surface);
      border: 1px solid var(--border2);
      border-radius: 10px;
      width: 440px; max-width: 100%;
      max-height: 85dvh; overflow-y: auto;
      padding: 20px;
      box-shadow: 0 12px 48px rgba(0,0,0,0.6);
    }
    .tdc-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 16px;
      color: var(--text);
      margin-bottom: 8px;
    }
    .tdc-sub { font-size: 12px; color: var(--text2); line-height: 1.5; margin-bottom: 14px; }
    .tdc-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
    .tdc-row {
      display: flex; align-items: center; gap: 10px;
      padding: 8px 10px;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      cursor: pointer;
    }
    .tdc-check { width: 16px; height: 16px; flex-shrink: 0; cursor: pointer; }
    .tdc-row-name { flex: 1; font-size: 13px; color: var(--text); min-width: 0; }
    .tdc-row-status {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--warning);
      flex-shrink: 0;
    }
    .tdc-actions { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }

    /* ── Critical Path view ── */
    .cp-section { margin-bottom: 8px; }
    .cp-head {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 12px;
      letter-spacing: 0.12em;
      text-transform: uppercase;
      color: var(--accent);
      padding: 12px 16px 8px;
    }
    .cp-head-sub {
      display: block;
      font-family: var(--font-body);
      font-weight: 400;
      font-size: 11px;
      letter-spacing: 0;
      text-transform: none;
      color: var(--text3);
      margin-top: 2px;
    }
    .cp-list { display: flex; flex-direction: column; }
    .cp-row {
      display: flex; align-items: center; gap: 8px;
      padding: 9px 16px;
      border-bottom: 1px solid var(--border);
      cursor: pointer;
      transition: background 0.15s;
      min-width: 0;
    }
    .cp-row:last-child { border-bottom: none; }
    .cp-row:hover { background: var(--surface2); }
    .cp-step {
      flex-shrink: 0;
      width: 20px; height: 20px;
      border-radius: 50%;
      background: var(--surface3);
      color: var(--text2);
      font-family: var(--font-mono);
      font-size: 10px;
      display: flex; align-items: center; justify-content: center;
    }
    .cp-row-name {
      flex: 1;
      font-size: 13px;
      color: var(--text);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      min-width: 0;
    }
    .cp-row-meta {
      font-family: var(--font-mono);
      font-size: 12px;
      color: var(--text3);
      flex-shrink: 0;
    }
    .cp-tag {
      font-family: var(--font-display);
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      padding: 1px 6px;
      border-radius: 4px;
      flex-shrink: 0;
      white-space: nowrap;
    }
    .cp-next    { color: var(--accent); background: var(--accent-dim); border: 1px solid var(--accent); }
    .cp-ready   { color: var(--success); background: var(--success-dim); }
    .cp-blocked { color: var(--danger); background: var(--danger-dim); }

    .tasks-card-top {
      display: flex; align-items: center; gap: 8px;
      min-width: 0;
    }

    .tasks-card-name {
      flex: 1;
      font-size: 13px;
      font-weight: 500;
      color: var(--text);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      min-width: 0;
    }

    .tasks-card-meta {
      font-family: var(--font-mono);
      font-size: 12px;
      color: var(--text3);
      margin-top: 3px;
      padding-left: 28px; /* align under name, past done-btn */
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* One-line execution-description preview on the task list row — single line,
       ellipsised, aligned under the name (past the done-btn). Full text lives in
       the detail panel's .detail-exec block. */
    /* TKT-714 criterion 8: the execution instruction WRAPS (up to three lines) instead of
       being clipped to one. OT-402 carried two actions and the second was cut mid-word, so
       Craig did half the job and never knew there was more. `.is-clamped` is removed by the
       "⤢ more" toggle — the full text is reachable by tap, not only by mouse-hover tooltip. */
    .tasks-card-desc {
      font-size: 12.5px;
      color: var(--text2);
      margin-top: 3px;
      padding-left: 28px;
      white-space: normal;
      overflow-wrap: anywhere;
    }
    .tasks-card-desc.is-clamped {
      display: -webkit-box;
      -webkit-line-clamp: 3;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .tasks-desc-more {
      margin-left: 28px;
      margin-top: 2px;
      padding: 1px 6px;
      font-size: 11px;
      font-family: var(--font-mono);
      color: var(--text3);
      background: var(--surface3);
      border: 1px solid var(--border2);
      border-radius: 4px;
      cursor: pointer;
    }
    .tasks-desc-more:hover { color: var(--text1); }

    /* TKT-714 criterion 7: the row's citable id LEADS the title line, in bolder mono —
       Craig's own prescription ("It should be in bolder text right at the beginning:
       OT-###"). It is how a row is cited, referred to and found. */
    .tasks-card-ot {
      font-family: var(--font-mono);
      font-size: 12px;
      font-weight: 700;
      color: var(--text1);
      background: var(--surface3);
      border: 1px solid var(--border2);
      border-radius: 4px;
      padding: 1px 6px;
      margin-right: 6px;
      white-space: nowrap;
    }

    .tasks-done-btn {
      width: 20px; height: 20px;
      border-radius: 4px;
      border: 1px solid var(--border2);
      background: transparent;
      color: var(--text3);
      cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      font-size: 11px;
      flex-shrink: 0;
      transition: all 0.15s;
    }

    /* Batch "Apply changes" (hub-reliability-batch-apply-and-notion-retry). A pending optimistic
       mark-done shows a left accent + reduced opacity until Apply commits it. */
    .task-pending-done { position: relative; }
    .task-pending-done::before {
      content: '';
      position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
      background: var(--success);
      border-radius: 2px;
    }
    .task-apply-bar {
      position: fixed;
      left: 50%; bottom: max(16px, env(safe-area-inset-bottom));
      transform: translateX(-50%);
      z-index: 1200;
      display: flex; align-items: center; gap: 12px;
      padding: 10px 14px;
      background: var(--surface2, var(--surface));
      border: 1px solid var(--border);
      border-radius: 10px;
      box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
    }
    .task-apply-bar .tab-count { color: var(--text2); font-size: 12px; white-space: nowrap; }

    @media (hover: hover) and (pointer: fine) {
      .tasks-done-btn:hover { border-color: var(--success); color: var(--success); background: var(--success-dim); }
    }

    .tasks-name {
      flex: 1;
      font-size: 13px;
      color: var(--text);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      min-width: 0;
    }

    .tasks-company {
      font-size: 12px;
      color: var(--text2);
      flex-shrink: 0;
      width: 130px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .tasks-meta {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text3);
      flex-shrink: 0;
      white-space: nowrap;
    }

    .priority-low { background: var(--surface3); color: var(--text3); }

    .tasks-link {
      color: var(--blue);
      text-decoration: none;
      font-size: 14px;
      flex-shrink: 0;
      opacity: 0.65;
      transition: opacity 0.15s;
      line-height: 1;
    }

    .tasks-link:hover { opacity: 1; }

    .tasks-empty {
      padding: 18px 16px;
      text-align: center;
      color: var(--text3);
      font-size: 13px;
    }

    .tasks-loading {
      padding: 18px 16px;
      text-align: center;
      color: var(--text3);
      font-size: 13px;
      font-family: var(--font-mono);
    }

    /* Pre-paint hide of the flat tab bar when the faceted nav (HUB_NAV_MODES) was active last
       load (hub-fixes-batch Part A anti-flash). hub-session-guard.js adds this <html> class in
       <head> BEFORE first paint so a refresh never flashes "half a screen of tabs" before the
       faceted nav mounts; hub-nav-modes.js removes it (revealFlatBar) if the flag is off or the
       scaffold fails to mount, so the flat bar is never permanently lost. */
    html.hub-prepaint-navmodes .hub-tabs { display: none !important; }

    /* Hot Zone loading state (hub-fixes-batch Part C2) — mirrors .tasks-loading so the pane
       reads as loading, not dead, while the board + blocker/company lookups resolve. */
    .hot-zone-loading {
      padding: 16px;
      text-align: center;
      color: var(--text3);
      font-size: 13px;
      font-family: var(--font-mono);
    }

    /* ── HUB TABS ── */
    .hub-tabs {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      border-bottom: 1px solid var(--border);
      padding-bottom: 10px;
      margin-bottom: -8px;
      /* Keep the nav reachable while scrolling long lists (Craig: don't make me scroll
         back to the top to switch screens). Pins just under the sticky header at its MEASURED height (--hub-header-h, hub-nav-collapse.js) — 52px on a desktop, ~130px on a phone where the header wraps. The
         opaque page-bg + top padding fill the gap so scrolling content passes underneath
         rather than peeking through. z-index sits below the header (100). */
      position: sticky;
      top: var(--hub-header-h, 52px);
      z-index: 90;
      background: var(--bg);
      padding-top: 12px;
      margin-top: -12px;
    }

    .hub-tab {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 6px 16px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--text2);
      cursor: pointer;
      transition: all 0.15s;
    }

    .hub-tab:hover { border-color: var(--border2); color: var(--text); }
    .hub-tab.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }

    /* Mobile nav-collapse toggle (hub-nav-collapse.js): a single "☰ <active tab>" disclosure
       that stands in for the flat grid on phones. HIDDEN on desktop — only the ≤699px media
       query reveals it (and the matching .nav-collapsed hide rule), so the desktop bar is
       unchanged. Styled like a .hub-tab so it reads as part of the bar. */
    .hub-tabs-toggle {
      display: none;
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: var(--radius);
      padding: 6px 16px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--text);
      cursor: pointer;
    }

    /* ── MODE × DOMAIN FACETED NAV (HUB_NAV_MODES_ENABLED) ──
       Two dropdowns (Mode + Domain) + a filtered menu row + an optional submenu sub-row
       + a breadcrumb. Replaces the flat .hub-tabs bar when the flag is on (the flat bar is
       display:none'd by hub-nav-modes.js). Sticky under the header like the flat bar was. */
    .hub-nav-modes {
      display: flex;
      flex-direction: column;
      gap: 8px;
      border-bottom: 1px solid var(--border);
      padding-bottom: 10px;
      margin-bottom: -8px;
      position: sticky;
      top: var(--hub-header-h, 52px);
      z-index: 90;
      background: var(--bg);
      padding-top: 8px;
    }
    /* ON A PHONE THE FACETED NAV SCROLLS AWAY WITH THE PAGE (2026-09-25, Craig on the phone: "the background
       and the foreground overlap each other … I can't get to the actions button"). Measured at 375×812: the
       header wraps to ~130px and this nav is ~270px (three rows of menus + the sub-row), so pinning both left
       under half the screen for the page, and — while the nav pinned at a hard-coded 52px — the header covered
       its first two menu rows (Home, Customers, Vendors, Items, Machines & Manuals, Money answered the HEADER at
       elementFromPoint). The header stays pinned; the nav is one flick of a scroll away. */
    @media (max-width: 760px) {
      .hub-nav-modes { position: static; }
    }
    .hnm-facets { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
    .hnm-facet { display: flex; align-items: center; gap: 6px; }
    .hnm-facet-lbl {
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 10px;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--text3);
    }
    .hnm-select {
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: var(--radius);
      color: var(--text);
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: 0.04em;
      padding: 6px 10px;
      cursor: pointer;
      min-height: 36px;
    }
    .hnm-crumb {
      font-family: var(--font-mono);
      font-size: 11px;
      color: var(--text3);
      margin-left: auto;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      max-width: 50%;
    }
    .hnm-menus, .hnm-subs { display: flex; gap: 6px; flex-wrap: wrap; }
    .hnm-subs { padding-left: 2px; }
    .hnm-menu, .hnm-sub {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 6px 14px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--text2);
      cursor: pointer;
      transition: all 0.15s;
      display: inline-flex;
      align-items: center;
      gap: 5px;
    }
    .hnm-sub {
      font-size: 11px;
      padding: 5px 12px;
      text-transform: none;
      letter-spacing: 0.02em;
    }
    .hnm-menu:hover, .hnm-sub:hover { border-color: var(--border2); color: var(--text); }
    .hnm-menu.active, .hnm-sub.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
    .hnm-caret { font-size: 9px; color: var(--text3); }
    .hnm-soon {
      font-family: var(--font-mono);
      font-size: 8px;
      letter-spacing: 0.06em;
      color: var(--text3);
      border: 1px solid var(--border);
      border-radius: 3px;
      padding: 0 3px;
      text-transform: uppercase;
    }
    /* TKT-1108 step 0 — a leaf whose function is not yet released to the shop (development /
       admin modes only; operating mode does not render it at all). */
    .hnm-dev {
      font-family: var(--font-mono);
      font-size: 8px;
      letter-spacing: 0.06em;
      color: #e0a33e;
      border: 1px solid rgba(224, 163, 62, 0.55);
      border-radius: 3px;
      padding: 0 3px;
      text-transform: uppercase;
      margin-left: 4px;
    }

    /* ── STAT PILL CLICKABLE ── */
    .stat-pill.clickable {
      cursor: pointer;
      transition: border-color 0.15s, background 0.15s;
    }
    .stat-pill.clickable:hover {
      border-color: var(--border2);
      background: var(--surface2);
    }

    /* ── DETAIL / LIST PANEL ── */
    .detail-overlay {
      position: fixed; inset: 0;
      background: rgba(0,0,0,0.55);
      z-index: 400;
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.22s;
    }
    .detail-overlay.open { opacity: 1; pointer-events: all; }

    .detail-panel {
      position: fixed;
      top: 0; right: 0;
      /* min(): never wider than the viewport — the historical narrow-width bug was the
         fixed 400px panel parking partly off-canvas with buttons unreachable. */
      width: min(420px, 100vw);
      max-width: 100vw;
      height: 100vh;
      height: 100dvh;       /* dvh keeps the footer actions above the iOS Safari toolbar */
      background: var(--surface);
      border-left: 1px solid var(--border2);
      z-index: 401;
      display: flex;
      flex-direction: column;
      transform: translateX(100%);
      transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
      box-shadow: -10px 0 40px rgba(0,0,0,0.45);
    }
    .detail-panel.open { transform: translateX(0); }

    .detail-ph {
      display: flex; align-items: center; justify-content: space-between;
      padding: 13px 16px;
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
      gap: 12px;
    }
    .detail-ph-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 11px;
      letter-spacing: 0.15em;
      text-transform: uppercase;
      color: var(--text3);
    }
    .detail-close {
      width: 26px; height: 26px;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--surface2);
      color: var(--text2);
      cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      font-size: 14px; line-height: 1;
      transition: all 0.15s;
      flex-shrink: 0;
    }
    .detail-close:hover { border-color: var(--border2); color: var(--text); }

    .detail-body {
      flex: 1;
      overflow-y: auto;
      padding: 18px 16px;
      display: flex;
      flex-direction: column;
      gap: 14px;
    }
    .detail-body::-webkit-scrollbar { width: 4px; }
    .detail-body::-webkit-scrollbar-track { background: transparent; }
    .detail-body::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }

    .detail-heading {
      font-size: 16px;
      font-weight: 500;
      color: var(--text);
      line-height: 1.35;
    }
    .detail-divider { border: none; border-top: 1px solid var(--border); }

    .detail-field { display: flex; flex-direction: column; gap: 3px; }
    .detail-label {
      font-family: var(--font-mono);
      font-size: 11.5px;
      color: var(--text3);
      text-transform: uppercase;
      letter-spacing: 0.08em;
    }
    .detail-value {
      font-size: 13px;
      color: var(--text2);
      line-height: 1.5;
      word-break: break-word;
    }
    .detail-value.text {
      color: var(--text);
      font-size: 12px;
      line-height: 1.65;
      max-height: 180px;
      overflow-y: auto;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 9px 12px;
    }

    /* Execution description — the prominent "what to do / where / expected result"
       block shown directly under the task title in the detail panel. Full text,
       never truncated (pre-wrap preserves the source line breaks). Accent left rail
       so it reads as the primary instruction, not just another field. */
    .detail-exec {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-left: 3px solid var(--accent);
      border-radius: var(--radius);
      padding: 10px 12px;
      margin-top: 6px;
    }
    .detail-exec-label {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text3);
      text-transform: uppercase;
      letter-spacing: 0.08em;
      margin-bottom: 5px;
    }
    .detail-exec-body {
      font-size: 13px;
      color: var(--text);
      line-height: 1.6;
      white-space: pre-wrap;
      word-break: break-word;
    }
    /* Linkified URLs in the execution description (linkify()). */
    .detail-exec-body a {
      color: var(--accent);
      text-decoration: underline;
      word-break: break-all;
    }
    .detail-exec-body a:hover { color: var(--text); }
    /* Empty state: muted hint so a task missing its description is visibly flagged. */
    .detail-exec-empty {
      border-left-color: var(--border);
      color: var(--text3);
      font-size: 12px;
      font-style: italic;
    }

    /* ── COMPANY EDITOR ── */
    .company-edit-row {
      display: flex; align-items: center; gap: 6px; position: relative;
    }
    .company-edit-btn {
      background: none; border: none; cursor: pointer;
      color: var(--text3); font-size: 11px; padding: 1px 3px;
      border-radius: 3px; line-height: 1; flex-shrink: 0;
      transition: color 0.15s;
    }
    .company-edit-btn:hover { color: var(--accent); }
    .company-edit-wrap {
      position: relative; width: 100%; margin-top: 4px;
    }
    .company-edit-input {
      width: 100%; background: var(--surface2);
      border: 1px solid var(--accent); border-radius: var(--radius);
      color: var(--text); font-size: 13px; padding: 6px 10px;
      outline: none; font-family: var(--font-body);
    }
    .company-dropdown {
      position: absolute; top: calc(100% + 4px); left: 0; right: 0;
      background: var(--surface2); border: 1px solid var(--border2);
      border-radius: var(--radius); z-index: 200;
      max-height: 200px; overflow-y: auto;
    }
    .company-dropdown-item {
      padding: 8px 12px; cursor: pointer; font-size: 13px; color: var(--text);
      transition: background 0.1s;
    }
    .company-dropdown-item:hover { background: var(--surface3); }
    .company-dropdown-empty {
      padding: 8px 12px; font-size: 12px; color: var(--text3);
    }
    .company-edit-status {
      font-size: 11px; margin-top: 4px; min-height: 16px;
    }
    .company-edit-status.ok  { color: var(--success); }
    .company-edit-status.err { color: var(--danger); }

    .detail-actions {
      padding: 14px 16px;
      padding-bottom: max(14px, env(safe-area-inset-bottom));
      border-top: 1px solid var(--border);
      display: flex;
      flex-direction: column;
      gap: 7px;
      flex-shrink: 0;
    }
    .dp-btn {
      padding: 9px 14px;
      border-radius: var(--radius);
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: 0.07em;
      text-transform: uppercase;
      cursor: pointer;
      border: 1px solid transparent;
      transition: opacity 0.15s;
      text-align: center;
      text-decoration: none;
      display: block;
    }
    .dp-btn:hover { opacity: 0.8; }
    .dp-btn-green  { background: var(--success-dim); color: var(--success); border-color: var(--success); }
    .dp-btn-danger { background: var(--danger-dim);  color: var(--danger);  border-color: var(--danger); }
    .dp-btn-blue   { background: var(--blue-dim);    color: var(--blue);    border-color: var(--blue); }
    .dp-btn-ghost  { background: var(--surface2);    color: var(--text2);   border-color: var(--border); }

    .detail-spinner {
      display: flex; align-items: center; justify-content: center;
      padding: 40px 16px;
      color: var(--text3);
      font-family: var(--font-mono);
      font-size: 12px;
      gap: 10px;
    }
    .sp { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); animation: typingBounce 1.2s infinite; }
    .sp:nth-child(2) { animation-delay: 0.2s; }
    .sp:nth-child(3) { animation-delay: 0.4s; }

    /* list rows inside the panel (Needs Review / Unknown Senders) */
    .dp-list-item {
      padding: 10px 12px;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      cursor: pointer;
      transition: background 0.15s, border-color 0.15s;
      display: flex;
      flex-direction: column;
      gap: 4px;
    }
    .dp-list-item:hover { background: var(--surface2); border-color: var(--border2); }
    .dp-list-name { font-size: 13px; color: var(--text); line-height: 1.3; }
    .dp-list-meta { font-family: var(--font-mono); font-size: 12px; color: var(--text3); }
    .dp-list-action { font-size: 12px; color: var(--text2); line-height: 1.4; margin-top: 2px; }
    /* Contacts browse A–Z bar (hub-stabilization item 4): wrap-friendly, mobile-first
       tap targets. The active letter is highlighted via .contacts-az-on. */
    .contacts-az { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 12px; }
    .contacts-az-btn {
      min-width: 26px; padding: 4px 6px;
      background: var(--surface2); color: var(--text2);
      border: 1px solid var(--border); border-radius: var(--radius);
      font-family: var(--font-mono); font-size: 11px; cursor: pointer;
      transition: background 0.15s, border-color 0.15s, color 0.15s;
    }
    .contacts-az-btn:hover { color: var(--text); border-color: var(--accent); }
    .contacts-az-on { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
    .contacts-browse-meta {
      font-family: var(--font-mono); font-size: 10px; color: var(--text3);
      margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.04em;
    }
    #contactsBrowseList { display: flex; flex-direction: column; gap: 6px; }
    /* Click-to-call tel: links (TKT-81) — inherit surrounding size, read as a link. */
    .tel-link { color: var(--blue); text-decoration: none; }
    .tel-link:hover { text-decoration: underline; }
    /* mailto: links in the Contacts panel (TKT-111) — same affordance as tel: links. */
    .mail-link { color: var(--blue); text-decoration: none; }
    .mail-link:hover { text-decoration: underline; }
    /* Contact detail (TKT-111): Role(s) chips + the main/mobile phone tag. */
    .contact-role-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
    .contact-role-chip {
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: 999px;
      padding: 2px 10px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 11px;
      letter-spacing: 0.04em;
      color: var(--text2);
      white-space: nowrap;
    }
    .contact-phone-tag {
      font-family: var(--font-display);
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      color: var(--text3);
      margin-left: 4px;
    }

    /* ── VERSION TAG ── */
    .version-tag {
      position: fixed;
      bottom: 10px;
      /* bottom-LEFT: the assistant dock FAB now owns the bottom-right corner */
      left: max(14px, env(safe-area-inset-left));
      right: auto;
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text3);
      opacity: 0.5;
      pointer-events: none;
      z-index: 50;
      letter-spacing: 0.05em;
    }

    /* ── QB DOCUMENT PROCESSOR ── */
    .invoices-toolbar {
      padding: 6px 12px;
      display: flex;
      align-items: center;
      gap: 10px;
      border-bottom: 1px solid var(--border);
    }

    .btn-deploy-iif {
      background: var(--accent);
      color: #000;
      border: none;
      border-radius: var(--radius);
      padding: 5px 12px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 13px;
      letter-spacing: 0.04em;
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .btn-deploy-iif:hover { filter: brightness(1.1); }
    .btn-deploy-iif.disabled, .btn-deploy-iif:disabled { background: var(--surface3); color: var(--text3); cursor: default; }

    .iif-count {
      background: rgba(0,0,0,0.3);
      border-radius: 10px;
      padding: 1px 6px;
      font-size: 11px;
    }

    .qb-badge {
      font-size: 12px;
      width: 18px;
      text-align: center;
      flex-shrink: 0;
    }

    .staging-detail-body {
      padding: 14px 16px;
      overflow-y: auto;
      flex: 1;
    }

    .staging-status-row {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-bottom: 12px;
    }

    .staging-status-badge {
      font-size: 11px;
      font-weight: 600;
      padding: 2px 8px;
      border-radius: 10px;
      background: var(--surface3);
      color: var(--text2);
    }

    .staging-confidence { font-size: 11px; color: var(--text3); }

    .staging-fields { margin-bottom: 12px; }

    .field-row {
      display: flex;
      gap: 8px;
      padding: 3px 0;
      font-size: 13px;
      border-bottom: 1px solid var(--border);
    }

    .field-label {
      width: 70px;
      flex-shrink: 0;
      color: var(--text3);
      font-size: 11px;
      padding-top: 2px;
    }

    .total-row { font-weight: 600; color: var(--accent); }

    .staging-flags {
      background: var(--accent-dim);
      border: 1px solid var(--accent-glow);
      border-radius: var(--radius);
      padding: 8px 10px;
      font-size: 12px;
      margin-bottom: 12px;
      color: var(--warning);
    }

    .staging-lines-section { margin-bottom: 12px; }

    .staging-lines-table {
      width: 100%;
      border-collapse: collapse;
      font-size: 11px;
      margin-top: 6px;
    }

    .staging-lines-table th {
      text-align: left;
      padding: 3px 4px;
      color: var(--text3);
      border-bottom: 1px solid var(--border2);
    }

    .staging-lines-table td {
      padding: 3px 4px;
      border-bottom: 1px solid var(--border);
    }

    .staging-lines-table .fuzzy-match { color: var(--warning); }
    .staging-lines-table .unmatched   { color: var(--danger); }

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

    .btn-stage, .btn-unstage {
      background: var(--accent);
      color: #000;
      border: none;
      border-radius: var(--radius);
      padding: 6px 12px;
      font-size: 12px;
      font-weight: 600;
      cursor: pointer;
    }

    .btn-unstage { background: var(--surface3); color: var(--text2); }

    .btn-notion-link {
      background: var(--surface3);
      color: var(--text2);
      border: 1px solid var(--border2);
      border-radius: var(--radius);
      padding: 5px 10px;
      font-size: 12px;
      text-decoration: none;
      cursor: pointer;
    }

    .btn-mark-done {
      background: transparent;
      color: var(--text3);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 5px 10px;
      font-size: 12px;
      cursor: pointer;
    }

    /* ── NOTIFICATIONS BADGE (header) ── */
    .notif-badge-btn {
      position: relative;
      display: flex; align-items: center; justify-content: center;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 4px 8px;
      cursor: pointer;
      transition: border-color 0.15s;
    }
    .notif-badge-btn:hover { border-color: var(--border2); }

    .notif-badge {
      font-family: var(--font-mono);
      font-size: 11px;
      font-weight: 500;
      color: var(--text3);
      min-width: 20px;   /* fits a 3-digit / "999+" count without clipping */
      text-align: center;
    }
    .notif-badge.notif-badge-has-items { color: var(--warning); }

    .notif-stuck-dot {
      position: absolute;
      top: 3px; right: 3px;
      width: 6px; height: 6px;
      border-radius: 50%;
      background: var(--danger);
    }

    .notif-tab-count {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--warning);
    }

    /* ── APPROVALS BADGE (header, TKT-1280) — transactions waiting for your OK ── */
    .aprv-header-btn {
      display: flex; align-items: center; gap: 5px;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 4px 8px;
      cursor: pointer;
      font-size: 11px;
      color: var(--text3);
    }
    .aprv-header-btn[hidden] { display: none; }
    .aprv-header-btn:hover { border-color: var(--border2); }
    .aprv-header-count { font-family: var(--font-mono); font-weight: 500; min-width: 14px; text-align: center; }
    .aprv-header-btn.aprv-header-has-items { border-color: var(--warning); color: var(--warning); }
    @media (max-width: 640px) { .aprv-header-label { display: none; } }

    /* ── QUICKBOOKS-DOWN BANNER (TKT-861) ──
       Full-width, above the header, on every screen. Craig: "an alert that pops up, it's
       unmistakable, I don't have to look at something and then make a judgment call." So it
       is deliberately loud — this is the surface that has to make a third silent multi-day
       outage impossible, and a tasteful one would be missed. It carries no link and no
       button: the Hub feed renders escaped plain text and a phone cannot act on an anchor. */
    /* TKT-752: the newer-version nudge — same shell slot as the QuickBooks banner, calmer colour: it is an offer, not an outage. */
    .version-nudge { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 6px 12px; padding: 10px 14px; border: 1px solid #2e86c1; border-radius: 8px; background: rgba(46, 134, 193, .12); }
    .version-nudge-title { font-weight: 700; }
    .version-nudge-detail { flex: 1 1 320px; opacity: .85; }
    .version-nudge-reload { min-height: 40px; padding: 0 16px; border: 1px solid #2e86c1; border-radius: 6px; background: #2e86c1; color: #fff; font-weight: 600; cursor: pointer; }
    .version-nudge-reload:hover { filter: brightness(1.1); }
    .qbdown-banner {
      padding: 10px 16px;
      border-bottom: 2px solid rgba(231,76,60,0.55);
      background: rgba(231,76,60,0.14);
      color: var(--text);
      font-size: 13px;
      line-height: 1.45;
    }
    .qbdown-banner[hidden] { display: none; }
    /* STALE is amber, not red: "nothing has come through for N hours" may be a quiet
       weekend. DOWN is red because the probe actually failed. Two triggers, one banner,
       but the reader can still tell at a glance which one fired. */
    .qbdown-banner.qbdown-stale {
      border-bottom-color: rgba(243,156,18,0.55);
      background: rgba(243,156,18,0.12);
    }
    .qbdown-title { font-weight: 700; font-size: 14px; margin-bottom: 3px; }
    .qbdown-cause { opacity: 0.92; }
    .qbdown-do    { margin-top: 4px; opacity: 0.92; }
    /* TKT-1157 criterion 4: a post QuickBooks refused, waiting for a person — red like DOWN, because it needs a person. */
    .qbrefused-banner {
      padding: 10px 16px;
      border-bottom: 2px solid rgba(231,76,60,0.55);
      background: rgba(231,76,60,0.14);
      color: var(--text);
      font-size: 13px;
      line-height: 1.45;
    }
    .qbrefused-banner[hidden] { display: none; }
    .qbrefused-title { font-weight: 700; font-size: 14px; margin-bottom: 3px; }
    .qbrefused-do    { opacity: 0.92; }
    .qbrefused-open  { margin-top: 6px; min-height: 36px; padding: 0 14px; border: 1px solid rgba(231,76,60,0.7); border-radius: 6px; background: transparent; color: var(--text); font-weight: 600; cursor: pointer; }

    /* ── NOTIFICATIONS PANEL ── */
    .notif-backlog-banner {
      display: flex; align-items: center; justify-content: space-between;
      padding: 8px 14px;
      background: rgba(243,156,18,0.1);
      border: 1px solid rgba(243,156,18,0.35);
      border-radius: var(--radius);
      margin-bottom: 10px;
      font-size: 12px;
      color: var(--warning);
    }
    .notif-banner-close {
      background: none; border: none; color: var(--warning); cursor: pointer;
      font-size: 14px; padding: 0 4px; line-height: 1;
    }

    .notif-panel-header {
      display: flex; flex-direction: column; gap: 8px;
      padding: 12px 0;
      margin-bottom: 4px;
    }

    .notif-filter-row {
      display: flex; flex-wrap: wrap; gap: 6px;
      align-items: center;
    }

    .notif-chip-group {
      display: flex; align-items: center; gap: 4px;
    }
    .notif-chip-label {
      font-family: var(--font-mono);
      font-size: 10px;
      color: var(--text3);
      letter-spacing: 0.05em;
      white-space: nowrap;
    }
    .notif-chip {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: 10px;
      padding: 2px 9px;
      font-size: 11px;
      color: var(--text2);
      cursor: pointer;
      transition: all 0.12s;
      white-space: nowrap;
    }
    .notif-chip:hover { border-color: var(--border2); color: var(--text); }
    .notif-chip.notif-chip-active {
      background: var(--accent-dim);
      border-color: var(--accent);
      color: var(--accent);
    }

    .notif-search-input {
      width: 100%;
      background: var(--surface2);
      border: 1px solid var(--border2);
      border-radius: var(--radius);
      color: var(--text);
      font-family: var(--font-body);
      font-size: 12px;
      padding: 6px 10px;
      outline: none;
    }
    .notif-search-input:focus { border-color: var(--accent); }
    .notif-search-input::placeholder { color: var(--text3); }

    .notif-clear-filters-btn {
      background: none; border: none;
      color: var(--blue); cursor: pointer;
      font-size: 12px; text-decoration: underline; padding: 0;
    }

    /* ── NOTIFICATION ROWS ── */
    .notif-list {
      display: flex; flex-direction: column;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
    }

    .notif-empty-msg {
      padding: 20px 16px;
      text-align: center;
      color: var(--text3);
      font-size: 13px;
    }

    .notif-row {
      display: grid;
      grid-template-columns: 20px 120px 1fr 130px 60px 32px auto;
      align-items: center;
      gap: 8px;
      padding: 8px 14px;
      border-bottom: 1px solid var(--border);
      cursor: pointer;
      transition: background 0.12s;
      position: relative;
    }
    .notif-row:last-child { border-bottom: none; }
    .notif-row:hover { background: var(--surface2); }

    .notif-row-sev { font-size: 13px; flex-shrink: 0; }
    .notif-row-producer {
      font-family: var(--font-mono); font-size: 10px; color: var(--text2);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .notif-row-reason {
      font-size: 12px; color: var(--text);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .notif-row-subject {
      font-size: 11px; color: var(--text3);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .notif-row-age {
      font-family: var(--font-mono); font-size: 10px;
      color: var(--text3); text-align: right; white-space: nowrap;
    }
    .notif-row-recur {
      font-family: var(--font-mono); font-size: 10px;
      color: var(--warning); text-align: center;
    }

    .notif-row-actions {
      display: flex; gap: 3px;
      opacity: 0; transition: opacity 0.1s;
    }
    .notif-row:hover .notif-row-actions { opacity: 1; }

    @media (max-width: 767px) {
      .notif-row-actions { display: none; }
      .notif-row { grid-template-columns: 20px 1fr auto; }
      .notif-row-producer, .notif-row-subject, .notif-row-age, .notif-row-recur { display: none; }
    }

    .notif-action-btn {
      width: 22px; height: 22px;
      border-radius: 4px;
      border: 1px solid var(--border2);
      background: transparent;
      color: var(--text3);
      cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      font-size: 11px; line-height: 1;
      transition: all 0.12s;
    }
    .notif-btn-ack:hover     { border-color: var(--success); color: var(--success); background: var(--success-dim); }
    .notif-btn-resolve:hover { border-color: var(--blue);    color: var(--blue);    background: var(--blue-dim); }
    .notif-btn-dismiss:hover { border-color: var(--danger);  color: var(--danger);  background: var(--danger-dim); }
    .notif-btn-link:hover    { border-color: var(--accent);  color: var(--accent);  background: var(--accent-dim); }

    /* Fade-and-remove animation */
    .notif-row-fading {
      opacity: 0.35;
      text-decoration: line-through;
      transition: opacity 1.5s ease;
      pointer-events: none;
    }

    /* ── NOTIFICATIONS MODAL ── */
    .notif-modal-overlay {
      position: fixed; inset: 0;
      background: rgba(0,0,0,0.65);
      z-index: 500;
    }

    /* The `hidden` attribute must win over the modal's `display:flex` below. A class
       selector outranks the UA `[hidden]{display:none}` rule, so without this the empty
       modal renders centered on page load. Keep these alongside the rules they override. */
    .notif-modal[hidden],
    .notif-modal-overlay[hidden] { display: none; }

    .notif-modal {
      position: fixed;
      top: 50%; left: 50%;
      transform: translate(-50%, -50%);
      width: 520px; max-width: calc(100vw - 24px);
      max-height: calc(100vh - 40px);
      max-height: calc(100dvh - 40px);   /* keep the modal inside the iOS visual viewport */
      background: var(--surface);
      border: 1px solid var(--border2);
      border-radius: 8px;
      z-index: 501;
      display: flex; flex-direction: column;
      overflow: hidden;
      box-shadow: 0 20px 60px rgba(0,0,0,0.55);
    }

    .notif-modal-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 12px 16px;
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
    }

    .notif-modal-badges { display: flex; gap: 8px; align-items: center; }

    .notif-modal-close {
      background: none; border: 1px solid var(--border);
      border-radius: var(--radius); padding: 3px 7px;
      color: var(--text2); cursor: pointer; font-size: 13px;
      transition: all 0.12s;
    }
    .notif-modal-close:hover { border-color: var(--border2); color: var(--text); }

    .notif-modal-body {
      flex: 1; overflow-y: auto; padding: 16px;
      display: flex; flex-direction: column; gap: 12px;
    }
    .notif-modal-body::-webkit-scrollbar { width: 4px; }
    .notif-modal-body::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }

    .notif-modal-section { display: flex; flex-direction: column; gap: 4px; }
    .notif-modal-label {
      font-family: var(--font-mono); font-size: 10px;
      color: var(--text3); text-transform: uppercase; letter-spacing: 0.08em;
    }

    .notif-modal-action-section { display: flex; flex-direction: column; gap: 4px; }
    .notif-modal-action-text {
      font-size: 13px; color: var(--text); line-height: 1.55;
      background: var(--surface2); border: 1px solid var(--border);
      border-radius: var(--radius); padding: 8px 10px;
    }

    .notif-modal-links { display: flex; flex-wrap: wrap; gap: 6px; }
    .notif-modal-link {
      background: var(--blue-dim); border: 1px solid rgba(74,158,255,0.25);
      border-radius: var(--radius); padding: 3px 10px;
      color: var(--blue); font-size: 11px; cursor: pointer;
      text-decoration: none; transition: opacity 0.12s;
    }
    .notif-modal-link:hover { opacity: 0.8; }

    .notif-payload-details {
      background: var(--surface2); border: 1px solid var(--border);
      border-radius: var(--radius); overflow: hidden;
    }
    .notif-payload-details > summary {
      padding: 6px 10px; cursor: pointer;
      font-family: var(--font-mono); font-size: 11px; color: var(--text3);
      user-select: none;
    }
    .notif-payload-pre {
      padding: 8px 10px; margin: 0;
      font-family: var(--font-mono); font-size: 10px; color: var(--text2);
      line-height: 1.5; overflow-x: auto; max-height: 160px;
      white-space: pre; border-top: 1px solid var(--border);
    }

    .notif-modal-textarea {
      background: var(--surface2); border: 1px solid var(--border2);
      border-radius: var(--radius); color: var(--text);
      font-family: var(--font-body); font-size: 12px;
      padding: 7px 10px; resize: vertical; outline: none;
      min-height: 60px; width: 100%; box-sizing: border-box;
    }
    .notif-modal-textarea:focus { border-color: var(--accent); }
    .notif-modal-textarea-sm { min-height: 40px; }

    .notif-modal-lifecycle {
      display: flex; gap: 8px; flex-wrap: wrap;
      border-top: 1px solid var(--border); padding-top: 10px;
    }

    .notif-modal-btn {
      padding: 7px 14px;
      border-radius: var(--radius);
      font-family: var(--font-display); font-weight: 600;
      font-size: 12px; letter-spacing: 0.06em;
      text-transform: uppercase; cursor: pointer; border: 1px solid transparent;
      transition: opacity 0.12s;
    }
    .notif-modal-btn:hover { opacity: 0.85; }
    .notif-btn-ack-modal     { background: var(--success-dim); color: var(--success); border-color: var(--success); }
    .notif-btn-resolve-modal { background: var(--blue-dim);    color: var(--blue);    border-color: var(--blue); }
    .notif-btn-dismiss-modal { background: var(--danger-dim);  color: var(--danger);  border-color: var(--danger); }
    .notif-btn-ghost         { background: var(--surface3);    color: var(--text2);   border-color: var(--border2); }

    .notif-modal-footer {
      display: flex; flex-wrap: wrap; gap: 10px;
      padding: 10px 0 2px;
      font-family: var(--font-mono); font-size: 10px; color: var(--text3);
      border-top: 1px solid var(--border);
    }

    /* Severity / Status badge pills */
    .notif-sev-badge, .notif-st-badge {
      font-size: 11px; font-weight: 600;
      padding: 2px 8px; border-radius: 10px;
    }
    .notif-sev-critical { background: var(--danger-dim);  color: var(--danger); }
    .notif-sev-warn     { background: var(--accent-dim);  color: var(--warning); }
    .notif-sev-info     { background: var(--surface3);    color: var(--text2); }
    .notif-st-pending   { background: var(--accent-dim);  color: var(--accent); }
    .notif-st-ack       { background: var(--blue-dim);    color: var(--blue); }
    .notif-st-resolved  { background: var(--success-dim); color: var(--success); }
    .notif-st-dismissed { background: var(--surface3);    color: var(--text3); }

    .notif-ellipsis {
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }

    /* ── NAV RESTRUCTURE: first-class pages (Intake Review / Tasks / Cases / Assistant) ──
       Added with the DASHBOARD·INTAKE REVIEW·TASKS·CASES·ASSISTANT·NOTIFICATIONS nav.
       Reuses the existing surface/border/radius language so the new pages match the Hub. */

    /* Intake Review page — hosts the hub-intake-review.js queue + detail flow full-pane.
       The queue/detail markup reuses .dp-list-item / .dp-btn / .detail-spinner (already
       styled for the slide-over), so this only needs the page frame. */
    .ir-page {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      display: flex;
      flex-direction: column;
      min-height: 360px;
      overflow: hidden;
    }
    .ir-page-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 13px 16px;
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
    }
    .ir-page-title {
      font-family: var(--font-display);
      font-weight: 600; font-size: 14px;
      color: var(--text);
    }
    /* Six card-panels (service-call, rentals, work-orders, record-need, quote-capture, rfq) wrap their
       title in .ir-page-head — a class that had NO rules, so the title sat flush against the card top and
       the SECTION-LABEL eyebrow above the card (margin-bottom:-8px, sized for the module grid) printed
       over it: "SERVICE CALL" on top of "Service Call". Craig's iPad, 2026-09-24. Styled like the
       .ir-page-header the other 33 panels use. */
    .card > .ir-page-head {
      display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
      padding: 8px 0 10px; margin: 0 0 12px;   /* 8px top: the eyebrow above the card pulls -8px into it */
      border-bottom: 1px solid var(--border);
    }
    /* A section-label INSIDE a rendered body is a heading over a row of fields, not an eyebrow over a
       module grid: the grid's -8px pull is what ran "PARTS USED / LEFT AT THE CUSTOMER" into the Part #
       and Qty labels and put the note input on top of "CALL NOTES". */
    #serviceCallBody .section-label, .card .ir-page-body .section-label, #recordNeedBody .section-label {
      margin: 14px 0 8px;
    }
    .ir-page-body { flex: 1; overflow-y: auto; padding: 12px 16px; }
    .ir-page-body::-webkit-scrollbar { width: 4px; }
    .ir-page-body::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }
    /* Record-detail action buttons: compact 3-column grid (intake-review-proposal-transparency)
       — was a full-width flex-wrap list that ran the full screen height. Each button fills its
       cell so the grid stays even regardless of label length. */
    .ir-page-actions {
      display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
      padding: 12px 16px;
      border-top: 1px solid var(--border);
      flex-shrink: 0;
    }
    .ir-page-actions .dp-btn { width: 100%; }
    .ir-page-actions:empty { display: none; }

    /* Assistant page — the Master Control Agent chat plus Craig's most-used controls
       (Voice Relay + Coordination Channel). DOM order is chat → relay → channel (so the
       dock teleport's #controlAgentPanel is found and re-homed predictably), but CSS
       `order` floats relay + channel ABOVE the chat so they sit at the top of the page —
       reachable without scrolling past the chat (hub-ui-followup). Each is display:none
       until its flag is on, so an off card adds no gap. (The "Prioritized Actions — Coming
       soon" placeholder was removed as dead space in the same brief.) */
    .assistant-page { display: flex; flex-direction: column; gap: 14px; }
    .assistant-page > #voiceRelayPanel { order: 1; }
    .assistant-page > #groupChatPanel  { order: 2; }
    .assistant-page > #controlAgentPanel { order: 3; }

    /* Cases page — stub. Mirrors the COMING SOON module-card treatment. */
    .stub-page {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 28px 24px;
      max-width: 720px;
    }
    .stub-page-title {
      font-family: var(--font-display);
      font-weight: 600; font-size: 16px;
      color: var(--text);
      margin-bottom: 4px;
    }
    .stub-page-status {
      font-size: 11px; font-weight: 600;
      color: var(--text3);
      letter-spacing: 0.08em;
      margin-bottom: 14px;
    }
    .stub-page-desc { font-size: 13px; color: var(--text2); line-height: 1.6; }

    /* ── CONTROLS (Toggle Board) ── */
    .ctrl-board { max-width: 900px; margin: 0 auto; padding: 8px 0 40px; }
    .ctrl-title {
      font-family: var(--font-display);
      font-size: 20px; font-weight: 700; letter-spacing: 0.06em;
      text-transform: uppercase; color: var(--accent);
      margin-bottom: 14px;
    }
    .ctrl-head { margin-bottom: 18px; }
    /* Active QuickBooks connection banner (read-routing indicator). TEST is calm; LIVE is
       highlighted so the operator can never mistake which company file is being hit. */
    .ctrl-qbtarget { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
      font-size: 13px; padding: 8px 12px; border-radius: 8px; margin-bottom: 12px;
      border: 1px solid var(--line); background: var(--bg2); color: var(--text2); }
    .ctrl-qbtarget-label { color: var(--text2); }
    .ctrl-qbtarget strong { color: var(--text); letter-spacing: .03em; }
    .ctrl-qbtarget-test { border-color: var(--line); }
    .ctrl-qbtarget-live { border-color: #d98324; background: rgba(217, 131, 36, .12); }
    .ctrl-qbtarget-live strong { color: #d98324; }
    .ctrl-qbtarget-unconfigured, .ctrl-qbtarget-unknown { border-color: #c0392b; background: rgba(192, 57, 43, .10); }
    .ctrl-qbtarget-warn { color: #c0392b; font-weight: 600; }
    /* Entity-mirror (vendor/customer list) staleness banner + rebuild (TKT-223). */
    .ctrl-entitymirror { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
      font-size: 13px; padding: 8px 12px; border-radius: 8px; margin-bottom: 12px;
      border: 1px solid var(--line); background: var(--bg2); color: var(--text2); }
    .ctrl-entitymirror-label { color: var(--text2); }
    .ctrl-entitymirror strong { color: var(--text); }
    .ctrl-entitymirror-stale { border-color: #d98324; background: rgba(217, 131, 36, .12); }
    .ctrl-entitymirror-missing, .ctrl-entitymirror-unknown { border-color: #c0392b; background: rgba(192, 57, 43, .10); }
    .ctrl-entitymirror-warn { color: #c0392b; font-weight: 600; }
    .ctrl-entitymirror-origin { flex-basis: 100%; font-size: 0.82em; color: #7f8c8d; word-break: break-all; }
    .ctrl-entitymirror .ctrl-refresh { margin-left: auto; }
    .ctrl-head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
    .ctrl-legend { display: flex; flex-direction: column; gap: 5px; }
    .ctrl-legend-item { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text2); }
    .ctrl-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
    .ctrl-dot-critical { background: var(--danger); }
    .ctrl-dot-normal { background: var(--success); }
    .ctrl-refresh {
      background: var(--surface3); border: 1px solid var(--border2); color: var(--text2);
      border-radius: var(--radius); padding: 6px 12px; font-size: 12px; cursor: pointer;
      font-family: var(--font-body);
    }
    .ctrl-refresh:hover { color: var(--text); border-color: var(--accent); }
    .ctrl-head-btns { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
    /* Flag search (TKT-612). Wide enough to hold a phrase, because the point is searching by
       DESCRIPTION ("photo thumbnails ahead of time") and not only by key. */
    .ctrl-search-input {
      min-width: 260px; flex: 0 1 320px;
      background: var(--surface3); border: 1px solid var(--border2); color: var(--text);
      border-radius: 999px; padding: 5px 12px; font-size: 12px; font-family: var(--font-body);
    }
    .ctrl-search-input::placeholder { color: var(--text3); }
    .ctrl-search-input:focus { outline: none; border-color: var(--accent); }
    .ctrl-search-summary {
      font-size: 12px; color: var(--text2); font-family: var(--font-mono);
      margin: 0 0 10px; padding: 6px 10px;
      background: var(--surface3); border-left: 2px solid var(--accent); border-radius: 4px;
    }

    /* ── Collapsible groups (PASS 2a master→child tree) ──
       Each group is a clickable header (chevron + name + count) over a body that
       collapses to zero height. Live groups open by default; the dead "Legacy /
       Inactive" group is collapsed and calmly styled so it never looks armable. */
    .ctrl-group { margin-bottom: 16px; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
    .ctrl-group-head {
      display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none;
      padding: 11px 14px; background: var(--surface2); border-bottom: 1px solid var(--border);
    }
    .ctrl-group-head:hover { background: var(--surface3); }
    .ctrl-group.collapsed .ctrl-group-head { border-bottom-color: transparent; }
    .ctrl-chevron { color: var(--text3); font-size: 12px; transition: transform 0.15s; transform: rotate(90deg); }
    .ctrl-group.collapsed .ctrl-chevron { transform: rotate(0deg); }
    .ctrl-group-title {
      font-family: var(--font-display);
      font-size: 13px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
      color: var(--text2); flex: 1 1 auto;
    }
    .ctrl-group-count {
      font-family: var(--font-mono); font-size: 11px; color: var(--text3);
      background: var(--surface3); border: 1px solid var(--border); border-radius: 999px; padding: 1px 9px;
    }
    .ctrl-group-body { padding: 4px 12px 8px; }
    .ctrl-group.collapsed .ctrl-group-body { display: none; }
    .ctrl-group-note { font-size: 12px; color: var(--text3); font-style: italic; padding: 8px 2px 4px; }
    /* Reserved slot for PASS 2b (per-lane QB TEST/LIVE switches) — visible, inert seam. */
    .ctrl-seam {
      font-size: 11.5px; color: var(--text3); margin: 6px 2px 2px; padding: 6px 10px;
      border: 1px dashed var(--border2); border-radius: var(--radius); background: var(--surface2);
    }

    /* Legacy / Inactive group: dashed + dimmed so dead flags can't be mistaken for live. */
    .ctrl-group-legacy { border-style: dashed; opacity: 0.85; }
    .ctrl-group-legacy .ctrl-group-head { background: transparent; }
    .ctrl-group-legacy .ctrl-group-title { color: var(--text3); }

    .ctrl-row {
      display: flex; align-items: center; justify-content: space-between; gap: 16px;
      padding: 11px 12px; border-radius: var(--radius);
      border: 1px solid transparent;
    }
    .ctrl-row + .ctrl-row { border-top: 1px solid var(--border); border-radius: 0; }
    .ctrl-row:hover { background: var(--surface2); }
    .ctrl-row-critical { }
    /* A row that governs others (a master / parent) gets a subtle accent rail. */
    .ctrl-row-master { border-left: 3px solid var(--accent-glow); }
    /* Governed-off child: greyed, and its toggle visibly can't be armed. */
    .ctrl-row-governed { opacity: 0.55; }
    .ctrl-row-governed:hover { background: transparent; }
    /* Legacy row: dimmed, dashed top rule, never an armable switch. */
    .ctrl-row-legacy { opacity: 0.6; }
    .ctrl-row-legacy:hover { background: transparent; }
    .ctrl-legacy-state {
      font-family: var(--font-mono); font-size: 11px; font-weight: 600; letter-spacing: 0.05em;
      color: var(--text3); background: var(--surface2); border: 1px dashed var(--border2);
      border-radius: 4px; padding: 2px 8px; white-space: nowrap;
    }
    .ctrl-legacy-state.on { color: var(--warn, #d98324); }

    /* Pills: master / governed / legacy markers on the name line. */
    .ctrl-pill {
      font-size: 9px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
      border-radius: 3px; padding: 1px 6px; white-space: nowrap;
    }
    .ctrl-pill-master { color: var(--accent); background: var(--accent-dim); border: 1px solid var(--accent-glow); }
    .ctrl-pill-governed { color: var(--text3); background: var(--surface3); border: 1px solid var(--border2); text-transform: none; letter-spacing: 0; }
    .ctrl-pill-legacy { color: var(--text3); background: var(--surface2); border: 1px dashed var(--border2); text-transform: none; letter-spacing: 0; }
    /* WAITING FOR INPUT (TKT-295): built module, no feeder wired — grayed, non-armable. */
    .ctrl-pill-waiting { color: var(--text3); background: var(--surface2); border: 1px dashed var(--border2); }
    .ctrl-row-waiting { opacity: 0.6; }
    .ctrl-row-waiting:hover { background: transparent; }
    .ctrl-waiting-state { color: var(--text3); border-style: dashed; }

    .ctrl-row-main { min-width: 0; }
    .ctrl-name {
      font-family: var(--font-mono); font-size: 13px; color: var(--text);
      display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    }
    .ctrl-lock { font-size: 12px; }
    .ctrl-desc { font-size: 12px; color: var(--text2); margin-top: 3px; line-height: 1.45; }
    /* Plain-English operator note (flag-observability) — set apart from the technical desc. */
    .ctrl-opnote {
      font-size: 12px; color: var(--text); margin-top: 4px; line-height: 1.45;
      padding-left: 8px; border-left: 2px solid var(--accent-glow);
    }
    /* TKT-1157 criterion 7: a QuickBooks path's record, beside its VERIFY switch. */
    .ctrl-record {
      font-size: 12px; color: var(--text2); margin-top: 4px; line-height: 1.45;
      padding-left: 8px; border-left: 2px solid var(--border2); overflow-wrap: anywhere;
    }
    .ctrl-ovr-badge {
      font-size: 9px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
      color: var(--accent); background: var(--accent-dim);
      border: 1px solid var(--accent-glow); border-radius: 3px; padding: 1px 5px;
    }
    .ctrl-row-ctl { display: flex; align-items: center; gap: 10px; flex: none; }
    .ctrl-state { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; width: 26px; text-align: left; }
    .ctrl-state.on { color: var(--success); }
    .ctrl-state.off { color: var(--text3); }

    /* Toggle switch */
    .ctrl-toggle {
      position: relative; width: 42px; height: 22px; border-radius: 999px;
      background: var(--surface3); border: 1px solid var(--border2);
      cursor: pointer; padding: 0; transition: background 0.15s, border-color 0.15s; flex: none;
    }
    .ctrl-toggle .ctrl-knob {
      position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
      background: var(--text2); transition: transform 0.15s, background 0.15s;
    }
    .ctrl-toggle.on { background: var(--success-dim); border-color: var(--success); }
    .ctrl-toggle.on .ctrl-knob { transform: translateX(20px); background: var(--success); }
    .ctrl-toggle.on.critical { background: var(--danger-dim); border-color: var(--danger); }
    .ctrl-toggle.on.critical .ctrl-knob { background: var(--danger); }
    .ctrl-toggle:hover { border-color: var(--accent); }
    /* Governed-off toggle that cannot be armed: no pointer, no hover affordance. */
    .ctrl-toggle:disabled { cursor: not-allowed; opacity: 0.5; }
    .ctrl-toggle:disabled:hover { border-color: var(--border2); }
    .ctrl-toggle.governed { border-style: dashed; }

    .ctrl-group-ro .ctrl-row-ro:hover { background: transparent; }
    .ctrl-roval { font-family: var(--font-mono); font-size: 12px; color: var(--text2); background: var(--surface2); padding: 2px 7px; border-radius: 4px; }

    .ctrl-footer {
      margin-top: 24px; padding: 12px 14px; border-radius: var(--radius);
      background: var(--surface2); border: 1px solid var(--border);
      font-size: 12px; color: var(--text2); line-height: 1.6;
    }
    .ctrl-footer code { font-family: var(--font-mono); color: var(--accent); font-size: 11px; }

    /* ── TICKETS (AE_Tasks review + update, TKT-96) ──
       Hosted in the .ir-page frame (responsive + scrollable). Rows reuse .dp-list-item;
       detail reuses .detail-field / .detail-label / .detail-value / .detail-heading. Only
       the toolbar, status badges, filter chips, and the small detail controls are new. */
    .tk-toolbar {
      display: flex; align-items: center; justify-content: space-between;
      gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
    }
    .tk-chips { display: flex; gap: 6px; flex-wrap: wrap; }
    .tk-chip {
      background: var(--surface3); border: 1px solid var(--border2); color: var(--text2);
      border-radius: 999px; padding: 5px 12px; font-size: 12px; cursor: pointer;
      font-family: var(--font-body);
    }
    .tk-chip:hover { color: var(--text); border-color: var(--accent); }
    .tk-chip-on { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
    /* Find a ticket by number or words (TKT-597). Sits between the chips and the right-hand
       counts, and takes the slack so it stays usable as the toolbar wraps on a narrow pane. */
    .tk-search { display: flex; align-items: center; gap: 6px; flex: 1 1 240px; min-width: 200px; }
    .tk-search-input {
      flex: 1 1 auto; min-width: 0;
      background: var(--surface3); border: 1px solid var(--border2); color: var(--text);
      border-radius: 999px; padding: 5px 12px; font-size: 12px; font-family: var(--font-body);
    }
    .tk-search-input::placeholder { color: var(--text3); }
    .tk-search-input:focus { outline: none; border-color: var(--accent); color: var(--text); }
    .tk-search-clear { padding: 5px 10px; line-height: 1; }
    /* While a search is running the chips are not filtering anything — a lit chip would claim the
       results are narrowed by it. Faded, not disabled: clicking one is still how you leave a search. */
    .tk-chips-idle { opacity: 0.45; }
    .tk-chips-idle:hover { opacity: 1; }
    .tk-toolbar-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
    .tk-count { font-size: 12px; color: var(--text2); font-family: var(--font-mono); }

    .tk-list { display: flex; flex-direction: column; gap: 6px; }
    .tk-row { cursor: pointer; }
    .tk-row-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
    .tk-row-title { font-size: 13px; }
    /* Outline tree (hub-stabilization item 6): one-level child indent, a faded context
       parent (.tk-row-dim), and the parent "N of M open" roll-up pill. Indent is shallow
       and tightens further on small screens (see the mobile breakpoint below). */
    .tk-child { margin-left: 22px; border-left: 2px solid var(--border2); }
    .tk-row-dim { opacity: 0.55; }
    .tk-rollup {
      font-family: var(--font-mono); font-size: 10px; color: var(--text3);
      border: 1px solid var(--border2); border-radius: 3px; padding: 1px 6px; margin-left: auto;
    }
    .tk-ticketid { font-family: var(--font-mono); font-size: 12px; color: var(--accent); font-weight: 500; }
    .tk-ticketid-lg { font-size: 14px; }
    .tk-pri, .tk-type {
      font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
      color: var(--text3); border: 1px solid var(--border2); border-radius: 3px; padding: 1px 6px;
    }

    .tk-badge {
      font-size: 10px; font-weight: 700; letter-spacing: 0.04em;
      border-radius: 3px; padding: 2px 7px; white-space: nowrap;
    }
    .tk-badge-accent { color: var(--accent);  background: var(--accent-dim);  border: 1px solid var(--accent-glow); }
    .tk-badge-blue   { color: var(--blue);    background: var(--blue-dim);    border: 1px solid var(--blue); }
    .tk-badge-green  { color: var(--success); background: var(--success-dim); border: 1px solid var(--success); }
    .tk-badge-danger { color: var(--danger);  background: var(--danger-dim);  border: 1px solid var(--danger); }
    .tk-badge-open   { color: var(--text2);   background: var(--surface3);    border: 1px solid var(--border2); }
    .tk-badge-muted  { color: var(--text3);   background: var(--surface2);    border: 1px solid var(--border); }

    .tk-back { margin-bottom: 10px; font-size: 11px; }
    .tk-detail-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
    .tk-pre { white-space: pre-wrap; line-height: 1.5; }

    /* Acceptance-criteria ledger (TKT-578): Open / Done read as distinct states, and the
       closeability verdict is stated rather than left to be inferred from an empty box. */
    .tk-ac-open   { border-left: 3px solid var(--warn, #d08b28); padding-left: 10px; }
    .tk-ac-done   { border-left: 3px solid var(--success); padding-left: 10px; color: var(--text2); }
    .tk-ac-clear  { color: var(--success); }
    .tk-ac-legacy { border-left: 3px solid var(--border2); padding-left: 10px; color: var(--text3); font-style: italic; }
    .tk-ac-none   { color: var(--text3); font-style: italic; }
    .tk-ac-verdict {
      border-radius: var(--radius); padding: 8px 10px; font-size: 12px; line-height: 1.45;
    }
    .tk-ac-verdict-yes { color: var(--success); background: var(--success-dim); border: 1px solid var(--success); }
    .tk-ac-verdict-no  { color: var(--text2);   background: var(--surface3);    border: 1px solid var(--border2); }

    /* Domain scoping on the Tickets board (TKT-579). */
    .tk-domain-scope   { color: var(--text3); }
    .tk-domain-tag     { color: var(--blue);  background: var(--blue-dim); border: 1px solid var(--blue); }
    .tk-domain-untagged{ color: var(--text3); background: var(--surface2); border: 1px dashed var(--border2); }
    /* Inline assignment on an untagged ROW — sized down so it reads as a row affordance, not a
       form field, and min-width:0 so it cannot push the ticket title out of the head. */
    .tk-domain-select  { min-width: 0; width: auto; flex: 0 0 auto; font-size: 11px; padding: 3px 6px; }
    .tk-domain-hint    { color: var(--text3); font-size: 11px; line-height: 1.45; margin-top: 6px; }

    .tk-status-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
    .tk-select {
      background: var(--surface3); border: 1px solid var(--border2); color: var(--text);
      border-radius: var(--radius); padding: 8px 10px; font-size: 13px;
      font-family: var(--font-body); min-width: 200px; flex: 1;
    }
    .tk-textarea {
      width: 100%; box-sizing: border-box;
      background: var(--surface3); border: 1px solid var(--border2); color: var(--text);
      border-radius: var(--radius); padding: 8px 10px; font-size: 13px;
      font-family: var(--font-body); resize: vertical;
    }
    .tk-blockers { display: flex; flex-direction: column; gap: 4px; }
    .tk-blocker {
      font-size: 12px; color: var(--blue); cursor: pointer;
      border: 1px solid var(--border2); border-radius: var(--radius);
      padding: 5px 8px; background: var(--surface2);
    }
    .tk-blocker:hover { border-color: var(--blue); }
    .tk-detail-actions { margin-top: 16px; }
    .tk-msg {
      margin-top: 12px; padding: 9px 12px; border-radius: var(--radius);
      font-size: 12px; line-height: 1.45;
    }
    .tk-msg-info { color: var(--text2); background: var(--surface2); border: 1px solid var(--border); }
    .tk-msg-ok   { color: var(--success); background: var(--success-dim); border: 1px solid var(--success); }
    .tk-msg-err  { color: var(--danger);  background: var(--danger-dim);  border: 1px solid var(--danger); }

    /* "Your Action" surfacing (tickets-action-line). LIST: a compact accent-bordered line
       under the title on Awaiting_Review rows, truncated to one line (full text in detail).
       DETAIL: a prominent call-to-action banner at the top. The .tk-action-missing variant
       flags an Awaiting_Review ticket with no "CRAIG ACTION:" line (a convention slip). */
    .tk-action {
      display: flex; align-items: baseline; gap: 6px;
      margin-top: 5px; padding: 4px 8px;
      font-size: 12px; line-height: 1.4;
      background: var(--accent-dim);
      border-left: 2px solid var(--accent);
      border-radius: 3px;
      min-width: 0;   /* let the text child shrink so ellipsis works inside flex */
    }
    .tk-action-arrow { color: var(--accent); font-size: 10px; flex: 0 0 auto; }
    .tk-action-text {
      color: var(--text2);
      min-width: 0;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .tk-action.tk-action-missing {
      background: rgba(243,156,18,0.12);
      border-left-color: var(--warning);
      color: var(--warning);
    }

    .tk-action-banner {
      display: flex; align-items: flex-start; gap: 10px;
      margin-bottom: 14px; padding: 12px 14px;
      background: var(--accent-dim);
      border: 1px solid var(--accent-glow);
      border-left: 3px solid var(--accent);
      border-radius: var(--radius);
    }
    .tk-action-banner .tk-action-arrow { font-size: 13px; line-height: 1.5; }
    .tk-action-banner-label {
      font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
      color: var(--accent); margin-bottom: 3px;
    }
    .tk-action-banner-text { font-size: 14px; line-height: 1.5; color: var(--text); }
    .tk-action-banner.tk-action-missing {
      background: rgba(243,156,18,0.10);
      border-color: var(--warning);
      border-left-color: var(--warning);
      color: var(--warning);
    }
    .tk-action-banner.tk-action-missing .tk-action-banner-label { color: var(--warning); }
    .tk-action-banner.tk-action-missing .tk-action-banner-text { color: var(--text2); }

    /* ============================================================================
       OMNIPRESENT ASSISTANT DOCK (Part B — hub-responsive-assistant)
       A FAB on every tab opens a chat drawer that hosts the teleported live
       .agent-panel. Desktop/tablet = right-side panel; phone = bottom sheet.
       ============================================================================ */
    .assistant-dock-fab {
      position: fixed;
      /* z 250: above page content + header (100), but BELOW every modal overlay
         (settings/log-viewer 300, detail 400, notif 500) and the dock drawer/overlay
         (448/449) — so an open panel automatically covers the FAB and it can never sit
         over a panel's action buttons (the historical unreachable-button bug). */
      z-index: 250;
      right: max(16px, env(safe-area-inset-right));
      bottom: calc(16px + env(safe-area-inset-bottom));
      width: 54px; height: 54px;
      min-width: 44px; min-height: 44px;   /* touch target */
      border-radius: 50%;
      background: var(--accent);
      color: #000;
      border: none;
      cursor: pointer;
      font-size: 22px; line-height: 1;
      display: flex; align-items: center; justify-content: center;
      box-shadow: 0 6px 22px rgba(0,0,0,0.45), 0 0 0 1px var(--accent-glow);
      transition: transform 0.15s, box-shadow 0.15s, opacity 0.15s;
    }
    .assistant-dock-fab:hover { transform: translateY(-2px); }
    .assistant-dock-fab:active { transform: translateY(0); }
    /* Hidden on the Assistant full page (chat is already full-page there) and while the
       drawer is open (the close button + overlay handle dismissal). */
    body.on-assistant-tab .assistant-dock-fab,
    body.assistant-dock-open .assistant-dock-fab { display: none; }

    .assistant-dock-overlay {
      position: fixed; inset: 0;
      background: rgba(0,0,0,0.5);
      z-index: 448;
    }
    .assistant-dock-overlay[hidden] { display: none; }

    .assistant-dock {
      position: fixed;
      z-index: 449;
      background: var(--surface);
      border: 1px solid var(--border2);
      display: flex; flex-direction: column;
      overflow: hidden;
      box-shadow: -10px 0 40px rgba(0,0,0,0.45);
      /* desktop / tablet: right-side panel, never wider than the viewport */
      top: 0; right: 0;
      height: 100vh; height: 100dvh;
      width: min(420px, 100vw);
      transform: translateX(100%);
      transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
    }
    .assistant-dock.open { transform: translateX(0); }
    .assistant-dock[hidden] { display: none; }

    .assistant-dock-handle {
      display: flex; align-items: center; justify-content: space-between;
      padding: 12px 16px;
      padding-top: max(12px, env(safe-area-inset-top));
      border-bottom: 1px solid var(--border);
      flex-shrink: 0;
    }
    .assistant-dock-title {
      font-family: var(--font-display);
      font-weight: 700; font-size: 13px;
      letter-spacing: 0.1em; text-transform: uppercase;
      color: var(--accent);
    }
    .assistant-dock-close {
      width: 32px; height: 32px;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      background: var(--surface2);
      color: var(--text2);
      cursor: pointer;
      font-size: 13px; line-height: 1;
      display: flex; align-items: center; justify-content: center;
      flex-shrink: 0;
      transition: all 0.15s;
    }
    .assistant-dock-close:hover { border-color: var(--border2); color: var(--text); }

    .assistant-dock-body {
      flex: 1; min-height: 0;
      display: flex;
    }
    /* The teleported chat fills the drawer; its own header is redundant with the handle. */
    #assistantDock .agent-panel {
      height: 100%; width: 100%;
      border: none; border-radius: 0;
      flex: 1; min-height: 0;
    }
    #assistantDock .agent-header { display: none; }
    /* keep the docked input clear of the home indicator */
    #assistantDock .agent-input-area {
      padding-bottom: max(12px, env(safe-area-inset-bottom));
    }

    /* ============================================================================
       PHONE BREAKPOINT (<700px) — single-column, scrollable tab strip, stacked
       controls, full-width tappable action buttons, bottom-sheet assistant drawer.
       ============================================================================ */
    @media (max-width: 699px) {
      /* Header: WRAP to multiple rows on phones so the left cluster (logo / domain / version chip)
         and the right cluster (status + action buttons) never clip or run off-screen (#2/#3). The
         sticky header grows in height as needed instead of squeezing its contents off the edge. */
      .header {
        height: auto;
        min-height: 52px;
        flex-wrap: wrap;
        row-gap: 6px;
        padding-top: 8px;
        padding-bottom: 8px;
      }
      .header-left, .header-right { flex-wrap: wrap; gap: 10px; }
      /* Header chrome on a phone (TKT-534). Three changes, all measured on a 390px iPhone-13-Pro
         header carrying the gateway's two auth-injected buttons (🩺 diagnostics + ⏻ sign-out):

         justify-content — a wrapped row starts at the LEFT by default, which is what put the
         time-clock badge on the left margin under the logo. Right-align so wrapped rows hug the
         corner the controls belong in. A no-op at desktop, where the row never wraps.

         gap 10 -> 8 — this is the one that buys back a whole row. The controls total 684px of
         content in a 350px row, so two bands (700px) DO fit — but flex packs greedily and wasted
         101px, spilling one item to a third band; the badge missed the second band by THREE pixels.
         At 8px the whole cluster lands on two bands: header 181px -> 131px. There is ~9px of slack,
         so a device whose font metrics run wider simply falls back to the old three-band layout —
         it degrades, it does not break. (≤380px already sets 8px; 381-699px was still on 10px.) */
      .header-right { justify-content: flex-end; gap: 8px; }
      .status-indicator { font-size: 11px; }

      .main {
        padding: 14px 14px 48px;
        padding-left: max(14px, env(safe-area-inset-left));
        padding-right: max(14px, env(safe-area-inset-right));
        padding-bottom: max(48px, calc(32px + env(safe-area-inset-bottom)));
        gap: 16px;
      }

      /* module cards: single column */
      .module-grid { grid-template-columns: 1fr; }

      /* tickets outline: shallower child indent so deep rows don't crowd off-screen */
      .tk-child { margin-left: 12px; }
      /* contacts A–Z bar: slightly larger tap targets on phones */
      .contacts-az-btn { min-width: 30px; padding: 6px 7px; }

      /* tab row: WRAP to multiple rows on phones so every tab is visible — nothing runs off-screen
         (#2/#3). (Previously a one-line horizontal-scroll strip, which hid tabs past the edge.) */
      .hub-tabs {
        flex-wrap: wrap;
        row-gap: 6px;
        padding-bottom: 8px;
      }
      .hub-tab { min-height: 40px; }
      /* COLLAPSE (hub-nav-collapse.js): on phones the flat grid collapses behind a single
         "☰ <active tab>" disclosure so it stops eating ~2/3 of the screen (#1). The toggle
         shows here; when .nav-collapsed is set every real tab is hidden (the toggle is not a
         .hub-tab, so it stays). Tapping the toggle removes .nav-collapsed → full wrapped grid;
         picking a tab re-adds it. When the faceted nav is on, .hub-tabs is display:none'd by
         hub-nav-modes.js and this whole bar (toggle included) is gone — no collision. */
      .hub-tabs-toggle { display: inline-flex; align-items: center; min-height: 40px; }
      .hub-tabs.nav-collapsed { gap: 0; }
      .hub-tabs.nav-collapsed .hub-tab { display: none; }

      /* faceted nav: the portrait win — the two dropdowns sit on one compact line and the
         menu / sub rows become single horizontally-scrollable strips (no wrapped rows). */
      .hnm-facets { gap: 8px; }
      /* Each dropdown gets its own full-width row on phones — keeps long option labels
         (e.g. "Scott-Precision") fully visible without horizontal clipping. The compact
         caption stays as the row's leading label. */
      .hnm-facet { flex: 1 1 100%; min-width: 0; }
      .hnm-select { flex: 1 1 auto; width: 100%; min-width: 0; min-height: 40px; }
      .hnm-crumb { flex-basis: 100%; margin-left: 0; max-width: 100%; order: 3; }
      /* faceted menu + sub rows WRAP on phones (#2/#3) — all menus visible, none off-screen.
         (Previously horizontal-scroll strips.) */
      .hnm-menus, .hnm-subs {
        flex-wrap: wrap;
        row-gap: 6px;
        padding-bottom: 4px;
      }
      .hnm-menu, .hnm-sub { min-height: 40px; }

      /* stat pills wrap cleanly and stay tappable */
      .stats-bar { gap: 8px; }
      .stat-pill { padding: 7px 12px; }

      /* primary tap targets ≥44px */
      .dp-btn, .btn, .notif-modal-btn, .lv-btn, .tasks-tab {
        min-height: 44px;
        display: flex; align-items: center; justify-content: center;
      }
      .icon-btn { width: 38px; height: 38px; }
      .tc-badge { height: 38px; }   /* TKT-534 — the clock badge is a tap target like its neighbours */
      .send-btn { min-height: 44px; }

      /* Intake Review action row: drop the desktop 3-column grid to 2 columns at phone width
         so labels stay readable without crowding off-screen. */
      .ir-page-actions { grid-template-columns: repeat(2, 1fr); gap: 8px; }
      .ir-page-actions .dp-btn { width: 100%; }

      /* slide-over + drawer take the whole width on phone */
      .detail-panel { width: 100vw; max-width: 100vw; }

      /* Controls rows stack: name + description above, state + toggle below */
      .ctrl-row { flex-direction: column; align-items: stretch; gap: 10px; }
      .ctrl-row-ctl { justify-content: flex-end; min-height: 44px; gap: 14px; }
      .ctrl-board, .stub-page { max-width: 100%; }

      /* Tickets: stack the status control + button to full width so nothing crowds off
         the right edge (the iPad/iPhone off-screen-button pain point). */
      .tk-status-row { flex-direction: column; align-items: stretch; }
      .tk-select { min-width: 0; width: 100%; }
      .tk-status-row .dp-btn { width: 100%; }
      .tk-detail-actions .dp-btn { width: 100%; }

      /* notif modal: near full-bleed */
      .notif-modal { width: calc(100vw - 16px); }

      /* tables/lists: contain within the viewport, no horizontal page overflow */
      .tasks-company { width: auto; max-width: 96px; }
      .staging-lines-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }

      /* Assistant dock → bottom sheet */
      .assistant-dock {
        top: auto; bottom: 0; left: 0; right: 0;
        width: 100%;
        height: 74vh; height: 74dvh;
        max-height: 74vh; max-height: 74dvh;
        border-left: none;
        border-top: 1px solid var(--border2);
        border-radius: 14px 14px 0 0;
        transform: translateY(100%);
        box-shadow: 0 -10px 40px rgba(0,0,0,0.5);
      }
      .assistant-dock.open { transform: translateY(0); }
      /* grab-handle affordance on the bottom sheet */
      .assistant-dock-handle::before {
        content: '';
        position: absolute;
        top: 6px; left: 50%; transform: translateX(-50%);
        width: 36px; height: 4px; border-radius: 2px;
        background: var(--border2);
      }
      .assistant-dock-handle { position: relative; padding-top: 16px; }
    }

    /* Fine-tune the very narrow phone case (≤380px): tighter chrome. */
    @media (max-width: 380px) {
      .logo { font-size: 16px; }
      .header { gap: 8px; padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right)); }
      .header-right { gap: 8px; }
      .hub-tab { padding: 6px 12px; }
    }

/* ============================================================
   PIPELINE TAB (TKT-108) — read-only intake-pipeline visibility.
   Vertical funnel of stage cards (count + status colour), stall
   indicators, store heartbeat, drill-down rows, and a per-message
   trace timeline. iPad-first: large touch targets, no h-scroll.
   ============================================================ */
.pl-header { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; }
.pl-controls { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.pl-win { display:flex; gap:2px; background:var(--surface2); border:1px solid var(--border); border-radius:8px; padding:3px; }
.pl-win-btn { font-family:var(--font-body); font-size:13px; color:var(--text2); background:transparent; border:none; padding:7px 12px; border-radius:6px; cursor:pointer; min-height:36px; }
.pl-win-btn.active { background:var(--accent-dim); color:var(--accent); font-weight:600; }
.pl-refresh { font-family:var(--font-body); font-size:13px; color:var(--text2); background:var(--surface2); border:1px solid var(--border); padding:7px 14px; border-radius:8px; cursor:pointer; min-height:36px; }
.pl-refresh:active { background:var(--surface3); }

.pl-heartbeat { display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:12px 14px; margin:12px 0 8px; background:var(--surface2); border:1px solid var(--border); border-radius:10px; }
.pl-hb-dot { width:10px; height:10px; border-radius:50%; flex:0 0 auto; box-shadow:0 0 8px currentColor; }
.pl-hb-main { font-family:var(--font-body); font-size:15px; color:var(--text); }
.pl-hb-main b { color:var(--text); }
.pl-hb-sub { font-family:var(--font-mono); font-size:11px; color:var(--text3); margin-left:auto; }

.pl-indicators { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:10px; }
.pl-ind-label { font-family:var(--font-mono); font-size:11px; color:var(--text3); width:100%; margin-bottom:2px; }
.pl-ind-clear { font-family:var(--font-body); font-size:13px; color:var(--success); padding:8px 0; }
.pl-chip { font-family:var(--font-body); font-size:13px; color:var(--text2); background:var(--surface2); border:1px solid var(--border); padding:7px 12px; border-radius:16px; cursor:pointer; min-height:34px; }
.pl-chip-amber { color:var(--warning); border-color:var(--warning); background:rgba(243,156,18,0.10); }

/* Quality / Success panel (intake-processing-success-metrics) */
.pl-quality { margin:8px 0 10px; }
.pl-q-loading { color:var(--text3); font-size:13px; padding:8px 2px; }
.pl-q-head { display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-bottom:8px; }
.pl-q-light { display:inline-flex; align-items:center; gap:8px; font-family:var(--font-display); font-size:15px; font-weight:600; padding:7px 14px; border-radius:10px; border:1px solid var(--border); }
.pl-q-light .pl-q-dot { width:10px; height:10px; border-radius:50%; display:inline-block; }
.pl-q-go { color:var(--success); border-color:var(--success); background:rgba(46,204,113,0.10); }
.pl-q-go .pl-q-dot { background:var(--success); }
.pl-q-stop { color:var(--warning); border-color:var(--warning); background:rgba(243,156,18,0.10); }
.pl-q-stop .pl-q-dot { background:var(--warning); }
.pl-q-gates { display:flex; gap:8px; flex-wrap:wrap; }
.pl-q-gate { font-family:var(--font-mono); font-size:12px; padding:3px 8px; border-radius:6px; border:1px solid var(--border); color:var(--text3); }
.pl-q-gate-ok { color:var(--success); border-color:var(--success); }
.pl-q-gate-bad { color:var(--warning); border-color:var(--warning); }
.pl-q-cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:8px; }
.pl-q-card { background:var(--surface2); border:1px solid var(--border); border-radius:10px; padding:10px 12px; }
.pl-q-card-other { border-color:var(--border2); }
.pl-q-k { font-family:var(--font-mono); font-size:11px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text3); margin-bottom:4px; }
.pl-q-v { font-family:var(--font-display); font-size:24px; font-weight:700; color:var(--text); line-height:1.1; }
.pl-q-sub { font-size:11.5px; color:var(--text3); margin-top:4px; }
.pl-q-risk { font-family:var(--font-display); font-size:18px; font-weight:700; border:none; background:none; padding:0; cursor:default; }
.pl-q-risk-hot { color:var(--danger,#e74c3c); cursor:pointer; text-decoration:underline; }
.pl-q-risk-zero { color:var(--success); }
.pl-q-accuracy { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:8px; }
.pl-q-acc-k { font-family:var(--font-mono); font-size:11.5px; color:var(--text3); }
.pl-q-acc-chip { font-size:12px; color:var(--text2); background:var(--surface2); border:1px solid var(--border); padding:3px 9px; border-radius:14px; }

.pl-searchbar { display:flex; gap:8px; margin:6px 0 16px; }
.pl-search-input { flex:1; font-family:var(--font-body); font-size:15px; color:var(--text); background:var(--surface2); border:1px solid var(--border); border-radius:8px; padding:11px 14px; min-height:44px; }
.pl-search-input:focus { outline:none; border-color:var(--accent); }
.pl-search-btn { font-family:var(--font-body); font-size:14px; color:var(--bg); background:var(--accent); border:none; border-radius:8px; padding:0 20px; cursor:pointer; font-weight:600; min-height:44px; }

/* Funnel — vertical stack of stage cards with down-arrows. */
.pl-funnel { display:flex; flex-direction:column; align-items:stretch; }
.pl-stage { background:var(--surface2); border:1px solid var(--border); border-left:4px solid var(--text3); border-radius:10px; padding:14px 16px; cursor:pointer; transition:background .12s; }
.pl-stage:active { background:var(--surface3); }
.pl-stage.pl-flowing { border-left-color:var(--success); }
.pl-stage.pl-stalled { border-left-color:var(--warning); background:rgba(243,156,18,0.06); }
.pl-stage.pl-empty   { border-left-color:var(--border2); opacity:0.72; }
.pl-stage-head { display:flex; align-items:center; gap:10px; }
.pl-stage-label { font-family:var(--font-display); font-size:18px; font-weight:600; letter-spacing:0.3px; color:var(--text); text-transform:uppercase; }
.pl-stage-count { margin-left:auto; font-family:var(--font-mono); font-size:24px; font-weight:500; color:var(--text); }
.pl-stale-badge { font-family:var(--font-mono); font-size:10px; color:var(--warning); border:1px solid var(--warning); border-radius:10px; padding:2px 7px; text-transform:uppercase; }
.pl-stage-sub { display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-top:8px; }
.pl-pill { font-family:var(--font-mono); font-size:11px; color:var(--text2); background:var(--surface3); border-radius:5px; padding:3px 8px; }
.pl-pill b { color:var(--text); font-weight:600; }
.pl-pill-ok b { color:var(--success); }
.pl-pill-amber { color:var(--warning); } .pl-pill-amber b { color:var(--warning); }
.pl-note { font-family:var(--font-body); font-size:11px; color:var(--text3); font-style:italic; flex-basis:100%; line-height:1.4; margin-top:2px; }
.pl-stage-foot { font-family:var(--font-mono); font-size:10px; color:var(--text3); margin-top:8px; display:flex; justify-content:space-between; gap:8px; }
.pl-drill-hint { color:var(--blue); }
.pl-arrow { text-align:center; color:var(--text3); font-size:18px; line-height:1; padding:4px 0; }

/* Drill-down rows (rendered into the shared #detailPanel). */
.pl-drill-count { font-family:var(--font-mono); font-size:11px; color:var(--text3); margin-bottom:10px; }
.pl-drill-row { padding:12px; border:1px solid var(--border); border-radius:8px; margin-bottom:8px; cursor:pointer; background:var(--surface2); }
.pl-drill-row:active { background:var(--surface3); }
.pl-drill-subj { font-family:var(--font-body); font-size:15px; color:var(--text); }
.pl-drill-meta { font-family:var(--font-mono); font-size:11px; color:var(--text3); margin-top:3px; }
.pl-drill-why { font-family:var(--font-body); font-size:12px; color:var(--warning); margin-top:5px; }

/* Trace journey — vertical timeline of the 7 stage steps. */
.pl-journey { margin-bottom:22px; }
.pl-journey-head { padding-bottom:12px; border-bottom:1px solid var(--border); margin-bottom:12px; }
.pl-journey-subj { font-family:var(--font-display); font-size:18px; font-weight:600; color:var(--text); }
.pl-journey-meta { font-family:var(--font-mono); font-size:11px; color:var(--text3); margin-top:3px; word-break:break-all; }
.pl-journey-rests { font-family:var(--font-body); font-size:13px; color:var(--accent); margin-top:8px; }
.pl-journey-rests b { color:var(--accent); }
.pl-steps { position:relative; }
.pl-step { display:flex; gap:12px; padding-bottom:14px; }
.pl-step-dot { font-size:14px; line-height:1.3; flex:0 0 16px; text-align:center; }
.pl-step-body { flex:1; border-left:1px solid var(--border); margin-left:-9px; padding-left:18px; padding-bottom:2px; }
.pl-step-head { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.pl-step-stage { font-family:var(--font-body); font-size:14px; font-weight:600; color:var(--text); }
.pl-step-status { font-family:var(--font-mono); font-size:10px; color:var(--text2); background:var(--surface3); border-radius:4px; padding:1px 6px; }
.pl-step-when { font-family:var(--font-mono); font-size:10px; color:var(--text3); margin-left:auto; }
.pl-step-detail { font-family:var(--font-body); font-size:12px; color:var(--text2); margin-top:2px; }
.pl-step-reason { font-family:var(--font-body); font-size:12px; color:var(--text3); font-style:italic; margin-top:3px; }
.pl-step-done .pl-step-dot { color:var(--success); }
.pl-step-rests .pl-step-dot { color:var(--accent); }
.pl-step-rests .pl-step-stage { color:var(--accent); }
.pl-step-future { opacity:0.5; }
.pl-step-future .pl-step-dot { color:var(--text3); }

/* Pipeline fail-soft notice (TKT-108 fix) — endpoints missing / proxy not restarted. */
.pl-unavailable { padding:28px 18px; text-align:center; background:var(--surface2); border:1px solid var(--warning); border-radius:10px; }
.pl-unavailable-title { font-family:var(--font-display); font-size:18px; font-weight:600; color:var(--warning); text-transform:uppercase; letter-spacing:0.4px; }
.pl-unavailable-msg { font-family:var(--font-body); font-size:14px; color:var(--text2); margin:10px auto 16px; max-width:520px; line-height:1.5; }

/* ── Intake Review controls + detail (TKT-108 review-UX batch) ─────────────── */
/* Queue sort/filter bar — mirrors the Tasks-tab control pattern. */
.ir-controls { display:flex; flex-wrap:wrap; gap:10px 16px; align-items:flex-end; padding:10px 0 6px; border-bottom:1px solid var(--border); margin-bottom:8px; }
.ir-ctrl-group { display:flex; align-items:center; gap:6px; }
.ir-ctrl-label { font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text3); }
.ir-ctrl-select, .ir-ctrl-date { background:var(--surface2); border:1px solid var(--border2); color:var(--text); border-radius:var(--radius); padding:4px 6px; font-family:var(--font-body); font-size:13px; }
/* TKT-1284 — Intake Review search box: full width on its own row, so it is the first thing a phone shows. */
.ir-search-bar { align-items:center; }
.ir-ctrl-search { flex:1 1 260px; min-width:0; background:var(--surface2); border:1px solid var(--border2); color:var(--text); border-radius:var(--radius); padding:6px 8px; font-family:var(--font-body); font-size:16px; }
.ir-ctrl-dir { background:var(--surface2); border:1px solid var(--border2); color:var(--text2); border-radius:var(--radius); padding:4px 8px; cursor:pointer; font-size:12.5px; }
/* TKT-715 — the intake domain bar: what this list is showing, and the way to the unassigned
   set. Sits above the field filters because it is a SCOPE, not a filter. */
.ir-domain-bar { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.ir-ctrl-dir.ir-ctrl-on { border-color:var(--accent, #58a6ff); color:var(--accent, #58a6ff); }
.ir-ctrl-dash { color:var(--text3); }
.ir-ctrl-clear { background:transparent; border:1px solid var(--border2); color:var(--text2); border-radius:var(--radius); padding:4px 8px; cursor:pointer; font-size:12.5px; }
.ir-count { font-family:var(--font-mono); font-size:12px; color:var(--text3); margin:2px 0 8px; }

/* Bulk-action toolbar + per-row selection checkbox (review-queue bulk actions). */
.ir-bulk-bar { display:flex; flex-wrap:wrap; align-items:center; gap:8px 14px; padding:8px 10px; margin-bottom:10px; background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); }
.ir-bulk-all { display:flex; align-items:center; gap:6px; font-size:12.5px; color:var(--text2); cursor:pointer; user-select:none; }
.ir-bulk-count { font-family:var(--font-mono); font-size:12px; color:var(--text3); }
.ir-bulk-actions { display:flex; flex-wrap:wrap; gap:6px; margin-left:auto; }
.ir-bulk-btn { font-size:12.5px; padding:4px 10px; }
.ir-bulk-btn:disabled { opacity:0.45; cursor:not-allowed; }
/* Bulk Set-category: inline dropdown + Apply button inside the bulk actions row. */
.ir-bulk-setcat { display:inline-flex; align-items:center; gap:4px; }
.ir-bulk-cat { font-size:12px; padding:3px 6px; max-width:200px; background:var(--surface); color:var(--text); border:1px solid var(--border); border-radius:var(--radius); }
/* Confidence-threshold selector: "Select ≥ X%" cutoff input + incl-OTHER toggle, left of the actions. */
.ir-bulk-confsel { display:inline-flex; align-items:center; gap:6px; font-size:12.5px; color:var(--text2); }
.ir-bulk-confinput { width:52px; font-size:12px; padding:3px 4px; background:var(--surface); color:var(--text); border:1px solid var(--border); border-radius:var(--radius); }
.ir-bulk-conflbl { display:inline-flex; align-items:center; gap:3px; font-size:11.5px; color:var(--text3); cursor:pointer; user-select:none; }
.ir-bulk-confbtn { font-size:12.5px; padding:4px 10px; }
/* One-line accuracy-band hint near the Accept-proposed action (wraps to its own row). */
.ir-bulk-hint { flex-basis:100%; font-size:11.5px; color:var(--text3); }
.ir-bulk-hint a { color:var(--accent); }
/* TKT-1341 — the bulk status line: what is running, how many, how far along, then what happened. */
.ir-bulk-status { display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; padding:8px 12px; margin:-4px 0 10px; border-radius:var(--radius); font-size:13px; line-height:1.4; }
.ir-bulk-status-empty { display:none; }
.ir-bulk-status-running { background:var(--accent-dim, rgba(52,152,219,0.12)); border:1px solid var(--accent); color:var(--text); font-weight:600; }
.ir-bulk-status-done { background:var(--surface2); border:1px solid var(--border2); color:var(--text); }
.ir-bulk-status-hasfail, .ir-bulk-status-error { background:var(--danger-dim); border:1px solid var(--danger); color:var(--text); }
.ir-bulk-status-spin { width:14px; height:14px; border:2px solid var(--accent); border-right-color:transparent; border-radius:50%; animation:scanspin 0.9s linear infinite; flex:none; }
.ir-bulk-status-text { flex:1 1 auto; }
.ir-bulk-status-close { background:none; border:none; color:var(--text3); cursor:pointer; font-size:14px; padding:0 4px; }
.ir-bulk-status-fails { flex-basis:100%; margin:2px 0 0 18px; padding:0; font-size:12.5px; color:var(--text2); }
.ir-bulk-status-fails li { margin:2px 0; }
/* "Select similar" panel in the detail view — criterion checkboxes + the select button. */
.ir-similar { background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:10px 12px; margin:12px 0; }
.ir-similar-head { font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text2); margin-bottom:8px; }
.ir-similar-hint { color:var(--text3); text-transform:none; letter-spacing:0; font-size:11px; margin-left:6px; }
.ir-similar-crits { display:flex; flex-wrap:wrap; gap:6px 16px; margin-bottom:10px; }
.ir-similar-crits label { display:flex; align-items:center; gap:5px; font-size:12.5px; color:var(--text2); cursor:pointer; user-select:none; }
/* Row gains a leading checkbox; the body keeps the original stacked title/meta + click target. */
.dp-list-item.ir-row { flex-direction:row; align-items:flex-start; gap:10px; }
.ir-row-check { margin-top:2px; flex:0 0 auto; cursor:pointer; }
.ir-row-body { display:flex; flex-direction:column; gap:4px; flex:1 1 auto; min-width:0; cursor:pointer; }

/* Copyable intake_uid chip (dispatcher-operator-visibility). */
.ir-uid-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.ir-uid { font-family:var(--font-mono); font-size:12px; color:var(--text2); background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:3px 7px; word-break:break-all; user-select:all; }
.ir-uid-copy { background:var(--surface2); border:1px solid var(--border2); color:var(--text2); border-radius:var(--radius); padding:3px 9px; cursor:pointer; font-size:12px; white-space:nowrap; }
.ir-uid-copy:hover { border-color:var(--accent); color:var(--accent); }

/* Read-only proposed-task preview (dispatcher-operator-visibility). */
.ir-taskproposal { background:var(--surface2); border:1px solid var(--border2); border-left:3px solid var(--accent); border-radius:var(--radius); padding:10px 12px; margin:12px 0; }
.ir-tp-head { font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--accent); margin-bottom:6px; }
.ir-tp-hint { color:var(--text3); text-transform:none; letter-spacing:0; font-size:11px; margin-left:6px; }
.ir-tp-title { font-size:14px; font-weight:600; color:var(--text); margin-bottom:6px; }
.ir-tp-row { display:flex; gap:8px; font-size:12.5px; margin:2px 0; }
.ir-tp-k { flex:0 0 84px; color:var(--text3); }
.ir-tp-v { color:var(--text2); min-width:0; word-break:break-word; }
/* Always-shown task-decision box states (intake-review-proposal-transparency). The rationale row
   on a proposed task gets a subtle top divider; the "No task" and "Not evaluated" boxes drop the
   accent left-border for a quieter, neutral read (the reason is still shown). */
.ir-tp-rationale { margin-top:6px; padding-top:6px; border-top:1px dashed var(--border2); }
.ir-tp-notask { font-size:13px; color:var(--text2); word-break:break-word; }
.ir-tp-reason { color:var(--text); }
.ir-taskproposal.ir-tp-notask-box { border-left-color:var(--border2); }
.ir-taskproposal.ir-tp-none { border-left-color:var(--border2); }
.ir-taskproposal.ir-tp-none .ir-tp-head { color:var(--text3); }

/* Detail panel: per-field rows, body excerpt, attachment list, decided-by block. */
.ir-detail-top { display:flex; align-items:center; gap:10px; margin-bottom:10px; }
.ir-back { background:var(--surface2); border:1px solid var(--border2); color:var(--text2); border-radius:var(--radius); padding:4px 10px; cursor:pointer; font-size:12.5px; }
.ir-back:disabled { opacity:0.4; cursor:default; }
.ir-detail-nav { display:inline-flex; gap:6px; }
.ir-pos { font-family:var(--font-mono); font-size:12px; color:var(--text3); }
.ir-field { margin-bottom:10px; }
.ir-field-label { font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text3); margin-bottom:2px; }
.ir-field-val { font-size:13.5px; color:var(--text2); line-height:1.45; word-break:break-word; }
.ir-muted { color:var(--text3); }
.ir-att-list { list-style:none; margin:0; padding:0; }
.ir-att-list li { font-size:13px; color:var(--text2); padding:2px 0; }
.ir-att-name { color:var(--text); }
/* Inline "Doc type" field label (TKT-355) — reuses .ir-field-label so the caps/mono/colour stay a
   single source with every other field header on the screen; only the flow differs. Same idiom as
   .ir-submission-expiry .ir-field-label below. */
.ir-att-doctype-lab { display:inline; margin:0 5px 0 0; }
.ir-att-doctype { font-weight:600; color:var(--text); }
.ir-att-doctype.ir-muted { font-weight:500; }
.ir-att-meta { font-family:var(--font-mono); font-size:11.5px; color:var(--text3); }
.ir-body { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:10px 12px; font-size:13.5px; color:var(--text2); line-height:1.5; white-space:pre-wrap; word-break:break-word; max-height:340px; overflow:auto; }
.ir-decision { background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:10px 12px; margin-top:12px; }
.ir-decision .ir-field-val { color:var(--text); }

/* "Pipeline info" decision trace (slicer-escalation-transparency) — an expandable, read-only
   panel surfacing the persisted classification trace. Native <details>; closed by default. */
.ir-pipeline { background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); margin:12px 0; }
.ir-pipeline-summary { cursor:pointer; list-style:none; padding:10px 12px; font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text2); user-select:none; }
.ir-pipeline-summary::-webkit-details-marker { display:none; }
.ir-pipeline-summary::before { content:'▸'; display:inline-block; margin-right:8px; color:var(--text3); transition:transform .12s; }
.ir-pipeline[open] .ir-pipeline-summary::before { transform:rotate(90deg); }
.ir-pipeline-body { padding:0 12px 12px; border-top:1px solid var(--border2); }
.ir-pi-row { display:flex; gap:10px; padding:5px 0; font-size:13px; border-bottom:1px solid var(--border); }
.ir-pi-row:last-child { border-bottom:none; }
.ir-pi-k { flex:0 0 150px; color:var(--text3); font-size:12px; }
.ir-pi-v { color:var(--text); word-break:break-word; }
.ir-pi-cand { display:inline-block; font-family:var(--font-mono); font-size:11.5px; background:var(--surface); border:1px solid var(--border2); border-radius:var(--radius); padding:1px 6px; margin:1px 2px; color:var(--text2); }
.ir-pi-cand-chosen { background:var(--blue-dim); border-color:var(--blue); color:var(--text); }
.ir-pi-recall { border-radius:var(--radius); padding:8px 10px; margin:10px 0; font-size:13px; line-height:1.45; }
.ir-pi-recall-ok { background:var(--success-dim); border:1px solid var(--success); color:var(--text); }
.ir-pi-recall-miss { background:var(--danger-dim); border:1px solid var(--warning); color:var(--text); }
.ir-pi-recall-na { background:var(--surface); border:1px solid var(--border2); color:var(--text3); }

/* Per-field "this is wrong" flag (review_flags). A small ghost toggle on every DERIVED
   field's label; lights amber/red when raised. Raw-extracted fields have no flag. */
.ir-flag { display:inline-flex; align-items:center; justify-content:center; margin-left:6px;
  width:20px; height:20px; padding:0; line-height:1; vertical-align:middle; cursor:pointer;
  background:transparent; border:1px solid var(--border2); border-radius:var(--radius);
  color:var(--text3); font-size:12px; transition:all .12s; }
.ir-flag:hover { color:var(--danger); border-color:var(--danger); }
.ir-flag:disabled { opacity:.5; cursor:default; }
.ir-flag-on { background:var(--danger-dim); color:var(--danger); border-color:var(--danger); }

/* Decided-characteristics block — groups the flaggable derived Step-0 fields. */
.ir-derived { background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:10px 12px; margin:12px 0; }
.ir-derived-head { font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text2); margin-bottom:8px; display:flex; justify-content:space-between; align-items:center; }
.ir-derived-hint { color:var(--text3); text-transform:none; letter-spacing:0; font-size:11px; }
.ir-derived .ir-field { margin-bottom:8px; }
.ir-derived .ir-field:last-child { margin-bottom:0; }

/* Submission-with-link callout (ffm-submission-link-loop) — an FFM email carrying a transfer link. */
.ir-submission { background:var(--surface2); border:1px solid var(--accent); border-left-width:3px; border-radius:var(--radius); padding:10px 12px; margin:12px 0; }
.ir-submission-head { font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--accent); margin-bottom:6px; }
.ir-submission-svc { color:var(--text3); text-transform:none; letter-spacing:0; }
.ir-submission-routed { color:var(--text3); text-transform:none; letter-spacing:0; }
.ir-submission-links { list-style:none; margin:0; padding:0; }
.ir-submission-links li { margin:2px 0; }
.ir-submission-links a { color:var(--accent); word-break:break-all; font-size:13px; }
.ir-submission-expiry { margin-top:6px; font-size:12.5px; color:var(--text2); }
.ir-submission-expiry .ir-field-label { display:inline; margin:0 6px 0 0; }

/* Recipients — raw address + derived receiver type + its flag, one row each. */
.ir-recip-list { list-style:none; margin:0; padding:0; }
.ir-recip { display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; font-size:13px; padding:3px 0; }
.ir-recip-role { font-family:var(--font-mono); font-size:11px; color:var(--text3); min-width:28px; }
.ir-recip-addr { color:var(--text); word-break:break-word; }
.ir-recip-type { color:var(--text2); }

/* Flagged-fields view — chips naming which fields are flagged on each record. */
.ir-flag-chips { display:flex; flex-wrap:wrap; gap:4px; margin-top:4px; }
.ir-flag-chip { font-family:var(--font-mono); font-size:11px; color:var(--danger); background:var(--danger-dim); border:1px solid var(--danger); border-radius:var(--radius); padding:1px 6px; }
.ir-ctrl-flagged { background:transparent; border:1px solid var(--border2); color:var(--text2); border-radius:var(--radius); padding:4px 8px; cursor:pointer; font-size:12.5px; margin-left:auto; }
.ir-ctrl-flagged:hover { border-color:var(--danger); color:var(--danger); }

/* From-extraction Re-process divergence: the "logic is still wrong" set-aside signal. */
.ir-ctrl-diverged { background:transparent; border:1px solid var(--warning); color:var(--warning); border-radius:var(--radius); padding:4px 8px; cursor:pointer; font-size:12.5px; }
.ir-ctrl-diverged:hover { background:rgba(243,156,18,0.12); }
.ir-ctrl-diverged-on { background:rgba(243,156,18,0.18); }
.ir-diverged-badge { font-size:11px; color:var(--warning); background:rgba(243,156,18,0.12); border:1px solid var(--warning); border-radius:var(--radius); padding:1px 6px; margin-left:6px; white-space:nowrap; }
.ir-row-diverged { border-left:3px solid var(--warning); }

/* Controls — editable date-floor tunables. */
.ctrl-row-ctl-date { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.ctrl-date-input { background:var(--surface2); border:1px solid var(--border2); color:var(--text); border-radius:var(--radius); padding:4px 6px; font-size:13px; }
.ctrl-date-save { background:var(--accent-dim); border:1px solid var(--accent); color:var(--accent); border-radius:var(--radius); padding:4px 10px; cursor:pointer; font-size:12.5px; }
.ctrl-date-clear { background:transparent; border:1px solid var(--border2); color:var(--text2); border-radius:var(--radius); padding:4px 8px; cursor:pointer; font-size:12.5px; }

/* Per-lane Conductor target control (PASS 2b): effective-target badge + 3-state selector. */
.ctrl-row-ctl-lane { display:flex; align-items:center; gap:8px; flex-wrap:wrap; justify-content:flex-end; }
.ctrl-lane-select { background:var(--surface2); border:1px solid var(--border2); color:var(--text); border-radius:var(--radius); padding:4px 6px; font-size:12.5px; cursor:pointer; }
.ctrl-lane-badge { font-family:var(--font-mono); font-size:11px; font-weight:700; letter-spacing:.04em; padding:2px 7px; border-radius:4px; border:1px solid var(--border2); color:var(--text2); }
.ctrl-lane-badge-test { background:var(--surface2); color:var(--text2); border-color:var(--border2); }
.ctrl-lane-badge-live { background:rgba(192,57,43,.14); color:#c0392b; border-color:#c0392b; }
/* A LIVE target whose connection isn't configured: keep the red LIVE but add a warning ring. */
.ctrl-lane-badge-live.unconfigured { box-shadow:0 0 0 2px rgba(192,57,43,.25); }
.ctrl-lane-badge-test.unconfigured { color:#c0392b; border-color:#c0392b; }
.ctrl-lane-badge-unknown { background:transparent; color:var(--text3); border-style:dashed; }

/* Pipeline — "Last maintenance cycle" card (item ⑥). */
.pl-maint { background:var(--surface2); border:1px solid var(--border); border-radius:10px; padding:12px 14px; margin:8px 0; }
.pl-maint-empty { background:var(--surface2); border:1px dashed var(--border2); border-radius:10px; padding:10px 14px; margin:8px 0; color:var(--text3); font-size:13px; }
.pl-maint-abort { border-color:var(--warning); }
.pl-maint-head { font-family:var(--font-display); font-size:15px; font-weight:600; color:var(--text); letter-spacing:0.3px; }
.pl-maint-when { font-family:var(--font-mono); font-size:12px; color:var(--text3); font-weight:400; margin-left:6px; }
.pl-maint-badge { font-family:var(--font-mono); font-size:11px; padding:1px 6px; border-radius:4px; margin-left:6px; }
.pl-maint-badge-abort { background:var(--danger-dim); color:var(--danger); }
.pl-maint-msg { font-size:13px; color:var(--text2); margin-top:6px; }
.pl-maint-passes { margin-top:8px; display:flex; flex-direction:column; gap:3px; }
.pl-maint-pass { display:flex; justify-content:space-between; gap:12px; font-size:13px; color:var(--text2); }
.pl-maint-pass-name { color:var(--text); }
.pl-maint-pass-tally { font-family:var(--font-mono); font-size:12px; color:var(--text3); text-align:right; }
.pl-maint-off { opacity:0.55; }
.pl-maint-off .pl-maint-pass-tally { font-style:italic; }

/* ============================================================
   PROJECT MAP TAB (hub-map.js) — Domain → Department → Initiative → Task,
   a live "you are here" view built from the AE_Tasks ticket graph. Read-only.
   ============================================================ */
.map-toolbar { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:8px; }
.map-summary { font-family:var(--font-mono); font-size:12.5px; color:var(--text2); }
.map-toolbar-right { display:flex; align-items:center; gap:8px; }

/* Legend — the status colour scheme, read straight off MAP_BUCKETS. */
.map-legend { display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding:8px 10px; margin-bottom:10px; background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); }
.map-legend-item { display:inline-flex; align-items:center; gap:6px; font-size:12px; color:var(--text2); }
.map-legend-note { color:var(--text3); font-style:italic; margin-left:auto; }

/* Status dot — colour buckets shared by the legend, node dots, and bars. */
.map-dot { width:9px; height:9px; border-radius:50%; flex-shrink:0; background:var(--text3); }
.map-done    { background:var(--success); }
.map-active  { background:var(--blue); }
.map-review  { background:var(--accent); }
.map-planned { background:var(--text3); }
.map-blocked { background:var(--danger); }
.map-closed  { background:var(--border2); }
.map-empty   { background:var(--surface3); }

/* ── Visual boxed layout: domain cards → department lanes → initiative boxes ─────
   The map is rendered by the pure module hub-map-render.js. Status colour is carried
   by the shared bucket classes above (.map-done/.map-active/.map-review/.map-planned/
   .map-blocked) on dots, status pills, rollup bars, and the initiative-box border. */
.map-domains { display:flex; flex-direction:column; gap:16px; }

/* Domain = a top-level card. */
.map-domain-card { background:var(--surface); border:1px solid var(--border); border-radius:calc(var(--radius) + 2px); padding:12px 14px; }
.map-domain-head { display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding-bottom:10px; margin-bottom:10px; border-bottom:1px solid var(--border); }
.map-domain-head > .map-dot { width:11px; height:11px; }
.map-domain-link { display:inline-flex; align-items:baseline; gap:8px; text-decoration:none; min-width:0; }
.map-domain-title { font-family:var(--font-display); font-weight:700; font-size:18px; letter-spacing:0.01em; color:var(--text); }
.map-domain-link:hover .map-domain-title { text-decoration:underline; }

/* Department = a labelled lane: a left label column + a wrapping row of init boxes. */
.map-domain-lanes { display:flex; flex-direction:column; gap:10px; }
.map-dept-lane { display:flex; align-items:flex-start; gap:14px; }
.map-dept-label { flex:0 0 188px; display:flex; align-items:center; gap:7px; flex-wrap:wrap; padding-top:8px; }
.map-dept-link { display:inline-flex; align-items:baseline; gap:7px; text-decoration:none; min-width:0; }
.map-dept-title { font-weight:600; font-size:14px; color:var(--text); }
.map-dept-link:hover .map-dept-title { text-decoration:underline; }
.map-dept-count { font-family:var(--font-mono); font-size:11px; color:var(--text3); }
.map-dept-inits { flex:1 1 auto; min-width:0; display:flex; flex-wrap:wrap; gap:8px; align-items:stretch; }

/* Initiative = a rounded, status-coloured box (the whole box is the click-through link). */
.map-init-box { display:flex; flex-direction:column; gap:5px; width:200px; max-width:100%; box-sizing:border-box; padding:8px 10px; text-decoration:none; background:var(--surface2); border:1px solid var(--border2); border-left:3px solid var(--text3); border-radius:var(--radius); transition:border-color 0.12s ease, background 0.12s ease, transform 0.08s ease; }
.map-init-box:hover { background:var(--surface3); transform:translateY(-1px); }
.map-init-box.map-bd-done    { border-left-color:var(--success); }
.map-init-box.map-bd-active  { border-left-color:var(--blue); }
.map-init-box.map-bd-review  { border-left-color:var(--accent); }
.map-init-box.map-bd-planned { border-left-color:var(--text3); }
.map-init-box.map-bd-blocked { border-left-color:var(--danger); }
.map-init-top { display:flex; align-items:center; gap:7px; }
.map-init-top > .map-dot { width:8px; height:8px; }
.map-init-title { font-size:13px; color:var(--text); line-height:1.3; }
.map-init-tasks { font-family:var(--font-mono); font-size:10.5px; color:var(--text3); }
.map-ticketid { font-family:var(--font-mono); font-size:11px; color:var(--text3); flex-shrink:0; }

/* Rollup progress bar (domain header). */
.map-rollup { display:inline-flex; align-items:center; gap:8px; flex-shrink:0; }
.map-bar { width:90px; height:6px; border-radius:3px; background:var(--surface3); overflow:hidden; border:1px solid var(--border); }
.map-bar-fill { display:block; height:100%; background:var(--success); border-radius:3px; }
.map-bar.map-blocked .map-bar-fill { background:var(--danger); }
.map-bar.map-active  .map-bar-fill { background:var(--blue); }
.map-bar.map-review  .map-bar-fill { background:var(--accent); }
.map-bar.map-planned .map-bar-fill { background:var(--text3); }
.map-bar.map-empty   .map-bar-fill { background:transparent; }
.map-rollup-text { font-family:var(--font-mono); font-size:11px; color:var(--text3); white-space:nowrap; }

/* Status pill — bucket colour as text+tint (sits inside the initiative box). */
.map-status { font-family:var(--font-mono); font-size:10px; padding:1px 7px; border-radius:10px; white-space:nowrap; border:1px solid var(--border2); color:var(--text2); background:var(--surface2); margin-left:auto; }
.map-status.map-done    { color:var(--success); background:var(--success-dim); border-color:var(--success); }
.map-status.map-active  { color:var(--blue);    background:var(--blue-dim);    border-color:var(--blue); }
.map-status.map-review  { color:var(--accent);  background:var(--accent-dim);  border-color:var(--accent-glow); }
.map-status.map-blocked { color:var(--danger);  background:var(--danger-dim);  border-color:var(--danger); }
.map-status.map-planned { color:var(--text3);   background:var(--surface2);    border-color:var(--border); }
.map-status.map-closed  { color:var(--text3);   background:var(--surface3);    border-color:var(--border2); }

.map-empty-hint { font-size:12px; color:var(--text3); font-style:italic; padding:8px 2px; }

/* Inline authoring — per-node hover-revealed "+" (no top-level "+ Add domain"). */
.map-add-mini { flex-shrink:0; width:20px; height:20px; line-height:1; font-size:14px; color:var(--text3); background:transparent; border:1px solid transparent; border-radius:50%; cursor:pointer; opacity:0; transition:opacity 0.12s ease, color 0.12s ease, border-color 0.12s ease; }
.map-domain-head:hover .map-add-mini,
.map-dept-label:hover .map-add-mini { opacity:1; }
.map-add-mini:hover { color:var(--accent); border-color:var(--accent-glow); background:var(--surface2); }
.map-add-mini:focus { opacity:1; outline:none; color:var(--accent); border-color:var(--accent-glow); }

/* The inline name input form (department form spans the lanes; initiative form sits
   among the boxes). */
.map-dept-add, .map-init-add { flex-basis:100%; }
.map-add-form { display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding-top:6px; padding-bottom:8px; padding-right:8px; }
.map-add-input { flex:1; min-width:180px; max-width:380px; font-family:var(--font-body); font-size:13px; color:var(--text); background:var(--surface); border:1px solid var(--accent-glow); border-radius:var(--radius); padding:5px 9px; }
.map-add-input:focus { outline:none; border-color:var(--accent); }
.map-add-input:disabled { opacity:0.6; }
.map-add-save { font-family:var(--font-mono); font-size:12px; color:var(--bg); background:var(--accent); border:1px solid var(--accent); border-radius:var(--radius); padding:5px 12px; cursor:pointer; }
.map-add-save:hover:not(:disabled) { filter:brightness(1.08); }
.map-add-save:disabled { opacity:0.6; cursor:default; }
.map-add-cancel { font-family:var(--font-mono); font-size:12px; color:var(--text3); background:transparent; border:1px solid var(--border); border-radius:var(--radius); padding:5px 10px; cursor:pointer; }
.map-add-cancel:hover:not(:disabled) { color:var(--text); border-color:var(--border2); }
.map-add-cancel:disabled { opacity:0.6; cursor:default; }
.map-add-err { flex-basis:100%; font-size:12px; color:var(--danger); font-family:var(--font-mono); }

/* Responsive: on narrow screens a department lane stacks (label above its boxes) and
   the initiative boxes grow to fill the row instead of holding a fixed 200px. */
@media (max-width: 700px) {
  .map-dept-lane { flex-direction:column; gap:6px; }
  .map-dept-label { flex:0 0 auto; padding-top:0; }
  .map-init-box { width:auto; flex:1 1 160px; }
}

/* ============================================================
   REQUISITION TAB (TKT-180 — part-capture screen)
   Hosted in the .ir-page frame. Part-picker typeahead over /items/search,
   add-line form, and a status-coloured lines table.
   ============================================================ */
.req-toolbar { display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
.req-summary { font-size:13px; color:var(--text2); }
.req-summary b { color:var(--text); }
.req-toolbar-right { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.req-filter { font-family:var(--font-mono); font-size:12px; color:var(--text); background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:5px 8px; }
.req-group-toggle { font-size:12px; color:var(--text3); display:flex; align-items:center; gap:5px; cursor:pointer; }

.req-capture-card { background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:14px 16px; margin-bottom:16px; }
.req-capture-title { font-family:var(--font-display); font-size:16px; letter-spacing:0.04em; color:var(--accent); margin-bottom:10px; text-transform:uppercase; }
.req-picker { position:relative; margin-bottom:12px; }
.req-search-input { width:100%; font-family:var(--font-body); font-size:14px; color:var(--text); background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:9px 12px; box-sizing:border-box; }
.req-search-input:focus { outline:none; border-color:var(--accent); }
.req-res-meta { display:flex; align-items:center; gap:6px; flex-shrink:0; }
.req-res-oh { font-family:var(--font-mono); font-size:11px; color:var(--text3); }
.req-res-bin { font-family:var(--font-mono); font-size:11px; color:var(--blue); }
.req-pill { font-size:10px; font-family:var(--font-mono); padding:1px 6px; border-radius:10px; }
.req-pill-short { background:var(--danger-dim); color:var(--danger); }

.req-picked { background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:10px 12px; margin-bottom:12px; }
.req-picked-head { display:flex; justify-content:space-between; align-items:center; }
.req-picked-name { font-size:14px; font-weight:600; color:var(--text); }
.req-picked-clear { background:transparent; border:none; color:var(--text3); cursor:pointer; font-size:14px; }
.req-picked-clear:hover { color:var(--danger); }
.req-picked-snap { display:flex; flex-wrap:wrap; gap:14px; margin-top:6px; font-size:12px; color:var(--text3); }
.req-picked-snap b { color:var(--text2); }
.req-snap-short b { color:var(--danger); }
.req-picked-desc { margin-top:5px; font-size:12px; color:var(--text3); font-style:italic; }
.req-picked-empty { font-size:12px; color:var(--text3); margin-bottom:12px; }

.req-fields { display:flex; flex-wrap:wrap; gap:10px 14px; }
.req-field { display:flex; flex-direction:column; gap:3px; min-width:120px; }
.req-field-wide { flex:1 1 240px; }
.req-field label { font-size:11px; color:var(--text3); text-transform:uppercase; letter-spacing:0.03em; }
.req-field input { font-family:var(--font-body); font-size:13px; color:var(--text); background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:6px 8px; }
.req-field input:focus { outline:none; border-color:var(--accent); }
.req-field-qty input { border-color:var(--border2); }
.req-form-err { margin-top:10px; font-size:12px; color:var(--danger); font-family:var(--font-mono); }
.req-form-actions { margin-top:12px; }

.req-empty { font-size:13px; color:var(--text3); padding:24px 0; text-align:center; }
.req-group { margin-bottom:18px; }
.req-group-head { font-family:var(--font-display); font-size:14px; color:var(--accent); text-transform:uppercase; letter-spacing:0.03em; margin-bottom:6px; padding-bottom:4px; border-bottom:1px solid var(--border); }
.req-group-meta { font-family:var(--font-mono); font-size:11px; color:var(--text3); text-transform:none; }

.req-table { width:100%; border-collapse:collapse; font-size:12px; }
.req-table th { text-align:left; font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); padding:6px 8px; border-bottom:1px solid var(--border2); white-space:nowrap; }
.req-h-short { color:var(--accent); }
.req-table td { padding:7px 8px; border-bottom:1px solid var(--border); color:var(--text2); vertical-align:top; }
.req-row td { border-left:3px solid transparent; }
.req-c-part .req-part-no { font-family:var(--font-mono); color:var(--text); font-weight:600; }
.req-c-part .req-edit-part { font-family:var(--font-mono); font-weight:600; margin-bottom:4px; }
.req-c-part .req-part-desc { font-size:11px; color:var(--text3); }
.req-c-num { text-align:right; font-family:var(--font-mono); white-space:nowrap; }
.req-c-short { text-align:right; font-family:var(--font-mono); font-weight:700; }
.req-short-hot { color:var(--danger); }
.req-short-zero { color:var(--text3); }
.req-c-actions { white-space:nowrap; }
.req-icon-btn { background:transparent; border:1px solid var(--border); border-radius:var(--radius); color:var(--text3); cursor:pointer; padding:3px 7px; font-size:12px; margin-left:3px; }
.req-icon-btn:hover { color:var(--text); border-color:var(--border2); }
.req-del:hover { color:var(--danger); border-color:var(--danger); }
.req-save:hover { color:var(--success); border-color:var(--success); }
.req-notes-row td { border-bottom:1px solid var(--border); }
.req-notes { font-size:11px; color:var(--text3); font-style:italic; padding-top:0 !important; }
.req-row-editing td { background:var(--surface2); }
.req-edit-in { width:100%; box-sizing:border-box; font-family:var(--font-body); font-size:12px; color:var(--text); background:var(--surface3); border:1px solid var(--border2); border-radius:4px; padding:4px 6px; }
.req-edit-num { text-align:right; }
.req-edit-notes { width:100%; }

/* per-row status select + left accent by status */
.req-row-status { font-family:var(--font-mono); font-size:11px; border:1px solid var(--border); border-radius:var(--radius); padding:3px 6px; background:var(--surface2); color:var(--text); }
.req-status-open td:first-child { border-left-color:var(--accent); }
.req-status-onpo td:first-child { border-left-color:var(--blue); }
.req-status-rfqsent td:first-child { border-left-color:var(--warning, #d29922); } /* TKT-1003 — out for quote */
.req-status-received td:first-child { border-left-color:var(--success); }
.req-status-open.req-row-status { color:var(--accent); }
.req-status-onpo.req-row-status { color:var(--blue); }
.req-status-rfqsent.req-row-status { color:var(--warning, #d29922); }
.req-status-received.req-row-status { color:var(--success); }
.req-status-received td { opacity:0.72; }

/* ============================================================
   PROCUREMENT tab (TKT-193) — used-machine acquisition leads search/list
   ============================================================ */
.proc-toolbar { display:flex; justify-content:space-between; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:14px; }
.proc-summary { font-size:13px; color:var(--text2); }
.proc-summary b { color:var(--text); }
.proc-toolbar-right { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.proc-search-input { width:280px; max-width:48vw; font-family:var(--font-body); font-size:13px; color:var(--text); background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:7px 11px; box-sizing:border-box; }
.proc-search-input:focus { outline:none; border-color:var(--accent); }
.proc-filter { font-family:var(--font-mono); font-size:12px; color:var(--text); background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:5px 8px; }
.proc-scott-toggle { font-size:12px; color:var(--text2); display:flex; align-items:center; gap:5px; cursor:pointer; white-space:nowrap; }
.proc-sort-btn { font-family:var(--font-mono); font-size:12px; color:var(--text2); background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:5px 9px; cursor:pointer; }
.proc-sort-btn:hover { color:var(--text); border-color:var(--border2); }

/* add-lead form (TKT-680) */
.proc-add-btn, .proc-add-save { font-size:12px; color:#fff; background:var(--accent); border:1px solid var(--accent); border-radius:var(--radius); padding:5px 11px; cursor:pointer; white-space:nowrap; }
.proc-add-save:disabled { opacity:0.6; cursor:default; }
.proc-add-cancel { font-size:12px; color:var(--text2); background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:5px 11px; cursor:pointer; }
.proc-notice:empty { display:none; }
.proc-notice { font-size:13px; color:var(--success); margin-bottom:10px; }
.proc-add-panel[hidden] { display:none; }
.proc-add-panel { background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); padding:12px 14px; margin-bottom:14px; }
.proc-add-title { font-weight:600; color:var(--text); margin-bottom:10px; }
.proc-add-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(190px, 1fr)); gap:10px 12px; }
.proc-add-field { display:flex; flex-direction:column; gap:3px; font-size:11px; color:var(--text3); }
.proc-add-field input, .proc-add-field select, .proc-add-field textarea { font-family:var(--font-body); font-size:13px; color:var(--text); background:var(--surface); border:1px solid var(--border2); border-radius:var(--radius); padding:6px 9px; box-sizing:border-box; }
.proc-add-notes { margin-top:10px; }
.proc-add-errors { color:var(--danger, #c0392b); font-size:12px; margin-top:8px; }
.proc-add-actions { display:flex; justify-content:flex-end; align-items:center; gap:10px; margin-top:10px; flex-wrap:wrap; }
.proc-add-actions .proc-muted { margin-right:auto; font-size:11px; }

.proc-empty { font-size:13px; color:var(--text3); padding:24px 0; text-align:center; }
.proc-muted { color:var(--text3); }

.proc-table { width:100%; border-collapse:collapse; font-size:12px; }
.proc-table th { text-align:left; font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); padding:6px 8px; border-bottom:1px solid var(--border2); white-space:nowrap; }
.proc-table td { padding:8px 8px; border-bottom:1px solid var(--border); color:var(--text2); vertical-align:top; }
.proc-row td:first-child { border-left:3px solid transparent; }
.proc-c-machine .proc-machine { color:var(--text); font-weight:600; }
.proc-machine-link { color:var(--text); text-decoration:none; }
.proc-machine-link:hover { color:var(--accent); text-decoration:underline; }
.proc-c-machine .proc-lead-id { font-family:var(--font-mono); font-size:10px; color:var(--text3); margin-top:2px; }
.proc-c-num { text-align:right; font-family:var(--font-mono); white-space:nowrap; color:var(--text); }
.proc-c-asof { font-family:var(--font-mono); white-space:nowrap; }
.proc-age { color:var(--text3); font-size:10px; }
.proc-status-pill { font-size:10px; padding:1px 7px; border-radius:10px; border:1px solid var(--border2); text-transform:uppercase; letter-spacing:0.03em; }
.proc-notes-row td { border-bottom:1px solid var(--border); }
.proc-notes { font-size:11px; color:var(--text3); font-style:italic; padding-top:0 !important; }

/* status left-accent + pill colour (mirrors req status cues) */
.proc-st-available td:first-child { border-left-color:var(--success); }
.proc-st-pending td:first-child { border-left-color:var(--accent); }
.proc-st-purchased td:first-child { border-left-color:var(--blue); }
.proc-st-closed td:first-child { border-left-color:var(--text3); }
.proc-st-closed td { opacity:0.7; }
.proc-status-pill.proc-st-available { color:var(--success); }
.proc-status-pill.proc-st-pending { color:var(--accent); }
.proc-status-pill.proc-st-purchased { color:var(--blue); }
.proc-status-pill.proc-st-closed { color:var(--text3); }

/* ============================================================
   BILL REVIEW tab (TKT-182) — extracted vendor invoice → gated A/P bill
   ============================================================ */
.bill-layout { display:flex; gap:16px; align-items:flex-start; }
.bill-list-col { flex:0 0 320px; max-width:320px; }
.bill-review-col { flex:1 1 auto; min-width:0; }
.bill-sort-ctrls { display:flex; align-items:center; gap:6px; margin-bottom:8px; font-size:12px; }
.bill-sort-label { color:var(--text3); }
.bill-sort-select { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:3px 6px; color:var(--text); font-size:12px; }
.bill-acct-q { display:block; width:100%; max-width:340px; margin-bottom:3px; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:3px 6px; color:var(--text); font-size:12px; }
.bill-list-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; }
.bill-list-title { font-family:var(--font-display); font-size:13px; color:var(--text2); text-transform:uppercase; letter-spacing:0.04em; }
.bill-gate-note { font-size:11px; color:var(--warning); background:rgba(243,156,18,0.08); border:1px solid rgba(243,156,18,0.3); border-radius:var(--radius); padding:6px 8px; margin-bottom:10px; }
.bill-list { display:flex; flex-direction:column; gap:6px; }
.bill-row { border:1px solid var(--border); border-left:3px solid var(--border2); border-radius:var(--radius); background:var(--surface2); padding:8px 10px; cursor:pointer; }
.bill-row:hover { border-color:var(--border2); }
.bill-row-selected { outline:2px solid var(--accent); }
.bill-row-main { display:flex; justify-content:space-between; gap:8px; align-items:baseline; }
.bill-row-vendor { font-weight:600; color:var(--text); font-size:13px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.bill-row-total { font-family:var(--font-mono); color:var(--text); font-size:13px; }
.bill-row-meta { display:flex; gap:8px; flex-wrap:wrap; margin-top:4px; font-size:11px; color:var(--text3); font-family:var(--font-mono); }
.bill-row-cat { font-size:10px; padding:1px 6px; border-radius:10px; border:1px solid var(--border2); color:var(--text2); letter-spacing:0.02em; }
.bill-row-cat-none { color:var(--text3); border-style:dashed; font-style:italic; }
.bill-hidden-note { font-size:11px; color:var(--text3); font-style:italic; padding:2px 4px 6px; border-bottom:1px dashed var(--border2); margin-bottom:4px; }
/* Source-filter footnote: what was dropped as confidently-not-a-bill, and why. Deliberately
   quiet — it is an accountability line, not a call to action. */
.bill-excluded-note { font-size:10px; color:var(--text3); font-style:italic; padding:8px 4px 2px; margin-top:6px; border-top:1px dashed var(--border2); }

/* ── Bill Review flag classes + the message (TKT-1012) ────────────────────────────────── */
.bill-row-confirm { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--warn, #d9a13b); color:var(--warn, #d9a13b); white-space:nowrap; }
.bill-row-confirm-row { border-color:var(--warn, #d9a13b); }
.bill-row-cleared { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--success); color:var(--success); white-space:nowrap; }
.bill-row-note { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--border2); color:var(--text3); white-space:nowrap; }
/* TKT-1011 — identity from the document: QB-resolved vendor mark, sender-sourced name mark, duplicate note, identity line on the detail. */
.bill-row-qbv { font-size:9px; font-weight:700; letter-spacing:.04em; padding:0 5px; margin-left:6px; border-radius:6px; border:1px solid var(--success); color:var(--success); vertical-align:middle; white-space:nowrap; }
.bill-row-from-sender { font-size:9px; padding:0 5px; margin-left:6px; border-radius:6px; border:1px dashed var(--warn, #b8860b); color:var(--warn, #b8860b); vertical-align:middle; white-space:nowrap; }
.bill-row-dup { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--accent, #4a7bd0); color:var(--accent, #4a7bd0); white-space:nowrap; }
.bill-identity-line { display:flex; flex-direction:column; gap:3px; margin:2px 0 8px; font-size:12px; }
.bill-identity-line .bill-link { margin-left:4px; }
/* TKT-1013 — statement reconciliation, folded charge breakdowns, extraction failures. */
.bill-row-fail { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--danger, #c0392b); color:var(--danger, #c0392b); white-space:nowrap; }
.bill-row-stmt { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--accent, #4a7bd0); color:var(--accent, #4a7bd0); white-space:nowrap; }
.bill-row-stmt-ok { border-color:var(--success); color:var(--success); }
.bill-banner-fail { border-color:var(--danger, #c0392b); }
.bill-banner-note { padding:8px 10px; border:1px solid var(--border2); border-radius:8px; color:var(--text3); margin:6px 0 10px; font-size:12px; }
.bill-stmt { margin:8px 0 12px; padding:10px 12px; border:1px solid var(--border2); border-radius:8px; }
.bill-stmt-head { margin-bottom:6px; font-size:12px; }
.bill-stmt-table td, .bill-stmt-table th { font-size:12px; vertical-align:middle; }
.bill-stmt-kind { font-size:9px; letter-spacing:.04em; text-transform:uppercase; padding:0 5px; border-radius:6px; border:1px solid var(--border2); color:var(--text3); margin-right:4px; }
.bill-stmt-kind-charge { border-color:var(--warn, #b8860b); color:var(--warn, #b8860b); }
.bill-stmt-kind-payment, .bill-stmt-kind-credit { opacity:.7; }
.bill-stmt-matched, .bill-stmt-entered { opacity:.85; }
.bill-stmt-unmatched td { background:rgba(240,165,0,.06); }
.bill-stmt-note { margin-top:6px; font-size:11px; }
.bill-stmt-from { padding:8px 10px; border:1px solid var(--accent, #4a7bd0); border-radius:8px; margin:2px 0 10px; font-size:12px; }
.bill-line-fold { cursor:pointer; }
.bill-line-fold td { background:rgba(255,255,255,.03); }
.bill-line-fold-unassigned td { background:rgba(240,165,0,.08); }
.bill-fold-caret { display:inline-block; width:12px; color:var(--text3); }
.bill-fold-note { font-size:11px; color:var(--text3); margin:4px 0 6px; }
.bill-actions-stmt [data-bill-preview], .bill-actions-stmt [data-bill-post], .bill-actions-stmt .bill-gate-hint { display:none; }
/* TKT-1029 — freight bills feed the Shipments store: the row chip, the bill's shipments section, the Shipments screen. */
.bill-row-freight { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--accent, #4a7bd0); color:var(--accent, #4a7bd0); white-space:nowrap; }
.bill-freight .bill-stmt-head .bill-link { margin-left:8px; }
.ship-toolbar { display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:6px; }
.ship-filters { display:flex; gap:6px; flex-wrap:wrap; }
.ship-sort { display:flex; gap:6px; align-items:center; font-size:12px; color:var(--text3); }
.ship-totals { font-size:12px; margin-bottom:8px; }
.ship-feed-msg { font-size:12px; margin:4px 0 8px; padding:6px 8px; border-left:3px solid var(--accent, #4a90d9); background:var(--surface-2, rgba(74,144,217,.08)); }
.ship-match { grid-column:1 / -1; margin-top:6px; padding-top:6px; border-top:1px dashed var(--border, #ccc); }
.ship-suggest { list-style:none; margin:4px 0; padding:0; }
.ship-suggest li { margin:3px 0; }
.ship-match-form { margin-top:6px; font-size:12px; }
.ship-match-form input { font:inherit; padding:2px 6px; }
.ship-table td, .ship-table th { font-size:12px; vertical-align:middle; }
.ship-table code { font-size:11px; }
.ship-row { cursor:pointer; }
.ship-row-open td { background:rgba(255,255,255,.04); }
.ship-detail td { background:rgba(255,255,255,.02); }
.ship-detail-grid { display:grid; grid-template-columns:1fr; gap:4px; padding:6px 4px; font-size:12px; }
.ship-pill { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--border2); color:var(--text3); white-space:nowrap; }
.ship-pill-verified { border-color:var(--success); color:var(--success); }
.ship-pill-under_recovered { border-color:var(--warn, #b8860b); color:var(--warn, #b8860b); }
.ship-pill-wrong_party { border-color:var(--danger, #c0392b); color:var(--danger, #c0392b); }
.ship-pill-unmatched { border-color:var(--accent, #4a7bd0); color:var(--accent, #4a7bd0); }
/* TKT-1146 — a PO's freight: billed on our account when the PO said the vendor pays; a receipt with no bill after 30 days */
.ship-pill-discrepancy, .ship-pill-overdue { border-color:var(--danger, #c0392b); color:var(--danger, #c0392b); }
.ship-under_recovered td, .ship-unmatched td, .ship-wrong_party td, .ship-discrepancy td, .ship-overdue td { background:rgba(240,165,0,.05); }
.bill-banner-confirm { border-color:var(--warn, #d9a13b); background:rgba(217,161,59,0.08); }
.bill-flag-actions { display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-top:8px; }
.bill-flag-cleared { font-size:12px; color:var(--success); display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.bill-msg { border:1px solid var(--border2); border-radius:var(--radius); margin:8px 0; background:var(--surface2); }
.bill-msg-head { display:flex; justify-content:space-between; align-items:center; gap:8px; padding:7px 10px; cursor:pointer; font-size:12px; }
.bill-msg-head:hover { color:var(--accent); }
.bill-msg-body { padding:4px 10px 10px; font-size:12px; display:flex; flex-direction:column; gap:4px; }
.bill-msg-kv { display:grid; grid-template-columns:70px 1fr; gap:8px; align-items:baseline; }
.bill-msg-k { color:var(--text3); font-size:10px; text-transform:uppercase; letter-spacing:.04em; }
.bill-msg-internal { color:var(--accent); }
.bill-msg-us { font-size:9px; padding:0 5px; border-radius:8px; border:1px solid var(--accent); color:var(--accent); margin-left:3px; }
.bill-msg-text { white-space:pre-wrap; font-family:inherit; font-size:12px; max-height:320px; overflow:auto; background:var(--surface); border:1px solid var(--border2); border-radius:var(--radius); padding:8px; margin:4px 0; }

/* ── Money › Bills — the AP ledger (TKT-1017) ─────────────────────────────────────────── */
.bl-toolbar { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; margin-bottom:6px; }
.bl-qb-note { font-size:11px; color:var(--text3); margin:2px 0 8px; }
.bl-qb-stale { color:var(--danger); font-weight:600; }
.bl-qb-missing { color:var(--danger); }
.bl-list { display:flex; flex-direction:column; gap:2px; }
.bl-head-row, .bl-row { display:grid; grid-template-columns: minmax(160px,2fr) minmax(110px,1.2fr) 88px 88px 110px 96px 84px; gap:8px; align-items:center; padding:7px 8px; }
.bl-head-row { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); border-bottom:1px solid var(--border2); }
.bl-row { border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); cursor:pointer; font-size:12px; }
.bl-row:hover { border-color:var(--accent); }
.bl-row-settled { opacity:.72; }
.bl-c-amt { text-align:right; font-variant-numeric:tabular-nums; font-weight:600; }
.bl-amt-zero { color:var(--text3); font-weight:400; }
.bl-c-vendor { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.bl-c-ref, .bl-c-date { font-family:var(--mono, ui-monospace, monospace); font-size:11px; color:var(--text2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bl-origin { font-size:10px; padding:1px 7px; border-radius:9px; border:1px solid var(--border2); white-space:nowrap; }
.bl-origin-hub { color:var(--accent); border-color:var(--accent); }
.bl-origin-quickbooks { color:var(--blue); border-color:var(--blue); }
.bl-origin-both { color:var(--success); border-color:var(--success); }
.bill-pill-draft { color:var(--accent); }
.bill-pill-held { color:var(--danger); }
.bill-pill-posted { color:var(--success); }
.bill-pill-paid { color:var(--text3); }
.bill-pill-dismissed { color:var(--text3); }
.bill-pill-fraud { color:var(--danger); border-color:rgba(231,76,60,0.5); }
.bl-detail { display:flex; flex-direction:column; gap:6px; font-size:12px; }
.bl-badges { display:flex; gap:6px; flex-wrap:wrap; margin-bottom:4px; }
.bl-kv { display:grid; grid-template-columns: 130px 1fr; gap:8px; align-items:baseline; }
.bl-k { color:var(--text3); font-size:10px; text-transform:uppercase; letter-spacing:.04em; }
.bl-v { overflow-wrap:anywhere; }
.bl-muted { color:var(--text3); font-size:11px; }
.bl-section { margin-top:10px; padding-top:8px; border-top:1px solid var(--border2); font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); }

/* TKT-1084 — Record a payment. Phone-first: every control is full width and stacks, because iOS
   is the Hub's real operator surface (AM-6491) and this is entered standing at a desk. */
.bl-payments { display:flex; flex-direction:column; gap:6px; }
.bl-pay-summary { display:flex; flex-wrap:wrap; gap:10px; align-items:center; font-size:13px; }
.bl-pay-row { display:flex; flex-wrap:wrap; gap:8px; align-items:baseline; font-size:12px; padding:3px 0; border-bottom:1px solid var(--border2); }
.bl-pay-amt { font-variant-numeric:tabular-nums; font-weight:600; }
.bl-pay-when, .bl-pay-how { color:var(--text2); }
/* Amber, not red: an unreadable store or an overpayment is something to LOOK at, not an error the
   operator caused. Red here would train him to ignore it (AM-6438). */
.bl-pay-warn { font-size:12px; color:var(--warn,#d8a657); border:1px dashed var(--warn,#d8a657); border-radius:6px; padding:5px 8px; }
.bl-pay-form { display:flex; flex-direction:column; gap:7px; margin-top:8px; padding:9px; border:1px solid var(--border2); border-radius:8px; background:var(--surface2); }
.bl-pay-note { font-size:11px; color:var(--text3); }
.bl-pay-f { display:grid; grid-template-columns:110px 1fr; gap:8px; align-items:center; font-size:12px; }
.bl-pay-f > span { color:var(--text2); }
.bl-pay-f input, .bl-pay-f select { width:100%; box-sizing:border-box; }
.bl-pay-actions { display:flex; gap:6px; margin-top:2px; }
.bl-pay-msg { font-size:12px; min-height:1em; }
.bl-pay-ok { color:var(--success,#6fbf73); }
.bl-pay-bad { color:var(--danger,#e06c6c); }
.bl-pay-warnmsg { color:var(--warn,#d8a657); }
/* Status pills reuse the bill-pill shape; only the payment-specific states need a colour. */
.bill-pill-part_paid { color:var(--warn,#d8a657); border-color:var(--warn,#d8a657); }
.bill-pill-overpaid { color:var(--danger,#e06c6c); border-color:var(--danger,#e06c6c); }
.bill-pill-unknown  { color:var(--text3); border-style:dashed; }

@media (max-width:520px) {
  /* Stack the label above the field — a 110px label column leaves nothing for the input. */
  .bl-pay-f { grid-template-columns:1fr; gap:3px; }
}
.bl-source { border:1px solid var(--border2); border-radius:var(--radius); padding:6px 8px; margin-top:6px; }
.bl-source-head { display:flex; justify-content:space-between; align-items:center; gap:8px; flex-wrap:wrap; font-size:11px; }
.bl-source-actions { display:flex; gap:6px; }
.bl-source-frame-host { margin-top:6px; }
.bl-source-frame-host .bill-source-frame { height:420px; max-height:60vh; }
.bl-domain-select { font-size:11px; padding:2px 4px; }
/* TKT-1141 Cash: account + today / scheduled / projected + the QuickBooks comparison; the register
   pullout lines up date, type, name, in, out, balance. Phone: the numbers stack under labels. */
.cash-head-row, .cash-row { display:grid; grid-template-columns: minmax(170px,2fr) repeat(3, minmax(90px,1fr)) minmax(150px,1.4fr); gap:8px; align-items:center; padding:7px 8px; }
.cash-head-row { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); border-bottom:1px solid var(--border2); }
.cash-row { border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); cursor:pointer; font-size:12px; margin-bottom:4px; }
.cash-row:hover { border-color:var(--accent); }
.cash-c-acct { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cash-c-n { text-align:right; font-variant-numeric:tabular-nums; font-weight:600; }
.cash-head-row .cash-c-n { font-weight:500; }
.cash-n-zero { color:var(--text3); font-weight:400; }
.cash-c-q { font-size:11px; }
.cash-q-ok { color:var(--green, #2e7d32); }
.cash-q-diff { color:var(--red, #c62828); font-weight:600; }
.cash-q-none { color:var(--text3); }
.cash-reg-head, .cash-reg-row { display:grid; grid-template-columns: 84px minmax(90px,1fr) 88px 92px; gap:6px; align-items:center; padding:5px 6px; font-size:11px; }
.cash-reg-head { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); border-bottom:1px solid var(--border2); }
.cash-reg-row { border-bottom:1px solid var(--border2); }
.cash-reg-scheduled { background:var(--surface3, rgba(0,0,0,.03)); }
.cash-r-n { text-align:right; font-variant-numeric:tabular-nums; }
.cash-r-name { overflow-wrap:anywhere; }
@media (max-width: 760px) {
  .cash-head-row { display:none; }
  .cash-row { grid-template-columns: repeat(3, 1fr); row-gap:6px; }
  .cash-c-acct, .cash-c-q { grid-column: 1 / -1; white-space:normal; }
  .cash-row .cash-c-n { text-align:left; }
  .cash-row .cash-c-n::before { content: attr(data-b); display:block; font-size:9px; font-weight:400; color:var(--text3); text-transform:uppercase; letter-spacing:.04em; }
  .cash-reg-head, .cash-reg-row { grid-template-columns: 70px minmax(60px,1fr) 76px 80px; font-size:10.5px; }
}
/* TKT-1142 statements on Money › Cash: the list above an account's register (period, matched, ties?),
   one statement's lines (three columns — date, description with what it matched, amount), and the
   per-file result of an upload. */
.cash-reg-head.stmt-line, .cash-reg-row.stmt-line { grid-template-columns: 84px minmax(90px,1fr) 92px; }
.stmt-line-open { background:var(--surface3, rgba(0,0,0,.03)); }
.stmt-elsewhere { color:var(--amber, #b26a00); }
.stmt-head, .stmt-row { display:grid; grid-template-columns: minmax(130px,1.4fr) minmax(90px,1fr) minmax(110px,1fr); gap:6px; align-items:center; padding:5px 6px; font-size:11px; }
.stmt-head { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); border-bottom:1px solid var(--border2); }
.stmt-row { border-bottom:1px solid var(--border2); cursor:pointer; }
.stmt-row:hover { background:var(--surface2); }
.stmt-enter-btn { margin-left:6px; padding:1px 8px; font-size:10.5px; border:1px solid var(--accent); border-radius:var(--radius); background:transparent; color:var(--accent); cursor:pointer; }
.stmt-enter-btn:hover { background:var(--accent); color:var(--bg, #000); }
.stmt-entered { color:var(--accent); }
.stmt-enter-form { margin:4px 6px 10px; padding:8px 10px; border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); display:grid; gap:6px; font-size:12px; }
.stmt-f { display:grid; grid-template-columns: 70px minmax(0,1fr); gap:6px; align-items:center; }
.stmt-f > span { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); }
.stmt-in { width:100%; min-width:0; box-sizing:border-box; }
.stmt-vendor-results:empty { display:none; }
.stmt-vendor-results { padding-left:76px; }
.stmt-enter-actions { display:flex; gap:8px; }
/* TKT-1152 1b: a customer's payment — each open invoice on its line, what the deposit pays on it beneath. */
.stmt-invoices { display:grid; gap:4px; }
.stmt-inv { padding:4px 0; border-bottom:1px solid var(--border2); }
.stmt-inv-pick { display:block; overflow-wrap:anywhere; }
.stmt-inv-amt { display:inline-flex; align-items:center; gap:4px; margin:3px 10px 0 22px; }
.stmt-inv-amt > span { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); }
.stmt-inv-amt .stmt-in { width:88px; }
.stmt-upload { margin:6px 0 8px; padding:8px 10px; border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); font-size:12px; line-height:1.6; }
@media (max-width: 760px) {
  .cash-reg-head.stmt-line, .cash-reg-row.stmt-line { grid-template-columns: 70px minmax(60px,1fr) 76px; }
  .stmt-head, .stmt-row { grid-template-columns: minmax(90px,1.3fr) minmax(70px,1fr) minmax(80px,1fr); font-size:10.5px; }
  .stmt-f { grid-template-columns: 1fr; gap:2px; }
  .stmt-vendor-results { padding-left:0; }
}
/* TKT-1021 Inventory Balances: item + seven bucket columns + available + last movement. Reuses the
   bl-row skin (border, hover, tabular numbers) with its own grid so the numeric columns line up. */
.ib-head-row, .ib-row { display:grid; grid-template-columns: minmax(170px,2fr) repeat(8, minmax(64px,1fr)) 118px; gap:8px; align-items:center; padding:7px 8px; }
.ib-head-row { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); border-bottom:1px solid var(--border2); }
.ib-row { border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); cursor:pointer; font-size:12px; }
.ib-row:hover { border-color:var(--accent); }
.ib-c-item { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ib-c-n { text-align:right; font-variant-numeric:tabular-nums; font-weight:600; }
.ib-head-row .ib-c-n { font-weight:500; }
.ib-n-zero { color:var(--text3); font-weight:400; }
.ib-c-when, .ib-c-src { font-family:var(--mono, ui-monospace, monospace); font-size:11px; color:var(--text2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ib-mov-head, .ib-mov-row { display:grid; grid-template-columns: 118px 84px 56px minmax(120px,1.4fr) minmax(120px,1fr); gap:8px; align-items:center; padding:5px 6px; font-size:11px; }
.ib-mov-head { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); border-bottom:1px solid var(--border2); }
.ib-mov-row { border-bottom:1px solid var(--border2); }
.ib-c-move { overflow-wrap:anywhere; }
@media (max-width: 760px) {
  .ib-head-row { display:none; }
  .ib-row { grid-template-columns: repeat(4, 1fr); row-gap:6px; }
  .ib-c-item { grid-column: 1 / -1; white-space:normal; }
  .ib-row .ib-c-n { text-align:left; }
  .ib-row .ib-c-n::before { content: attr(data-b); display:block; font-size:9px; font-weight:400; color:var(--text3); text-transform:uppercase; letter-spacing:.04em; }
  .ib-row .ib-c-when { grid-column: 1 / -1; white-space:normal; }
  .ib-mov-head { display:none; }
  .ib-mov-row { grid-template-columns: 1fr 1fr 1fr; }
  .ib-mov-row .ib-c-move, .ib-mov-row .ib-c-src { grid-column: 1 / -1; white-space:normal; }
}
/* TKT-1027 Rentals: the fleet list (die / status / customer / out since / days) on the ib-row skin,
   status counters as tap targets, the register + action forms, the customer picker. Phone-first:
   under 760px the row folds to labelled cells the way Inventory Balances does. */
.ru-stats { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:12px; }
.ru-stat { min-height:44px; min-width:96px; display:flex; flex-direction:column; align-items:flex-start; gap:2px; padding:6px 10px; border:1px solid var(--border2); border-radius:var(--radius); color:inherit; cursor:pointer; font-size:11px; }
.ru-stat b { font-size:16px; }
.ru-stat-on { border-color:var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.ru-head-row, .ru-row { display:grid; grid-template-columns: minmax(180px,2fr) 150px minmax(140px,1.4fr) 110px 70px; gap:8px; align-items:center; padding:8px; }
.ru-head-row { font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:var(--text3); border-bottom:1px solid var(--border2); }
.ru-row { border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); cursor:pointer; font-size:12px; min-height:44px; margin-top:4px; }
.ru-row:hover { border-color:var(--accent); }
.ru-c-die { overflow:hidden; text-overflow:ellipsis; }
.ru-form { display:flex; flex-wrap:wrap; gap:10px; }
.ru-facts { display:grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap:8px 14px; padding:8px 10px; border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); font-size:12px; }
.ru-facts > div { display:flex; flex-direction:column; gap:2px; }
.ru-action { border:1px solid var(--border2); border-radius:var(--radius); padding:10px; margin:6px 0 12px; background:var(--surface2); }
.ru-insp { padding:6px 0; border-bottom:1px solid var(--border2); font-size:12px; }
.ru-cust-hits { position:absolute; left:0; right:0; top:100%; z-index:5; display:flex; flex-direction:column; gap:2px; background:var(--surface, #0e1116); }
/* TKT-1024 Work Orders: the list on the ru-row skin with its own five columns; steps, parts and
   nested builds as tap-sized rows. Under 760px the list folds like Rentals and the step / part
   rows wrap their action buttons onto their own line. */
.ru-head-row.wo-grid, .ru-row.wo-grid { grid-template-columns: minmax(200px,2.4fr) 130px 130px 110px 80px; }
/* TKT-1028 Rentals R2: the Agreements list (die · customer · shipped · weeks billed · next draft) and
   the billing history (week · period · amount · status · actions) on the same ru-row skin; both fold
   to the two-column card under 760px through the generic .ru-row rule below. */
.ru-head-row.ru-ag-grid, .ru-row.ru-ag-grid { grid-template-columns: minmax(200px,2.2fr) minmax(140px,1.4fr) 110px 110px 120px; }
.ru-head-row.ru-bp-grid, .ru-row.ru-bp-grid { grid-template-columns: 110px minmax(180px,1.6fr) 90px minmax(140px,1fr) minmax(200px,1.4fr); }
@media (max-width: 760px) {
  .ru-row.ru-bp-grid .ru-c:last-child { grid-column: 1 / -1; display:flex; gap:8px; flex-wrap:wrap; }
}
.wo-step, .wo-line { display:grid; gap:8px; align-items:center; padding:8px 6px; border-bottom:1px solid var(--border2); font-size:12px; min-height:44px; }
.wo-step { grid-template-columns: 28px 1fr auto; }
.wo-step-n { display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; border-radius:13px; border:1px solid var(--border2); font-size:11px; }
.wo-step-done .wo-step-n { background:rgba(63,185,80,.25); border-color:rgba(63,185,80,.5); }
.wo-step-done .wo-step-text { color:var(--text2); }
.wo-step-act, .wo-line-act { display:flex; gap:6px; }
.wo-line { grid-template-columns: minmax(140px,2fr) 70px minmax(150px,1.2fr) auto; }
.wo-line-qty { text-align:right; font-variant-numeric:tabular-nums; font-weight:600; }
.wo-child { padding:8px; border:1px solid var(--border2); border-radius:var(--radius); background:var(--surface2); margin-top:4px; cursor:pointer; min-height:44px; display:flex; align-items:center; gap:8px; }
.wo-child:hover { border-color:var(--accent); }
@media (max-width: 760px) {
  .wo-step { grid-template-columns: 28px 1fr; }
  .wo-step-act { grid-column: 1 / -1; }
  .wo-line { grid-template-columns: 1fr auto; }
  .wo-line-src, .wo-line-act { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
  .ru-head-row { display:none; }
  .ru-row { grid-template-columns: repeat(2, 1fr); row-gap:6px; }
  .ru-c-die { grid-column: 1 / -1; white-space:normal; }
  .ru-row .ru-c::before { content: attr(data-b); display:block; font-size:9px; font-weight:400; color:var(--text3); text-transform:uppercase; letter-spacing:.04em; }
  .ru-row .ib-c-n { text-align:left; }
}
@media (max-width: 760px) {
  .bl-head-row { display:none; }
  .bl-row { grid-template-columns: 1fr auto; grid-template-areas: "vendor amt" "ref status" "date origin"; }
  .bl-c-vendor { grid-area:vendor; } .bl-c-amt { grid-area:amt; } .bl-c-ref { grid-area:ref; }
  .bl-c-status { grid-area:status; text-align:right; } .bl-c-origin { grid-area:origin; text-align:right; }
  .bl-c-date:nth-of-type(4) { display:none; }
  .bl-c-date { grid-area:date; }
}
/* TKT-221 segment-and-flag: Queue vs Set-aside tabs + set-aside reason / uncertain chips. */
.bill-seg-tabs { display:flex; gap:6px; margin:6px 0 2px; }
.bill-seg-tab { font-size:11px; padding:3px 10px; border-radius:10px 10px 0 0; border:1px solid var(--border2); border-bottom:none; background:var(--surface2); color:var(--text2); cursor:pointer; }
.bill-seg-tab:hover { color:var(--accent); }
.bill-seg-on { background:var(--surface); color:var(--text); border-color:var(--accent); font-weight:600; }
.bill-seg-n { font-family:var(--font-mono); color:var(--text2); }
.bill-seg-uncertain { color:var(--danger); font-family:var(--font-mono); }
.bill-row-reason { font-size:10px; padding:1px 6px; border-radius:10px; border:1px solid var(--border2); color:var(--text2); background:var(--surface2); }
.bill-row-uncertain { font-size:10px; padding:1px 6px; border-radius:10px; border:1px solid var(--danger); color:var(--danger); letter-spacing:0.02em; }
/* TKT-602 — the classifier flagged this as probable fraud. Deliberately the loudest thing in
   the list: filled, not outlined, so it cannot be mistaken for the softer "maybe a bill" chip. */
.bill-row-suspicious { font-size:10px; padding:1px 7px; border-radius:10px; background:var(--danger); color:#fff; font-weight:700; letter-spacing:0.04em; }
.bill-row-suspicious-row { border-left-color:var(--danger); border-left-width:4px; background:color-mix(in srgb, var(--danger) 7%, var(--surface2)); }
.bill-row-suspicion-why { margin-top:4px; font-size:11px; color:var(--danger); font-style:italic; line-height:1.35; }
.bill-banner-fraud { border-color:var(--danger); }
/* TKT-604 — the "why this was flagged / what to correct" panel inside the fraud banner. Quiet
   typography on purpose: the banner is the alarm, this is the instruction sheet. */
.bill-flag-why { margin-top:10px; padding-top:8px; border-top:1px solid var(--border2); }
.bill-flag-why-h { font-size:11px; font-weight:700; letter-spacing:0.04em; text-transform:uppercase; color:var(--text2); margin-bottom:6px; }
.bill-flag-fact { display:grid; grid-template-columns:170px 1fr; gap:8px; font-size:12px; padding:3px 0; align-items:baseline; }
.bill-flag-fact-k { color:var(--text3); }
.bill-flag-fact-v { color:var(--text); font-family:var(--font-mono); word-break:break-word; }
.bill-flag-fact-d { grid-column:2; color:var(--text3); font-size:11px; font-style:italic; line-height:1.4; margin-top:2px; }
.bill-flag-fact-weak .bill-flag-fact-v { color:var(--danger); font-weight:600; }
.bill-flag-fix { margin:8px 0 0; padding-left:18px; font-size:12px; line-height:1.5; color:var(--text); }
.bill-flag-fix li { margin-bottom:5px; }
.bill-flag-note { margin-top:8px; font-size:11px; color:var(--text3); font-style:italic; }
@media (max-width:860px) { .bill-flag-fact { grid-template-columns:1fr; gap:0; } .bill-flag-fact-d { grid-column:1; } }
.bill-row-flag { border-left-color:var(--danger); }
.bill-status-review { border-left-color:var(--accent); }
.bill-status-previewed { border-left-color:var(--blue); }
.bill-status-held { border-left-color:var(--danger); }
.bill-status-posted { border-left-color:var(--success); }
.bill-status-dismissed { border-left-color:var(--text3); opacity:0.7; }
.bill-status-fraud { border-left-color:var(--danger); background:rgba(231,76,60,0.06); }
.bill-pill { font-size:10px; padding:1px 6px; border-radius:10px; border:1px solid var(--border2); text-transform:uppercase; letter-spacing:0.03em; }
.bill-pill-bill-status-review { color:var(--accent); }
.bill-pill-bill-status-previewed { color:var(--blue); }
.bill-pill-bill-status-held { color:var(--danger); }
.bill-pill-bill-status-posted { color:var(--success); }
.bill-pill-bill-status-dismissed { color:var(--text3); }
.bill-pill-bill-status-fraud { color:var(--danger); border-color:rgba(231,76,60,0.5); }
.bill-list-head-ctrls { display:flex; align-items:center; gap:6px; }
.bill-filter-toggle { font-size:11px; padding:2px 9px; border-radius:10px; border:1px solid var(--border2); background:var(--surface2); color:var(--text2); cursor:pointer; }
.bill-filter-toggle:hover { border-color:var(--accent); color:var(--accent); }
/* TKT-1009: the domain toggle in its WIDENED (show all domains) state — visibly not the default. */
.bill-filter-toggle-on { border-color:var(--accent); color:var(--accent); background:var(--surface); }
.bill-dismiss-btn { color:var(--text3); }
.bill-empty { color:var(--text3); padding:24px; text-align:center; font-size:13px; }

.bill-review-head { display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:10px; padding-bottom:8px; border-bottom:1px solid var(--border); }
.bill-review-title { font-family:var(--font-display); font-size:15px; color:var(--text); }
.bill-banner { border-radius:var(--radius); padding:8px 10px; margin-bottom:10px; font-size:12px; }
.bill-banner-block { background:rgba(231,76,60,0.1); border:1px solid rgba(231,76,60,0.4); color:var(--danger); }
.bill-banner-soft { background:rgba(243,156,18,0.08); border:1px solid rgba(243,156,18,0.3); color:var(--warning); }
.bill-banner-ok { background:rgba(46,204,113,0.08); border:1px solid rgba(46,204,113,0.3); color:var(--success); }
/* TKT-457 piece 4 — the link-bill-to-PO picker inside the open-PO banner */
.bill-po-pick { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:8px; color:var(--text); }
.bill-po-pick > div { flex-basis:100%; }
/* TKT-456/459 — live-gate banner accent, line delete, readiness chips */
.bill-gate-live { background:rgba(231,76,60,0.12); border:1px solid rgba(231,76,60,0.45); color:var(--danger); font-weight:600; }
.bill-line-deleted td { opacity:0.55; }
.bill-line-del { background:none; border:none; color:var(--danger); cursor:pointer; font-size:13px; padding:2px 6px; opacity:0.6; }
.bill-line-del:hover { opacity:1; }
.bill-readiness { display:flex; flex-wrap:wrap; gap:8px; margin:10px 0 2px; }
.bill-ready { font-size:12px; padding:3px 10px; border-radius:14px; border:1px solid var(--border,#334); }
.bill-ready-ok { background:rgba(46,204,113,0.10); border-color:rgba(46,204,113,0.4); color:var(--success); }
.bill-ready-no { background:rgba(148,163,184,0.08); color:var(--muted,#8a94a1); }
.bill-dup-list { margin:6px 0 0; padding-left:18px; }
.bill-dup-list li { margin:2px 0; }
.bill-dup-strong { font-weight:700; font-size:10px; padding:1px 5px; border-radius:3px; background:rgba(231,76,60,0.18); color:var(--danger); }

/* ── AR Reminders tab (TKT-179/150) — reuses the bill-* layout; these add the stage/status
   pills, the email + invoice-PDF preview, and the batch-approve row. ── */
.ar-batch-row { margin:8px 0 6px; }
.ar-list-section-head { font-size:11px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); margin:10px 4px 4px; }
.ar-stage-arpre { color:var(--text3); }
.ar-stage-arpd1 { color:var(--blue); }
.ar-stage-arpdw { color:var(--warning); }
.ar-stage-arfin { color:var(--danger); }
.ar-status-arq { color:var(--accent); }
.ar-status-arsent { color:var(--success); }
.ar-status-arblock { color:var(--warning); }
.ar-status-arskip { color:var(--text3); }
.ar-status-arerr { color:var(--danger); }
.ar-detail-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px 12px; margin-bottom:10px; }
.ar-email-preview { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:10px; margin-bottom:10px; }
.ar-email-subject { font-size:13px; color:var(--text); margin-bottom:6px; }
.ar-email-body { font-family:var(--font-mono,monospace); font-size:12px; color:var(--text2); white-space:pre-wrap; word-break:break-word; margin:0; max-height:240px; overflow:auto; }
.ar-pdf-preview { margin-bottom:10px; }
.ar-pdf-label { font-size:11px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); margin-bottom:4px; }
.ar-pdf-frame { width:100%; height:420px; border:1px solid var(--border); border-radius:var(--radius); background:#fff; }
.ar-resumed-tag { font-size:10px; color:var(--warning); border:1px solid rgba(243,156,18,0.4); border-radius:10px; padding:1px 6px; }

/* Holds panel + the "hold until" form */
.ar-holds-panel { border:1px solid var(--border); border-radius:var(--radius); padding:8px 10px; margin-bottom:12px; background:var(--surface2); }
.ar-holds-head { display:flex; align-items:center; justify-content:space-between; gap:10px; }
.ar-holds-title { font-family:var(--font-display); font-size:13px; color:var(--text); }
.ar-holds-ctrls { display:flex; gap:6px; }
.ar-holds-empty { font-size:12px; color:var(--text3); padding:6px 2px 2px; }
.ar-hold-list { margin-top:8px; display:flex; flex-direction:column; gap:6px; }
.ar-hold-row { border:1px solid var(--border); border-radius:var(--radius); padding:6px 8px; background:var(--surface); }
.ar-hold-row.ar-hold-released, .ar-hold-row.ar-hold-expired { opacity:0.6; }
.ar-hold-main { display:flex; align-items:center; gap:8px; flex-wrap:wrap; font-size:12px; }
.ar-hold-scope { font-size:10px; text-transform:uppercase; letter-spacing:0.03em; color:var(--text3); border:1px solid var(--border2); border-radius:10px; padding:1px 6px; }
.ar-hold-target { font-weight:600; color:var(--text); }
.ar-hold-until { color:var(--text2); }
.ar-hold-state { color:var(--text3); }
.ar-hold-note { font-size:11px; color:var(--text3); margin-top:3px; }
.ar-hold-actions { display:flex; gap:6px; margin-top:4px; }
.ar-hold-edit { display:flex; gap:6px; align-items:center; margin-top:4px; }
.ar-hold-form { border:1px solid var(--border); border-radius:var(--radius); padding:10px; margin-top:10px; background:var(--surface2); }
.ar-hold-form-title { font-size:12px; color:var(--text); margin-bottom:8px; }
.ar-hold-form-row { display:flex; gap:12px; align-items:center; flex-wrap:wrap; margin-bottom:8px; font-size:12px; }
.ar-hold-form-actions { display:flex; gap:6px; }

.bill-vendor-confirmed { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:8px 10px; margin-bottom:10px; font-size:13px; }
.bill-vendor-pick { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:10px; margin-bottom:10px; }
.bill-vendor-search { display:flex; gap:6px; }
.bill-vendor-search input { flex:1 1 auto; }
.bill-cands { margin-top:8px; }
.bill-cands-head { font-size:11px; color:var(--text3); margin-bottom:6px; }
.bill-cand { border:1px solid var(--border); border-radius:var(--radius); padding:6px 8px; margin-bottom:4px; cursor:pointer; background:var(--surface); }
.bill-cand:hover { border-color:var(--accent); }
.bill-cand-main { display:flex; gap:8px; align-items:baseline; }
.bill-cand-conf { font-size:10px; padding:0 5px; border-radius:8px; border:1px solid var(--border2); }
.bill-conf-high { color:var(--success); }
.bill-conf-medium { color:var(--warning); }
.bill-conf-low { color:var(--text3); }
.bill-cand-meta { font-size:11px; color:var(--text3); font-family:var(--font-mono); margin-top:2px; }

.bill-header-grid { display:grid; grid-template-columns:repeat(3, 1fr); gap:10px; margin-bottom:12px; }
/* TKT-1056 — "Enter a bill by hand": the form in the review column, and the typed mark on a row. */
.bill-manual .bill-field { margin-bottom:10px; min-width:0; }
.bill-manual .bill-field input { width:100%; min-width:0; box-sizing:border-box; }   /* a date input's intrinsic width must not push its grid column past the form */
.bill-manual .bill-header-grid { grid-template-columns:repeat(4, 1fr); }
.bill-manual .bm-po { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:5px 7px; color:var(--text); font-size:12px; max-width:100%; }
.bm-lines { margin:6px 0 10px; }
.bm-line { display:grid; grid-template-columns:minmax(0,3fr) minmax(0,1.3fr) minmax(0,0.7fr) minmax(0,1fr) minmax(0,1fr) auto; gap:6px; align-items:center; margin-bottom:5px; }
.bm-line input { min-width:0; background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:5px 7px; color:var(--text); font-size:12px; }
.bm-line .bm-qty, .bm-line .bm-price, .bm-line .bm-amt { font-family:var(--font-mono); text-align:right; }
.bm-line-head { font-size:10px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); }
.bm-line-head .bm-qty, .bm-line-head .bm-price, .bm-line-head .bm-amt { font-family:inherit; }
.bm-total { font-size:13px; margin-bottom:10px; }
.bm-total b { font-family:var(--font-mono); }
.bill-row-typed { color:var(--accent); }
@media (max-width: 760px) {
  .bill-manual .bill-header-grid { grid-template-columns:1fr 1fr; }
  .bm-line { grid-template-columns:1fr 1fr 1fr auto; }
  .bm-line .bm-desc { grid-column:1 / -1; }
  .bm-line .bm-part { grid-column:1 / -1; }
  .bm-line-head { display:none; }
}
.bill-field { display:flex; flex-direction:column; gap:3px; }
.bill-field label { font-size:11px; color:var(--text3); }
.bill-field input { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:5px 7px; color:var(--text); font-size:12px; }
.bill-field input:disabled { opacity:0.6; }

.bill-lines-table { width:100%; border-collapse:collapse; font-size:12px; margin-bottom:8px; }
.bill-lines-table th { text-align:left; font-size:10px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); padding:4px 6px; border-bottom:1px solid var(--border); }
.bill-lines-table td { padding:6px; border-bottom:1px solid var(--border); vertical-align:top; }
.bill-l-amt, .bill-l-qty { font-family:var(--font-mono); }
.bill-acct-select { width:100%; max-width:340px; background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:4px 6px; color:var(--text); font-size:12px; }
/* Editable line amount — a mis-read figure corrected in place. Corrected = the scan's figure shown beside it. */
.bill-amt-input { width:96px; text-align:right; font-family:var(--font-mono); background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:3px 6px; color:var(--text); font-size:12px; }
.bill-amt-input.bill-amt-corrected, #billTotal.bill-amt-corrected { border-color:var(--warn, #d9a441); background:color-mix(in srgb, var(--warn, #d9a441) 12%, var(--surface2)); }
.bill-amt-was { display:block; font-size:10px; color:var(--muted); text-decoration:line-through; white-space:nowrap; }
.bill-src { display:inline-block; margin-top:3px; font-size:10px; padding:1px 6px; border-radius:8px; }
.bill-src-auto { color:var(--success); background:rgba(39,174,96,0.1); }
.bill-src-pick { color:var(--warning); background:rgba(243,156,18,0.1); }
.bill-src-none { color:var(--text3); }
.bill-line-charge td { background:rgba(52,152,219,0.05); }
.bill-charge-tag { display:inline-block; font-size:9px; text-transform:uppercase; letter-spacing:0.04em; padding:1px 5px; border-radius:7px; color:var(--accent,#3498db); background:rgba(52,152,219,0.12); vertical-align:middle; }
.bill-muted { color:var(--text3); }
.bill-ok { color:var(--success); }
.bill-warn { color:var(--warning); }

.bill-recon { font-size:12px; padding:6px 8px; border-radius:var(--radius); margin-bottom:12px; }
.bill-recon-ok { background:rgba(39,174,96,0.07); border:1px solid rgba(39,174,96,0.25); }
.bill-recon-bad { background:rgba(243,156,18,0.08); border:1px solid rgba(243,156,18,0.3); }

.bill-actions { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin:10px 0; }
/* touch-action: remove the tap delay / double-tap-zoom so action buttons fire reliably on a
   phone (TKT-221 — Craig's mobile-as-coordination-layer). */
.bill-actions .btn { touch-action:manipulation; }
.bill-gate-hint { font-size:11px; color:var(--text3); }
.bill-post-btn:disabled { opacity:0.5; cursor:not-allowed; }
.bill-source-btn { color:var(--text2); }
.bill-fraud-btn { color:var(--danger); }
.bill-fraud-btn:hover { background:rgba(231,76,60,0.1); }

/* Inline source-document viewer (TKT-221): the original invoice PDF / email shown in place. */
.bill-source-view { margin:0 0 12px; }
.bill-source-view:empty { display:none; }
.bill-source-bar { display:flex; align-items:center; justify-content:space-between; gap:8px; font-size:12px; padding:6px 8px; background:var(--surface2); border:1px solid var(--border); border-bottom:none; border-radius:var(--radius) var(--radius) 0 0; color:var(--text2); }
.bill-source-bar-actions { display:flex; align-items:center; gap:10px; }
.bill-source-open { font-size:11px; color:var(--accent); text-decoration:none; }
.bill-source-open:hover { text-decoration:underline; }
.bill-source-frame { width:100%; height:640px; max-height:75vh; border:1px solid var(--border); border-radius:0 0 var(--radius) var(--radius); background:var(--surface); }
.bill-source-loading { font-size:12px; color:var(--text3); padding:14px; text-align:center; }
.bill-source-err { font-size:12px; color:var(--warning); background:rgba(243,156,18,0.08); border:1px solid rgba(243,156,18,0.3); border-radius:var(--radius); padding:8px 10px; }

/* Mobile: the two-column Bill Review layout must STACK on a narrow screen, otherwise the fixed
   320px list column crushes the review pane (and its action buttons) into an unusable sliver —
   the real cause of "the buttons don't fire on my phone" (TKT-221). On desktop it is unchanged. */
/* TKT-1082: the "Back to the list" button exists only when the list is stacked above the bill (hub-bills.js
   scrolls the bill to just under the pinned header, measured at the moment of the tap). */
.bill-back-to-list { display:none; }
@media (max-width: 860px) {
  .bill-layout { flex-direction:column; }
  .bill-list-col { flex:1 1 auto; max-width:none; width:100%; }
  .bill-review-col { width:100%; }
  .bill-back-to-list { display:inline-flex; margin-bottom:8px; min-height:40px; }
  .bill-source-frame { height:70vh; }
}
/* TKT-1283 — LIST BESIDE DETAIL: only the list scrolls, the selected record stays in view. One rule for every
   screen built on .bill-layout (Bill Review, AR Reminders). Each column is pinned under the header and the
   pinned nav (--hub-chrome-h, measured in hub-nav-collapse.js) and capped at the viewport, so the LIST scrolls
   inside its own column and scrolling it never moves the detail; a long detail scrolls inside its own column.
   Sticky needs every ancestor up to the window to NOT be a scroll container, and .ir-page (overflow:hidden) and
   .ir-page-body (overflow-y:auto, but never height-bounded, so it never scrolled) both were — which is why a
   sticky column alone measured as doing nothing (2026-10-07). Desktop only: stacked (≤860px) the window
   scrolls the list and hub-bills.js scrolls a tapped bill into view (TKT-1082). */
@media (min-width: 861px) {
  .ir-page:has(> .ir-page-body > .bill-layout),
  .ir-page:has(> .ir-page-body > .bill-layout) > .ir-page-body { overflow: visible; }
  .bill-layout > .bill-list-col,
  .bill-layout > .bill-review-col {
    position: sticky;
    top: calc(var(--hub-chrome-h, 52px) + 8px);
    max-height: calc(100vh - var(--hub-chrome-h, 52px) - 16px);
    max-height: calc(100dvh - var(--hub-chrome-h, 52px) - 16px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
.bill-form-err { color:var(--danger); font-size:12px; margin:6px 0; }
.bill-warn-inline { font-size:11px; color:var(--warning); margin-top:6px; }

/* TKT-962 — the second-transaction panel. The blocked variant is styled APART from the proposal
   on purpose: one is a routine confirmation, the other says a real payment cannot be recorded and
   the bill will post OPEN. They must not read alike at a glance. */
.bill-pay-panel { margin:10px 0 4px; padding:10px 12px; border-radius:6px; border-left:3px solid; }
.bill-pay-ok { border-color:var(--success); background:color-mix(in srgb, var(--success) 8%, transparent); }
.bill-pay-warn { border-color:var(--warning); background:color-mix(in srgb, var(--warning) 10%, transparent); }
.bill-pay-title { font-weight:600; font-size:13px; margin-bottom:3px; }
.bill-pay-warn .bill-pay-title { color:var(--warning); }
.bill-pay-detail { font-size:12px; opacity:.9; line-height:1.45; }
.bill-pay-check { display:flex; align-items:center; gap:6px; margin-top:8px; font-size:12px; cursor:pointer; }

.bill-preview-result { border-radius:var(--radius); padding:10px; margin-top:10px; font-size:12px; }
.bill-prev-ok { background:rgba(39,174,96,0.06); border:1px solid rgba(39,174,96,0.25); }
.bill-prev-warn { background:rgba(243,156,18,0.07); border:1px solid rgba(243,156,18,0.3); }
.bill-preview-head { font-weight:600; margin-bottom:6px; }
/* TKT-1007 — what QuickBooks will receive: the posted lines as a table above the raw payload */
.bill-posted-head { font-weight:600; margin:10px 0 2px; }
.bill-posted-note { margin-bottom:6px; }
.bill-posted-table { margin-bottom:8px; }
.bill-payload-details summary { cursor:pointer; margin:6px 0 4px; }
.bill-issues { margin:4px 0 8px 16px; color:var(--warning); }
.bill-payload { background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:8px; font-family:var(--font-mono); font-size:11px; color:var(--text2); max-height:240px; overflow:auto; white-space:pre; }
.bill-commit-result { border-radius:var(--radius); padding:10px; margin-top:10px; font-size:13px; }
.bill-commit-ok { background:rgba(39,174,96,0.08); border:1px solid rgba(39,174,96,0.3); color:var(--success); }
.bill-commit-blocked { background:rgba(243,156,18,0.08); border:1px solid rgba(243,156,18,0.35); color:var(--warning); }
.btn-sm { font-size:11px; padding:2px 8px; }

/* ── Betty tab (TKT-161 Hub trigger — render + preview a QB document) ───────── */
.betty-layout { display:flex; gap:16px; align-items:flex-start; }
.betty-form-col { flex:0 0 320px; max-width:320px; }
.betty-preview-col { flex:1 1 auto; min-width:0; }
.betty-note { font-size:11px; color:var(--text2); background:rgba(52,152,219,0.07); border:1px solid rgba(52,152,219,0.25); border-radius:var(--radius); padding:8px 10px; margin-bottom:12px; line-height:1.4; }
.betty-field { display:flex; flex-direction:column; gap:3px; margin-bottom:10px; }
.betty-field label { font-size:11px; color:var(--text3); }
.betty-field input, .betty-field select { background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:6px 8px; color:var(--text); font-size:12px; }
.betty-actions { margin-top:6px; }
.betty-form-err { color:var(--danger); font-size:12px; margin:6px 0; }
/* Customs / export sub-form: a distinct note tint + a two-up field row. */
.betty-note-export { background:rgba(155,89,182,0.08); border-color:rgba(155,89,182,0.30); }
.betty-field-row { display:flex; gap:8px; }
.betty-field-row .betty-field { flex:1 1 0; min-width:0; }
.betty-empty { color:var(--text3); padding:24px; text-align:center; font-size:13px; }
.betty-muted { color:var(--text3); }
.betty-ok { color:var(--success); font-weight:600; }

.betty-result-msg { border-radius:var(--radius); padding:14px; font-size:13px; }
.betty-result-notfound { background:rgba(243,156,18,0.07); border:1px solid rgba(243,156,18,0.3); color:var(--warning); }
.betty-result-error { background:rgba(231,76,60,0.07); border:1px solid rgba(231,76,60,0.3); }
.betty-result-head { color:var(--danger); margin-bottom:4px; }
.betty-result-hint { font-size:11px; color:var(--text3); }

.betty-result-bar { display:flex; align-items:center; gap:10px; margin-bottom:10px; padding-bottom:8px; border-bottom:1px solid var(--border); flex-wrap:wrap; }
.betty-meta { display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:4px 16px; margin-bottom:8px; }
.betty-meta-row { display:flex; justify-content:space-between; gap:8px; font-size:12px; border-bottom:1px dotted var(--border); padding:3px 0; }
.betty-meta-k { color:var(--text3); }
.betty-meta-v { color:var(--text); font-family:var(--font-mono); text-align:right; }
.betty-filed { font-size:11px; color:var(--text2); margin-bottom:10px; }
.betty-pdf-frame { border:1px solid var(--border); border-radius:var(--radius); overflow:hidden; background:var(--surface2); }
.betty-pdf { width:100%; height:640px; border:0; display:block; background:#fff; }

/* ── Project Graph tab — TheBrain-style navigable plex (TKT-220, Phase 1) ──────────
   The SVG itself carries inline tone colours (so it renders identically in the static
   preview + offline tests); these rules cover the chrome (toolbar, breadcrumb, legend)
   and the theme-aware SVG TEXT, which rides classes so it adapts to the dark Hub. */
.graph-beta-tag { font-family:var(--font-mono); font-size:10px; color:var(--accent); border:1px solid var(--accent-glow); border-radius:10px; padding:1px 7px; margin-left:8px; vertical-align:middle; }

.graph-toolbar { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:8px; }
.graph-toolbar-right { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }

/* Inline authoring (TKT-288 item 7) — "+ Add department/initiative" on the focused node. */
.graph-add-btn { font:inherit; font-size:12px; padding:5px 11px; border-radius:var(--radius); border:1px dashed var(--border2); background:transparent; color:var(--text2); cursor:pointer; }
.graph-add-btn:hover { border-color:var(--accent); border-style:solid; color:var(--accent); }
.graph-add-form { display:inline-flex; align-items:center; gap:6px; flex-wrap:wrap; }
.graph-add-input { font:inherit; font-size:12px; padding:5px 8px; border-radius:var(--radius); border:1px solid var(--border2); background:var(--surface2); color:var(--text); min-width:160px; }
.graph-add-input:focus { outline:none; border-color:var(--accent); }
.graph-add-save { font:inherit; font-size:12px; padding:5px 11px; border-radius:var(--radius); border:1px solid var(--accent); background:var(--accent-dim); color:var(--accent); cursor:pointer; }
.graph-add-save:disabled { opacity:0.5; cursor:not-allowed; }
.graph-add-cancel { font:inherit; font-size:12px; padding:5px 9px; border-radius:var(--radius); border:1px solid var(--border2); background:transparent; color:var(--text3); cursor:pointer; }
.graph-add-cancel:hover { color:var(--danger); border-color:var(--danger); }
.graph-add-error { font-size:11px; color:var(--danger); }

/* Breadcrumb path from the all-domains root to the current focus. */
.graph-crumbs { display:flex; align-items:center; gap:4px; flex-wrap:wrap; font-size:12.5px; }
.graph-crumb { background:none; border:none; cursor:pointer; color:var(--text2); font:inherit; padding:2px 4px; border-radius:4px; max-width:22ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.graph-crumb:last-child { max-width:32ch; color:var(--text); }
@media (max-width: 640px) { .graph-crumb { max-width:14ch; } .graph-crumb:last-child { max-width:22ch; } }
.graph-crumb:hover { color:var(--text); background:var(--surface3); }
.graph-crumb-sep { color:var(--text3); }

/* The colour legend (TKT-1210) — one row of lane chips with counts for the focus. A tap opens the
   focus's list filtered to that colour. The row scrolls inside itself; the page never scrolls sideways. */
.graph-legend-row { display:flex; gap:6px; overflow-x:auto; padding:2px 0 8px; scrollbar-width:none; -webkit-overflow-scrolling:touch; }
.graph-legend-row::-webkit-scrollbar { display:none; }
.graph-lchip { font:inherit; font-size:12px; flex:0 0 auto; display:inline-flex; align-items:center; gap:6px; padding:4px 10px; min-height:30px; border-radius:15px; border:1px solid var(--border2); background:var(--surface2); color:var(--text2); cursor:pointer; white-space:nowrap; }
.graph-lchip b { font-family:var(--font-mono); font-weight:600; color:var(--text); }
.graph-lchip.is-on { border-color:var(--accent); color:var(--accent); background:var(--accent-dim); }
.graph-ldot { width:10px; height:10px; border-radius:50%; flex-shrink:0; }

/* The stage (TKT-1210): the map is the centrepiece, drawn at the width it is given, and scrolls with
   the page. The tile follows the Customers screen's side window: on the large tier a pane pinned
   beside the map below the Hub's header (the map is re-drawn in the width left); below it a sheet
   over the screen from the right edge, above the header, with a backdrop that closes it on a tap. */
.graph-stage { display:grid; grid-template-columns:minmax(0, 1fr); gap:10px; align-items:start; }
.graph-stage.is-wide.has-drawer { grid-template-columns:minmax(0, 1fr) var(--graph-drawer-w); }
.graph-canvas { min-width:0; min-height:320px; padding:6px; overflow-x:hidden; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); }
.graph-svg { display:block; }
.graph-map-svg { margin:0 auto; }

/* The tile. */
.graph-drawer { display:flex; flex-direction:column; min-width:0; background:var(--surface2); border:1px solid var(--border2); border-radius:var(--radius); transition:transform 0.2s ease, opacity 0.2s ease; }
.graph-stage.is-wide .graph-drawer { position:sticky; top:calc(var(--hub-chrome-h, 52px) + 8px); max-height:calc(100vh - var(--hub-chrome-h, 52px) - 16px); }
.graph-stage.is-wide .graph-drawer.is-entering, .graph-stage.is-wide .graph-drawer.is-leaving { transform:translateX(24px); opacity:0; }
.graph-stage.is-narrow .graph-drawer { position:fixed; top:0; right:0; bottom:0; width:var(--graph-drawer-w); max-width:100vw; height:100vh; height:100dvh; z-index:150; border-radius:0; border-width:0 0 0 1px; padding-top:env(safe-area-inset-top); box-shadow:-10px 0 40px rgba(0,0,0,0.45); }
.graph-stage.is-narrow .graph-drawer.is-entering, .graph-stage.is-narrow .graph-drawer.is-leaving { transform:translateX(104%); }
.graph-scrim { position:fixed; inset:0; z-index:140; background:rgba(0, 0, 0, .5); }
.graph-drawer-head { display:flex; align-items:flex-start; gap:10px; padding:10px 12px; border-bottom:1px solid var(--border); flex-shrink:0; }
.graph-drawer-names { display:flex; flex-direction:column; gap:2px; min-width:0; flex:1; }
.graph-drawer-kind { font-family:var(--font-mono); font-size:10.5px; letter-spacing:0.03em; color:var(--text3); }
.graph-drawer-title { font-size:14px; font-weight:600; color:var(--text); line-height:1.3; overflow-wrap:anywhere; }
.graph-drawer-x { font:inherit; font-size:16px; line-height:1; width:36px; height:36px; flex-shrink:0; border-radius:var(--radius); border:1px solid var(--border2); background:var(--surface3); color:var(--text2); cursor:pointer; }
.graph-drawer-x:hover { color:var(--text); border-color:var(--accent); }
.graph-drawer-body { flex:1; min-height:0; overflow-y:auto; padding:10px 12px 18px; overscroll-behavior:contain; -webkit-overflow-scrolling:touch; }
.graph-drawer-body .mapreq { margin:0; border:none; padding:0; background:transparent; }
.graph-drawer-body .mapreq-heading { display:none; }   /* the tile's own header already names it */
.graph-tile-empty { font-size:13px; color:var(--text3); }
/* On a phone every pixel of width is map: the page body's padding gives way to it. */
@media (max-width: 640px) { #graphBody { padding:10px 6px; } }

/* SVG text — theme-aware (the one bit not inlined on the shapes). */
.graph-text { font-family:var(--font-condensed, var(--font-sans, sans-serif)); }
.graph-label   { fill:var(--text); font-size:12px; font-weight:500; }
.graph-sub     { fill:var(--text3); font-size:9.5px; font-family:var(--font-mono); }
.graph-readout { fill:var(--text2); font-size:10px; font-family:var(--font-mono); }
.graph-open-glyph { fill:#fff; font-size:10px; pointer-events:none; }
.graph-more-glyph { fill:var(--text2); font-size:11px; font-weight:700; pointer-events:none; }
/* The map's marks around a symbol (TKT-1210). */
.graph-node-bg { fill:var(--surface); }
.graph-mid    { fill:var(--text); font-size:12px; font-weight:600; font-family:var(--font-mono); }
.graph-mtitle { fill:var(--text2); font-size:11px; }
.graph-tag-text { font-size:10px; font-weight:600; font-family:var(--font-sans, sans-serif); pointer-events:none; }
.graph-tag-link { cursor:pointer; }
.graph-tag-link:hover rect, .graph-tag-link:focus rect { stroke-width:2; }
.graph-tag-link:focus { outline:none; }

/* Interaction affordances. */
.graph-node { cursor:pointer; }
.graph-node:hover .graph-label, .graph-node:hover .graph-mid { fill:var(--accent); }
.graph-node:focus { outline:none; }
.graph-node:focus-visible .graph-node-bg { stroke:var(--accent); stroke-width:2; }
.graph-open { cursor:pointer; }
.graph-open:hover circle { opacity:0.82; }

/* ── Phase 3 control dock (TKT-220) — gated by HUB_GRAPH_CONTROLS_ENABLED ──────────
   The "Execute next required task" surface under the graph; ships dark (only rendered
   when the flag is on). Scoped graph-dock-* classes; no edits to existing rules. */
.graph-dock { margin-top:12px; padding:12px 14px; background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); }
.graph-dock-head { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:8px; }
.graph-dock-label { font-family:var(--font-mono); font-size:11px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); }
.graph-dock-focus { font-size:13px; color:var(--text2); font-weight:500; }
.graph-dock-task { margin-bottom:10px; }
.graph-dock-task-title { font-size:14px; color:var(--text); font-weight:600; margin-bottom:5px; }
.graph-dock-chips { display:flex; gap:6px; flex-wrap:wrap; margin-bottom:5px; }
.graph-chip { font-size:11px; padding:1px 8px; border-radius:10px; background:var(--surface3); color:var(--text2); border:1px solid var(--border); }
.graph-chip-quiet { color:var(--text3); }
.graph-lane-automatable { background:rgba(46,139,87,0.18); color:#7ad19a; border-color:rgba(46,139,87,0.4); }
.graph-lane-human { background:rgba(47,111,214,0.18); color:#8fb6f0; border-color:rgba(47,111,214,0.4); }
.graph-lane-sensitive { background:rgba(192,57,43,0.18); color:#e89a90; border-color:rgba(192,57,43,0.4); }
.graph-dock-why { font-size:12px; color:var(--text3); }
.graph-dock-none { font-size:13px; color:var(--text2); margin-bottom:10px; }
.graph-dock-btn { font:inherit; font-size:13px; padding:7px 14px; border-radius:var(--radius); border:1px solid var(--accent); background:var(--accent-dim); color:var(--accent); cursor:pointer; }
.graph-dock-btn:hover:not(:disabled) { background:var(--accent-glow); }
.graph-dock-btn:disabled { opacity:0.5; cursor:not-allowed; border-color:var(--border2); color:var(--text3); background:transparent; }
.graph-dock-jump { margin-left:auto; border-color:var(--border2); background:var(--surface3); color:var(--text2); }
.graph-dock-hint { margin-top:6px; font-size:11px; color:var(--text3); font-style:italic; }

/* ── Project Map — "What's left" (TKT-1204) ─────────────────────────────────────────
   Per focus: the triage panel's seven statuses as lanes, the initiatives to pick from, and
   per ticket what is still required. Rendered by hub-map-requirements.js; phone-first — every
   row wraps, nothing scrolls sideways. */
.mapreq { margin:0 0 12px; padding:12px 14px; background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); }
.mapreq-top { display:flex; align-items:baseline; justify-content:space-between; gap:8px 14px; flex-wrap:wrap; margin-bottom:8px; }
.mapreq-heading { font-size:15px; color:var(--text); }
.mapreq-heading b { color:var(--accent); font-weight:600; }
.mapreq-total { font-family:var(--font-mono); font-size:11.5px; color:var(--text3); }
.mapreq-chips { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:8px; }
.mapreq-chip { font:inherit; font-size:12px; display:inline-flex; align-items:center; gap:6px; padding:4px 10px; border-radius:14px; border:1px solid var(--border2); background:var(--surface3); color:var(--text2); cursor:pointer; min-height:30px; }
.mapreq-chip b { font-family:var(--font-mono); font-weight:600; color:var(--text); }
.mapreq-chip[aria-pressed="true"] { border-color:var(--accent); color:var(--accent); background:var(--accent-dim); }
.mapreq-parked { display:inline-flex; align-items:center; gap:6px; font-size:12px; color:var(--text3); margin-bottom:8px; }
.mapreq-sub { font-family:var(--font-mono); font-size:11px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); margin:6px 0 6px; }
.mapreq-groups { display:grid; gap:6px; margin-bottom:12px; }
.mapreq-group { font:inherit; text-align:left; display:grid; grid-template-columns:1fr auto; gap:4px 10px; padding:8px 10px; border:1px solid var(--border); border-radius:var(--radius); background:var(--surface); color:var(--text); cursor:pointer; }
.mapreq-group:hover { border-color:var(--accent); }
.mapreq-group-title { font-size:13.5px; font-weight:500; min-width:0; overflow-wrap:anywhere; }
.mapreq-group-title i { font-style:normal; font-family:var(--font-mono); font-size:11px; color:var(--text3); }
.mapreq-group-n { font-family:var(--font-mono); font-size:11.5px; color:var(--text3); white-space:nowrap; }
.mapreq-group-lanes { grid-column:1 / -1; display:flex; flex-wrap:wrap; gap:4px; }
.mapreq-mini { font-size:11px; padding:1px 7px; border-radius:10px; background:var(--surface3); color:var(--text2); border:1px solid var(--border); }
.mapreq-list { display:grid; gap:8px; }
.mapreq-card { padding:10px 12px; border:1px solid var(--border); border-left:3px solid var(--border2); border-radius:var(--radius); background:var(--surface); min-width:0; }
.mapreq-card[data-lane="done-not-closed"] { border-left-color:var(--success); }
.mapreq-card[data-lane="shipped-one"], .mapreq-card[data-lane="shipped-many"] { border-left-color:var(--blue); }
.mapreq-card[data-lane="started-not-shipped"] { border-left-color:var(--warning); }
.mapreq-card[data-lane="pr-open"] { border-left-color:var(--accent); }
.mapreq-card[data-lane="active"] { border-left-color:#8e7cf0; }
.mapreq-head { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.mapreq-id { font:inherit; font-family:var(--font-mono); font-size:12px; color:var(--accent); background:none; border:none; padding:0; cursor:pointer; text-decoration:underline; text-underline-offset:2px; }
.mapreq-title { font-size:13.5px; color:var(--text); min-width:0; overflow-wrap:anywhere; }
.mapreq-meta { display:flex; flex-wrap:wrap; align-items:center; gap:4px 8px; margin-top:5px; font-size:11.5px; color:var(--text3); }
.mapreq-meta a { color:var(--blue); }
.mapreq-lane { font-size:11px; padding:1px 8px; border-radius:10px; background:var(--surface3); color:var(--text2); border:1px solid var(--border2); white-space:nowrap; }
.mapreq-lane-done-not-closed { color:#7ad19a; border-color:rgba(46,139,87,0.5); }
.mapreq-lane-shipped-one, .mapreq-lane-shipped-many { color:#8fb6f0; border-color:rgba(47,111,214,0.5); }
.mapreq-lane-started-not-shipped { color:#f3c16b; border-color:rgba(243,156,18,0.45); }
.mapreq-lane-pr-open { color:var(--accent); border-color:var(--accent-glow); }
.mapreq-lane-active { color:#b9adf7; border-color:rgba(142,124,240,0.5); }
/* Blocked, and by what (TKT-1210). */
.mapreq-blocked, .mapreq-lane-blocked { color:#f0968d; border-color:rgba(208,69,58,0.55); }
.mapreq-block { margin-top:7px; padding:6px 9px; border-left:3px solid #d0453a; border-radius:0; background:rgba(208,69,58,0.08); }
.mapreq-block-partly { border-left-color:#d9822b; background:rgba(217,130,43,0.08); }
.mapreq-block-head { font-family:var(--font-mono); font-size:10.5px; text-transform:uppercase; letter-spacing:0.04em; color:var(--text3); margin:3px 0; }
.mapreq-block ul { margin:0 0 4px; padding:0; list-style:none; display:grid; gap:4px; }
.mapreq-block li { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 8px; font-size:12.5px; color:var(--text2); min-width:0; }
.mapreq-block li i { font-style:normal; font-size:11px; color:var(--text3); }
.mapreq-jump { font:inherit; font-family:var(--font-mono); font-size:12px; min-height:28px; padding:2px 8px; border-radius:var(--radius); border:1px solid var(--border2); background:var(--surface3); color:var(--accent); cursor:pointer; }
.mapreq-jump:hover { border-color:var(--accent); }
.mapreq-jump-title { min-width:0; overflow-wrap:anywhere; }
.mapreq-block-why { font-size:12.5px; color:var(--text2); }
.mapreq-window { margin-top:5px; font-size:12px; color:var(--text2); overflow-wrap:anywhere; }
.mapreq-crit { margin:7px 0 0; padding:0; list-style:none; display:grid; gap:4px; }
.mapreq-crit li { display:grid; grid-template-columns:auto 1fr; gap:8px; align-items:baseline; font-size:12.5px; color:var(--text2); }
.mapreq-text { min-width:0; overflow-wrap:anywhere; }
.mapreq-long summary { cursor:pointer; list-style:none; }
.mapreq-long summary::-webkit-details-marker { display:none; }
.mapreq-long[open] summary { display:none; }
.mapreq-who { font-family:var(--font-mono); font-size:10px; text-transform:uppercase; padding:0 6px; border-radius:8px; border:1px solid var(--border2); color:var(--text3); }
.mapreq-owner-craig .mapreq-who { color:var(--accent); border-color:var(--accent-glow); background:var(--accent-dim); }
.mapreq-owner-craig .mapreq-text { color:var(--text); }
.mapreq-warn { margin-top:7px; font-size:12px; color:var(--warning); }
.mapreq-none { margin-top:6px; font-size:12px; color:var(--text3); }
.mapreq-ready { font-size:12.5px; color:#7ad19a; flex-basis:100%; }
.mapreq-actions { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:8px; }
.mapreq-btn { font:inherit; font-size:13px; padding:6px 12px; min-height:34px; border-radius:var(--radius); border:1px solid var(--accent); background:var(--accent-dim); color:var(--accent); cursor:pointer; }
.mapreq-btn:disabled { opacity:0.5; cursor:not-allowed; }
.mapreq-quiet { border-color:var(--border2); background:transparent; color:var(--text2); }
.mapreq-close { border-color:var(--success); background:var(--success-dim); color:#7ad19a; }
.mapreq-more { margin-top:10px; }
/* The picker STACKS: a select sizes itself to its longest option (an initiative title runs to 150 characters), so
   in a row it pushed Save and Cancel off a phone screen — measured on the bench at 840px inside a 283px card. */
.mapreq-place { display:grid; grid-template-columns:minmax(0, 1fr); gap:6px; width:100%; min-width:0; flex-basis:100%; }
.mapreq-place-label { font-size:12px; color:var(--text2); }
.mapreq-place-sel { font:inherit; font-size:13px; width:100%; min-width:0; max-width:100%; padding:6px 8px; min-height:34px; border-radius:var(--radius); border:1px solid var(--border2); background:var(--surface2); color:var(--text); text-overflow:ellipsis; }
.mapreq-place-btns { display:flex; gap:8px; flex-wrap:wrap; }
.mapreq-err { flex-basis:100%; font-size:12px; color:var(--danger); }
.mapreq-msg { margin:0 0 8px; padding:6px 10px; border-radius:var(--radius); font-size:12.5px; }
.mapreq-msg-ok { background:var(--success-dim); color:#7ad19a; }
.mapreq-msg-err { background:var(--danger-dim); color:#e89a90; }
.mapreq-msg-warn { background:rgba(243,156,18,0.12); color:#f3c16b; }
.mapreq-foot { margin-top:10px; font-size:11px; color:var(--text3); font-style:italic; }

/* ── Scan a Document tab (TKT-243) ──────────────────────────────────────────
   Mobile-first scan intake channel: capture → confirm → done. Scoped to the panel. */
#hub-panel-scan-document .scan-wrap { max-width: 720px; margin: 0 auto; }
#hub-panel-scan-document .scan-sub { color: var(--text3); font-size: 13px; line-height: 1.5; margin: 4px 0 14px; }
#hub-panel-scan-document .scan-capture-row { display: flex; gap: 10px; margin-bottom: 14px; }
#hub-panel-scan-document .scan-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  flex: 1; padding: 13px 16px; border-radius: var(--radius); border: 1px solid var(--border2);
  background: var(--surface2); color: var(--text); font-size: 15px; font-weight: 500;
  cursor: pointer; text-align: center; font-family: var(--font-body);
}
#hub-panel-scan-document .scan-btn:active { opacity: 0.7; }
#hub-panel-scan-document .scan-btn:disabled { opacity: 0.4; cursor: not-allowed; }
#hub-panel-scan-document .scan-btn-primary { background: var(--blue-dim); border-color: var(--blue); color: var(--blue); }
#hub-panel-scan-document .scan-btn-success { background: var(--success-dim); border-color: var(--success); color: var(--success); }
#hub-panel-scan-document .scan-process { width: 100%; margin-top: 14px; }
#hub-panel-scan-document .scan-cancel { width: 100%; margin-top: 14px; color: var(--text3); }
#hub-panel-scan-document .scan-empty { color: var(--text3); font-size: 13px; padding: 18px; text-align: center; border: 1px dashed var(--border2); border-radius: var(--radius); }
#hub-panel-scan-document .scan-thumbs { display: flex; flex-wrap: wrap; gap: 10px; }
#hub-panel-scan-document .scan-thumb { width: 120px; border: 1px solid var(--border2); border-radius: var(--radius); overflow: hidden; background: var(--surface2); }
#hub-panel-scan-document .scan-thumb img { width: 100%; height: 120px; object-fit: cover; display: block; }
#hub-panel-scan-document .scan-thumb-bar { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px; font-size: 11px; color: var(--text3); }
#hub-panel-scan-document .scan-mini { background: var(--surface3); border: 1px solid var(--border2); color: var(--text2); border-radius: 4px; cursor: pointer; font-size: 12px; padding: 1px 6px; margin-left: 2px; }
#hub-panel-scan-document .scan-mini:disabled { opacity: 0.35; cursor: not-allowed; }
#hub-panel-scan-document .scan-mini.scan-del { color: var(--danger); border-color: var(--danger); }
#hub-panel-scan-document .scan-progress { margin: 12px 0; color: var(--accent); font-size: 13px; }
#hub-panel-scan-document .scan-error { margin: 12px 0; color: var(--danger); font-size: 13px; }
#hub-panel-scan-document .scan-spin { display: inline-block; width: 12px; height: 12px; border: 2px solid var(--border2); border-top-color: var(--accent); border-radius: 50%; animation: scanspin 0.7s linear infinite; vertical-align: middle; margin-right: 6px; }
@keyframes scanspin { to { transform: rotate(360deg); } }
#hub-panel-scan-document .scan-verdict { font-size: 18px; font-weight: 600; margin-bottom: 4px; color: var(--text); }
#hub-panel-scan-document .scan-verdict.scan-done { color: var(--success); }
/* Rejected scan (TKT-580) — reads as a stop, not a warning. No field values accompany it. */
#hub-panel-scan-document .scan-verdict.scan-rejected { color: var(--danger, #ff6b6b); }
#hub-panel-scan-document .scan-reject-list { list-style: none; padding: 0; margin: 10px 0 16px; display: flex; flex-direction: column; gap: 8px; }
#hub-panel-scan-document .scan-reject-row { padding: 10px 12px; border: 1px solid var(--danger, #ff6b6b); border-left-width: 3px; border-radius: var(--radius); background: var(--bg2, transparent); font-size: 13px; line-height: 1.5; color: var(--text); }
/* TKT-923 — non-text elements skipped on purpose (barcodes, logos). Informational, NOT a
   defect, so it must not read like the red reject rows above it. */
#hub-panel-scan-document .scan-note-line { opacity: .75; font-size: 12px; margin: 4px 0 0; }
/* TKT-924 — look at a held-back scan before deciding. The gap context is the substitute for
   highlighting the image, so it has to be READABLE: monospaced, wrapped, the gap itself the
   only thing shouting. */
#hub-panel-scan-document .scan-look { margin: 10px 0; padding: 10px 12px; border: 1px solid var(--border, #334); border-radius: var(--radius); background: var(--bg2, transparent); }
#hub-panel-scan-document .scan-gap-row { padding: 8px 10px; border: 1px solid var(--border, #334); border-left: 3px solid var(--warn, #f0b43c); border-radius: var(--radius); background: var(--bg, transparent); }
#hub-panel-scan-document .scan-gap-ctx { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 1.6; margin-top: 4px; white-space: normal; word-break: break-word; }
#hub-panel-scan-document .scan-gap-mark { background: var(--warn, #f0b43c); color: #1b1b1b; padding: 1px 5px; border-radius: 4px; font-weight: 700; }
#hub-panel-scan-document .scan-look-frame { width: 100%; height: 60vh; min-height: 320px; margin-top: 10px; border: 1px solid var(--border, #334); border-radius: var(--radius); background: #fff; }
#hub-panel-scan-document .scan-look-open { margin: 10px 0 0; font-size: 14px; }
#hub-panel-scan-document .scan-look-open a { display: inline-block; min-height: 44px; line-height: 44px; padding: 0 16px; border: 1px solid var(--accent, #4f9dff); border-radius: var(--radius); background: rgba(79,157,255,.12); color: inherit; text-decoration: none; font-weight: 600; }
#hub-panel-scan-document .scan-muted { color: var(--text3); }
/* A rejected scan needs a way OUT, not just a way round again (TKT-614). The screen previously
   offered "Rescan" alone, which on a phone reads as the only exit — the nav is scrolled off the
   top behind a tall list of reasons. Both actions clear the scan; only the labels differ. */
#hub-panel-scan-document .scan-reject-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 4px 0 12px; }
#hub-panel-scan-document .scan-reject-actions .scan-btn { flex: 1 1 200px; }
/* The separation card's actions (TKT-973) — approve, and the discard that screen had no way to
   offer until now. Same row shape as the reject actions above, with ONE deliberate difference:
   approve is given twice the basis, so on a narrow screen it takes the width and the discard
   wraps beneath it rather than sitting shoulder to shoulder. This is the control the operator
   presses for EVERY scan; its neighbour throws the scan away, and they must not look alike.
   .scan-cancel is width:100% on its own (it is a full-width button everywhere else on this
   screen), so the flex basis here is what keeps it in the row at all. */
#hub-panel-scan-document .scan-sep-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 4px 0 2px; }
#hub-panel-scan-document .scan-sep-actions .scan-btn { flex: 2 1 260px; }
#hub-panel-scan-document .scan-sep-actions .scan-cancel { flex: 1 1 160px; width: auto; margin-top: 0; }
/* Auto-uprighted scan (TKT-584) — informational, not alarming: it worked, but the operator
   should know the values came from a re-read rather than the first pass. */
#hub-panel-scan-document .scan-rotated-note { padding: 9px 12px; margin: 0 0 12px; border-radius: var(--radius); border: 1px solid var(--border2); border-left: 3px solid var(--accent); font-size: 13px; line-height: 1.5; color: var(--text2, var(--text)); }
#hub-panel-scan-document .scan-pay-note { padding: 9px 12px; margin: 0 0 12px; border-radius: var(--radius); border: 1px solid var(--border2); border-left: 3px solid var(--green, var(--accent)); font-size: 13px; line-height: 1.5; color: var(--text2, var(--text)); }  /* TKT-1079: the payment half of an already-paid bill */
#hub-panel-scan-document .scan-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; margin: 12px 0 18px; }
#hub-panel-scan-document .scan-field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text3); }
#hub-panel-scan-document .scan-field input, #hub-panel-scan-document .scan-field select {
  padding: 9px 10px; border: 1px solid var(--border2); border-radius: var(--radius);
  background: var(--surface); color: var(--text); font-size: 14px; font-family: var(--font-body);
}
/* TKT-972 — the duplicate-bill verdict, above the actions. FOUR STATES THAT MUST NOT BE
   MISTAKEN FOR EACH OTHER at a glance: definitive match (red, it IS already there), possible
   match (amber, your call), clear (green, checked and clean), and NOT CHECKED (grey with a
   warning rule — the one that must never look like "clear"). */
#hub-panel-scan-document .scan-dup { border-radius: 8px; padding: 10px 12px; margin: 0 0 14px; border: 1px solid var(--border); background: var(--surface2); }
#hub-panel-scan-document .scan-dup-head { font-size: 13px; font-weight: 700; letter-spacing: 0.02em; margin-bottom: 4px; }
#hub-panel-scan-document .scan-dup-msg { font-size: 13px; line-height: 1.45; }
#hub-panel-scan-document .scan-dup-list { margin: 8px 0 4px; padding-left: 18px; font-size: 13px; line-height: 1.6; }
#hub-panel-scan-document .scan-dup-tag { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; padding: 1px 5px; border-radius: 4px; background: var(--danger, #b42318); color: #fff; }
#hub-panel-scan-document .scan-dup-searched { font-size: 12px; color: var(--text3); margin-top: 6px; }
#hub-panel-scan-document .scan-dup-foot { font-size: 12px; color: var(--text3); margin-top: 6px; line-height: 1.45; }
#hub-panel-scan-document .scan-dup-definitive { border-color: var(--danger, #b42318); background: color-mix(in srgb, var(--danger, #b42318) 10%, var(--surface2)); }
#hub-panel-scan-document .scan-dup-definitive .scan-dup-head { color: var(--danger, #b42318); }
#hub-panel-scan-document .scan-dup-maybe { border-color: var(--warn, #b54708); background: color-mix(in srgb, var(--warn, #b54708) 10%, var(--surface2)); }
#hub-panel-scan-document .scan-dup-maybe .scan-dup-head { color: var(--warn, #b54708); }
#hub-panel-scan-document .scan-dup-clear { border-color: var(--ok, #067647); }
#hub-panel-scan-document .scan-dup-clear .scan-dup-head { color: var(--ok, #067647); }
#hub-panel-scan-document .scan-dup-unknown { border-left: 4px solid var(--warn, #b54708); }
#hub-panel-scan-document .scan-dup-unknown .scan-dup-head { color: var(--text2); }

#hub-panel-scan-document .scan-actions-label { font-size: 12px; font-weight: 600; color: var(--text3); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 8px; }
#hub-panel-scan-document .scan-actions { display: flex; flex-direction: column; gap: 8px; }
#hub-panel-scan-document .scan-action {
  display: flex; flex-direction: column; gap: 2px; text-align: left; padding: 11px 14px;
  border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2);
  color: var(--text); cursor: pointer; font-family: var(--font-body);
}
#hub-panel-scan-document .scan-action:active { opacity: 0.75; }
#hub-panel-scan-document .scan-action:disabled { opacity: 0.5; cursor: not-allowed; }
#hub-panel-scan-document .scan-action strong { font-size: 14px; font-weight: 600; }
#hub-panel-scan-document .scan-action span { font-size: 12px; color: var(--text3); }
#hub-panel-scan-document .scan-action-rec { border-color: var(--accent); background: var(--accent-dim); }
/* ── Batch scanning (TKT-582): separation screen + batch review list ── */
#hub-panel-scan-document .scan-doc-card { border: 1px solid var(--border2); border-radius: var(--radius);
  background: var(--surface2); padding: 12px 14px; margin: 0 0 12px; }
#hub-panel-scan-document .scan-doc-head { font-size: 14px; margin-bottom: 8px; line-height: 1.4; }
#hub-panel-scan-document .scan-doc-done { border-left: 3px solid var(--success); }
#hub-panel-scan-document .scan-doc-bad { border-left: 3px solid var(--danger, #ff6b6b); }
#hub-panel-scan-document .scan-thumbs-row { align-items: center; }
#hub-panel-scan-document .scan-thumb-sm { width: 86px; }
#hub-panel-scan-document .scan-thumb-sm img { height: 86px; }
/* A PDF capture entry / PDF-sourced page has no pixel thumbnail — a labelled card stands in. */
#hub-panel-scan-document .scan-pdf-card { display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 86px; padding: 6px; text-align: center; font-size: 11px; line-height: 1.35; color: var(--text2); overflow: hidden; }
#hub-panel-scan-document .scan-thumb:not(.scan-thumb-sm) .scan-pdf-card { height: 120px; font-size: 12px; }
#hub-panel-scan-document .scan-split-btn { align-self: center; }
/* ── Separation approval for watched-inbox scans (TKT-953) ──
   One card per parked scan, sitting ABOVE the review list because nothing in it has been read
   yet — it is the queue that still costs something to leave alone. A struck page stays fully
   legible: it is dimmed and ruled through, never hidden, because the operator is the check on
   a heuristic that has already been wrong in both directions. */
#hub-panel-scan-document .scan-sep-wrap { margin: 0 0 20px; padding: 0 0 14px; border-bottom: 1px solid var(--border2); }
#hub-panel-scan-document .scan-sep-card { border: 1px solid var(--success); border-radius: var(--radius);
  background: var(--surface2); padding: 12px 14px; margin: 0 0 14px; }
#hub-panel-scan-document .scan-sep-card .scan-doc-card { background: var(--surface); }
#hub-panel-scan-document .scan-doc-card-empty { opacity: 0.55; border-style: dashed; }
/* A proposal has no page images — the page is cut from source.pdf on demand (TKT-959). The card
   is wider than a thumbnail because it has to show a readable PAGE, not a stamp. */
#hub-panel-scan-document .scan-thumb-page { width: 190px; display: flex; flex-direction: column; }
/* AN OPEN PAGE TAKES THE WHOLE ROW, and that is the entire point (TKT-960). It used to render
   into the 210px thumbnail slot at 300px tall — Craig: "It never actually blows up big enough
   for me to read it." A bill in a 210px column is not a page, it is a stamp. These are the
   dimensions of .scan-look-frame, the viewer on the review queue that already works. */
#hub-panel-scan-document .scan-thumb-open { width: 100%; flex-basis: 100%; }
/* THE THUMBNAIL IS THE DEFAULT. Every page renders small; the button enlarges it. Tall enough
   to recognise a bill from its masthead and layout, which is what the operator is judging. */
#hub-panel-scan-document .scan-page-frame { width: 100%; height: 240px;
  border: 1px solid var(--border2); border-radius: var(--radius); background: #fff; }
/* Enlarged: the dimensions of .scan-look-frame, the review-queue viewer that already worked. */
#hub-panel-scan-document .scan-thumb-open .scan-page-frame { height: 70vh; min-height: 420px; }
/* Deliberately the same shape as .scan-look-open — a real 44px control that inherits the text
   colour. NOT a small blue link: blue on the dark theme was unreadable, and it was the route
   that actually worked. */
#hub-panel-scan-document .scan-page-open { margin: 10px 0 0; font-size: 14px; }
#hub-panel-scan-document .scan-page-open a { display: inline-block; min-height: 44px; line-height: 44px;
  padding: 0 16px; border: 1px solid var(--accent, #4f9dff); border-radius: var(--radius);
  background: rgba(79,157,255,.12); color: inherit; text-decoration: none; font-weight: 600; }
#hub-panel-scan-document .scan-thumb-struck { opacity: 0.45; }
#hub-panel-scan-document .scan-thumb-struck .scan-pdf-card { text-decoration: line-through; }
#hub-panel-scan-document .scan-thumb-struck .scan-thumb-bar { text-decoration: line-through; }
#hub-panel-scan-document .scan-thumb-struck .scan-thumb-bar .scan-mini { text-decoration: none; }
/* Pending-scans review queue (TKT-583, the watched inbox) */
#hub-panel-scan-document .scan-pending-banner { width: 100%; margin-top: 10px; }
#hub-panel-scan-document .scan-sel { display: inline-flex; align-items: center; margin-right: 6px; }
#hub-panel-scan-document .scan-sel input { width: 16px; height: 16px; }
@media (max-width: 640px) {
  #hub-panel-scan-document .scan-fields { grid-template-columns: 1fr; }
}

/* ── Three-way match panel (TKT-902): billed vs ordered vs received, in Bill Review ── */
.bill-3way { border: 1px solid var(--border2); border-radius: var(--radius); padding: 10px 14px; margin: 10px 0; background: var(--surface2); }
.bill-3way-ok { border-left: 3px solid var(--success); }
.bill-3way-hold { border-left: 3px solid var(--warning, #e0a83a); }
.bill-3way-head { font-size: 13px; margin-bottom: 8px; line-height: 1.5; }
.bill-3way-row { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: baseline; padding: 4px 0; border-top: 1px dashed var(--border2); font-size: 13px; }
.bill-3way-row.ok .bill-3way-verdict { color: var(--success); }
.bill-3way-row.warn .bill-3way-verdict { color: var(--warning, #e0a83a); }
.bill-3way-row.bad .bill-3way-verdict { color: var(--danger, #ff6b6b); font-weight: 600; }
.bill-3way-row.dim { opacity: 0.75; }
.bill-3way-desc { flex: 1 1 220px; min-width: 180px; }
.bill-3way-qty { white-space: nowrap; }

/* ── Admin panel (TKT-265 Phase 1.4 — actors / roles / overrides / autonomy) ─────────────── */
#hub-panel-admin .ctrl-board { max-width: 1040px; }
.adm-head { margin-bottom: 16px; }
.adm-head-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.adm-legend { font-size: 13px; color: var(--text2); }
.adm-head-btns { display: flex; gap: 8px; }
.adm-cutover-note { margin-top: 10px; font-size: 12px; color: var(--text2);
  border: 1px dashed var(--border); border-left: 3px solid var(--accent); border-radius: 6px; padding: 8px 12px; background: var(--accent-dim); }
.adm-cutover-note code { font-family: var(--font-mono); font-size: 11px; color: var(--accent); }

.adm-notice { max-width: 640px; margin: 24px auto; padding: 18px 20px; border: 1px solid var(--border);
  border-radius: 8px; background: var(--surface); color: var(--text2); }
.adm-notice-title { font-family: var(--font-display); font-size: 18px; color: var(--accent); margin-bottom: 8px; text-transform: uppercase; letter-spacing: .05em; }
.adm-notice code { font-family: var(--font-mono); font-size: 12px; color: var(--accent); }

.adm-section { margin-bottom: 26px; }
.adm-section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  border-bottom: 1px solid var(--border); padding-bottom: 6px; margin-bottom: 10px; }
.adm-section-title { font-family: var(--font-display); font-size: 17px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text); }
.adm-count { font-size: 12px; color: var(--text3); margin-left: 4px; }
.adm-hint { font-size: 12px; color: var(--text3); margin-top: 6px; }
.adm-hint-block { margin: 0 0 10px; }
.adm-hint code, .adm-hint-block code { font-family: var(--font-mono); font-size: 11px; color: var(--text2); }
.adm-muted { color: var(--text3); font-size: 12px; }
.adm-empty { color: var(--text3); padding: 12px; }
.adm-ok { color: var(--success); font-size: 12px; }
.adm-warn { color: var(--warning); font-size: 12px; }
/* TKT-981: an EMPTY assignment state must read as a state, not as small print above a picker. */
.adm-empty-state { font-size: 13px; font-weight: 600; padding: 6px 8px; border: 1px dashed var(--warning); border-radius: 4px; margin-bottom: 8px; }
.adm-add-label { margin-right: 6px; white-space: nowrap; }
.adm-assigned { color: var(--success); border: 1px solid var(--success); background: transparent; font-size: 10px; letter-spacing: .04em; padding: 1px 6px; border-radius: 3px; margin-right: 6px; }

/* Buttons */
.adm-btn { font-family: var(--font-body); font-size: 13px; padding: 5px 12px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text2); cursor: pointer; }
.adm-btn:hover { color: var(--text); border-color: var(--accent); }
.adm-btn-primary { color: var(--accent); border-color: var(--accent); background: var(--accent-dim); }
.adm-btn-danger { color: var(--danger); border-color: var(--danger); }
.adm-btn-danger:hover { background: var(--danger-dim); }
.adm-btn-mini { font-size: 12px; padding: 3px 8px; }

/* Badges + chips */
.adm-badge { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; padding: 2px 6px;
  border-radius: 4px; border: 1px solid var(--border); color: var(--text2); }
.adm-badge-active { color: var(--success); border-color: var(--success); background: var(--success-dim); }
.adm-badge-inactive { color: var(--danger); border-color: var(--danger); background: var(--danger-dim); }
.adm-badge-seed { color: var(--text3); }
.adm-badge-kind { font-size: 10px; }
.adm-kind-agent { color: var(--blue); border-color: var(--blue); background: var(--blue-dim); }
.adm-kind-human { color: var(--text2); }
.adm-chip { display: inline-block; font-size: 11px; padding: 2px 7px; border-radius: 10px;
  border: 1px solid var(--border); color: var(--text2); margin-right: 4px; }
.adm-chip-primary { border-color: var(--accent); color: var(--accent); }
.adm-chip-ovr { background: var(--bg); }

/* Actor list */
.adm-actor, .adm-role { border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px; background: var(--surface); overflow: hidden; }
.adm-actor-head, .adm-role-head { display: flex; align-items: center; gap: 8px; padding: 9px 12px; cursor: pointer; flex-wrap: wrap; }
.adm-actor-head:hover, .adm-role-head:hover { background: var(--accent-dim); }
.adm-chevron { color: var(--text3); transition: transform .12s; display: inline-block; }
.adm-actor.open .adm-chevron, .adm-role.open .adm-chevron { transform: rotate(90deg); }
.adm-actor-name, .adm-role-label { font-weight: 600; color: var(--text); }
.adm-actor-id, .adm-role-id { font-family: var(--font-mono); font-size: 11px; color: var(--text3); }
.adm-actor-roles { margin-left: auto; }
.adm-actor-pw { font-size: 11px; }
.adm-role-summary { margin-left: auto; font-size: 11px; color: var(--text3); font-family: var(--font-mono); }

.adm-actor-body, .adm-role-body { padding: 12px; border-top: 1px solid var(--border); background: var(--bg); }
.adm-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.adm-block { border: 1px solid var(--border); border-radius: 6px; padding: 10px 12px; background: var(--surface); }
.adm-block-wide { grid-column: 1 / -1; }
.adm-block-title { font-family: var(--font-display); font-size: 13px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 8px; }
.adm-block-actions { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }

.adm-field { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--text2); margin-bottom: 8px; }
.adm-field-label { color: var(--text2); }
.adm-field input, .adm-field select, .adm-ovadd select, .adm-ovadd input, .adm-rolerow select,
.adm-newactor input, .adm-newactor select, .adm-matrix-sel, .adm-autorow input, .adm-autorow select,
.adm-roleedit input, .adm-roleedit select {
  font-family: var(--font-body); font-size: 13px; padding: 5px 8px; border-radius: 5px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text); }
.adm-inline { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--text2); }

/* Set-password field: reveal toggle + inline mismatch message (TKT-269) */
.adm-pw-wrap { display: flex; align-items: stretch; gap: 6px; }
.adm-pw-wrap input { flex: 1 1 auto; min-width: 0; }
.adm-pw-reveal { flex: 0 0 auto; align-self: center; }
.adm-pw-msg { font-size: 12px; color: var(--danger); margin: -2px 0 8px; }

/* Roles + overrides rows */
.adm-rolerow, .adm-ovrow, .adm-dialrow { display: flex; align-items: center; gap: 8px; padding: 4px 0; flex-wrap: wrap; }
.adm-rolerow-id { font-family: var(--font-mono); font-size: 12px; color: var(--text); min-width: 110px; }
.adm-rolerow-add { margin-top: 6px; border-top: 1px dashed var(--border); padding-top: 8px; }
.adm-ovrow-key { font-family: var(--font-mono); font-size: 12px; color: var(--text); }
.adm-ovrow-arrow { color: var(--text3); }
.adm-ovrow-val { color: var(--accent); font-family: var(--font-mono); font-size: 12px; }
.adm-ovrow-note { cursor: help; color: var(--blue); }
.adm-ovadd { display: flex; align-items: center; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.adm-ovnote-in { min-width: 140px; }

/* Autonomy dials */
.adm-dialhead { display: grid; grid-template-columns: 1.2fr 1.2fr 1.6fr 1fr; gap: 8px; font-size: 11px;
  text-transform: uppercase; letter-spacing: .04em; color: var(--text3); padding: 4px 0; border-bottom: 1px solid var(--border); }
.adm-dialrow { display: grid; grid-template-columns: 1.2fr 1.2fr 1.6fr 1fr; gap: 8px; align-items: center; }
.adm-dial-action { font-weight: 600; color: var(--text); }
.adm-dial-level { font-family: var(--font-mono); font-size: 12px; color: var(--text2); }
.adm-dial-flag { font-family: var(--font-mono); font-size: 11px; color: var(--text3); }

/* Role editor */
/* ── Role editor on functions (TKT-979) ─────────────────────────────────────────── */
.adm-field-wide { display: block; }
.adm-role-resp-in { width: 100%; min-height: 64px; resize: vertical; font: inherit; font-size: 13px; padding: 6px 8px;
  background: var(--bg2); color: var(--text); border: 1px solid var(--border); border-radius: 6px; }
.adm-fn-banner { margin: 10px 0; padding: 8px 12px; border-radius: 6px; font-size: 12.5px; line-height: 1.45; border: 1px solid; }
.adm-fn-banner-off { color: var(--warning, #E0B24A); border-color: var(--warning, #E0B24A); background: var(--warning-dim, rgba(224,178,74,.12)); }
.adm-fn-banner-on { color: var(--success); border-color: var(--success); background: var(--success-dim); }
.adm-fn-shortcuts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 10px; }
.adm-fn-groups { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.adm-fn-group > summary { list-style: none; cursor: pointer; }
.adm-fn-group > summary::-webkit-details-marker { display: none; }
.adm-fn-group[open] > summary .adm-chevron { transform: rotate(90deg); }
.adm-fn-group-set { margin-left: auto; font-size: 11px; color: var(--text3); }
.adm-fn-group-set select { font-size: 11px; padding: 2px 4px; }
.adm-fn-rows { display: flex; flex-direction: column; gap: 4px; padding: 6px 10px 10px; }
.adm-fn-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--border); }
.adm-fn-row:last-child { border-bottom: 0; }
.adm-fn-sel { width: 96px; flex: none; font-family: var(--font-mono); font-size: 11px; }
.adm-fn-label { font-size: 13px; color: var(--text); }
.adm-cat-money { color: var(--warning, #E0B24A); font-family: var(--font-mono); font-size: 11px; }
.adm-cat-sensitive { color: var(--danger); border-color: var(--danger); }
.adm-cat-level { font-family: var(--font-mono); }
.adm-cat-level-read { color: var(--text2); }
.adm-cat-level-lookup { color: var(--warning, #E0B24A); border-color: var(--warning, #E0B24A); }
.adm-cat-level-act { color: var(--accent); border-color: var(--accent); }
.adm-cat-fn { padding: 8px 0; border-bottom: 1px dashed var(--border); }
.adm-cat-fn:last-child { border-bottom: 0; }
.adm-cat-fn-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.adm-cat-fn-label { font-size: 13px; color: var(--text); }
.adm-cat-fn-meta { font-size: 11px; margin-top: 2px; }
@media (max-width: 600px) { .adm-fn-row { flex-wrap: wrap; } .adm-fn-group-set { margin-left: 0; } }

.adm-matrix { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 6px; margin-bottom: 8px; }
.adm-matrix-row { display: flex; align-items: center; justify-content: space-between; gap: 6px;
  border: 1px solid var(--border); border-radius: 5px; padding: 4px 8px; }
.adm-matrix-area { font-size: 12px; color: var(--text2); }
.adm-gates { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 8px; }
.adm-autorow { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.adm-autorow .adm-auto-action { flex: 1; }
.adm-autorow .adm-auto-flag { flex: 1; }

.adm-newactor { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 12px;
  padding: 10px; border: 1px dashed var(--border); border-radius: 6px; background: var(--surface); }

@media (max-width: 760px) {
  .adm-detail-grid { grid-template-columns: 1fr; }
  .adm-actor-roles, .adm-role-summary, .adm-actor-pw { margin-left: 0; width: 100%; }
}

/* ============================================================
   REFERENCE SURFACE (Master docs / Users Manual)
   The single home for master reference documents, auto-listed from
   reference/_index.json, scoped to the viewer, with revision history.
   ============================================================ */
.ref-intro { font-size: 12px; color: var(--text3); margin: 2px 0 14px; line-height: 1.5; }
.ref-area-label {
  font-family: var(--font-display); text-transform: uppercase; letter-spacing: 0.08em;
  font-size: 12px; color: var(--accent); margin: 16px 0 8px; border-bottom: 1px solid var(--border);
  padding-bottom: 4px;
}
.ref-card {
  background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 14px; margin-bottom: 10px; cursor: pointer; transition: border-color .12s, background .12s;
}
.ref-card:hover, .ref-card:focus { border-color: var(--accent); background: var(--surface3); outline: none; }
.ref-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ref-card-title { font-family: var(--font-display); font-weight: 600; font-size: 16px; color: var(--text); }
.ref-card-chips { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.ref-chip {
  font-family: var(--font-mono); font-size: 10px; text-transform: lowercase; color: var(--text2);
  background: var(--surface3); border: 1px solid var(--border2); border-radius: 4px; padding: 1px 6px;
}
.ref-chip-area { color: var(--blue); border-color: var(--blue-dim); }
.ref-chip-aud { color: var(--accent); border-color: var(--accent-dim); }
.ref-card-desc { font-size: 13px; color: var(--text2); line-height: 1.5; margin-top: 7px; }
.ref-card-hints { font-size: 12px; color: var(--text3); line-height: 1.5; margin-top: 6px; }
.ref-hints-label { color: var(--accent); font-weight: 600; }
.ref-card-meta { font-family: var(--font-mono); font-size: 10px; color: var(--text3); margin-top: 8px; }
.ref-uncommitted { color: var(--warning); }

.ref-empty, .ref-error, .ref-history-none {
  font-size: 13px; color: var(--text3); padding: 18px; text-align: center;
}
.ref-error { color: var(--danger); }

/* Reader */
.ref-reader-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.ref-back-btn {
  font-family: var(--font-mono); font-size: 12px; color: var(--text2); background: var(--surface2);
  border: 1px solid var(--border2); border-radius: 4px; padding: 4px 10px; cursor: pointer;
}
.ref-back-btn:hover { border-color: var(--accent); color: var(--text); }
.ref-reader-title { font-family: var(--font-display); font-weight: 600; font-size: 18px; color: var(--text); }
.ref-reader-meta { font-family: var(--font-mono); font-size: 11px; color: var(--text3); margin-bottom: 10px; }
.ref-history { margin: 6px 0 14px; }
.ref-history summary { font-size: 12px; color: var(--blue); cursor: pointer; }
.ref-history-list { list-style: none; margin: 8px 0 0; padding: 0; }
.ref-history-list li { font-family: var(--font-mono); font-size: 11px; color: var(--text2); padding: 2px 0; }
.ref-rev-date { color: var(--text3); }
.ref-rev-sha { color: var(--accent); }
.ref-rev-author { color: var(--text3); }

/* Rendered markdown body */
.ref-doc { color: var(--text2); font-size: 14px; line-height: 1.65; max-width: 900px; }
.ref-doc .ref-h { font-family: var(--font-display); color: var(--text); line-height: 1.25; margin: 20px 0 8px; }
.ref-doc h1.ref-h { font-size: 24px; border-bottom: 1px solid var(--border); padding-bottom: 6px; }
.ref-doc h2.ref-h { font-size: 20px; color: var(--accent); margin-top: 26px; }
.ref-doc h3.ref-h { font-size: 16px; }
.ref-doc h4.ref-h, .ref-doc h5.ref-h, .ref-doc h6.ref-h { font-size: 14px; color: var(--text); }
.ref-doc p { margin: 8px 0; }
.ref-doc a { color: var(--blue); text-decoration: none; }
.ref-doc a:hover { text-decoration: underline; }
.ref-doc strong { color: var(--text); }
.ref-doc code { font-family: var(--font-mono); font-size: 12px; background: var(--surface3); border: 1px solid var(--border); border-radius: 3px; padding: 1px 4px; color: var(--accent); }
.ref-pre { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; overflow-x: auto; margin: 10px 0; }
.ref-pre code { background: none; border: none; padding: 0; color: var(--text2); }
.ref-list { margin: 8px 0; padding-left: 22px; }
.ref-list li { margin: 4px 0; }
.ref-hr { border: none; border-top: 1px solid var(--border); margin: 18px 0; }
.ref-quote { border-left: 3px solid var(--accent); background: var(--accent-dim); margin: 12px 0; padding: 8px 14px; color: var(--text2); border-radius: 0 var(--radius) var(--radius) 0; }
.ref-table-wrap { overflow-x: auto; margin: 12px 0; }
.ref-table { border-collapse: collapse; width: 100%; font-size: 13px; }
.ref-table th, .ref-table td { border: 1px solid var(--border2); padding: 6px 10px; text-align: left; vertical-align: top; }
.ref-table th { background: var(--surface3); color: var(--text); font-family: var(--font-display); font-weight: 600; }
.ref-table td { color: var(--text2); }
.ref-table tr:nth-child(even) td { background: var(--surface); }

/* ============================================================
   HOME FAVORITES (TKT-288 item 5) — user-curated shortcut grid on the dashboard.
   ============================================================ */
#hub-favorites { margin-bottom: 16px; }
.fav-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.fav-title { font-family: var(--font-display); text-transform: uppercase; letter-spacing: 0.08em; font-size: 12px; color: var(--accent); }
.fav-edit-btn { font-family: var(--font-mono); font-size: 11px; color: var(--text2); background: var(--surface2); border: 1px solid var(--border2); border-radius: 4px; padding: 4px 10px; cursor: pointer; }
.fav-edit-btn:hover { border-color: var(--accent); color: var(--text); }
.fav-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.fav-tile { font-family: var(--font-display); font-weight: 600; font-size: 13px; color: var(--text); background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 14px; cursor: pointer; }
.fav-tile:hover { border-color: var(--accent); background: var(--surface3); }
.fav-picker { display: flex; flex-wrap: wrap; gap: 6px; }
.fav-pick { font-family: var(--font-mono); font-size: 11px; color: var(--text2); background: var(--surface2); border: 1px solid var(--border2); border-radius: 999px; padding: 4px 10px; cursor: pointer; }
.fav-pick.on { color: var(--accent); border-color: var(--accent); background: var(--accent-dim); }
.fav-empty { font-size: 12px; color: var(--text3); }

/* ============================================================
   APPROVALS / QUEUES (TKT-295) — the nine per-path gated write/output module views.
   Overview table + the shared per-module queue-view component (hub-approvals.js).
   ============================================================ */
.aprv-intro { font-size: 12px; color: var(--text3); margin-bottom: 12px; }
.aprv-loading, .aprv-empty { font-size: 12px; color: var(--text3); padding: 12px 0; }
.aprv-error { font-size: 12px; color: var(--danger, #e05252); padding: 12px 0; }
.aprv-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.aprv-table th, .aprv-table td { border: 1px solid var(--border2); padding: 6px 10px; text-align: left; }
.aprv-table th { background: var(--surface3); color: var(--text); font-family: var(--font-display); font-weight: 600; }
.aprv-row { cursor: pointer; }
.aprv-row:hover td { background: var(--surface3); }
.aprv-label { color: var(--text); font-weight: 600; }
.aprv-kind { display: block; font-family: var(--font-mono); font-size: 10px; color: var(--text3); font-weight: 400; }
.aprv-num { text-align: right; font-family: var(--font-mono); color: var(--text2); }
.aprv-state { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.06em; border-radius: 999px; padding: 2px 8px; white-space: nowrap; }
.aprv-state-waiting { color: var(--text3); border: 1px solid var(--border2); background: var(--surface2); }
.aprv-state-dark { color: var(--text2); border: 1px solid var(--border); background: var(--surface); }
.aprv-state-live { color: var(--accent); border: 1px solid var(--accent); background: var(--accent-dim); }
/* TKT-1157 criterion 2: the Bills row — its items are approved by posting them in Bill Review. */
.aprv-state-bills { color: var(--text); border: 1px solid var(--border2); background: var(--surface2); }
.aprv-mod-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.aprv-mod-flags { font-family: var(--font-mono); font-size: 11px; color: var(--text3); }
.aprv-refresh { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text2); background: var(--surface2); border: 1px solid var(--border2); border-radius: 4px; padding: 4px 10px; cursor: pointer; }
.aprv-refresh:hover { border-color: var(--accent); color: var(--text); }
.aprv-notice { font-size: 11px; color: var(--accent); }
.aprv-group { margin-bottom: 16px; }
.aprv-group-head { font-family: var(--font-display); text-transform: uppercase; letter-spacing: 0.08em; font-size: 11px; color: var(--accent); margin-bottom: 6px; }
.aprv-group-count { font-family: var(--font-mono); color: var(--text3); margin-left: 6px; }
.aprv-item { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface2); padding: 10px 12px; margin-bottom: 8px; }
.aprv-item-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.aprv-item-id { font-family: var(--font-mono); font-size: 11px; color: var(--text3); }
.aprv-item-sum { font-size: 12px; color: var(--text); }
.aprv-item-when { margin-left: auto; font-family: var(--font-mono); font-size: 10px; color: var(--text3); }
.aprv-item-note { font-size: 11px; color: var(--text2); margin-top: 4px; font-style: italic; }
.aprv-item-payload { margin-top: 6px; }
.aprv-item-payload summary { font-family: var(--font-mono); font-size: 10px; color: var(--text3); cursor: pointer; }
.aprv-item-payload pre { font-family: var(--font-mono); font-size: 10px; color: var(--text2); background: var(--surface); border: 1px solid var(--border2); border-radius: 4px; padding: 8px; overflow-x: auto; max-height: 280px; }
.aprv-item-actions { display: flex; gap: 6px; margin-top: 8px; }
/* TKT-1157: the gate an item waits at, and its audit trail. */
.aprv-gate { display: inline-block; margin-top: 4px; font-size: 11px; font-weight: 600; color: var(--text2); border: 1px solid var(--border2); border-radius: 10px; padding: 1px 8px; }
.aprv-gate-booking { color: var(--accent); border-color: var(--accent); }
.aprv-item-history { margin-top: 6px; }
.aprv-item-history summary { font-family: var(--font-mono); font-size: 10px; color: var(--text3); cursor: pointer; }
.aprv-history { margin: 6px 0 0; padding-left: 18px; font-size: 11px; color: var(--text2); }
.aprv-history li { margin: 2px 0; overflow-wrap: anywhere; }
.aprv-history-when { font-family: var(--font-mono); font-size: 10px; color: var(--text3); }
/* TKT-1157 criterion 4: a post QuickBooks refused heads the page, and its module row is marked, until a person resolves it. */
.aprv-refused-callout { border: 1px solid rgba(231,76,60,0.6); background: rgba(231,76,60,0.12); border-radius: var(--radius); padding: 10px 12px; margin-bottom: 12px; font-size: 12px; color: var(--text); line-height: 1.45; }
.aprv-refused-title { font-weight: 700; margin-bottom: 3px; }
.aprv-row-refused td:first-child { box-shadow: inset 3px 0 0 rgba(231,76,60,0.8); }
.aprv-refused-count { display: inline-block; font-size: 10px; font-weight: 700; color: #e74c3c; }
.aprv-act { font-family: var(--font-mono); font-size: 11px; color: var(--text2); background: var(--surface); border: 1px solid var(--border2); border-radius: 4px; padding: 4px 12px; cursor: pointer; }
.aprv-act:hover { border-color: var(--accent); color: var(--text); }
.aprv-act[data-action="approve"] { color: var(--accent); border-color: var(--accent); }
.aprv-act[data-action="discard"]:hover { border-color: var(--danger, #e05252); color: var(--danger, #e05252); }
/* TKT-1023 / TKT-1045 (S8): the ledger-summary LINE TABLE, Hold line, Run now, the reconcile block,
   and the module-focused overview the two Money leaves open. */
.aprv-focus-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.aprv-focus-title { font-family: var(--font-display); font-size: 14px; font-weight: 600; color: var(--text); }
.aprv-focus-queue { margin-top: 16px; }
.aprv-row-focus td { background: var(--surface3); }
.aprv-run { font-family: var(--font-mono); font-size: 11px; color: var(--accent); background: var(--surface2); border: 1px solid var(--accent); border-radius: 4px; padding: 4px 10px; cursor: pointer; }
.aprv-run:hover { background: var(--accent-dim); color: var(--text); }
.aprv-run:disabled { opacity: 0.5; cursor: wait; }
/* TKT-1151: Approve all (payroll journals) — the one bulk action; a disabled one is waiting on its switch, not busy */
.aprv-bulk { font-weight: 600; }
.aprv-bulk:disabled[title] { cursor: not-allowed; }
.aprv-run-result { font-size: 12px; color: var(--text); background: var(--surface2); border: 1px solid var(--border2); border-radius: 4px; padding: 6px 10px; margin-bottom: 12px; }
.aprv-ledger { margin-top: 8px; }
.aprv-ledger-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-size: 12px; color: var(--text); margin-bottom: 6px; }
.aprv-ledger-head .aprv-kind { display: inline; margin-left: auto; }
.aprv-ledger-note { margin-top: 6px; }
.aprv-line-table td { vertical-align: top; }
/* TKT-1151: a payroll journal on a phone — the memo column gives way, and the table scrolls in its own box, never the queue */
.aprv-journal-scroll { overflow-x: auto; }
@media (max-width: 600px) { .aprv-journal-memo { display: none; } }
.aprv-line-actions { white-space: nowrap; }
.aprv-line-actions .aprv-act { margin-left: 6px; }
.aprv-line-detail { display: inline-block; }
.aprv-line-detail summary { font-family: var(--font-mono); font-size: 10px; color: var(--text3); cursor: pointer; }
.aprv-line-detail[open] { display: block; }
.aprv-mov-table { margin-top: 6px; font-size: 11px; }
.aprv-mov-table th, .aprv-mov-table td { padding: 3px 8px; }
.aprv-net { font-weight: 600; }
.aprv-net-pos { color: var(--accent); }
.aprv-net-neg { color: var(--danger, #e05252); }
.aprv-delta { color: var(--text2); }
.aprv-mono { font-family: var(--font-mono); font-size: 10px; color: var(--text3); white-space: nowrap; }
.aprv-note-cell { font-size: 11px; color: var(--text2); }
.aprv-recon { margin-top: 4px; }

/* ── Clickable Parts Diagram (TKT-407 / PR-C) — ported from Scotty5000_Clickable_Proof.html,
   scoped under #pdStage / #pdDetail / #pvStage so the proof class names don't collide with the Hub. */
.parts-diagram-wrap { display:flex; gap:0; height:calc(100vh - 120px); }
/* ── THE VIEWER IS A COLUMN (TKT-797) — the verify editor keeps the row layout above. ─────────
   Craig, with an iPad screenshot: the three-pane row starved the drawing to a ~360px column
   stretched to viewport height — the drawing was 20% of the frame inside a tall dead-white
   strip, and everything scrolled together. Now: nav header on top (compact dropdowns), the
   drawing full width at ITS OWN ratio, detail + list underneath. */
#pdViewerView.parts-diagram-wrap { flex-direction:column; height:auto; }
#pdViewerView #pdNav { width:auto !important; min-width:0 !important; max-width:none !important;
  border-right:none; border-bottom:1px solid var(--border,#262b36); padding:8px 12px; overflow:visible; }
/* THE DRAWING STAYS ON SCREEN: the whole drawing block (image + control bar) is sticky, so the
   lists scroll under it and the illustration never leaves the page. Opaque background — content
   scrolling beneath must never ghost around the page edges. */
#pdViewerView .diagram { position:sticky; top:0; z-index:3; flex:none; min-height:0;
  background:var(--surface,#171a21); }
/* THE BOX IS THE PAGE SHAPE: aspect-ratio from the image itself (--pd-ar, set by the zoom layer
   at img load), full width, capped at 72vh so a landscape sheet on a wide screen leaves room for
   the panels, centred when the cap bites. Dead white is structurally impossible — the white box
   and the drawing are the same rectangle. */
#pdViewerView .stage-box { flex:none; width:min(100%, calc(72vh * var(--pd-ar, 1.415)));
  aspect-ratio:var(--pd-ar, 1.415); margin:0 auto; }
#pdViewerView .dz-controls { position:static; align-self:center; margin:6px auto; flex-wrap:wrap;
  justify-content:center; max-width:100%; }
/* Detail + list ride side by side when width allows, stacking when it does not. */
#pdViewerView .parts-diagram-side { width:auto; min-width:0; flex-direction:row; flex-wrap:wrap;
  border-left:none; border-top:1px solid var(--border,#262b36); }
#pdViewerView #pdDetail { flex:1 1 340px; min-width:280px; border-bottom:none;
  border-right:1px solid var(--border,#262b36); }
#pdViewerView .pd-list-sec { flex:1 1 380px; min-width:300px; display:flex; flex-direction:column; }
/* The compact nav is a HEADER ROW in the viewer at every width — dropdowns beside each other,
   Browse all at the left. Expanded, the full tree opens as a height-capped scrollable block so
   hunting for a page never shoves the drawing off screen. */
#pdViewerView .pdnav-compact { flex-direction:row; align-items:center; flex-wrap:wrap; }
#pdViewerView .pdnav-compact .pdnav-select { width:auto; flex:1 1 220px; }
#pdViewerView #pdNav:not(.pdnav-is-compact) { max-height:40vh; overflow:auto; }
/* The page-thumbnail grid (TKT-800): pictures first, captions under, current page ringed amber.
   Height-capped + scrollable like the expanded tree — browsing never shoves the drawing away. */
.pdnav-thumbs { display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:8px;
  max-height:46vh; overflow:auto; margin-top:8px; }
.pdnav-thumb { cursor:pointer; border:1px solid var(--border,#262b36); border-radius:6px;
  overflow:hidden; background:#fff; }
.pdnav-thumb img { width:100%; display:block; min-height:60px; }
.pdnav-thumb .cap { font-size:11px; padding:4px 6px; background:var(--surface,#171a21);
  color:var(--text2,#9aa4b2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pdnav-thumb:hover .cap { color:inherit; }
.pdnav-thumb.cur { outline:2px solid #e0a33e; }
/* Pull & Count (TKT-802): shortages scream, pulled lines recede, drift gets a quiet chip. */
.pl-pullcount td { vertical-align:middle; }
.pl-pullcount tr.pl-short td { background:rgba(224,83,62,.14); }
.pl-pullcount tr.pl-pulled td { opacity:.55; }
.pl-pullcount tr.pl-pulled.pl-short td { opacity:1; }   /* a pulled-but-short line must NOT fade */
.pl-short-chip { color:#e0533e; border:1px solid #e0533e; border-radius:4px; padding:1px 6px; font-weight:700; }
.pl-drift { color:#e0a33e; border:1px solid #e0a33e; border-radius:4px; padding:0 4px; font-size:11px; white-space:nowrap; }
/* TKT-1042 (S5): the scanned line lights up; the phone rules (B9) — under 720px the walking table
   folds into stacked cards the way the ib- / ru- rows do: the pulled check and the scan field
   first, every tap target 44px, no horizontal scroll. */
.pl-pullcount tr.pl-scan-hit td { background:rgba(224,163,62,.22); outline:2px solid #e0a33e; }
.pl-consolidated summary { font-weight:600; }
@media (max-width: 720px) {
  .pl-pullcount { display:block; }
  .pl-pullcount thead, .pl-pullcount tr:first-child { display:none; }
  .pl-pullcount tr.pl-line { display:grid; grid-template-columns: 1fr 1fr; gap:4px 8px; padding:8px 6px; border:1px solid var(--border2,#262b36); border-radius:8px; margin-bottom:8px; }
  .pl-pullcount tr.pl-line td { display:block; border:0; padding:2px 0; }
  .pl-pullcount tr.pl-line td:nth-child(1) { grid-column: 1 / -1; display:flex; align-items:center; gap:6px; }
  .pl-pullcount tr.pl-line td:nth-child(3) { grid-column: 1 / -1; }
  .pl-pullcount tr.pl-line td:nth-child(3) b { font-size:16px; }
  .pl-pullcount tr.pl-line td.pl-for { white-space:normal; }
  .pl-pullcount tr.pl-line td input[type=number] { min-height:44px; }
  .pl-scan input { font-size:16px; }
  .pl-table.pl-pullcount td, .pl-table.pl-pullcount th { min-width:0; }
}
/* THE DRAWING IS FITTED TO THE BOX, NOT JUST ITS WIDTH (TKT-564). It used to be "width:100%;
   height:auto" inside a fixed-height white panel — so a LANDSCAPE sheet (the pages are 2339x1653,
   aspect 1.42) rendered to the column width and left the rest of the panel white below it. Craig:
   "the blank canvas for the image is much larger than the image itself." Now it is centred and
   constrained on BOTH axes, so it takes whichever dimension runs out first.
   overflow:hidden, not auto: zoom/pan is a transform on the stage (hub-diagram-zoom.js), and a
   scrollbar fighting the pan would double-move the page. touch-action:none so a pinch zooms the
   drawing instead of the browser zooming the Hub. */
.parts-diagram-wrap .diagram { flex:1; overflow:hidden; position:relative; display:flex;
  flex-direction:column; touch-action:none; }
/* .stage-box is the box the zoom layer owns (TKT-791): it is the stage's containing block, the
   pan clamp's frame, and the clip. The control bar is its SIBLING — absolute over it on desktop,
   a normal-flow strip below it on phones — so reserving room for the bar shrinks THIS box and the
   fitted drawing with it, instead of the bar covering balloons. */
.parts-diagram-wrap .stage-box { flex:1; min-height:0; position:relative; overflow:hidden;
  background:#fff; touch-action:none; }
/* THE TRANSFORM OWNS PLACEMENT — the box deliberately does NOT centre with flex. It did at first,
   and the two centrings stacked: the clamp in hub-diagram-zoom.js also centres content smaller than
   the box, so the drawing was pushed half the slack off to one side. One thing centres, and it is
   the code that also has to clamp the panning.
   The stage shrink-wraps the image so the balloons' percentage positions stay true — they are
   positioned against the STAGE, so it must be exactly the image's box and nothing more. */
#pdStage, #pvStage { position:absolute; left:0; top:0; width:auto; height:auto;
  max-width:100%; max-height:100%; line-height:0; will-change:transform; }
#pdStage img, #pvStage img { display:block; width:auto; height:auto; max-width:100%; max-height:100%; }
.parts-diagram-wrap .stage-box.dz-pannable { cursor:grab; }
.parts-diagram-wrap .stage-box.dz-pannable:active { cursor:grabbing; }
/* Zoom controls sit ON the drawing, bottom-right, away from the top-left title block. 44px targets. */
.dz-controls { position:absolute; right:10px; bottom:10px; display:flex; gap:6px; align-items:center;
  background:rgba(15,21,32,.86); border:1px solid var(--border,#262b36); border-radius:8px; padding:5px; z-index:5; }
.dz-controls button { min-width:44px; min-height:44px; cursor:pointer; border:1px solid var(--border,#334);
  background:var(--bg2,#1b2836); color:#e6eaf0; border-radius:6px; font-size:15px; line-height:1; }
.dz-controls .dz-lab { min-width:52px; text-align:center; font-size:12px; color:var(--text2,#9aa4b2);
  font-variant-numeric:tabular-nums; }
/* PHONE: the bar LEAVES the overlay (TKT-791). Craig, on an iPhone 13 Pro, first real use: the
   bar sat on top of the drawing and a balloon underneath it could not be tapped. In flow below
   .stage-box it occupies real space instead of covering any; wrap keeps every 44px target usable
   on a 390px screen. */
@media (max-width: 900px) {
  .dz-controls { position:static; align-self:center; margin:6px auto; flex-wrap:wrap;
    justify-content:center; max-width:100%; }
}
#pdStage .hot, #pvStage .hot {
  position:absolute; width:2.1%; aspect-ratio:1; transform:translate(-50%,-50%); border-radius:50%;
  border:2px solid rgba(91,141,239,0); cursor:pointer; transition:.12s; box-sizing:border-box; }
#pdStage .hot:hover, #pdStage .hot.peer, #pvStage .hot:hover { border-color:#5b8def; background:rgba(91,141,239,.18); }
#pdStage .hot.active { border-color:#e0533e; background:rgba(224,83,62,.22); }
/* Already on the ACTIVE list (TKT-795): amber, always visible, so returning to a page shows at a
   glance which callouts are covered. Declared BEFORE .msel so a live selection (green) wins the
   moment the operator is actually choosing. */
#pdStage .hot.onlist { border-color:#e0a33e; background:rgba(224,163,62,.28); box-shadow:0 0 0 2px rgba(224,163,62,.35); }
/* Multi-select (TKT-786): a collected balloon reads green — same vocabulary as verify's pv-sel. */
#pdStage .hot.msel { border-color:#3fb950; background:rgba(63,185,80,.30); box-shadow:0 0 0 2px rgba(63,185,80,.45); }
/* The line(s) a hovered on-list balloon points at (TKT-795). */
#pdList tr.pl-hl td { background:rgba(224,163,62,.18); }
.dz-controls #pdMsBtn.active { border-color:#3fb950; color:#3fb950; }
#pvStage .hot.pv-edit { border-color:#5b8def; background:rgba(91,141,239,.14); }
#pvStage .hot.pv-low { border-color:#e0a33e; background:rgba(224,163,62,.22); }
#pvStage .hot .pv-num { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:9px; color:#0f1115; font-weight:700; }
/* The per-balloon delete control is GONE (TKT-538). Measured at 390px it was 15px against an 8px
   balloon with its centre 3px away, so elementFromPoint at the balloon's own centre returned the ✕ —
   on a touchscreen, tapping a balloon deleted it. Deletion now lives in the action bar, acts on an
   explicitly selected balloon, and asks first. Do not reintroduce a destructive control on the mark. */
#pvStage .hot { touch-action: none; }                    /* or the browser scrolls instead of dragging */
#pvStage .hot.pv-sel { border-color:#3fb950; background:rgba(63,185,80,.30); box-shadow:0 0 0 2px rgba(63,185,80,.45); }
/* An 8px mark is far under the ~44px a fingertip covers. Expand the HIT AREA without changing the
   drawn circle, so the balloon stays visually precise but is reachable with a finger. */
@media (pointer: coarse) {
  #pvStage .hot::before { content:''; position:absolute; inset:-14px; border-radius:50%; }
}
/* THE SIGN-OFF BUTTON (TKT-538 follow-up). It carried class="pri", but `.pri` has exactly ONE rule in
   this stylesheet — `#pdDetail .acts .pri` — which does not match a button in the .pd-toolbar. So the
   class was inert and the most consequential control on the screen rendered identically to
   "+ Add balloon". The instructions said "press the green button" and there was no green button.
   Style it explicitly here rather than relying on a class whose only definition lives elsewhere. */
#pvSaveBtn {
  background: var(--success, #27ae60);
  border: 1px solid var(--success, #27ae60);
  color: #fff;
  font-weight: 600;
  padding: 7px 12px;
  border-radius: var(--radius, 6px);
  cursor: pointer;
}
#pvSaveBtn:hover { filter: brightness(1.1); }
/* Once there are unsaved corrections it is no longer a plain "looks right" — amber says "you have
   changes to commit", so the two meanings the label carries are also carried by colour. */
#pvSaveBtn.pv-has-edits { background: var(--accent, #f0a500); border-color: var(--accent, #f0a500); color: #1a1a1a; }

.pv-actions .pv-sel-label { color:var(--text2,#9aa4b2); font-size:12px; margin-right:2px; }
.pv-actions .pv-danger { border-color:var(--danger,#e74c3c); color:var(--danger,#e74c3c); }
/* "Not a parts page" is a page-level judgement, not a destructive balloon action — deliberately NOT
   danger-red (nothing is deleted) but set apart from the plain actions, and pushed to the right so it
   is never hit while reaching for Undo (TKT-543). */
.pv-actions .pv-reject { margin-left:auto; border-color:var(--warn,#d79a3a); color:var(--warn,#d79a3a); }
.pv-rejected-banner { padding:8px 12px; font-size:12px; line-height:1.45;
  color:var(--warn,#d79a3a); background:var(--surface2,#121224);
  border-bottom:1px solid var(--warn,#d79a3a); }
.pv-actions button[disabled] { opacity:.4; cursor:default; }
.pv-howto { padding:8px 12px; font-size:12px; line-height:1.45; color:var(--text2,#9aa4b2);
  border-bottom:1px solid var(--border,#262b36); background:var(--surface2,#121224); }
.pv-howto b { color:var(--text,#ececf6); }
.pv-howto em { font-style:normal; color:var(--text,#ececf6); font-weight:600; }
/* Name the button by its LABEL, shown the way the button looks. The instructions used to say "press
   the green button", which failed twice over: the button was not green, and pointing at a control by
   colour alone is unusable for anyone who cannot distinguish it (TKT-538 follow-up). */
.pv-cta { display:inline-block; background:var(--success,#27ae60); color:#fff; font-weight:600;
  border-radius:4px; padding:1px 6px; white-space:nowrap; }
.parts-diagram-side { width:390px; min-width:390px; background:var(--surface,#171a21); border-left:1px solid var(--border,#262b36); display:flex; flex-direction:column; }
/* Phone layout (TKT-531 follow-through): the desktop row is nav(≥190px) + diagram(flex:1) + side(390px)
   — 580px of FIXED width, so on a 375px phone the diagram collapses to 0px and the page renders as a
   blank dark column (exactly what the installed web app showed). Below 900px the three panes STACK. */
@media (max-width: 900px) {
  .parts-diagram-wrap { flex-direction: column; height: auto; }
  .parts-diagram-wrap #pdNav { width: auto !important; min-width: 0 !important; max-width: none !important; max-height: 220px; border-right: none; border-bottom: 1px solid var(--border,#262b36); }
  /* 300px of DRAWING plus the in-flow control bar below it (TKT-791) — the old 300px total would
     leave ~240px of drawing once the bar takes its row. */
  .parts-diagram-wrap .diagram { min-height: 360px; width: 100%; }
  .parts-diagram-side { width: auto; min-width: 0; border-left: none; border-top: 1px solid var(--border,#262b36); }
}
#pdDetail { padding:14px 16px; border-bottom:1px solid var(--border,#262b36); min-height:180px; }
#pdDetail .pn { font-size:20px; font-weight:700; letter-spacing:.3px; }
#pdDetail .badge { font-size:10px; font-weight:700; padding:2px 7px; border-radius:4px; text-transform:uppercase; vertical-align:middle; margin-left:8px; }
#pdDetail .b-made { background:rgba(74,144,217,.15); color:#4a90d9; border:1px solid #4a90d9; }
#pdDetail .b-buy  { background:rgba(224,163,62,.15); color:#e0a33e; border:1px solid #e0a33e; }
/* The supersession callout (TKT-801): amber like the on-list vocabulary — it changes what you PULL. */
#pdDetail .pd-sup { margin:8px 0; padding:7px 9px; border:1px solid #e0a33e; border-radius:6px;
  background:rgba(224,163,62,.12); font-size:13px; }
#pdDetail .kv { display:grid; grid-template-columns:auto 1fr; gap:3px 12px; margin:10px 0; font-size:13px; }
#pdDetail .kv b { color:var(--text2,#9aa4b2); font-weight:500; }
#pdDetail .subs { margin-top:8px; border-top:1px dashed var(--border,#262b36); padding-top:8px; }
#pdDetail .subs .s { display:flex; justify-content:space-between; color:var(--text2,#9aa4b2); font-size:12px; padding:2px 0; }
/* An option-marked sub is an ALTERNATIVE, not an addition (TKT-546). Marked where the operator is
   choosing, and deliberately not auto-excluded — which of two options is right is their call. */
#pdDetail .subs .pd-opt { margin-left:6px; padding:0 5px; border-radius:3px; font-size:10px;
  text-transform:uppercase; letter-spacing:.03em; color:var(--warn,#d79a3a);
  border:1px solid var(--warn,#d79a3a); }
#pdDetail .acts { display:flex; gap:8px; margin-top:10px; flex-wrap:wrap; }
#pdDetail .acts .pri { background:#5b8def; border-color:#5b8def; color:#fff; font-weight:600; }
/* TKT-459 r3 — receiving-on-file block inside the PO-hold banner */
.bill-rcv { margin-top: 10px; padding: 8px 10px; border: 1px solid var(--border,#334); border-radius: 8px; background: rgba(148,163,184,0.06); color: var(--text); }
.bill-rcv-head { font-weight: 600; margin-bottom: 4px; }
.bill-rcv-row { font-size: 12.5px; padding: 2px 0; }
.bill-rcv-row a { color: inherit; }
/* TKT-459 r6 — receipt line summary inside the receiving-on-file rows */
.bill-rcv-lines { font-size: 11.5px; color: var(--muted,#8a94a1); padding: 1px 0 3px 12px; }

/* TKT-517 header compaction (Craig): Mode + Domain are small selectable badges in the header;
   the stat strip stays on ONE line (scrolls sideways on a phone rather than stacking). */
.hnm-badge { font-size: 11px; padding: 3px 6px; border-radius: 10px; max-width: 130px;
  background: var(--surface, #171a21); color: inherit; border: 1px solid var(--border2, #2a2f3a); }
.stats-bar { flex-wrap: nowrap !important; overflow-x: auto; }

/* ── Parts catalogue (TKT-558) ────────────────────────────────────────────────
   The line chooser is a always-visible button strip, not a dropdown. Craig: "it would be very handy
   to be able to see the E-Z parts, can it just be selectable?" — a select would hide both the
   options and their counts behind a tap. Wraps and scrolls sideways on a phone. */
.pc-lines { display: flex; gap: 6px; flex-wrap: wrap; padding: 8px 12px;
  border-bottom: 1px solid var(--border, #262b36); }
.pc-tab { cursor: pointer; border: 1px solid var(--border, #334); background: var(--bg2, #1b2836);
  color: inherit; border-radius: 999px; font-size: 12px; padding: 5px 11px; white-space: nowrap; }
.pc-tab.active { background: var(--accent, #2d6cdf); border-color: var(--accent, #2d6cdf); color: #fff; }
.pc-tab[disabled] { opacity: .4; cursor: default; }
.pc-tab .pc-n { opacity: .75; font-variant-numeric: tabular-nums; margin-left: 3px; }

.pc-count { font-size: 12px; color: var(--text2, #9aa4b2); padding: 0 2px 8px; }
.pc-warn { font-size: 12px; padding: 8px 10px; margin-bottom: 10px; border-radius: 6px;
  background: rgba(220, 160, 40, .12); border: 1px solid rgba(220, 160, 40, .4); }
.pc-link { background: none; border: none; padding: 0; color: var(--accent, #6ea8fe);
  cursor: pointer; font: inherit; text-decoration: underline; }

.pc-row { padding: 9px 2px; border-bottom: 1px solid var(--border, #262b36); }
.pc-main { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pc-part { font-weight: 600; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }
.pc-desc { font-size: 13px; margin-top: 2px; }
.pc-meta { font-size: 11px; color: var(--text2, #9aa4b2); margin-top: 3px; display: flex; gap: 10px; }
.pc-line { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; padding: 2px 7px;
  border-radius: 999px; border: 1px solid var(--border2, #2a2f3a); }
.pc-line-scott { background: rgba(60, 170, 110, .16); border-color: rgba(60, 170, 110, .45); }
.pc-line-ez { background: rgba(150, 150, 160, .14); border-color: rgba(150, 150, 160, .4); }
.pc-line-film { background: rgba(90, 140, 220, .14); border-color: rgba(90, 140, 220, .4); }
.pc-line-universal { background: rgba(190, 140, 220, .14); border-color: rgba(190, 140, 220, .4); }
.pc-line-unknown { background: rgba(220, 160, 40, .14); border-color: rgba(220, 160, 40, .4); }
/* WHY the line was decided, not just what it is. An account-derived line is a different kind of
   claim from a pattern-derived one, and a filtered-out part must be checkable. */
.pc-why { font-size: 10px; color: var(--text2, #9aa4b2); opacity: .8; }

/* ── Manuals browse tree, collapsed (TKT-564) ─────────────────────────────────
   Craig: "that list on the left should be like a drop down menu that you can select from and it
   just shows whichever one you're on now instead of showing all the others and taking up so much of
   the screen." Collapsed, the pane stops being a 230px column and becomes a strip. */
#pdNav.pdnav-is-compact { width: auto !important; min-width: 0 !important; max-width: 320px !important;
  border-right: 1px solid var(--border, #262b36); }
.pdnav-compact { display: flex; flex-direction: column; gap: 8px; }
.pdnav-expand { cursor: pointer; border: 1px solid var(--border, #334); background: var(--bg2, #1b2836);
  color: inherit; border-radius: 6px; font-size: 12px; padding: 8px 10px; min-height: 40px; text-align: left; }
.pdnav-where { font-size: 11px; color: var(--text2, #9aa4b2); }
.pdnav-select { width: 100%; min-height: 40px; padding: 7px 8px; border: 1px solid var(--border, #334);
  border-radius: 6px; background: var(--bg2, #151f2a); color: inherit; font-size: 13px; }
/* Collapsed on a phone the strip goes full width and short — the drawing gets the height. */
@media (max-width: 820px) {
  .parts-diagram-wrap #pdNav.pdnav-is-compact { max-width: none !important; max-height: none; }
  .pdnav-compact { flex-direction: row; align-items: center; }
  .pdnav-compact .pdnav-where { display: none; }
  .pdnav-select { flex: 1; }
}

/* ── Verify from a matching page (TKT-565) ────────────────────────────────────
   A row has to carry enough to decide WITHOUT leaving the screen: which page, how many balloons,
   which already-verified page they come from, and whose sign-off that was. */
.ct-head { font-size: 13px; padding: 4px 2px 12px; }
.ct-head .ct-sub { display: block; font-size: 11px; color: var(--text2, #9aa4b2); margin-top: 3px; }
.ct-ed { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--text2, #9aa4b2);
  margin: 14px 0 4px; padding-top: 8px; border-top: 1px solid var(--border, #262b36); }
.ct-row { padding: 9px 2px; border-bottom: 1px solid var(--border, #262b36); }
.ct-main { display: flex; gap: 10px; align-items: baseline; }
.ct-page { font-weight: 600; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px; }
.ct-n { font-size: 12px; color: var(--text2, #9aa4b2); }
.ct-from { font-size: 12px; margin-top: 2px; }
.ct-acts { display: flex; gap: 8px; margin-top: 7px; flex-wrap: wrap; }
/* 44px targets: this is used on a phone, and the right-hand button signs a page off. */
.ct-acts button { min-height: 44px; cursor: pointer; border: 1px solid var(--border, #334);
  background: var(--bg2, #1b2836); color: inherit; border-radius: 6px; font-size: 13px; padding: 6px 14px; }
.ct-acts button.pri { background: var(--accent, #2d6cdf); border-color: var(--accent, #2d6cdf); color: #fff; }
.ct-acts button[disabled] { opacity: .55; cursor: default; }

/* ── Activity feed (TKT-571) ───────────────────────────────────────────────
   A chronological read of the operational event log. Deliberately dense and
   scannable rather than card-heavy: the value is seeing a day's worth of what
   happened at a glance, and Craig reads this on an iPad in the shop, so the
   time column is fixed-width and the type colour is a left rule rather than a
   badge — colour identifies the KIND without competing with the text. */
.activity-controls { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  padding: 4px 0 12px; border-bottom: 1px solid var(--border); margin-bottom: 12px; }
.activity-controls select, .activity-controls input[type="date"] {
  background: var(--surface2); color: var(--text); border: 1px solid var(--border2);
  border-radius: 6px; padding: 6px 10px; font-size: 13px; min-height: 36px; }
.activity-since { display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--text2, #b8b8cc); }
.activity-count { margin-left: auto; font-size: 12px; color: var(--text2, #b8b8cc); }

.activity-day { margin-bottom: 18px; }
.activity-day-label { font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text2, #b8b8cc); margin: 0 0 6px 2px; }
.activity-list { list-style: none; margin: 0; padding: 0; }

.activity-row { display: flex; gap: 12px; align-items: baseline;
  padding: 7px 10px 7px 12px; border-left: 3px solid var(--border2);
  border-radius: 0 6px 6px 0; background: var(--surface); margin-bottom: 3px; }
.activity-row:hover { background: var(--surface2); }
.activity-time { flex: 0 0 42px; font-variant-numeric: tabular-nums;
  font-size: 12px; color: var(--text2, #b8b8cc); }
.activity-main { display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline; min-width: 0; }
.activity-title { font-size: 13px; color: var(--text); }
.activity-detail { font-size: 12px; color: var(--text2, #b8b8cc); }

/* The left rule carries the event class. */
.activity-row.act-po      { border-left-color: var(--blue); }
.activity-row.act-receipt { border-left-color: var(--success); }
.activity-row.act-req     { border-left-color: var(--accent); }
.activity-row.act-bill    { border-left-color: var(--warning); }
.activity-row.act-so      { border-left-color: var(--accent); }
/* A10 (TKT-1039): the stock families */
.activity-row.act-inventory { border-left-color: #2e8b8b; }
.activity-row.act-rental    { border-left-color: #8e6bd1; }
.activity-row.act-wo        { border-left-color: #d29922; }
.activity-row.act-other   { border-left-color: var(--border2); }

.activity-badge { font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
  padding: 1px 6px; border-radius: 10px; background: var(--accent-dim);
  color: var(--accent); border: 1px solid var(--accent-glow); }

/* An empty log is a NORMAL state on a fresh store, so it reads as an explanation
   rather than an error — the two are indistinguishable from a blank panel. */
.activity-empty { padding: 28px 8px; text-align: center; }
.activity-empty-heading { font-size: 14px; color: var(--text); margin-bottom: 6px; }
.activity-empty-body { font-size: 12px; color: var(--text2, #b8b8cc);
  max-width: 460px; margin: 0 auto; line-height: 1.5; }
.activity-error { padding: 14px; border-radius: 6px; background: var(--danger-dim);
  border: 1px solid var(--danger); color: var(--text); font-size: 13px; }

/* Cases tab — the engine status strip (TKT-816). Chips ride the activity palette. */
.ce-status { display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 10px 12px; margin-bottom: 14px; border: 1px solid var(--border2);
  border-radius: 8px; background: var(--bg2, rgba(255,255,255,.02)); }
.ce-chip { font-size: 11px; font-weight: 700; letter-spacing: .08em;
  padding: 3px 10px; border-radius: 12px; border: 1px solid var(--border2); }
.ce-chip.ce-off { color: var(--text2, #b8b8cc); }
.ce-chip.ce-observe { color: var(--accent); background: var(--accent-dim);
  border-color: var(--accent-glow); }
.ce-chip.ce-live { color: var(--danger); background: var(--danger-dim);
  border-color: var(--danger); }
.ce-fact { font-size: 12px; color: var(--text2, #b8b8cc); }
.ce-fact.ce-props { color: var(--text); font-weight: 600; }
/* TKT-831 — the sweep's proof of life. A healthy heartbeat stays quiet in weight (it is the normal
   case and must not shout); overdue / failed / never-armed is the one that has to catch the eye,
   because it is the state Craig had no way to see at all. */
.ce-fact.ce-sweep-ok  { color: var(--ok, #4caf50); }
.ce-fact.ce-sweep-bad { color: var(--warn, #e0a33e); font-weight: 600; }
.ce-fact.ce-sweep-off { color: var(--text2, #b8b8cc); font-style: italic; }
.ce-feed-label { font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text2, #b8b8cc); margin: 0 0 8px 2px; }
.ce-notice { padding: 10px 12px; margin-bottom: 12px; border-radius: 6px;
  background: var(--accent-dim); border: 1px solid var(--accent-glow);
  color: var(--text); font-size: 13px; }

/* Case detail (TKT-825) */
.ce-caselink { background: none; border: none; padding: 0; font: inherit; cursor: pointer;
  color: var(--accent); text-decoration: underline; }
.ce-detail-head { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline;
  margin: 10px 0 6px; }
.ce-gap { font-size: 12px; padding: 4px 8px; margin-top: 4px; border-radius: 4px;
  background: var(--danger-dim); border: 1px solid var(--danger); color: var(--text); }
.ce-listener { font-size: 12px; color: var(--text2, #b8b8cc); margin-top: 2px; }
.ce-listener .ce-when { color: var(--text); }
.ce-listener .ce-then { color: var(--accent); }
.activity-truncated { font-size: 12px; color: var(--text2, #b8b8cc);
  padding: 8px 2px; border-top: 1px solid var(--border); }

@media (max-width: 640px) {
  .activity-count { margin-left: 0; width: 100%; }
  .activity-main { gap: 4px; }
}
/* ── The review run bar (TKT-565) ─────────────────────────────────────────────
   Craig: "give me a next button and I'll zip through it." Sits above the drawing during a run and
   is hidden otherwise. "Use it & next" is the primary because it is the only button pressed on a
   normal pass; Skip and Back exist for the pages that are not normal. */
.ct-runbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  padding: 8px 12px; border-bottom: 1px solid var(--border, #262b36); background: var(--surface, #171a21); font-size: 13px; }
.ct-run-pos { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ct-run-from { color: var(--text2, #9aa4b2); flex: 1 1 260px; min-width: 0; }
.ct-run-acts { display: flex; gap: 8px; margin-left: auto; }
/* 44px: this is the button pressed dozens of times in a row, often on a phone. */
.ct-run-acts button { min-height: 44px; cursor: pointer; border: 1px solid var(--border, #334);
  background: var(--bg2, #1b2836); color: inherit; border-radius: 6px; font-size: 13px; padding: 6px 14px; white-space: nowrap; }
.ct-run-acts button.pri { background: var(--accent, #2d6cdf); border-color: var(--accent, #2d6cdf); color: #fff; }
.ct-run-acts button[disabled] { opacity: .55; cursor: default; }
/* A refusal STOPS the run and says why, right where the next click would have been. */
.ct-run-note { flex-basis: 100%; font-size: 12px; padding: 6px 8px; border-radius: 6px;
  background: rgba(220, 160, 40, .12); border: 1px solid rgba(220, 160, 40, .4); }
@media (max-width: 820px) {
  .ct-run-from { flex-basis: 100%; order: 3; }
  .ct-run-acts { margin-left: 0; width: 100%; }
  .ct-run-acts button { flex: 1; }
}

/* ── TKT-694: Tasks-screen fixes ─────────────────────────────────────────────── */
/* Domain + mode on every task row (criterion 3): both drive the filtering, so a
   mis-scoped row must be diagnosable from the screen it appears on. */
.task-dm-chip {
  display: inline-block;
  font-family: var(--font-mono); font-size: 10px; line-height: 1;
  padding: 2px 6px; margin-right: 5px; border-radius: 999px;
  background: var(--surface3); border: 1px solid var(--border2); color: var(--text2);
  vertical-align: 1px;
}
.task-dm-chip.task-dm-mode { color: var(--text3); }
.task-dm-chip.task-dm-untagged { border-color: var(--warning, #b58900); color: var(--warning, #b58900); }
/* Task search (criterion 4) — reuses the Tickets-tab input skin. */
.task-searchbar { display: flex; align-items: center; gap: 8px; }
.task-searchbar .tk-search-input { flex: 1 1 240px; min-width: 180px; }
/* While a search is running the view/category chips are not filtering anything. */
.task-views.task-chips-idle, .task-chips-idle .task-chip { opacity: 0.45; }
.task-views.task-chips-idle:hover, .task-chips-idle .task-chip:hover { opacity: 1; }

/* One-click ticket Resolve (criterion 9): the control lives ON the row. */
.tk-resolve-btn {
  margin-left: auto; flex: 0 0 auto;
  background: var(--surface3); border: 1px solid var(--border2); color: var(--success);
  border-radius: 6px; padding: 3px 10px; font-size: 12px; line-height: 1.4; cursor: pointer;
}
.tk-resolve-btn:hover { background: var(--accent-dim); border-color: var(--success); }
/* The undo toast — fixed so it is in reach wherever the list is scrolled. */
.tk-undo-toast {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%);
  z-index: 1000;
  display: flex; align-items: center; gap: 12px;
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 10px;
  padding: 10px 16px; box-shadow: 0 6px 24px rgba(0,0,0,0.35);
  font-size: 13px; color: var(--text);
}
.tk-undo-toast .tk-undo-btn { white-space: nowrap; }

/* ── TKT-1282: the Undo bar and Recent actions (src/hub/hub-undo.js) ─────────────────────────────────────────────
   The bar is on <body>, not inside a screen, so a screen re-rendering never removes it. Above the assistant dock. */
.hu-bar {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: max(18px, calc(12px + env(safe-area-inset-bottom)));
  /* ABOVE every editor dialog (the BOM editor is 5000, the admin and lightbox overlays 9999) — an undo made inside one
     was journalled with its bar hidden underneath it (TKT-1345, found on the bench); below the session banner (99999). */
  z-index: 10000; display: flex; align-items: center; gap: 12px; max-width: min(92vw, 640px);
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 10px;
  padding: 10px 14px; box-shadow: 0 6px 24px rgba(0,0,0,0.35); font-size: 13px; color: var(--text);
}
.hu-bar[hidden] { display: none; }
.hu-bar-text { flex: 1 1 auto; min-width: 0; }
.hu-bar-x { background: none; border: none; color: var(--text3); font-size: 18px; cursor: pointer; padding: 0 4px; min-height: 32px; }
.hu-ok { color: var(--success); }
.hu-warn { color: var(--warning); }
.hu-backdrop { position: fixed; inset: 0; z-index: 1150; background: rgba(0,0,0,0.45); display: flex; justify-content: center; align-items: flex-start; padding: calc(var(--hub-header-h, 52px) + 8px) 12px 12px; }
.hu-backdrop[hidden] { display: none; }
.hu-panel { background: var(--surface); border: 1px solid var(--border2); border-radius: var(--radius); width: min(640px, 100%); max-height: calc(100dvh - var(--hub-header-h, 52px) - 24px); display: flex; flex-direction: column; }
.hu-panel-head { display: flex; align-items: center; gap: 6px; padding: 12px 14px; border-bottom: 1px solid var(--border); font-size: 13px; }
.hu-panel-head .hu-bar-x { margin-left: auto; }
.hu-list { overflow-y: auto; padding: 4px 0; }
.hu-row { display: flex; align-items: center; gap: 10px; padding: 9px 14px; border-bottom: 1px solid var(--border); font-size: 13px; }
.hu-row-undone .hu-row-sum { text-decoration: line-through; color: var(--text3); }
.hu-row-main { flex: 1 1 auto; min-width: 0; }
.hu-row-act { flex: 0 0 auto; max-width: 45%; text-align: right; }
.hu-muted { color: var(--text3); font-size: 11px; }
.hu-why { color: var(--warning); font-size: 11px; }
.hu-empty { padding: 14px; }
/* BUTTONS SAY WHAT THEY DO (TKT-1282): a control that REMOVES or DISMISSES a whole record never looks like one that
   clears or closes — it carries the danger colour, outlined. */
.btn-remove { color: var(--danger) !important; border: 1px solid var(--danger) !important; background: transparent !important; }

/* ── Quick-capture notes (TKT-916) ───────────────────────────────────────────
   The gesture overlay: menu, composer, floating button, pin indicator, toast.
   Every one of these is created by hub-quick-capture.js carrying data-qc-ui, which is
   what html2canvas excludes — so none of it can appear in the screenshot it is used to
   take. High z-index throughout: the composer must sit above the assistant dock and the
   lightbox, both of which are themselves overlays. */
.qc-menu {
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 10px;
  box-shadow: 0 8px 30px rgba(0,0,0,0.45); padding: 4px; min-width: 210px;
}
.qc-menu-item {
  display: block; width: 100%; text-align: left;
  background: none; border: 0; border-radius: 7px;
  padding: 11px 13px; font-size: 14px; line-height: 1.3; color: var(--text); cursor: pointer;
}
.qc-menu-item:hover, .qc-menu-item:focus-visible { background: var(--surface3); outline: none; }

.qc-backdrop {
  position: fixed; inset: 0; z-index: 100001;
  background: rgba(0,0,0,0.55);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 24px 12px; overflow-y: auto;
}
.qc-composer {
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.5);
  width: 100%; max-width: 460px; padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
}
.qc-composer.qc-dragover { outline: 2px dashed var(--accent); outline-offset: -6px; }
.qc-title { font-size: 15px; font-weight: 600; color: var(--text); }
.qc-row { display: flex; align-items: center; gap: 10px; }
.qc-label { font-size: 12px; color: var(--text-dim); min-width: 62px; }
.qc-select, .qc-email {
  flex: 1; background: var(--surface3); border: 1px solid var(--border2); border-radius: 7px;
  padding: 8px 10px; font-size: 14px; color: var(--text);
}
.qc-body {
  width: 100%; resize: vertical; min-height: 84px;
  background: var(--surface3); border: 1px solid var(--border2); border-radius: 8px;
  padding: 10px; font-size: 15px; line-height: 1.45; color: var(--text); font-family: inherit;
}
.qc-modes { gap: 16px; flex-wrap: wrap; }
.qc-radio { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); cursor: pointer; }
.qc-status { font-size: 12px; color: var(--text-dim); min-height: 16px; }
.qc-error { font-size: 12px; color: var(--danger, #e06c6c); min-height: 15px; }
.qc-shots { display: flex; flex-wrap: wrap; gap: 8px; }
/* PORTRAIT TILE, AND `contain` RATHER THAN `cover`. The first version was a 92px SQUARE with
   object-fit: cover, which centre-crops — so a tall phone screenshot lost its top and bottom in
   the preview and Craig could not tell whether the capture was any good. The tile is now shaped
   roughly like a phone and shows the WHOLE image, letterboxed when the proportions differ.
   Never go back to `cover` here: cropping the preview of a screenshot defeats the preview. */
/* flex: 0 0 auto — a flex child SHRINKS by default, and on a narrow composer these tiles
   collapse toward zero width, which looks exactly like a broken image. Pin the basis. */
.qc-shot { position: relative; width: 84px; height: 150px; flex: 0 0 auto; }
.qc-shot-open {
  display: block; width: 100%; height: 100%; padding: 0;
  background: none; border: 0; cursor: zoom-in; border-radius: 7px;
}
.qc-shot-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.qc-shot img {
  width: 100%; height: 100%; object-fit: contain;
  border: 1px solid var(--border2); border-radius: 7px; background: var(--surface3);
}

/* The full-size viewer — the window onto the capture that was missing entirely. */
.qc-viewer {
  position: fixed; inset: 0; z-index: 100003;   /* above the composer, which is 100001 */
  background: rgba(0,0,0,0.92);
  display: flex; align-items: center; justify-content: center;
  padding: 12px; cursor: zoom-out;
}
.qc-viewer-img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;                          /* never crop: showing all of it IS the job */
  border-radius: 4px;
}
.qc-viewer-close {
  position: absolute; top: 10px; right: 12px;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--surface2); border: 1px solid var(--border2); color: var(--text);
  font-size: 22px; line-height: 1; cursor: pointer;
}
.qc-shot-rm {
  position: absolute; top: -7px; right: -7px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border2); color: var(--text);
  font-size: 14px; line-height: 1; cursor: pointer;
}
/* The fidelity limits, collapsed by default — present at the moment they matter without
   lecturing on every capture. Opened automatically when the capture FAILED, because then
   there is nothing to look at and the explanation is the only useful thing on screen. */
.qc-limits { font-size: 12px; color: var(--text-dim); }
.qc-limits summary { cursor: pointer; padding: 2px 0; }
.qc-limits summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.qc-limits-body { padding: 4px 0 2px; line-height: 1.5; }
.qc-limits-body p { margin: 0 0 6px; }
.qc-file { font-size: 12px; color: var(--text-dim); }
.qc-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 2px; }
.qc-btn {
  background: var(--surface3); border: 1px solid var(--border2); border-radius: 8px;
  padding: 9px 16px; font-size: 14px; color: var(--text); cursor: pointer;
}
.qc-btn-primary { background: var(--accent-dim); border-color: var(--accent); }
.qc-btn:disabled { opacity: 0.55; cursor: default; }

/* The floating button — the guaranteed target when the screen is too dense for dead space.
   Sits clear of the bottom nav on a phone and out of the way of the assistant dock. */
.qc-fab {
  position: fixed; right: 14px; bottom: 92px; z-index: 99999;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--surface2); border: 1px solid var(--border2); color: var(--text);
  font-size: 18px; line-height: 1; cursor: pointer; opacity: 0.75;
  box-shadow: 0 4px 16px rgba(0,0,0,0.4);
}
.qc-fab:hover, .qc-fab:focus-visible { opacity: 1; outline: none; }

.qc-pin {
  position: fixed; right: 14px; bottom: 144px; z-index: 99999;
  display: flex; align-items: center; gap: 6px;
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 16px;
  padding: 5px 8px 5px 11px; font-size: 12px; color: var(--text);
  box-shadow: 0 4px 16px rgba(0,0,0,0.4); max-width: 62vw;
}
.qc-pin span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qc-pin-clear {
  background: none; border: 0; color: var(--text-dim); font-size: 15px; line-height: 1; cursor: pointer;
}
.qc-toast {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 100002;
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 10px;
  padding: 10px 16px; font-size: 13px; color: var(--text);
  box-shadow: 0 6px 24px rgba(0,0,0,0.35); max-width: 88vw; text-align: center;
}
@media (max-width: 699px) {
  .qc-composer { max-width: none; }
  .qc-fab { bottom: 78px; }
  .qc-pin { bottom: 130px; }
}

/* ── Quick-capture: the dead-space rule, expressed in CSS (TKT-916 follow-up) ──
   THE BUG THIS FIXES, hit by Craig on his iPhone (OT-508 step 3): holding a blank area
   selected the nearest text and raised the native iOS callout, and BOTH menus appeared —
   Safari's and ours. The JS dead-space check only decided whether to start our timer; it
   never stopped iOS, and it could not, because that listener is passive.

   iOS decides selection behaviour from CSS, before any JS timer fires. So the same rule has
   to exist here: suppress selection and the callout by DEFAULT, then hand it back to
   everything that actually holds text. A press on padding or background finds an element
   with none and does nothing; a press on real text finds one with `text` and behaves
   normally — copy-paste on the Hub is preserved, which was Craig's condition for the
   dead-space design in the first place.

   SCOPED TO body.qc-armed, added by hub-quick-capture.js only when the flag is ON. With the
   feature off, none of this applies and the Hub's selection behaviour is unchanged. */
body.qc-armed {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
/* Hand selection back to everything that carries readable or editable content. Deliberately
   broad: the cost of missing one is Craig unable to copy something, which is the failure this
   whole design was shaped to avoid. The cost of an extra one is a long-press on chrome
   selecting a word — visible, harmless, and reversible. */
body.qc-armed p, body.qc-armed span, body.qc-armed a,
body.qc-armed h1, body.qc-armed h2, body.qc-armed h3,
body.qc-armed h4, body.qc-armed h5, body.qc-armed h6,
body.qc-armed li, body.qc-armed td, body.qc-armed th,
body.qc-armed dt, body.qc-armed dd, body.qc-armed label,
body.qc-armed code, body.qc-armed pre, body.qc-armed blockquote,
body.qc-armed input, body.qc-armed textarea, body.qc-armed select,
body.qc-armed [contenteditable],
body.qc-armed .hub-md, body.qc-armed .markdown-body {
  -webkit-touch-callout: default;
  -webkit-user-select: text;
  user-select: text;
}
/* Our own overlay is never selectable — a long-press inside the composer should type, not
   select, and the menu items are buttons rather than prose. */
body.qc-armed [data-qc-ui] {
  -webkit-user-select: none;
  user-select: none;
}
body.qc-armed .qc-body, body.qc-armed .qc-email {
  -webkit-touch-callout: default;
  -webkit-user-select: text;
  user-select: text;
}

/* ── Notes review screen (TKT-917) ───────────────────────────────────────────
   The other half of the capture gesture: where notes are read, edited, pinned,
   dismissed and merged. Prefixed .qcv- to stay clear of the composer's .qc-. */
.qcv { padding: 4px 2px 24px; }
.qcv-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 0 12px; border-bottom: 1px solid var(--border2); margin-bottom: 12px;
}
.qcv-title { margin: 0; font-size: 17px; font-weight: 600; color: var(--text); }
.qcv-counts { font-size: 12px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.qcv-search {
  flex: 1 1 200px; min-width: 140px;
  background: var(--surface3); border: 1px solid var(--border2); border-radius: 7px;
  padding: 7px 10px; font-size: 14px; color: var(--text);
}
.qcv-toggle { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); cursor: pointer; }
.qcv-btn {
  background: var(--surface3); border: 1px solid var(--border2); border-radius: 7px;
  padding: 6px 12px; font-size: 13px; color: var(--text); cursor: pointer;
}
.qcv-btn:hover { background: var(--surface2); }
.qcv-btn-primary { background: var(--accent-dim); border-color: var(--accent); }
.qcv-btn:disabled { opacity: 0.55; cursor: default; }
.qcv-error { font-size: 12px; color: var(--danger, #e06c6c); min-height: 16px; margin-bottom: 6px; }
.qcv-empty { padding: 28px 6px; font-size: 14px; color: var(--text-dim); text-align: center; }
.qcv-group {
  margin: 18px 0 8px; font-size: 12px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-dim);
}
.qcv-row {
  border: 1px solid var(--border2); border-radius: 9px; background: var(--surface2);
  padding: 10px 12px; margin-bottom: 8px;
}
/* Dismissed rows are visibly SET ASIDE rather than hidden-looking — you only see them because you
   asked to, and they should read as kept, not as pending work. */
.qcv-row-dismissed { opacity: 0.62; }
.qcv-row-head { display: flex; gap: 12px; align-items: flex-start; }
.qcv-thumb {
  flex: 0 0 auto; width: 52px; height: 84px; padding: 0;
  background: none; border: 0; border-radius: 6px; cursor: zoom-in;
}
.qcv-thumb-sm { width: 40px; height: 64px; }
.qcv-thumb img {
  width: 100%; height: 100%; object-fit: contain;   /* never crop — same rule as the composer */
  border: 1px solid var(--border2); border-radius: 6px; background: var(--surface3);
}
.qcv-thumb:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.qcv-main { flex: 1 1 auto; min-width: 0; }
.qcv-line1 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.qcv-type { font-size: 12px; font-weight: 600; color: var(--accent); }
.qcv-when { font-size: 11px; color: var(--text-dim); margin-left: auto; }
.qcv-pinned { font-size: 12px; }
.qcv-state { font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
  border: 1px solid var(--border2); border-radius: 100px; padding: 1px 7px; color: var(--text-dim); }
/* TKT-1057 §4d — the disposition badge. Only DONE is green: `consumed` used to be, which is how a
   note sitting in the catch-all reassured Craig that it had been handled. PARKED is deliberately
   the warning colour — a parked note is recorded and nothing more. */
.qcv-state-open { color: var(--text); }
.qcv-state-parked { color: var(--warn, #d8a657); border-color: var(--warn, #d8a657); }
.qcv-state-filed { color: var(--accent); border-color: var(--accent); }
.qcv-state-done { color: var(--success, #6fbf73); border-color: var(--success, #6fbf73); }
.qcv-state-dismissed { color: var(--text-dim); }
/* The degraded reading — ticket statuses unavailable. Neutral on purpose: it is not a state. */
.qcv-state-linked { color: var(--text-dim); border-style: dashed; }
/* Retained so a cached page mid-deploy does not render an unstyled badge. */
.qcv-state-consumed { color: var(--text-dim); }

.qcv-filter { display: flex; flex-wrap: wrap; gap: 4px; }
.qcv-filter-btn { font-size: 11px; padding: 2px 9px; font-variant-numeric: tabular-nums; }
.qcv-filter-on { border-color: var(--accent); color: var(--accent); background: var(--surface3); }
.qcv-degraded {
  flex-basis: 100%; font-size: 12px; color: var(--warn, #d8a657);
  border: 1px dashed var(--warn, #d8a657); border-radius: 6px; padding: 4px 8px;
}
.qcv-body { font-size: 14px; line-height: 1.45; color: var(--text); white-space: pre-wrap; word-break: break-word; }
.qcv-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.qcv-chip {
  font-size: 11px; color: var(--text-dim);
  background: var(--surface3); border: 1px solid var(--border2); border-radius: 100px; padding: 1px 8px;
}
.qcv-chip-ticket { color: var(--accent); border-color: var(--accent); }
/* The chip is a real button when the Tickets board is loaded (Craig's note, 2026-09-09). */
.qcv-chip-link { cursor: pointer; font-family: inherit; }
.qcv-chip-link:hover { background: var(--surface2); }
/* The catch-all is a drawer, not work — chipped muted so it cannot be mistaken for a live ticket. */
.qcv-chip-catchall { color: var(--text-dim); border-color: var(--border2); border-style: dashed; }
/* ONE delivery status. Red is reserved for "nothing got through" — see deliveryStatus(). */
.qcv-deliv-delivered { color: var(--success, #6fbf73); }
.qcv-deliv-pending { color: var(--text-dim); }
.qcv-deliv-failed { color: var(--danger, #e06c6c); border-color: var(--danger, #e06c6c); }
/* Retained for a cached page mid-deploy; the view no longer emits per-attempt chips. */
.qcv-deliv-sent { color: var(--success, #6fbf73); }
.qcv-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.qcv-editor {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border2);
  display: flex; flex-direction: column; gap: 6px;
}
.qcv-label { font-size: 11px; color: var(--text-dim); }
.qcv-edit-type, .qcv-edit-body {
  background: var(--surface3); border: 1px solid var(--border2); border-radius: 7px;
  padding: 8px 10px; font-size: 14px; color: var(--text); font-family: inherit; width: 100%;
}
.qcv-edit-body { resize: vertical; line-height: 1.45; }
.qcv-strip { display: flex; flex-wrap: wrap; gap: 6px; }
.qcv-editor .qcv-btn { align-self: flex-start; }
@media (max-width: 699px) {
  .qcv-bar { gap: 8px; }
  .qcv-when { margin-left: 0; }
}

/* ── TKT-926 — the assistant's queued notes, inside the dock drawer ──────────────────────────
   Deliberately quieter than the review screen (.qcv-*): this is a waiting room Craig passes
   through on his way to a conversation, not a place he works. Same tokens throughout so it reads
   as part of the dock rather than a panel bolted into it. */
/* Sits ABOVE the chat inside the drawer column, and is CAPPED so a long queue scrolls itself
   instead of pushing the chat input off the bottom of the screen — the input is why he opened
   the drawer, and a queue that buries it has taken the surface over. */
.adn { margin: 0 14px 12px; max-height: 46vh; overflow-y: auto; flex: 0 0 auto; }
.adn-title { font-size: 13px; font-weight: 600; margin: 0 0 6px; color: var(--text2); }
.adn-msg { font-size: 12px; color: var(--text2); min-height: 0; }
.adn-msg:not(:empty) { min-height: 18px; margin-bottom: 6px; }

.adn-card {
  border: 1px solid var(--border2); border-radius: 9px; background: var(--surface2);
  padding: 10px 12px; margin-bottom: 8px;
}
.adn-head { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; margin-bottom: 4px; }
.adn-type { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent); }
.adn-where { font-size: 11px; color: var(--text3); }
.adn-body { font-size: 13px; line-height: 1.45; white-space: pre-wrap; }

/* PORTRAIT, contain, never cover — a cropped preview is what stopped Craig judging a capture the
   first time round, and this is the third surface to show one. */
.adn-thumb {
  display: block; margin: 8px 0 0; padding: 0; border: 1px solid var(--border2);
  border-radius: 6px; background: var(--surface1); cursor: pointer; overflow: hidden;
  max-width: 140px;
}
.adn-thumb img { display: block; width: 100%; height: auto; object-fit: contain; }

.adn-reply {
  margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--border2);
  font-size: 12.5px; line-height: 1.45;
}
/* The age is NOT decoration. The reply is written when the note arrives and read whenever Craig
   gets to it, so the surface must say when the value was established (AM-6438). */
.adn-reply-when { font-size: 11px; color: var(--text3); margin-bottom: 3px; }
.adn-reply-text { white-space: pre-wrap; }
.adn-reply-none { color: var(--text3); font-style: italic; }

.adn-acts { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 9px; }
.adn-btn {
  font: inherit; font-size: 11.5px; padding: 3px 9px; cursor: pointer;
  border: 1px solid var(--border2); border-radius: 6px;
  background: var(--surface1); color: var(--text1);
}
.adn-btn:hover { background: var(--surface3); }

/* The count on the floating button. Absolute inside the FAB, which is already positioned. */
.adn-badge {
  position: absolute; top: -4px; right: -4px; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 9px; background: var(--accent); color: var(--bg1);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
  pointer-events: none;
}

/* ── PR Log (TKT-1065) ──────────────────────────────────────────────────────────
   AE_PRs, read-only. The nav leaf was a stub for two and a half months, so this
   log had no reader and 837 of 861 rows read "Open" unnoticed. Styling follows the
   existing token set; nothing here is bespoke. */
.prl-bar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.prl-chip {
  padding: 4px 10px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--text-dim); font: inherit; font-size: 12px;
  cursor: pointer;
}
.prl-chip:hover { color: var(--text); border-color: var(--border); }
.prl-chip b { color: var(--text); margin-left: 2px; }
.prl-chip-on { color: var(--text); border-color: var(--accent); }
.prl-refresh { margin-left: auto; }

.prl-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.prl-table th {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line);
  color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
}
.prl-table td { padding: 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
.prl-num { white-space: nowrap; font-family: var(--font-mono); }
.prl-num a { color: var(--blue); text-decoration: none; }
.prl-num a:hover { text-decoration: underline; }
.prl-when { white-space: nowrap; color: var(--text-dim); font-size: 12px; }
.prl-title div:first-child { color: var(--text); }
.prl-meta { margin-top: 3px; color: var(--muted); font-size: 11px; }
.prl-meta code { font-family: var(--font-mono); font-size: 11px; }
.prl-risk { color: var(--danger); }

.prl-pill {
  display: inline-block; padding: 2px 8px; border-radius: 10px;
  font-size: 11px; font-weight: 600; white-space: nowrap;
}
.prl-open     { background: var(--blue-dim);    color: var(--blue); }
.prl-merged   { background: var(--success-dim); color: var(--success); }
.prl-flagged  { background: var(--danger-dim);  color: var(--danger); }
.prl-reviewed { background: var(--accent-dim);  color: var(--accent); }
.prl-awaiting { background: var(--surface);     color: var(--text-dim); }
/* Closed = closed WITHOUT merging. Deliberately the quietest pill on the screen: it is a real
   terminal state, but it is the one nobody needs to act on. */
.prl-closed   { background: var(--surface);     color: var(--muted); }

.prl-empty { padding: 24px 8px; color: var(--muted); }
.prl-error { color: var(--danger); }

/* ── Customers › Directory (TKT-1108 step 1): the list, and the list with a side window open ──
   iPad Air is the base (820 portrait / 1180 landscape): one pane at a time, the side window
   overlays the list. From 1024px (iPad Pro landscape, desktop) the side window is the second pane
   beside the list and stays open. Rows are tap-sized (44px) and fold to a card under 760px. */
.cust-page { margin-top: 10px; }
.cust-layout { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.cust-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-bottom: 8px; }
.cust-toolbar input[type="search"] { flex: 1 1 200px; min-width: 0; min-height: 40px; padding: 6px 12px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); color: inherit; font-size: 14px; }
.cust-count { font-size: 12px; color: var(--text3); white-space: nowrap; }
/* TKT-1286: the directory's filters — a wrapping row under the search box, phone-first (40px targets). */
.cust-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; flex: 1 1 100%; }
.cust-filters select { min-height: 40px; padding: 4px 8px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); color: inherit; font-size: 14px; max-width: 100%; }
.cust-filters select.cust-filter-on { border-color: var(--accent, var(--border2)); font-weight: 600; }
.cust-filter-note { flex: 1 1 100%; font-size: 12px; color: var(--text3); }
.cust-group-label { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text3); margin: 10px 0 2px; }
.cust-head-row, .cust-row { display: grid; grid-template-columns: minmax(200px, 2.4fr) minmax(120px, 1.2fr) 120px minmax(120px, 1fr) 130px; gap: 8px; align-items: center; padding: 8px; }
.cust-head-row { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text3); border-bottom: 1px solid var(--border2); margin-top: 6px; }
.cust-row { border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); cursor: pointer; font-size: 12px; min-height: 44px; margin-top: 4px; }
.cust-row:hover, .cust-row:focus-visible { border-color: var(--accent); outline: none; }
.cust-row-on { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.cust-c { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cust-c-name { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; white-space: normal; }
.cust-name { font-weight: 600; font-size: 13px; }
.cust-sub { font-size: 11px; color: var(--text3); }
.cust-flag { font-size: 10px; padding: 1px 6px; border-radius: 999px; border: 1px solid var(--border2); white-space: nowrap; }
.cust-flag-owes { border-color: rgba(240,160,60,.6); color: #f0a03c; }
.cust-owes { color: #f0a03c; }
.cust-error { padding: 10px 14px; margin-bottom: 12px; border: 1px solid rgba(240,90,90,.5); background: rgba(240,90,90,.12); border-radius: 8px; font-size: 13px; }
/* The side window: an overlay on the base tier… */
.cust-side { position: fixed; top: 0; right: 0; bottom: 0; width: min(440px, 92vw); z-index: 40; overflow-y: auto; padding: 14px; background: var(--surface, #0e1116); border-left: 1px solid var(--border2); box-shadow: -12px 0 30px rgba(0,0,0,.35); }
.cust-side-empty { display: none; }
.cust-side-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.cust-side-title { font-size: 16px; font-weight: 700; display: flex; flex-direction: column; gap: 2px; }
.cust-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px 14px; padding: 10px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); font-size: 12px; }
.cust-fact { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cust-fact > span { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text3); }
.cust-fact > b { font-weight: 500; word-break: break-word; }
.cust-fact-wide { grid-column: 1 / -1; }
.cust-side-note { margin-top: 12px; font-size: 11px; color: var(--text3); }
/* BELOW THE LARGE TIER THE SIDE WINDOW IS A SHEET, AND A SHEET MUST BE ON TOP (2026-09-25, Craig on the iPad:
   "the background and the foreground overlap each other … I can't get to the actions button"). It used to sit
   at z-index 40 — UNDER the Hub's sticky header (100) — with no backdrop: the moment the page scrolled, the
   header covered the side window's ← and Actions ▾ (measured: elementFromPoint at Actions answered the HEADER
   at 768×1024 once scrollY > 0), and the list stayed visible and tappable around it, so rows' own Actions
   buttons sat under the sheet. Now: the sheet is above the header (below the assistant button and the detail
   overlay), a dimmed backdrop covers the list and closes the sheet on a tap, and the top clears the notch. */
.cust-side { z-index: 150; padding-top: max(14px, env(safe-area-inset-top)); overscroll-behavior: contain; }
.cust-scrim { position: fixed; inset: 0; z-index: 140; background: rgba(0, 0, 0, .5); }
/* …and the second pane on the large tier. */
@media (min-width: 1024px) {
  .cust-scrim { display: none; }
  .cust-layout-open .cust-side { z-index: auto; padding-top: 14px; }
  .cust-layout-open { grid-template-columns: minmax(0, 1fr) minmax(360px, 420px); align-items: start; }
  /* Pins BELOW the header and the pinned nav (--hub-chrome-h, measured in hub-nav-collapse.js), never at 8px: at 8px it slid under both once the page scrolled, and they covered its ← and Actions ▾ (measured 1180×820, scrollY 500). */
  .cust-layout-open .cust-side { position: sticky; top: calc(var(--hub-chrome-h, 52px) + 8px); width: auto; max-height: calc(100vh - var(--hub-chrome-h, 52px) - 16px); box-shadow: none; border: 1px solid var(--border2); border-radius: var(--radius); }
  .cust-side-empty { display: block; }
  .cust-layout:not(.cust-layout-open) .cust-side-empty { display: none; }
}
/* The PHONE rules for the directory rows and the side window live at the END of this section (after
   every desktop grid rule) — see "PHONE TIER" below. They used to sit here, and the two desktop
   grid rules that follow, at equal specificity and later in the file, silently WON on the phone:
   every row stayed six fixed columns (~800px), the list scrolled sideways under a 92vw fixed side
   window, and Craig had to drag the list aside to reach Actions ▾ (2026-09-24, on the phone). */
/* TKT-1108 step 2 — the one Actions ▾ dropdown, on every row and in the side window's header. */
.cust-head-row, .cust-row { grid-template-columns: minmax(200px, 2.4fr) minmax(120px, 1.2fr) 120px minmax(120px, 1fr) 130px 92px; }
/* TKT-1108 step 6 (second half) — a party with its own columns (Items: Type / On hand / On order / Price). */
.cust-cols-6 .cust-head-row, .cust-cols-6 .cust-row { grid-template-columns: minmax(220px, 2.6fr) 110px 120px 100px 110px 92px; }
/* TWO PANES ON THE LARGE TIER (2026-09-25, same report). With the side window open the list column is the
   grid's minmax(0, 1fr) — about 700px on an iPad in landscape — while the fixed row tracks above total ~830px,
   so every row spilled UNDER the side pane and its own Actions ▾ sat beneath it (measured at 1180×820:
   elementFromPoint at a row's Actions answered the side pane's .cust-facts). While two panes share the width,
   the middle tracks may shrink to nothing — their cells already ellipsize — and the name and Actions ▾ keep
   their room, so a row can never be wider than its column. The same holds BETWEEN the phone and large tiers
   (761–1023px, an iPad in portrait): one full-width list of ~730px under ~830px of fixed tracks scrolled the
   whole page sideways and put the rows' Actions ▾ past the screen edge. */
@media (min-width: 761px) and (max-width: 1023.98px) {
  .cust-head-row, .cust-row, .cust-cols-6 .cust-head-row, .cust-cols-6 .cust-row { grid-template-columns: minmax(140px, 2.4fr) minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) 92px; }
}
@media (min-width: 1024px) {
  .cust-list { min-width: 0; }
  .cust-layout-open .cust-head-row, .cust-layout-open .cust-row,
  .cust-layout-open.cust-cols-6 .cust-head-row, .cust-layout-open.cust-cols-6 .cust-row { grid-template-columns: minmax(140px, 2.4fr) minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) 92px; }
}
.cust-c-actions { overflow: visible; text-align: right; }
.cust-actions { position: relative; display: inline-block; }
.cust-actions-btn { min-height: 32px; white-space: nowrap; }
.cust-menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 45; min-width: 240px; padding: 6px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface, #0e1116); box-shadow: 0 10px 28px rgba(0,0,0,.4); text-align: left; }
.cust-menu-group { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text3); padding: 6px 8px 2px; }
.cust-menu-group-muted { border-top: 1px solid var(--border2); margin-top: 6px; padding-top: 8px; text-transform: none; letter-spacing: 0; font-size: 11px; }
.cust-menu-item { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; padding: 6px 10px; border: 0; border-radius: 6px; background: transparent; color: inherit; font-size: 13px; text-align: left; cursor: pointer; }
.cust-menu-item:hover, .cust-menu-item:focus-visible { background: var(--surface2); outline: none; }
.cust-menu-stub { opacity: .55; cursor: not-allowed; }
.cust-menu-note { font-size: 10px; color: var(--text3); }
.cust-menu-empty { padding: 8px 10px; font-size: 12px; color: var(--text3); max-width: 280px; }
.cust-side-head { justify-content: flex-start; }
.cust-side-actions { margin-left: auto; }
/* PHONE TIER (TKT-1108; corrected 2026-09-24 after Craig's first phone run). AFTER every desktop grid
   rule on purpose — same specificity, later wins. Rows fold to two columns with the name, the terms
   and the Actions ▾ cell full-width, so the list never grows wider than the phone. The side window
   is the WHOLE screen: fixed, full width, its own scroll, and overscroll-behavior: contain so a
   swipe inside it never scrolls the list underneath. The ← in its header is the way back. */
@media (max-width: 760px) {
  .cust-head-row, .cust-cols-6 .cust-head-row { display: none; }
  .cust-row, .cust-cols-6 .cust-row { grid-template-columns: 1fr 1fr; }
  .cust-c-name, .cust-c-terms { grid-column: 1 / -1; }
  .cust-c-actions { grid-column: 1 / -1; text-align: left; }
  .cust-side { left: 0; right: 0; width: 100vw; max-width: 100vw; border-left: 0; border-radius: 0; padding-bottom: 40px; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  .cust-side-head { position: sticky; top: 0; z-index: 2; padding: 4px 0 8px; background: var(--surface, #0e1116); }
}
/* TKT-1108 step 3 — the side window's tabs and the In progress stages. */
.cust-tabs { display: flex; gap: 4px; margin-top: 12px; border-bottom: 1px solid var(--border2); }
.cust-tab { min-height: 36px; padding: 6px 12px; border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--text3); font-size: 13px; cursor: pointer; }
.cust-tab-on { color: inherit; border-bottom-color: var(--accent); font-weight: 600; }
.cust-tab-body { padding-top: 10px; }
.cust-stage { margin-bottom: 12px; }
.cust-stage-head { display: flex; align-items: center; gap: 8px; padding: 6px 0 4px; border-bottom: 1px solid var(--border2); }
.cust-stage-head b { font-size: 13px; }
.cust-stage-next { margin-left: auto; font-size: 11px; color: var(--text3); }
.cust-stage-type { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text3); margin: 8px 0 2px; }
.cust-stage-empty { font-size: 12px; color: var(--text3); padding: 6px 0; }
.cust-item { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-height: 44px; padding: 6px 8px; margin-top: 4px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); font-size: 12px; cursor: pointer; }
.cust-item:hover, .cust-item:focus-visible { border-color: var(--accent); outline: none; }
.cust-item-date { color: var(--text3); white-space: nowrap; min-width: 84px; }
.cust-item-title { font-weight: 600; flex: 1 1 200px; }
.cust-item-who { color: var(--text3); font-size: 11px; }
.cust-menu-stage { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text3); min-width: 64px; }
/* TKT-1108 step 4 — History filters and Correspondence threads in the side window. */
.cust-hist-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 8px; }
.cust-hist-since { margin-left: auto; font-size: 11px; color: var(--text3); display: flex; align-items: center; gap: 6px; }
.cust-hist-since input { min-height: 32px; padding: 2px 6px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); color: inherit; font-size: 12px; }
.cust-thread { margin-top: 4px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); }
.cust-thread-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-height: 44px; padding: 6px 8px; font-size: 12px; cursor: pointer; }
.cust-thread-head:hover, .cust-thread-head:focus-visible { outline: none; background: var(--surface); }
.cust-thread-open { border-color: var(--accent); }
.cust-msg { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-height: 40px; padding: 4px 8px 4px 16px; border-top: 1px solid var(--border2); font-size: 12px; cursor: pointer; }
.cust-msg:hover, .cust-msg:focus-visible { outline: none; background: var(--surface); }
.cust-msg-dir { font-weight: 700; min-width: 14px; }
.cust-msg-in { color: #5dc26b; }
.cust-msg-out { color: var(--accent); }
.cust-msg-who { flex: 1 1 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* TKT-1108 step 5 — a stage row with nowhere to go yet (a sales order: no Hub screen until TKT-1038). */
.cust-item-static { cursor: default; }
.cust-item-static:hover { border-color: var(--border2); }

/* TKT-1134 — the task board grouped by initiative */
.task-group-summary { font-size: 12px; color: var(--text2, var(--text)); margin: 6px 0 10px; }
.task-group { border: 1px solid var(--border2); border-radius: var(--radius); margin: 0 0 12px; padding: 0 10px 8px; background: var(--bg2, transparent); }
.task-group > summary { cursor: pointer; list-style: none; padding: 10px 0 8px; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
.task-group > summary::-webkit-details-marker { display: none; }
.task-group > summary::before { content: '▸'; color: var(--text3); }
.task-group[open] > summary::before { content: '▾'; }
.task-group-title { font-weight: 600; }
.task-group-sub { font-size: 12px; color: var(--text3); }
.task-group-no_initiative, .task-group-no_ticket { border-style: dashed; }
.task-group-ticket { font-size: 12px; font-weight: 600; color: var(--text2, var(--text)); margin: 10px 0 4px; padding-top: 6px; border-top: 1px solid var(--border2); }
.task-group-n { font-weight: 400; color: var(--text3); margin-left: 4px; }
.task-crit-line { font-size: 11px; color: var(--text3); margin: 4px 0 -2px 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.task-crit-no { font-family: var(--font-mono); color: var(--accent); font-weight: 600; }

/* TKT-1136 — field explanations on a tap, not on screen */
#detailBody .detail-field.has-help .task-status-hint { display: none; }
#detailBody .detail-field.has-help.help-open .task-status-hint { display: block; }
.field-help-btn { margin-left: 6px; width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--border2); background: transparent; color: var(--text3); font: 600 11px/1 var(--font-mono, monospace); cursor: pointer; vertical-align: middle; padding: 0; }
.field-help-btn[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
.field-help-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* TKT-1079 c8 — a failed field read, said plainly, and a scan recognised from an accepted one */
#hub-panel-scan-document .scan-read-failed { padding: 9px 12px; margin: 0 0 12px; border-radius: var(--radius); border: 1px solid var(--border2); border-left: 3px solid var(--warn, #d98324); font-size: 13px; line-height: 1.5; color: var(--text2, var(--text)); }
#hub-panel-scan-document .scan-read-failed .scan-btn { display: block; margin-top: 8px; }
/* TKT-1281: the suspicion flag, shown before confirm so it is decided on this screen. */
#hub-panel-scan-document .scan-flag-note { padding: 9px 12px; margin: 0 0 12px; border-radius: var(--radius); border: 1px solid var(--border2); border-left: 3px solid var(--red, #c62828); font-size: 13px; line-height: 1.5; }
#hub-panel-scan-document .scan-flag-note ul { margin: 4px 0 4px 18px; padding: 0; }
#hub-panel-scan-document .scan-flag-how { color: var(--text2, var(--text)); margin-top: 4px; }
#hub-panel-scan-document .scan-known-note { padding: 9px 12px; margin: 0 0 12px; border-radius: var(--radius); border: 1px solid var(--border2); border-left: 3px solid var(--green, var(--accent)); font-size: 13px; line-height: 1.5; color: var(--text2, var(--text)); }

/* TKT-1138 — "Is this a bill we owe?" on a Bill Review Set aside item */
.bill-recat { padding: 9px 12px; margin: 10px 0; border-radius: var(--radius); border: 1px solid var(--border2); border-left: 3px solid var(--accent); font-size: 13px; line-height: 1.6; color: var(--text2, var(--text)); }
.bill-recat .btn { margin: 4px 4px 0 0; }

/* TKT-1137 — the page viewer, the full-screen view, the verdict question, recently filed */
#hub-panel-scan-document .scan-pages { border: 1px solid var(--border2); border-radius: var(--radius); padding: 8px; margin: 0 0 12px; max-height: 75vh; overflow-y: auto; -webkit-overflow-scrolling: touch; background: var(--bg2, transparent); }
#hub-panel-scan-document .scan-pages-compact { max-height: 60vh; }
#hub-panel-scan-document .scan-pages-bar { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 6px; position: sticky; top: -8px; background: var(--bg, #111); padding: 4px 0; z-index: 1; }
#hub-panel-scan-document .scan-page { margin-bottom: 10px; }
#hub-panel-scan-document .scan-page-label { font-size: 11px; color: var(--text3); margin: 2px 0; }
#hub-panel-scan-document .scan-page-frame { width: 100%; height: 70vh; border: 1px solid var(--border2); background: #fff; }
#hub-panel-scan-document .scan-overlay { position: fixed; inset: 0; z-index: 1000; background: var(--bg, #111); display: flex; flex-direction: column; }
#hub-panel-scan-document .scan-overlay-bar { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 10px 12px; padding-top: max(10px, env(safe-area-inset-top)); border-bottom: 1px solid var(--border2); }
#hub-panel-scan-document .scan-overlay-body { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 8px 12px; }
#hub-panel-scan-document .scan-page-frame-full { height: 85vh; }
#hub-panel-scan-document .scan-confirm-grid { display: block; }
@media (min-width: 900px) { #hub-panel-scan-document .scan-confirm-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: start; } #hub-panel-scan-document .scan-confirm-pages { position: sticky; top: 8px; } }
#hub-panel-scan-document .scan-verdict-fix { font-size: 13px; color: var(--text2, var(--text)); margin: 0 0 10px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
#hub-panel-scan-document .scan-recent { margin: 14px 0; }
#hub-panel-scan-document .scan-recent-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border2); font-size: 13px; }

/* TKT-1173 Money › Reconcile: one card per account for the month — its chip, its balances, and the lists that
   explain the difference (open by default: what the bank has that QuickBooks lacks, and amounts that differ). */
.rec-month { padding: 4px 6px; border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); color: inherit; font-size: 12px; }
.rec-summary { margin: 8px 0 10px; font-size: 12.5px; }
.rec-acct { border: 1px solid var(--border2); border-radius: var(--radius); background: var(--surface2); padding: 8px 10px; margin-bottom: 8px; font-size: 12px; }
.rec-acct-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 10px; }
.rec-acct-name { font-weight: 600; overflow-wrap: anywhere; }
.rec-last4 { font-weight: 400; color: var(--text3); font-size: 10.5px; }
.rec-chip { font-size: 11px; }
.rec-nums, .rec-why, .rec-anchor { margin-top: 4px; color: var(--text2, inherit); font-size: 11.5px; overflow-wrap: anywhere; }
.rec-anchor { color: var(--text3); }
.rec-warn { margin-top: 6px; padding: 5px 7px; border-left: 3px solid var(--red, #c62828); color: var(--red, #c62828); font-size: 11.5px; }
.rec-upload { margin-top: 6px; }
.rec-sec { margin-top: 6px; }
.rec-sec > summary { cursor: pointer; font-size: 11.5px; font-weight: 600; padding: 3px 0; }
.rec-row { display: grid; grid-template-columns: 52px minmax(0, 1fr) 84px; gap: 6px; align-items: start; padding: 4px 2px; border-bottom: 1px solid var(--border2); font-size: 11px; }
.rec-r-date { color: var(--text3); }
.rec-r-words { overflow-wrap: anywhere; }
.rec-r-note { display: block; color: var(--text3); font-size: 10.5px; }
.rec-r-n { text-align: right; font-variant-numeric: tabular-nums; }
/* TKT-1174: the report's actions — match by hand, leave it, undo — and the notice that says what happened. */
.rec-r-act { display: block; margin-top: 3px; }
.rec-act { padding: 2px 8px; font-size: 10.5px; border: 1px solid var(--border2); border-radius: var(--radius); background: transparent; color: inherit; cursor: pointer; }
.rec-act:hover { border-color: var(--accent); }
.rec-act-go { border-color: var(--accent); color: var(--accent); }
/* TKT-1174: the amount correction's form opens under its row — it wraps on a phone, the account list at full width. */
.rec-correct-form { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; font-size: 11.5px; }
.rec-correct-acct { max-width: 100%; min-width: 0; font-size: 11.5px; }
.rec-correct-form .rec-note { flex-basis: 100%; }
.rec-notice { margin: 6px 0; padding: 5px 8px; border-left: 3px solid var(--accent); font-size: 11.5px; }
.rec-left .rec-r-words, .rec-byhand .rec-r-words { color: var(--text3); }
/* TKT-1175: sign-off — the month banner, an account's sign-off line, a signed-off card, and what changed after it. */
.rec-banner { margin: 0 0 10px; padding: 5px 8px; border-left: 3px solid var(--border2); color: var(--text2, inherit); font-size: 11.5px; overflow-wrap: anywhere; }
.rec-banner-done { border-left-color: var(--green, #2e7d32); }
.rec-signoff { margin-top: 6px; font-size: 11.5px; overflow-wrap: anywhere; }
.rec-note { color: var(--text3); }
.rec-signed { border-left: 3px solid var(--green, #2e7d32); }
.rec-broken .rec-r-words { color: var(--red, #c62828); }

/* TKT-1301 — the Maintenance Run screen */
.mr-now { margin: 4px 0 8px; }
.mr-req { margin: 4px 0 8px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.mr-set { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--border, #333); max-width: 520px; }
.mr-set select, .mr-set input[type=number] { min-width: 7em; }
.mr-q { display: block; padding: 7px 4px; border-bottom: 1px solid var(--border, #333); overflow-wrap: anywhere; }
.mr-q input[type=checkbox] { transform: scale(1.3); margin-right: 8px; }
.mr-qhead { cursor: pointer; }
.mr-badge { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: 11px; font-weight: 600; border: 1px solid currentColor; vertical-align: 1px; margin-left: 4px; }
.mr-ready { color: var(--success); background: var(--success-dim); }
.mr-ask { color: #e5a13a; background: rgba(229,161,58,0.12); }
.mr-held { color: var(--text3, #999); font-weight: 500; }
.mr-question { white-space: pre-wrap; margin: 8px 0 6px 28px; padding: 8px 10px; border-left: 3px solid #e5a13a; background: rgba(229,161,58,0.06); font-size: 13px; line-height: 1.45; }
.mr-answer { display: block; width: calc(100% - 28px); margin: 0 0 6px 28px; box-sizing: border-box; font: inherit; font-size: 14px; padding: 6px 8px; }
.mr-answer-row { margin-left: 28px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.mr-done { opacity: .7; cursor: default; }
.mr-done-badge { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: 11px; font-weight: 600; color: var(--success); border: 1px solid var(--success); background: var(--success-dim); vertical-align: 1px; }
.mr-label { display: block; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--text3, #999); margin: 18px 0 6px; }
.mr-label:first-child { margin-top: 0; }

/* TKT-1275 — the header's Find-a-document panel. */
.hf-backdrop { position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:2000; display:flex; justify-content:center; align-items:flex-start; padding:56px 8px 8px; }
.hf-panel { background:var(--surface); border:1px solid var(--border2); border-radius:var(--radius); width:min(720px,100%); max-height:calc(100vh - 72px); display:flex; flex-direction:column; gap:8px; padding:10px; }
.hf-head { display:flex; justify-content:space-between; align-items:center; }
.hf-close { background:none; border:none; color:var(--text2); font-size:16px; cursor:pointer; }
.hf-q { width:100%; box-sizing:border-box; font-size:16px; padding:8px; background:var(--surface2); border:1px solid var(--border2); color:var(--text); border-radius:var(--radius); }
.hf-filters { display:flex; flex-wrap:wrap; gap:6px; align-items:center; font-size:12.5px; color:var(--text2); }
.hf-filters select, .hf-filters input { background:var(--surface2); border:1px solid var(--border2); color:var(--text); border-radius:var(--radius); padding:3px 5px; font-size:13px; }
.hf-filters input[type=number] { width:80px; }
.hf-results { overflow:auto; display:flex; flex-direction:column; gap:4px; }
.hf-hit { display:grid; grid-template-columns:1fr auto; gap:2px 8px; text-align:left; background:var(--surface2); border:1px solid var(--border); border-radius:var(--radius); padding:6px 8px; color:var(--text); cursor:pointer; font:inherit; }
.hf-hit:hover { border-color:var(--accent, var(--border2)); }
.hf-hit-who { font-weight:600; }
.hf-hit-sits { font-size:12px; color:var(--text2); justify-self:end; }
.hf-sits-needs_review { color:var(--warning, #c90); }
.hf-hit-meta, .hf-hit-what { grid-column:1 / -1; font-size:12px; color:var(--text2); }
.hf-count, .hf-empty { font-size:12.5px; color:var(--text2); padding:4px 2px; }
.hf-error { color:var(--danger, #c33); }
.hf-tabs { display:flex; gap:4px; margin-left:auto; margin-right:8px; }
.hf-tab, .hf-back { background:var(--surface2); border:1px solid var(--border2); color:var(--text2); border-radius:var(--radius); padding:3px 8px; font-size:12.5px; cursor:pointer; }
.hf-tab-on { color:var(--text); border-color:var(--text2); }
