/* UX26 (batch 44): text uses of --dim are --muted; the business chip is --accent2 (Settings 8 -> 6 text colours) *//* UX22 (batch 40): every text use of --green is --green-ink (one green for text; dark mode unchanged) */

  /* UX2: ux2 (ai-chat-bot batch 18, Fable 2026-10-10): one type scale, 11 / 12.5 / 13.5 / 16 / 20 / 28 px. See patch_ux2.py. */
  /* ── DESIGN TOKENS ─────────────────────────────────────────────────────────
     Three-step surface ladder instead of "cards floating in a black void":
     --bg is the app canvas, --panel is every pane that touches it, --panel2 is
     anything raised INSIDE a pane (inputs, hover states, chips). Each step is
     one visible notch lighter, so depth reads without shadows doing the work.
     Purple is spent ONLY on primary actions and the active state; green = live,
     amber = warning, red = error — never decoration. */
  /* BEM Chat design tokens: ONE file for the website and the app (v2 batch 6a, Fable 2026-10-07).
   The server inlines this into every page it serves (the console at import, the phone app and the public
   pages per request), so there is no extra request and no page can drift. Edit app/web/chat_tokens.css only.
   Light is the default (the website is light); the app picks light or dark with data-theme on <html>.
   The rule: one accent (violet), spent only on the action to take and the active state. Everything else is
   ink and grey; green = live or done, amber = warning, red = error, never decoration. */
:root, :root[data-theme="light"] {
  --bg:#f5f5f9; --panel:#ffffff; --panel2:#eceef5; --panel3:#e3e5ee;
  --border:#e3e5ee; --border2:#c9ccd9;
  --text:#14151c; --muted:#555a6b; --dim:#686c7e;
  --accent:#6d28d9; --accent2:#7935ed; --accent-deep:#5b21b6; --accent-soft:rgba(109,40,217,.10);
  --green:#0b7f5e; --green-soft:#e3f5ee; --red:#c62828; --amber:#9a5b00; --blue:#1d4ed8;
  --green-ink:#0a6b50; --amber-ink:#7a4700; --nav-ink:#6d28d9;
  --hairline:rgba(25,27,38,.08); --rowhover:rgba(25,27,38,.025);
  --warn-bg:#fdf3d8; --warn-border:#eadaa8; --warn-text:#7a5200;
  --shadow-menu:0 18px 44px rgba(30,32,48,.18), 0 2px 8px rgba(30,32,48,.10);
}
:root[data-theme="dark"] {
  --bg:#101116; --panel:#16171e; --panel2:#1d1f28; --panel3:#242631;
  --border:#262833; --border2:#2f3240;
  --text:#e9e9f0; --muted:#8f92a1; --dim:#828596;
  --accent:#7c3aed; --accent2:#a78bfa; --accent-deep:#6d28d9; --accent-soft:rgba(124,58,237,.14);
  --green:#34d399; --green-soft:rgba(52,211,153,.14); --red:#f87171; --amber:#fbbf24; --blue:#60a5fa;
  --green-ink:#34d399; --amber-ink:#fbbf24; --nav-ink:#a78bfa;
  --hairline:rgba(38,40,51,.55); --rowhover:rgba(255,255,255,.015);
  --warn-bg:#2a1a00; --warn-border:#4a2f00; --warn-text:#f5c877;
  --shadow-menu:0 18px 44px rgba(0,0,0,.5), 0 2px 8px rgba(0,0,0,.35);
}
:root {
  /* type, corners and the tap floor: the same in both themes */
  --font-display:'Bricolage Grotesque','Segoe UI',system-ui,sans-serif;
  --font-body:'Figtree','Segoe UI',system-ui,sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --r-lg:14px; --r-md:10px; --r-sm:8px; --tap:44px;
  /* the website's dark band ("Your phone"): the dark theme's surfaces whatever the page's theme */
  --night:#101116; --night2:#191a22; --night-line:#2a2c38; --night-ink:#e9e9f0; --night-mut:#9a9db0;
  /* the website's own names, kept so its rules read as they were written */
  --card:var(--panel); --ink:var(--text); --ink2:var(--muted); --line:var(--border); --soft:var(--panel2);
  --vio:var(--accent); --vio2:var(--accent-deep); --vio-soft:var(--accent-soft); --ok:var(--green); --ok-soft:var(--green-soft);
  --disp:var(--font-display); --body:var(--font-body); --r:var(--r-lg);
  --paper:var(--bg); --paper2:var(--panel2); --hair:var(--border); --verm:var(--accent); --verm2:var(--accent-deep); --moss:var(--green);
  --serif:var(--font-display); --sans:var(--font-body);
}

  /* Colours, type and corners come from app/web/chat_tokens.css: one file for the website and the app (batch 6a). */
  * { box-sizing:border-box; }
  /* OS scrollbars are the brightest thing on a dark screen. Thin, dark, quiet. */
  * { scrollbar-width:thin; scrollbar-color:var(--panel3) transparent; }
  *::-webkit-scrollbar { width:8px; height:8px; }
  *::-webkit-scrollbar-track { background:transparent; }
  *::-webkit-scrollbar-thumb { background:var(--panel3); border-radius:4px; }
  *::-webkit-scrollbar-thumb:hover { background:var(--border2); }
  /* One icon vocabulary. Inline SVGs inherit currentColor so every state
     (muted, hover, active) recolours the glyph for free. */
  .ico { width:17px; height:17px; flex:none; vertical-align:-3px; }
  /* Bare .dim spans had NO base rule — anywhere a context didn't restyle them
     ("seconds after the page loads", the save-status line) they rendered at the
     16px browser default in full text colour, larger than the headings. */
  .dim { color:var(--muted); }
  .gtest .dim, .savebar .dim { font-size:12.5px; }
  /* ── APP SHELL ─────────────────────────────────────────────────────────────
     This was a centred 1100px document column, which on a 1600px monitor left
     ~500px of dead black either side, and nothing was full-height so every view
     collapsed upward leaving a void beneath it. A console is an APPLICATION:
     fixed chrome, full viewport, panes that fill their space and scroll
     internally. `grid-template-columns: auto 1fr` means the rail contributes
     nothing when it is hidden, so the sign-in screen still centres normally. */
  html, body { height:100%; }
  body { margin:0; font-family:var(--font-body);
         background:var(--bg); color:var(--text);
         display:grid; grid-template-columns:auto 1fr; height:100vh; overflow:hidden; }
  a { color:var(--accent2); }

  /* ── left rail: identity, business, navigation, account ── */
  header { display:flex; flex-direction:column; gap:14px; width:236px; height:100vh;
           padding:16px 12px 12px; background:var(--panel);
           border-right:1px solid var(--border); overflow-y:auto; overscroll-behavior:contain; }
  header .logo { display:flex; align-items:center; gap:9px; font-size:16px; font-weight:700;
                 letter-spacing:.2px; padding:2px 6px 4px; }
  header .logo span { color:var(--accent2); }
  header .logo .mark { width:28px; height:28px; border-radius:9px; flex:none;
                       display:flex; align-items:center; justify-content:center;
                       background:linear-gradient(135deg, var(--accent), #5b21b6);
                       color:#fff; box-shadow:0 2px 8px rgba(124,58,237,.35); }
  header .logo .mark .ico { width:15px; height:15px; }
  header .spacer { flex:1; }
  /* Identity footer — a person, not a lone button in a void. */
  header .who { display:flex; align-items:center; gap:9px; color:var(--muted); font-size:12.5px;
                padding:8px; border-top:1px solid var(--border); }
  header .who:empty { display:none; }
  header .who .uav { width:28px; height:28px; border-radius:50%; flex:none; display:flex;
                     align-items:center; justify-content:center; font-size:11px; font-weight:700;
                     background:var(--panel3); color:var(--accent2); }
  header .who .un { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text); }
  header #logout { background:none; border:1px solid var(--border); color:var(--muted);
                   padding:8px 12px; border-radius:var(--r-sm); cursor:pointer; font-size:13.5px; width:100%; }
  header #logout:hover { color:var(--text); border-color:var(--border2); background:var(--panel2); }
  /* Theme toggle: a quiet rail control, styled like the nav it sits under. */
  header #themeBtn { display:flex; align-items:center; gap:11px; width:100%; text-align:left;
                     background:none; border:none; color:var(--muted); padding:9px 11px;
                     border-radius:var(--r-sm); cursor:pointer; font:inherit; font-size:13.5px; }
  header #themeBtn:hover { background:var(--panel2); color:var(--text); }
  header #themeBtn .ico { color:var(--muted); }
  header #themeBtn:focus-visible { outline:3px solid var(--accent2); outline-offset:2px; }
  /* The nav tabs and the business switcher had no ring at all — a keyboard user tabbing
     the primary navigation saw nothing move (design pass, 2026-09-04). Inset so the ring
     stays inside the full-width row instead of clipping at the sidebar edge. */
  header [role=tab]:focus-visible, #swBtn:focus-visible {
    outline:3px solid var(--accent2); outline-offset:-3px; border-radius:8px; }
  /* The switcher fills the rail rather than sitting inline in a top bar. */
  header .switch > button { width:100%; max-width:none; }

  main { padding:0; max-width:none; margin:0; height:100vh; overflow-y:auto;
         overscroll-behavior:contain;
         /* Focus targets scroll clear of the sticky save bar (~64px + slack). */
         scroll-padding-bottom:76px; }
  #app { padding:22px 28px 30px; }
  @media (max-width:900px) {
    body { grid-template-columns:1fr; grid-template-rows:auto 1fr; height:100vh; height:100dvh; }
    /* Grid items default to min-width:auto, so the header's nowrap tab strip
       set the single 1fr track to its min-content — measured 789px at a 375
       viewport (audit 2026-09-03), which is where the sideways scroll on
       tablets and phones came from. min-width:0 lets the track be the
       viewport; the strip already scrolls inside itself. */
    header, main { min-width:0; }
    /* Phone shell = a compact app bar, NOT the desktop rail turned sideways.
       The shipped fallback stacked the whole rail full-width, so a phone
       scrolled past ~1.5 screens of navigation before ANY content (operator's
       screenshot, 2026-07-28). This console is destined for a WebView inside
       the BEM hub app, so it behaves like an app header: two dense rows —
       identity + switcher + sign-out, then a horizontally scrolling nav — and
       respects the notch via safe-area insets. */
    header { width:100%; height:auto; flex-direction:row; align-items:center; flex-wrap:wrap;
             gap:8px 10px; padding:10px 12px 8px;
             padding-top:calc(10px + env(safe-area-inset-top));
             border-right:none; border-bottom:1px solid var(--border); overflow:visible; }
    header .logo { order:1; padding:0; font-size:16px; flex:none; }
    .switch { order:2; flex:1; min-width:0; }
    .switch > button { width:100%; padding:5px 10px; }
    .switch .swkey { display:none; }
    header #logout { order:3; width:auto; padding:6px 12px; font-size:12.5px; flex:none; }
    header #themeBtn { order:3; width:auto; padding:6px 10px; flex:none; }
    header .spacer, header .who { display:none; }
    /* header-prefixed: this block sits EARLIER in the sheet than the .tabs base
       rules, so bare .tabs ties on specificity and loses on source order —
       measured as flex-direction still "column" at 390px. */
    header .tabs { order:4; flex:1 0 100%; flex-direction:row; gap:4px; margin:0;
            overflow-x:auto; overscroll-behavior-x:contain; scrollbar-width:none; }
    header .tabs::-webkit-scrollbar { display:none; }
    header .jump { order:3; flex:1 0 100%; margin:4px 0; }
    header .tabs button { width:auto; flex:none; padding:7px 12px; white-space:nowrap; }
    header .tabs button.on::before { display:none; }  /* the left cap bar reads wrong horizontally */
    /* Section labels are a vertical-sidebar idiom; in the horizontal strip they
       would break the row flow, and the picker sits directly beside the tabs. */
    header .navsec, header .navgap { display:none; }
    main { height:auto; min-height:0; }
    #app { padding:14px 12px 20px; }
  }
  .hidden { display:none !important; }
  /* ── Motion + focus, product-wide (checklist audit 2026-09-03) ──
     29 of 29 controls changed state INSTANTLY: only five transition rules
     existed and none covered buttons, tabs, rows or pills. Colour-only
     properties on purpose — never transform/width/height, so hover can never
     shift layout. */
  button, [role=tab], [role=button], .conv, .pill, .ppill, a {
    transition: background-color .18s ease, border-color .18s ease,
                color .18s ease, box-shadow .18s ease, opacity .18s ease; }
  @media (prefers-reduced-motion: reduce) {
    button, [role=tab], [role=button], .conv, .pill, .ppill, a { transition: none; }
  }
  /* Seven :focus rules removed the outline and left only a border tint —
     keyboard focus was invisible on those fields while the other twelve had
     a ring. Same 3px accent-soft ring, additive; their own rules stand. */
  #login input:focus, .dlrow input:focus, .agentform textarea:focus,
  .agentform input[type=text]:focus, .dpv textarea:focus, .chipbox input:focus,
  .deptsel:focus, .ntadd textarea:focus {
    box-shadow: 0 0 0 3px var(--accent-soft); }
  /* ── login ── */
  /* Sign-in is NOT part of the app shell, and trying to live inside it is why it
     sat jammed against the left edge: `body` is a two-column grid whose FIRST
     column is `auto`, so with the rail hidden <main> lands in that column and
     shrinks to its content — 380px at x=0, with `margin:auto` given no room to
     centre anything. Lift it out of the grid entirely rather than fighting it. */
  #login { position:fixed; inset:0; z-index:50; display:flex; flex-direction:column;
           align-items:center; justify-content:center; padding:24px;
           overflow-y:auto; background:var(--bg); text-align:center; }
  #login .mark { width:52px; height:52px; border-radius:15px; margin-bottom:14px;
                 background:var(--accent); color:#fff; display:grid; place-items:center;
                 box-shadow:0 8px 22px rgba(124,58,237,.32); }
  #login .mark .ico { width:27px; height:27px; }
  #login .brand { font-size:28px; font-weight:800; letter-spacing:-.4px; margin-bottom:6px; }
  #login .brand span { color:var(--accent2); }
  #login .tag { color:var(--muted); font-size:13.5px; margin-bottom:22px; line-height:1.55;
                max-width:340px; }
  /* The form is the card — it gives the fields somewhere to sit instead of
     floating on the page background. */
  #login form { display:flex; flex-direction:column; gap:10px; text-align:left;
                width:100%; max-width:370px; background:var(--panel);
                border:1px solid var(--border); border-radius:16px; padding:22px;
                box-shadow:0 12px 34px rgba(0,0,0,.16); }
  #login .flabel { font-size:12.5px; font-weight:650; color:var(--muted);
                   margin-bottom:-4px; }
  #login .foot { color:var(--muted); font-size:12.5px; margin-top:18px; }
  #login input { background:var(--panel2); border:1px solid var(--border); color:var(--text);
                 padding:12px 14px; border-radius:10px; font-size:16px; min-height:44px; }
  #login input:focus { outline:none; border-color:var(--accent); }
  #login button { background:var(--accent); border:none; color:#fff; padding:12px; min-height:44px;
                  border-radius:10px; font-size:16px; font-weight:600; cursor:pointer; margin-top:4px; }
  #login button:hover { background:#6d28d9; }
  #login .err { color:var(--red); font-size:13.5px; min-height:18px; margin-top:4px; text-align:center; }
  /* ── tiles ── */
  .row { display:flex; align-items:center; gap:10px; margin:4px 0 14px; }
  /* View titles LEAD the type scale. Before this an 18px explanatory paragraph
     could sit under a 15px view title — the hierarchy read upside down. */
  h2 { font-family:var(--font-display); font-size:20px; font-weight:700; letter-spacing:-.02em; margin:0 0 16px; color:var(--text); }
  h2 .dim { color:var(--muted); font-weight:400; font-size:13.5px; letter-spacing:0; }
  .tiles { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:12px; }
  .tile { background:var(--panel); border:1px solid var(--border); border-radius:12px; padding:14px 16px; }
  .tile .prop { font-size:13.5px; color:var(--accent2); font-weight:600; margin-bottom:8px;
                overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .tile .nums { display:flex; flex-wrap:wrap; gap:10px 14px; }
  .tile .n { font-size:12.5px; color:var(--muted); }
  .tile .n b { color:var(--text); font-size:16px; font-weight:700; }
  .tile .n.live b { color:var(--green-ink, var(--green)); }
  /* ── table ── */
  #visitors { overflow-x:auto; }         /* many-column table scrolls inside itself on phones */
  table { width:100%; border-collapse:collapse; font-size:13.5px; }
  th { text-align:left; color:var(--muted); font-weight:500; font-size:11px; text-transform:uppercase;
       letter-spacing:.06em; padding:8px 10px; border-bottom:1px solid var(--border); white-space:nowrap; }
  td { padding:10px; border-bottom:1px solid var(--hairline); vertical-align:top; }
  tr:last-child td { border-bottom:none; }
  tbody tr:hover td, table tr:hover td { background:var(--rowhover); }
  .chatyes { color:var(--green-ink, var(--green)); font-weight:600; } .muted { color:var(--muted); }
  .pill { display:inline-block; font-size:11px; padding:2px 8px; border-radius:999px;
          background:var(--panel2); color:var(--accent2); border:1px solid var(--border); }
  .cc { display:inline-block; font-size:11px; font-weight:700; letter-spacing:.5px;
        padding:1px 5px; border-radius:4px; background:var(--panel2); color:var(--accent2);
        border:1px solid var(--border); vertical-align:middle; margin-right:4px; }
  .empty { color:var(--muted); padding:26px 0; text-align:center; }
  /* ── Contacts ────────────────────────────────────────────────────────────
     People who left details, one row each. The API for this existed with no
     screen; this is the screen. Search is client-side over what is loaded — the
     route returns the newest 200 and every business is far under that, so a
     second request would fetch the same rows back. */
  .ctools { display:flex; align-items:center; gap:10px; margin:0 0 12px; flex-wrap:wrap; }
  .ctools input[type=search] { flex:1; min-width:220px; max-width:420px; background:var(--panel2);
        border:1px solid var(--border); color:var(--text); border-radius:8px; padding:9px 12px;
        font:inherit; font-size:13.5px; min-height:44px; }
  .ctools input[type=search]:focus { outline:none; border-color:var(--accent); }
  .ctools .dim { white-space:nowrap; }
  .cname { display:flex; align-items:center; gap:10px; min-width:0; }
  .cav { width:30px; height:30px; border-radius:50%; flex:none; display:flex; align-items:center;
         justify-content:center; font-weight:700; font-size:12.5px; background:var(--accent); color:#fff; }
  .cav.anon { background:var(--panel2); color:var(--muted); border:1px solid var(--border); }
  .cname b { display:block; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cname .sub { display:block; color:var(--muted); font-size:11px; }
  .cintent { max-width:280px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ctbl .num { text-align:right; font-variant-numeric:tabular-nums; }
  .ctbl td a { color:var(--accent2); text-decoration:none; }
  .ctbl td a:hover { text-decoration:underline; }
  /* ── Print / copy (thread) ───────────────────────────────────────────────
     .printonly is filled by the Print button right before window.print() and
     never shows on screen. The print sheet keeps ONLY the open thread: rail,
     business picker, conversation list, composer, details panel and the
     header buttons themselves all drop out, and every scrolling ancestor is
     un-clipped so a long conversation paginates instead of printing one
     viewport's worth. */
  .printonly { display:none; }
  @media print {
    body { background:#fff !important; color:#000 !important; }
    header, .tabs, #switch, .navsec, #inboxScope > *:not(#thread), #ibxRail, #convList, #threadEmpty,
    #replyErr, #draftNote, #ibxDetails, .idetails, .cprof, #thread form, #thread textarea,
    #ibxStatus, #ibxAi, #ibxToggleDet, #ibxCopy, #ibxPrint, .tabs button { display:none !important; }
    /* The composer is rendered by script, not markup, so it has no stable id to
       name: keep the header, the messages and the meta line, drop everything else. */
    #thread > *:not(#threadHead):not(#threadMsgs):not(#printMeta) { display:none !important; }
    #app, main, #view-inbox, #inboxScope, #thread, #threadMsgs {
      display:block !important; position:static !important; height:auto !important;
      max-height:none !important; min-height:0 !important; overflow:visible !important;
      width:auto !important; margin:0 !important; padding:0 !important; box-shadow:none !important; }
    #view-inbox.hidden { display:block !important; }
    .printonly { display:block; font:12px/1.5 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
                 color:#555; border-bottom:1px solid #999; padding:0 0 8px; margin:0 0 12px; }
    .thead { border:none !important; background:none !important; padding:0 0 10px !important; }
    .tmsgs .m { break-inside:avoid; }
  }
  /* ── install ── */
  .instgrid { display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:16px; align-items:start;
              max-width:1100px; }
  @media (max-width:1000px) { .instgrid { grid-template-columns:minmax(0,1fr); } }
  .install { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg);
             padding:14px 16px; margin-bottom:12px; }
  .install .head { display:flex; align-items:center; gap:11px; flex-wrap:wrap; }
  .install .head .sico { width:34px; height:34px; border-radius:10px; flex:none;
                         display:flex; align-items:center; justify-content:center;
                         background:var(--panel2); border:1px solid var(--border); color:var(--accent2); }
  .install .head b { font-size:13.5px; } .install .head .host { color:var(--muted); font-size:12.5px; }
  .install .head .spacer { flex:1; }
  /* Buttons stay together on the right. Without this the second one wrapped to
     its own line at the far left, which read as an unrelated control. */
  .install .head .acts { display:flex; gap:8px; flex:none; }
  .install button { background:var(--panel2); border:1px solid var(--border); color:var(--accent2);
                    padding:7px 13px; border-radius:var(--r-sm); cursor:pointer; font:inherit; font-size:12.5px; }
  .install button:hover { border-color:var(--accent); color:var(--text); }
  .install pre { background:var(--bg); border:1px solid var(--border); border-radius:var(--r-sm); padding:12px;
                 overflow-x:auto; font-size:12.5px; color:var(--text); margin:10px 0 0; white-space:pre-wrap; word-break:break-all; }
  .insthelp { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg);
              padding:16px 18px; font-size:12.5px; color:var(--muted); line-height:1.6; }
  .insthelp h3 { margin:0 0 8px; font-size:11px; font-weight:700; letter-spacing:.08em;
                 text-transform:uppercase; color:var(--accent2); }
  .insthelp ol { margin:0 0 4px; padding-left:18px; }
  .insthelp li { margin-bottom:6px; }
  .insthelp li::marker { color:var(--accent2); font-weight:600; }
  /* Revoke: QUIET until intended. It used to wear red at rest, which put four
     shouting destructive buttons on a page whose whole job is copying one line
     — the loudest thing on screen was the one thing nobody should press. It
     turns red the moment a hand actually approaches it, and the confirm zone
     (.revwarn) still carries the full danger before anything happens. */
  .install .revoke { color:var(--muted); border-color:transparent; background:none; }
  .install .revoke:hover, .install .revoke:focus-visible {
    border-color:var(--red); color:var(--red); background:rgba(248,113,113,.10); }
  /* Install status at a glance — same honest signal as the setup checklist. */
  .instpill { flex:none; font-size:11px; font-weight:650; border-radius:999px;
              padding:3px 10px; margin-left:10px; white-space:nowrap; }
  .instpill.on { color:var(--green-ink, var(--green)); background:rgba(52,211,153,.10);
                 border:1px solid rgba(52,211,153,.35); }
  .instpill.off { color:var(--amber); background:rgba(251,191,36,.10);
                  border:1px solid rgba(251,191,36,.30); }
  :root[data-theme="light"] .instpill.on { color:#0b7a4b; background:rgba(11,122,75,.08);
                  border-color:rgba(11,122,75,.30); }
  :root[data-theme="light"] .instpill.off { color:#9a5b00; background:rgba(154,91,0,.08);
                  border-color:rgba(154,91,0,.30); }
  .install .kv { color:var(--muted); font-size:11px; }
  /* Direct chat link — quieter than the embed block above it; the embed is the
     required step, the link is the bonus. */
  .dlink { margin-top:12px; padding-top:12px; border-top:1px solid var(--hairline); }
  .dlink b { display:block; font-size:12.5px; margin-bottom:2px; }
  .dlink > .dim { display:block; font-size:12.5px; margin-bottom:8px; line-height:1.5; }
  .dlrow { display:flex; gap:8px; align-items:center; }
  .dlrow input { flex:1; min-width:0; background:var(--panel2); border:1px solid var(--border);
                 color:var(--muted); border-radius:8px; padding:7px 10px; font-size:12.5px;
                 font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
                 text-overflow:ellipsis; }
  .dlrow input:focus { outline:none; border-color:var(--accent); color:var(--text); }
  .dlrow .linkBtn { flex:none; }
  .dlrow .linkTry { flex:none; font-size:12.5px; color:var(--accent2); font-weight:600;
                    text-decoration:none; }
  .dlrow .linkTry:hover { text-decoration:underline; }
  .revwarn { margin-top:10px; background:rgba(248,113,113,.08); border:1px solid rgba(248,113,113,.35);
             border-radius:var(--r-sm); padding:11px 13px; font-size:12.5px; line-height:1.55; }
  .revwarn b { color:var(--red); }
  .revwarn .acts { display:flex; gap:8px; margin-top:10px; }
  .revwarn button { padding:7px 13px; font-size:12.5px; }
  .revwarn .go { background:var(--red); border:none; color:#1a0b0b; font-weight:700; }
  .revwarn .go:hover { background:#ef5350; }
  .notice { background:var(--warn-bg); border:1px solid var(--warn-border); color:var(--warn-text);
            border-radius:var(--r-md); padding:10px 14px; font-size:13.5px; margin-bottom:16px; }

  /* ── Agent capabilities (P3) ── */
  .caprow { display:flex; align-items:flex-start; gap:11px; padding:11px 0;
            border-bottom:1px solid var(--hairline); }
  .caprow:last-of-type { border-bottom:none; }
  .caprow .capbody { flex:1; min-width:0; }
  .caprow .capname { font-size:13.5px; font-weight:600; }
  .caprow .capwhy { color:var(--muted); font-size:12.5px; line-height:1.5; margin-top:2px; }
  /* Locked = visible but plainly not yours yet, with the price of yes. */
  .caprow.locked .capname { color:var(--muted); }
  .caprow .caplock { font-size:11px; font-weight:600; color:var(--amber);
                     background:rgba(251,191,36,.12); border:1px solid rgba(251,191,36,.3);
                     border-radius:999px; padding:2px 9px; white-space:nowrap; flex:none; }
  :root[data-theme="light"] .caprow .caplock { background:rgba(154,91,0,.10);
                     border-color:rgba(154,91,0,.30); }
  .capsw { position:relative; flex:none; margin-top:1px; }
  /* The invisible input IS the tap target: 11px above/below and 4px beside the 40x23 track
     = 48x45, track unchanged (checklist, 2026-09-04). */
  .capsw input { position:absolute; opacity:0; top:-11px; bottom:-11px; left:-4px; right:-4px;
                 width:auto; height:auto; margin:0; cursor:pointer; }
  .capsw .track { display:block; width:40px; height:23px; border-radius:12px;
                  background:var(--panel3); border:1px solid var(--border2); position:relative; }
  .capsw .track::after { content:""; position:absolute; top:3px; left:3px; width:15px; height:15px;
                         border-radius:50%; background:var(--muted); }
  @media (prefers-reduced-motion: no-preference) {
    .capsw .track, .capsw .track::after { transition:background .18s ease, transform .18s ease; }
  }
  .capsw input:checked + .track { background:var(--accent); border-color:var(--accent); }
  .capsw input:checked + .track::after { background:#fff; transform:translateX(17px); }
  .capsw input:disabled + .track { opacity:.4; }
  .capsw input:focus-visible + .track { outline:3px solid var(--accent2); outline-offset:2px; }

  /* Booking requests — the outcome a booking-tier client is paying for. */
  .pill.booking { background:rgba(52,211,153,.13); color:var(--green-ink, var(--green));
                  border-color:rgba(52,211,153,.32); }
  .bkcard { border:1px solid rgba(52,211,153,.35); background:rgba(52,211,153,.07);
            border-radius:var(--r-sm); padding:10px 12px; margin-top:6px; font-size:12.5px; }
  .bkcard b { display:block; font-size:12.5px; margin-bottom:4px; color:var(--green-ink, var(--green)); }
  .bkcard .said { color:var(--text); font-style:italic; }
  .bkcard .note { color:var(--muted); font-size:11px; margin-top:5px; line-height:1.5; }
  .bkcard .bkdone-btn { margin-left:4px; background:none; border:1px solid rgba(52,211,153,.4);
    color:var(--green-ink, var(--green)); font:inherit; font-size:11px; font-weight:650; padding:2px 8px;
    border-radius:999px; cursor:pointer; }
  .bkcard .bkdone-btn:hover { background:rgba(52,211,153,.15); }
  /* Handled: the same accent no longer reads as "still open" — quieted to the
     neutral panel tone so an operator scanning the thread sees at a glance
     which requests still need a callback and which are done. */
  .bkcard.bkdone { border-color:var(--border); background:var(--panel2, var(--bg)); }
  .bkcard.bkdone b { color:var(--text-2, var(--muted)); }
  /* #80: a reminder that needs the operator's hands (no email on file). */
  .bkcard .note.warn { color:var(--amber); }
  .bkcard .note.done { color:var(--green-ink, var(--green)); }
  .bkcard .note .linky { background:none; border:none; color:inherit; text-decoration:underline;
    font:inherit; font-size:inherit; cursor:pointer; padding:0; margin-left:2px; }
  /* C2 confirm block: the picker and the button are the ACTION of this card,
     so they get real control styling rather than the note's whisper. */
  .bkconfirm label { display:block; margin-bottom:3px; }
  .bkconfirm input[type="datetime-local"] { font:inherit; font-size:12.5px; color:var(--text);
    background:var(--bg); border:1px solid var(--border); border-radius:8px;
    padding:5px 8px; margin:0 6px 6px 0; color-scheme:light dark; }
  .bkconf-btn { background:var(--green); border:none; color:#fff; font:inherit;
    font-size:11px; font-weight:700; padding:6px 12px; border-radius:999px;
    cursor:pointer; }
  .bkconf-btn:hover { filter:brightness(1.08); }
  .bkconf-btn:disabled { opacity:.55; cursor:default; }
  :root[data-theme="dark"] .bkconf-btn { color:#06251a; }   /* UX15: dark text on dark mode's light green (8.5:1); white on light mode's (5:1) */
  /* UX15: the Inbox shows less until asked */
  #ibxSort { display:none; }
  #threadHead .tagrow .tagadd { display:none; }
  #threadMsgs .m.a .fixwrap { visibility:hidden; }
  #threadMsgs .m.a.lastai .fixwrap, #threadMsgs .m.a:hover .fixwrap, #threadMsgs .m.a:focus-within .fixwrap { visibility:visible; }
  .bkconf-msg { display:block; margin-top:5px; }

  /* ── Billing (#28) ── Money UI: the total is the loudest thing, and anything
     that cannot be billed is stated rather than quietly dropped. */
  .billpanel { max-width:1200px; }
  .billdue { font-size:13.5px; }
  .billsum { display:flex; align-items:baseline; gap:10px; margin-bottom:10px; }
  .billsum .amt { font-size:28px; font-weight:650; letter-spacing:-.02em;
                  font-variant-numeric:tabular-nums; }
  .billsum .cnt { color:var(--muted); font-size:12.5px; }
  .billrow { display:flex; align-items:center; gap:10px; padding:7px 0;
             border-bottom:1px solid var(--hairline); font-size:13.5px; }
  .billrow:last-child { border-bottom:none; }
  .billrow .amt { margin-left:auto; font-variant-numeric:tabular-nums; }
  .billrow .per { color:var(--muted); font-size:11px; }
  .billrow.blocked { color:var(--muted); }
  .billrow.blocked .why { color:var(--amber); font-size:11px; }
  .billnone { color:var(--muted); font-size:13.5px; padding:6px 0; }
  .billreport { margin-top:12px; border:1px solid var(--border); border-radius:var(--r-sm);
                padding:11px 13px; font-size:12.5px; }
  .billreport b { display:block; margin-bottom:5px; }
  .billreport .ok { color:var(--green-ink, var(--green)); }
  .billreport .skip { color:var(--amber); }
  .planrow { display:flex; align-items:baseline; gap:8px; padding:7px 0;
             border-bottom:1px solid var(--hairline); font-size:13.5px; }
  .planrow:last-of-type { border-bottom:none; }
  .planrow .pr { margin-left:auto; font-variant-numeric:tabular-nums; font-weight:600; }
  .planrow .unpriced { color:var(--amber); font-weight:600; font-size:12.5px; }
  .planrow .pc { color:var(--muted); font-size:11px; }

  /* ── Clients (org admin) ── */
  .orgsgrid { display:grid; grid-template-columns:minmax(0,1fr) 320px; gap:16px;
              align-items:start; max-width:1200px; }
  @media (max-width:1000px) { .orgsgrid { grid-template-columns:minmax(0,1fr); } }
  .orgcard { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg);
             padding:16px 18px; margin-bottom:14px; }
  .orghead { display:flex; align-items:baseline; gap:10px; margin-bottom:6px; }
  .orghead h3 { margin:0; font-size:16px; font-weight:650; }
  .orghead .oslug { color:var(--muted); font-size:12.5px; }
  .orgsec { margin-top:12px; }
  .orgsec h4 { margin:0 0 7px; font-size:11px; text-transform:uppercase; letter-spacing:.07em;
               color:var(--muted); font-weight:600; }
  .seattbl { margin-bottom:4px; }
  .seattbl th { font-size:11px; padding:5px 8px; }
  .seattbl td { padding:7px 8px; font-size:13.5px; }
  .orgform { display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-top:8px; }
  /* "No login yet?" is a secondary path — a link, not a third competing button. */
  /* .orgform button paints every button accent-filled, so this needs the same
     specificity to stay a quiet link and not a third competing CTA. */
  .orgform button.linky, .linky { background:none; border:none; color:var(--accent2);
           font:inherit; font-size:12.5px; text-decoration:underline; cursor:pointer;
           padding:6px 2px; }
  .orgform button.linky:hover { background:none; color:var(--text); }
  .newlogin { margin-top:10px; padding:10px; border:1px dashed var(--border);
              border-radius:10px; display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
  .newlogin .muted { flex-basis:100%; }
  .orgform input, .orgform select { background:var(--panel2); border:1px solid var(--border);
      color:var(--text); border-radius:var(--r-sm); padding:7px 10px; font:inherit; font-size:13.5px; }
  .orgform input:focus, .orgform select:focus { outline:none; border-color:var(--accent);
      box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  /* #wz1Next..#wz4Next had no rule and rendered as the browser default (design pass,
     2026-09-04). Same primary as every other action in this card. */
  .wizbar button { background:var(--accent); border:none; color:#fff; padding:9px 16px;
    border-radius:8px; font:inherit; font-weight:600; cursor:pointer; }
  .wizbar button:hover { background:#6d28d9; }
  .wizbar button:disabled { opacity:.55; cursor:default; }
  .wizbar button:focus-visible { outline:3px solid var(--accent2); outline-offset:2px; }
  .orgform button { background:var(--accent); border:none; color:#fff; padding:8px 14px;
      border-radius:var(--r-sm); font:inherit; font-size:13.5px; font-weight:600; cursor:pointer; }
  .orgform button:hover { background:#6d28d9; }
  .orgx { background:none; border:1px solid var(--border); color:var(--muted); cursor:pointer;
          border-radius:6px; padding:3px 9px; font:inherit; font-size:12.5px; }
  /* The jump into a client's branding — a quiet link-shaped control, not a
     second bordered button crowding the unlink ×. */
  .orglook { background:none; border:none; color:var(--accent2); cursor:pointer;
             font:inherit; font-size:12.5px; font-weight:600; padding:3px 4px; }
  .orglook:hover { text-decoration:underline; }
  .orgx:hover { color:var(--red); border-color:var(--red); }
  .proptags { display:flex; flex-wrap:wrap; gap:8px; font-size:13.5px; align-items:center; }
  .proptag { background:var(--panel2); border:1px solid var(--border); border-radius:999px;
             padding:4px 6px 4px 12px; display:inline-flex; align-items:center; gap:7px; }
  .extrased { background:var(--panel2); border:1px solid var(--border); border-radius:var(--r-sm);
              padding:12px 14px; margin-top:10px; font-size:13.5px; }
  .extrased .exhead { margin-bottom:8px; }
  .extrased .exrow { display:flex; align-items:center; gap:8px; padding:5px 0; cursor:pointer;
                     min-height:30px; }
  .extrased .exrow input { width:16px; height:16px; accent-color:var(--accent); }
  .extrased .exsave { background:var(--accent); color:#fff; border:none; border-radius:var(--r-sm);
                      padding:8px 16px; font:inherit; font-size:13.5px; cursor:pointer; }
  .extrased .exsave:disabled { opacity:.5; }
  /* Extras on the "link a business" form. These sit INSIDE .orgform, which
     paints every input as a padded bordered text box — the checkbox rules here
     have to beat it, which is why they carry the .orgform prefix. */
  .attcaps { flex-basis:100%; display:flex; flex-wrap:wrap; align-items:center; gap:6px 16px;
             padding:9px 11px; border:1px dashed var(--border); border-radius:var(--r-sm); }
  .attcaps .dim { flex-basis:100%; font-size:12.5px; }
  .orgform .attcaps .atrow { display:inline-flex; align-items:center; gap:7px; cursor:pointer;
                             font-size:13.5px; min-height:28px; }
  .orgform .attcaps input[type=checkbox] { width:16px; height:16px; padding:0; margin:0;
      border-radius:3px; accent-color:var(--accent); }
  .orgform .attcaps input[type=checkbox]:focus-visible { outline:3px solid var(--accent2);
      outline-offset:2px; box-shadow:none; }
  .orgstat { font-size:12.5px; margin-top:8px; min-height:16px; }
  /* Row-level status (2026-09-03): each form reports directly beneath itself.
     min-height keeps the layout from jumping when a message appears. */
  .rowstat { font-size:12.5px; margin-top:6px; min-height:16px; color:var(--muted); }
  .nlwhy { font-size:12.5px; margin:8px 0 6px; color:var(--text); }
  .newlogin { border-left:2px solid var(--accent); padding-left:10px; margin-top:8px; }
  .linkform { margin-top:8px; }
  /* Setup steps a seat cannot act on: quieter row, a one-line "who does this",
     and no button — the row is context, not a task. */
  .sustep.theirs { opacity:.72; }
  /* su1: the done, the delegated and the optional steps fold into one line; the card shows only what is left */
  .sufold { display:block; width:100%; text-align:left; background:none; border:0; border-top:1px solid var(--border); color:var(--muted);
            font:inherit; font-size:12.5px; font-weight:600; padding:10px 16px; cursor:pointer; min-height:40px; border-radius:0; }
  .sufold:hover { color:var(--text); background:var(--panel2); }
  .sufold::before { content:"▸ "; } .sufold[aria-expanded="true"]::before { content:"▾ "; }
  .sufolded > .sustep:first-child { border-top:1px solid var(--border); }
  /* Batch 2.3: optional steps — present, quieter, never counted. */
  .suhead { padding:12px 16px 2px; font-size:11px; font-weight:700; letter-spacing:.07em;
            text-transform:uppercase; color:var(--muted); border-top:1px solid var(--hairline, var(--border)); }
  .sustep.opt .sutick { border-style:dashed; }
  .sustep.opt .sut { font-weight:550; }
  .sustep .suby { display:block; font-size:11px; color:var(--accent2); margin-top:3px; }
  .orgnew input[type=text] { width:100%; background:var(--panel2); border:1px solid var(--border);
      color:var(--text); border-radius:var(--r-sm); padding:9px 10px; font:inherit; font-size:13.5px; }
  .orgnew input[type=text]:focus { outline:none; border-color:var(--accent);
      box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .orgnew .savebar { position:static; border-top:none; padding:12px 0 0; background:transparent; }
  .orgcard .orgx:focus-visible, .orgform button:focus-visible, #ogCreate:focus-visible {
      outline:3px solid var(--accent2); outline-offset:2px; }
  /* ── tabs ── */
  /* Vertical nav in the rail. Same buttons, same data-v hooks, same tab roles —
     the click census and the tablist semantics both depend on them. Active is a
     tinted surface with an accent cap, not a solid purple slab: the slab was the
     loudest element on every screen while saying nothing new. */
  .tabs { display:flex; flex-direction:column; gap:2px; margin:2px 0 0; }
  .tabs button { position:relative; display:flex; align-items:center; gap:11px; width:100%;
                 text-align:left; background:none; border:none; color:var(--muted);
                 padding:9px 11px; border-radius:var(--r-sm); cursor:pointer; font:inherit;
                 font-size:13.5px; font-weight:500; }
  .tabs button .ico { color:var(--muted); }
  .tabs button.on { background:var(--accent-soft); color:var(--text); font-weight:600; }
  .tabs button.on .ico { color:var(--accent2); }
  .tabs button.on::before { content:""; position:absolute; left:-12px; top:7px; bottom:7px;
                            width:3px; border-radius:0 3px 3px 0; background:var(--accent); }
  .tabs button:hover:not(.on) { background:var(--panel2); color:var(--text); }
  .tabs button:hover:not(.on) .ico { color:var(--muted); }
  /* #77: the Business picker scopes everything under "This business"; "Your
     agency" (Clients) is the only global section. Labels in the nav itself, not
     tooltips — the operator asked what the dropdown affects, so the sidebar
     answers it standing still. */
  .navsec { font-size:11px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
            color:var(--muted); padding:12px 10px 4px; }
  .navsec-agency { border-top:1px solid var(--border); margin-top:10px; padding-top:12px; }
  /* MN1 (2026-10-06): grouped menu. A thin rule splits the groups from Reports and
     Settings; Install stays in the DOM (the setup checklist clicks it) but off the menu;
     Settings lights up softly while the Install view is open, so the menu never shows
     nothing selected. Counts sit on the items that need you. */
  .navgap { border-top:1px solid var(--border); margin:10px 2px 6px; }
  .tabs button.navhide { display:none !important; }
  .tabs button.sub { background:var(--accent-soft); color:var(--text); }
  .tabs button .ct { margin-left:auto; min-width:20px; height:20px; padding:0 6px; border-radius:999px;
                     display:inline-grid; place-items:center; font-size:11px; font-weight:700;
                     font-variant-numeric:tabular-nums; background:var(--accent); color:#fff; }
  .tabs button .ct.live { background:transparent; color:var(--green-ink, var(--green)); padding:0 2px; }   /* UX15 (batch 33): one green for text */
  .tabs button .ct.live::before { content:""; width:7px; height:7px; border-radius:50%; background:var(--green);
                                  display:inline-block; margin-right:5px; }
  .vhost { display:grid; gap:14px; }
  .backlink { background:none; border:0; color:var(--accent2); cursor:pointer; font:inherit; font-size:13.5px;
              padding:0; margin:-8px 0 14px; }
  .backlink:hover { text-decoration:underline; }
  /* PF1 (2026-10-06): Pipeline board, lead panel, Follow-ups. */
  .pfhead { display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin:-2px 0 14px; }
  .pfstat { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-md); padding:10px 14px; min-width:150px; }
  .pfstat b { display:block; font-size:20px; font-variant-numeric:tabular-nums; }
  .pfstat span { color:var(--muted); font-size:12.5px; }
  .pfnote { color:var(--muted); font-size:12.5px; }
  .board { display:grid; grid-template-columns:repeat(5, minmax(200px, 1fr)); gap:12px; overflow-x:auto;
           padding-bottom:6px; align-items:start; }
  .pcol { background:var(--panel2); border:1px solid var(--border); border-radius:var(--r-lg); padding:10px;
          min-height:180px; display:flex; flex-direction:column; gap:8px; }
  .pcol.over { border-color:var(--accent); background:var(--accent-soft); }
  .pcol h3 { margin:2px 4px 4px; font-size:11px; letter-spacing:.07em; text-transform:uppercase; color:var(--muted);
             display:flex; justify-content:space-between; gap:8px; }
  .pcol h3 .v { color:var(--text); letter-spacing:0; text-transform:none; font-variant-numeric:tabular-nums; }
  .lcard { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-md); padding:10px 11px;
           cursor:pointer; text-align:left; width:100%; font:inherit; color:var(--text); display:block; }
  .lcard:hover { border-color:var(--border2); }
  .lcard:focus-visible { outline:3px solid var(--accent2); outline-offset:2px; }
  .lcard.dragging { opacity:.45; }
  .lcard b { display:block; font-size:13.5px; }
  .lcard .ask { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
                color:var(--muted); font-size:12.5px; margin-top:2px; }
  .lcard .meta { display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; font-size:11px; color:var(--muted); align-items:center; }
  .lchip { display:inline-flex; align-items:center; gap:4px; padding:2px 8px; border-radius:999px; border:1px solid var(--border);
           font-size:11px; color:var(--muted); white-space:nowrap; }
  .lchip.due { color:var(--accent2); border-color:var(--accent); }
  .lchip.late { color:var(--red); border-color:var(--red); }
  .lchip.none { color:var(--amber-ink); border-style:dashed; border-color:var(--amber-ink); }
  .lchip.won, .lchip.back { color:var(--green-ink); border-color:var(--green-ink); }
  .pcol .more { color:var(--muted); font-size:12.5px; text-align:center; padding:4px; }
  .pcol .zero { color:var(--muted); font-size:12.5px; text-align:center; padding:18px 6px; border:1px dashed var(--border);
                border-radius:var(--r-md); }
  .pdscrim { position:fixed; inset:0; background:rgba(0,0,0,.35); z-index:80; }
  .pdrawer { position:fixed; top:0; right:0; bottom:0; width:min(440px, 100vw); background:var(--panel);
             border-left:1px solid var(--border); box-shadow:var(--shadow-menu); z-index:81; display:flex; flex-direction:column; }
  .pdrawer[hidden] { display:none; }
  .pdhd { display:flex; align-items:flex-start; gap:10px; padding:18px 18px 12px; border-bottom:1px solid var(--border); }
  .pdhd h3 { margin:0 0 3px; font-size:16px; }
  .pdhd .sub { color:var(--muted); font-size:12.5px; }
  .pdhd .sub a { color:var(--accent2); }
  .pdhd button { padding:0 12px; min-height:36px; }
  .pdbody { padding:16px 18px 24px; overflow:auto; display:grid; gap:20px; align-content:start; }
  .pdsec h4 { margin:0 0 8px; font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); }
  .pdask { margin:0; color:var(--text); font-size:13.5px; }
  .stageseg { display:grid; grid-template-columns:repeat(5, 1fr); gap:4px; }
  .stageseg button { background:var(--panel2); border:1px solid var(--border); color:var(--muted); border-radius:var(--r-sm);
                     font:inherit; font-size:12.5px; font-weight:600; min-height:40px; cursor:pointer; padding:0 4px; }
  .stageseg button.on { background:var(--accent); border-color:var(--accent); color:#fff; }
  .stageseg button:disabled { cursor:default; }
  .pdrow { display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-top:12px; }
  .pdrow label { width:100%; font-size:12.5px; color:var(--muted); }
  .pdrow input, .tform input, .tform select, select.snz { background:var(--panel2); border:1px solid var(--border);
       color:var(--text); border-radius:var(--r-sm); padding:8px 10px; font:inherit; font-size:13.5px; min-height:40px; }
  .pdrow input { flex:1; min-width:0; }
  .pbtn { background:var(--accent); border:none; color:#fff; padding:0 14px; min-height:40px; border-radius:var(--r-sm);
          font:inherit; font-size:13.5px; font-weight:600; cursor:pointer; white-space:nowrap; }
  .pbtn:disabled { opacity:.55; cursor:default; }
  .pdmsg { font-size:12.5px; color:var(--muted); margin:6px 0 0; min-height:18px; }
  .pdmsg.err { color:var(--red); }
  .tform { display:flex; flex-wrap:wrap; gap:8px; margin:0 0 4px; }
  .tform input[name=ttl] { flex:1 1 240px; min-width:0; }
  .pdsec .tform { margin-top:10px; }
  .pdsec .tform input[name=ttl] { flex-basis:100%; }
  .tlist { display:grid; gap:8px; margin-top:12px; }
  .furow { display:flex; gap:12px; align-items:center; background:var(--panel); border:1px solid var(--border);
           border-radius:var(--r-md); padding:10px 12px; }
  #pdTasks .furow { background:var(--panel2); margin-bottom:6px; flex-wrap:wrap; }
  .furow .main { flex:1; min-width:0; }
  .furow .t { font-weight:600; font-size:13.5px; }
  .furow.done .t { text-decoration:line-through; color:var(--muted); }
  .furow .s { color:var(--muted); font-size:12.5px; margin-top:3px; display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
  .furow .s .lateTxt { color:var(--red); font-weight:600; }
  .furow .acts { display:flex; gap:6px; flex-wrap:wrap; justify-content:flex-end; align-items:center; }
  .furow .rowact, select.snz { min-height:36px; }
  .fucheck { width:30px; height:30px; border-radius:50%; border:2px solid var(--border2); background:none; cursor:pointer;
             flex:none; color:#fff; font-size:16px; line-height:1; }
  .fucheck:hover { border-color:var(--green); }
  .furow.done .fucheck { background:var(--green); border-color:var(--green); }
  /* IBX (batch 56): select mode */
  .ibxbulk { padding:4px 12px 6px; font-size:12.5px; border-bottom:1px solid var(--hairline); }
  .ibxbulk .bkbar { display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; }
  .ibxbulk .bkacts { display:flex; flex-wrap:wrap; gap:6px; width:100%; }
  .ibxbulk .bkacts button, .ibxbulk .bkacts select { font-size:12.5px; padding:5px 9px; min-height:32px; }
  .conv.picking .cav { display:none; }
  .conv .cpick { grid-row:1 / span 3; grid-column:1; width:18px; height:18px; margin:9px auto 0; accent-color:var(--accent); }
  .conv.picked { background:var(--accent-soft); }
  .pftoast { position:fixed; left:50%; bottom:22px; transform:translateX(-50%); background:var(--text); color:var(--bg);
             padding:10px 14px; border-radius:var(--r-md); font-size:13.5px; z-index:90; display:flex; gap:12px; align-items:center;
             box-shadow:var(--shadow-menu); }
  .pftoast.err { background:var(--red); color:#fff; }
  .pftoast button { background:none; border:0; color:inherit; font:inherit; font-weight:700; text-decoration:underline; cursor:pointer; }
  @media (max-width:900px) { .board { grid-template-columns:repeat(5, 240px); } .furow { flex-wrap:wrap; } }
  /* CR1 (2026-10-07): the customer record panel (over the lead panel when both are open). */
  .crscrim { z-index:84; }
  .crdrawer { z-index:85; width:min(560px, 100vw); }
  .crdrawer .pdbody { grid-template-columns:minmax(0, 1fr); }   /* CR1b: long lines never widen the panel */
  .crdrawer .pdsec, .crdrawer .crlist > * { min-width:0; }
  .crdrawer .crlist { grid-template-columns:minmax(0, 1fr); }
  .crform textarea { width:100%; box-sizing:border-box; }
  .crkick { font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--accent2); margin-bottom:2px; }
  /* ── 9: Settings > Integrations. ── */
  .ighooks .hrow { display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:12px; align-items:start; padding:12px 0; border-top:1px solid var(--hairline); }
  .ighooks .hrow:first-child { border-top:0; }
  .ighooks .hrow.off .hname, .ighooks .hrow.off .hurl { color:var(--muted); }
  .hname { font-weight:650; font-size:13.5px; }
  .hurl { font-size:12.5px; color:var(--muted); word-break:break-all; margin-top:2px; }
  .hev { display:flex; flex-wrap:wrap; gap:4px; margin-top:6px; }
  .hev span { font-size:11px; padding:1px 7px; border-radius:999px; border:1px solid var(--border); background:var(--panel2); color:var(--text); }
  .hstat { font-size:11px; color:var(--muted); margin-top:5px; }
  .hstat.warn { color:var(--amber-ink, var(--amber)); }
  .hacts { display:flex; gap:4px; flex-wrap:wrap; justify-content:flex-end; }
  .pcard .hacts button, .pcard .igform .x, .pcard .iglog button, .pcard.igkeys button.ghost, .pcard .igonce button, .pcard.igrec button { background:var(--panel2); color:var(--text); border:1px solid var(--border); border-radius:8px;
            padding:6px 10px; min-height:32px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
  .pcard .hacts button:hover, .pcard .iglog button:hover, .pcard.igkeys button.ghost:hover, .pcard .igonce button:hover, .pcard.igrec button:hover { border-color:var(--accent); color:var(--accent2); background:var(--panel2); }
  .pcard .hacts button:disabled { opacity:.5; cursor:default; }
  .igform { margin-top:12px; padding:14px; border:1px solid var(--border2); border-radius:var(--r-md); background:var(--panel2); }
  .igform h4, .iglog h4, .igkeys h4, .igrec h4 { margin:14px 0 6px; font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted); }
  .igform h4:first-child, .igrec h4:first-of-type { margin-top:0; }
  .igform input[type=text], .igform input[type=url], .igkeys input[type=text] { width:100%; background:var(--panel); border:1px solid var(--border); color:var(--text); border-radius:8px; padding:8px 10px; font:inherit; font-size:13.5px; min-height:36px; }
  .igform .evs { display:grid; grid-template-columns:repeat(auto-fit, minmax(260px, 1fr)); gap:6px 14px; }
  .igform .evs label { display:flex; gap:8px; align-items:flex-start; font-size:13.5px; cursor:pointer; }
  .igform .evs input { margin-top:3px; accent-color:var(--accent); width:16px; height:16px; flex:none; }
  .igform .evs small { display:block; color:var(--muted); font-size:11px; }
  .igform .foot { display:flex; gap:8px; align-items:center; margin-top:14px; flex-wrap:wrap; }
  .pcard .igform .foot button.go { background:var(--accent); border-color:var(--accent); color:#fff; }
  .pcard .igform .foot button.go:hover { background:#6d28d9; color:#fff; }
  .igmsg { font-size:12.5px; min-height:1em; margin:8px 0 0; color:var(--muted); }
  .igmsg.err { color:var(--red); }
  .igonce { margin-top:12px; padding:12px 14px; border:1px solid var(--accent); border-radius:var(--r-md); background:var(--accent-soft); }
  .igonce b { display:block; margin-bottom:6px; }
  .igonce .chancopy input { font-family:var(--font-mono); }
  .igonce p { margin:6px 0 0; font-size:12.5px; color:var(--muted); }
  .igonce pre { margin:8px 0 0; padding:10px 12px; background:var(--panel); border:1px solid var(--border); border-radius:8px; font-family:var(--font-mono); font-size:11px; white-space:pre-wrap; word-break:break-all; color:var(--text); }
  .iglog { margin-top:14px; padding-top:12px; border-top:1px solid var(--hairline); }
  .iglog .drow { display:grid; grid-template-columns:70px minmax(0,1fr) auto; gap:8px 12px; padding:8px 0; border-top:1px solid var(--hairline); font-size:12.5px; align-items:center; }
  .iglog .drow:first-of-type { border-top:0; }
  .iglog .drow .when { color:var(--muted); font-variant-numeric:tabular-nums; }
  .iglog .drow .dsub { color:var(--muted); font-size:11px; }
  .iglog .drow .dacts { display:flex; gap:4px; }
  .iglog .drow .dacts button { padding:0 9px; min-height:28px; font-size:12.5px; }
  .iglog .dbody { grid-column:1 / -1; margin:0; padding:10px 12px; background:var(--panel2); border:1px solid var(--border); border-radius:8px; font-family:var(--font-mono); font-size:11px; white-space:pre-wrap; word-break:break-all; max-height:260px; overflow:auto; }
  .pill.ok { color:var(--green-ink, var(--green)); border-color:rgba(52,211,153,.35); background:rgba(52,211,153,.1); }
  .pill.dead { color:var(--red); border-color:rgba(248,113,113,.35); background:rgba(248,113,113,.1); }
  .pill.pending { color:var(--amber-ink, var(--amber)); }
  .igkeys .krow { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:4px 12px; padding:10px 0; border-top:1px solid var(--hairline); font-size:13.5px; align-items:center; }
  .igkeys .krow:first-child { border-top:0; }
  .igkeys .krow code { font-family:var(--font-mono); font-size:12.5px; background:var(--panel2); padding:1px 6px; border-radius:5px; }
  .igkeys .krow .ksub { grid-column:1; font-size:11px; color:var(--muted); }
  .igkeys .knew { display:flex; gap:8px; margin-top:10px; flex-wrap:wrap; align-items:center; }
  .igkeys .knew input[type=text] { flex:1; min-width:160px; width:auto; }
  .igkeys .apiurl { font-family:var(--font-mono); font-size:12.5px; background:var(--panel2); padding:6px 9px; border-radius:7px; display:inline-block; margin-top:4px; word-break:break-all; }
  .igkeys ul, .igrec ol { margin:6px 0 0; padding-left:20px; font-size:13.5px; line-height:1.6; }
  .igrec .rcp { padding:10px 0; border-top:1px solid var(--hairline); }
  .igrec .rcp:first-of-type { border-top:0; }
  .igrec .rcp b { font-size:13.5px; }
  .igrec pre { margin:8px 0 0; padding:10px 12px; background:var(--panel2); border:1px solid var(--border); border-radius:8px; font-family:var(--font-mono); font-size:11px; white-space:pre-wrap; word-break:break-all; color:var(--text); }
  /* ── 8: the Reports page. ── */
  .rpt { display:grid; gap:14px; }
  .rpthead { display:flex; flex-wrap:wrap; gap:10px 16px; align-items:center; justify-content:space-between; }
  .rptdl { display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
  .rptdl .dim { margin-right:4px; font-size:12.5px; }
  .rptdl button { background:var(--panel2); color:var(--text); border:1px solid var(--border); border-radius:8px; padding:0 12px; min-height:34px;
                  font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; display:inline-flex; align-items:center; gap:6px; }
  .rptdl button:hover { border-color:var(--accent); color:var(--accent2); }
  .rptdl button:disabled { opacity:.5; cursor:default; }
  .rptdl button .ico { width:14px; height:14px; }
  .rptnote { margin:0; font-size:12.5px; color:var(--muted); }
  .rpt .stat.warn .v { color:var(--amber-ink, var(--amber)); }
  .rpt .stat .v small { font-size:13.5px; font-weight:600; color:var(--muted); margin-left:4px; }
  .rptgrid2 { display:grid; grid-template-columns:repeat(auto-fit, minmax(300px, 1fr)); gap:14px; align-items:start; }
  .rptchart { position:relative; }
  .rptchart svg { width:100%; height:200px; display:block; overflow:visible; }
  .rptchart .ax { font-size:11px; fill:var(--dim); }
  .rptchart .gl { stroke:var(--hairline); stroke-width:1; }
  .rptchart .b-chats { fill:var(--accent); } .rptchart .b-leads { fill:var(--green); } .rptchart .b-missed { fill:var(--amber); }
  .rptchart rect:hover { opacity:.75; }
  .rptleg { display:flex; gap:14px; font-size:11px; color:var(--muted); flex-wrap:wrap; }
  .rptleg i { display:inline-block; width:10px; height:10px; border-radius:2px; margin-right:5px; vertical-align:-1px; }
  .rptleg .l-chats i { background:var(--accent); } .rptleg .l-leads i { background:var(--green); } .rptleg .l-missed i { background:var(--amber); }
  .rptrow { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:4px 12px; padding:9px 0; border-top:1px solid var(--hairline); font-size:13.5px; align-items:baseline; }
  .rptrow:first-child { border-top:0; }
  .rptrow .n { font-variant-numeric:tabular-nums; font-weight:650; white-space:nowrap; }
  .rptrow .n small { font-weight:500; color:var(--muted); font-size:11px; margin-left:4px; }
  .rptrow .sub { grid-column:1 / -1; font-size:11px; color:var(--muted); }
  .rptwithin { display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:6px 10px; align-items:center; font-size:12.5px; color:var(--muted); margin-top:10px; }
  .rptwithin .bar { height:8px; border-radius:999px; background:var(--panel2); overflow:hidden; }
  .rptwithin .bar i { display:block; height:100%; background:var(--green); border-radius:999px; }
  .rptwithin b { font-variant-numeric:tabular-nums; color:var(--text); }
  .rptwithin .tgt { color:var(--text); font-weight:650; }
  .rptmiss { display:grid; gap:0; }
  .rptmiss .mrow { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:4px 10px; padding:10px 0; border-top:1px solid var(--hairline); font-size:13.5px; }
  .rptmiss .mrow:first-child { border-top:0; }
  .rptmiss .mrow .q { grid-column:1; grid-row:1; font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .rptmiss .mrow .m { grid-column:1; grid-row:2; font-size:11px; color:var(--muted); }
  .rptmiss .mrow .m b { color:var(--amber-ink, var(--amber)); font-weight:600; }
  .rptmiss .mrow button { grid-column:2; grid-row:1 / span 2; align-self:center; background:var(--panel2); color:var(--text); border:1px solid var(--border); border-radius:8px;
                          padding:0 12px; min-height:34px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
  .rptmiss .mrow button:hover { border-color:var(--accent); color:var(--accent2); }
  .rptsplit { display:flex; gap:14px; flex-wrap:wrap; font-size:12.5px; color:var(--muted); margin-bottom:6px; }
  .rptsplit b { color:var(--text); font-variant-numeric:tabular-nums; }
  .rpttbl { width:100%; border-collapse:collapse; font-size:13.5px; }
  .rpttbl th { text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); font-weight:600; padding:0 0 8px; }
  .rpttbl th.num, .rpttbl td.num { text-align:right; font-variant-numeric:tabular-nums; }
  .rpttbl td { padding:8px 0; border-top:1px solid var(--hairline); }
  .rpttbl td.p { max-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .rpttbl tr.other td { color:var(--muted); }
  .rptstrip { display:flex; align-items:flex-end; gap:3px; height:64px; margin-top:6px; }
  .rptstrip i { flex:1; display:block; background:var(--accent); border-radius:3px 3px 0 0; min-height:2px; opacity:.85; }
  .rptstrip i.zero { background:var(--panel2); opacity:1; }
  .rptstrip i.peak { background:var(--accent2); }
  .rptaxis { display:flex; justify-content:space-between; font-size:11px; color:var(--muted); margin-top:4px; }
  .rptaxis.days span { flex:1; text-align:center; }
  .rptwhen { display:grid; grid-template-columns:repeat(auto-fit, minmax(260px, 1fr)); gap:18px; }
  /* UX13: by page / by source / by hour fold under "More detail" (remembered per person) */
  .rptmore > summary { cursor:pointer; list-style:none; display:flex; align-items:center; gap:8px; min-height:40px; padding:6px 10px;
    border-radius:8px; color:var(--text); font-weight:600; }
  .rptmore > summary::-webkit-details-marker { display:none; }
  .rptmore > summary::before { content:'›'; display:inline-block; color:var(--muted); transition:transform .15s ease; }
  .rptmore[open] > summary::before { transform:rotate(90deg); }
  .rptmore > summary:hover, .rptmore > summary:focus-visible { background:var(--accent-soft); }
  .rptmore > summary .dim { font-weight:400; }
  .rptmore:not([open]) > .rptfold { display:none; }           /* an author display beats the UA's closed-details rule */
  .rptmore[open] > .rptfold { display:grid; gap:14px; margin-top:10px; }
  .rptwhen h4 { margin:0; font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); font-weight:600; }
  .rptwhen h4 span { text-transform:none; letter-spacing:0; font-weight:500; margin-left:6px; }
  #reportsHost #periodCard, #reportsHost #pagesCard { display:none; }
  .rpt .empty { padding:14px 0; text-align:left; }
  /* ── 7: automation rules (Settings > Automations) and assignment (Inbox). ── */
  .rules .rrow { display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:12px; align-items:start; padding:11px 0; border-top:1px solid var(--hairline); }
  .rules .rrow:first-child { border-top:0; }
  .rules .rrow.off .rsum, .rules .rrow.off .rname { color:var(--muted); }
  .rsw { width:38px; height:22px; border-radius:999px; border:1px solid var(--border2); background:var(--panel2); position:relative; cursor:pointer; padding:0; min-height:0; flex:none; margin-top:2px; }
  .rsw::after { content:''; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%; background:var(--muted); transition:left .15s, background .15s; }
  .rsw[aria-checked="true"] { background:var(--accent); border-color:var(--accent); }
  .rsw[aria-checked="true"]::after { left:18px; background:#fff; }
  .rname { font-weight:650; font-size:13.5px; }
  .rsum { font-size:12.5px; color:var(--muted); margin-top:3px; line-height:1.5; }
  .rsum b { color:var(--text); font-weight:600; }
  .rstat { font-size:11px; color:var(--muted); margin-top:3px; }
  .racts { display:flex; gap:4px; align-items:center; }
  /* .pcard button is the card's filled primary; these are quiet. Only + New rule and Save stay filled. */
  .pcard .racts button, .pcard .rbuild .rline button.x, .pcard .rtry button, .pcard .rbuild .rfoot button { background:var(--panel2); color:var(--text); border:1px solid var(--border); border-radius:8px;
            padding:6px 10px; min-height:32px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
  .pcard .racts button:hover, .pcard .rbuild .rline button.x:hover, .pcard .rtry button:hover, .pcard .rbuild .rfoot button:hover { border-color:var(--accent); color:var(--accent2); background:var(--panel2); }
  .pcard .racts button:disabled { opacity:.4; cursor:default; }
  .pcard .rules + .rnew { margin-top:10px; }
  .pcard .rruns button.linky { background:none; border:0; color:var(--accent2); padding:0; min-height:0; font:inherit; font-size:12.5px; font-weight:600; text-decoration:underline; cursor:pointer; }
  .rsum .tdot { margin:0 4px 0 1px; }
  .rbuild { margin-top:12px; padding:14px; border:1px solid var(--border2); border-radius:var(--r-md); background:var(--panel2); }
  .rbuild h4, .rtry h4, .rruns h4 { margin:14px 0 6px; font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted); }
  .rbuild h4:first-child { margin-top:0; }
  .rbuild .rtop { display:grid; grid-template-columns:minmax(0,1fr) auto auto; gap:8px; align-items:center; }
  .rbuild input[type=text], .rbuild select, .rtry input[type=text], .rtry select { background:var(--panel); border:1px solid var(--border); color:var(--text); border-radius:8px; padding:7px 9px; font:inherit; font-size:13.5px; min-height:36px; }
  .rbuild input[type=text] { width:100%; }
  .pcard .rbuild select, .pcard .rtry select { width:auto; flex:0 0 auto; max-width:100%; }
  .rbuild .rline { display:flex; flex-wrap:wrap; gap:8px; align-items:center; padding:6px 0; }
  .rbuild .rline select { max-width:100%; }
  .rbuild .rline input[type=text] { flex:1; min-width:180px; width:auto; }
  .rbuild .rline .chk { display:inline-flex; align-items:center; gap:5px; font-size:12.5px; color:var(--text); margin-right:4px; }
  .rbuild .rline .chk input { accent-color:var(--accent); width:16px; height:16px; }
  .rbuild .rline button.x { padding:0 9px; min-height:30px; }
  .pcard .rbuild .radd { background:none; border:1px dashed var(--border2); color:var(--accent2); border-radius:8px; padding:6px 10px; min-height:32px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
  .pcard .rbuild .radd:hover { border-color:var(--accent); background:none; }
  .rbuild .rfoot { display:flex; gap:8px; align-items:center; margin-top:14px; flex-wrap:wrap; }
  .pcard .rbuild .rfoot button.go { background:var(--accent); border-color:var(--accent); color:#fff; }
  .pcard .rbuild .rfoot button.go:hover { background:#6d28d9; color:#fff; }
  .rbuild .rhint { font-size:12.5px; color:var(--muted); margin:2px 0 0; }
  .rmsg { font-size:12.5px; min-height:1em; margin:8px 0 0; }
  .rmsg.err { color:var(--red); }
  .rtry { margin-top:14px; padding-top:12px; border-top:1px solid var(--hairline); }
  .rtry form { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
  .rtry form input[type=text] { flex:1; min-width:200px; }
  .rtry .rfires { margin-top:8px; font-size:13.5px; }
  .rtry .rfires div { padding:4px 0; }
  .rtry .rfires b { font-weight:650; }
  .rruns { margin-top:14px; padding-top:12px; border-top:1px solid var(--hairline); }
  .rruns .rrun { display:grid; grid-template-columns:72px minmax(0,1fr); gap:10px; padding:6px 0; font-size:12.5px; border-top:1px solid var(--hairline); }
  .rruns .rrun:first-of-type { border-top:0; }
  .rruns .rrun .when { color:var(--muted); font-variant-numeric:tabular-nums; }
  .rruns .rrun .did { color:var(--muted); margin-top:2px; }
  .rruns .rrun .did .no { color:var(--amber-ink, var(--amber)); }
  .rruns .rrun button.linky { padding:0; min-height:0; }
  .pill.who { color:var(--text); }
  .pill.who::before { content:''; display:inline-block; width:6px; height:6px; border-radius:50%; background:var(--accent); margin-right:5px; vertical-align:1px; }
  .thead { position:relative; }
  .whomenu { position:absolute; z-index:30; top:calc(100% - 4px); background:var(--panel); border:1px solid var(--border2); border-radius:var(--r-md);
             box-shadow:var(--shadow-menu); padding:6px; min-width:200px; display:flex; flex-direction:column; gap:2px; }
  .whomenu button { display:flex; align-items:center; gap:8px; width:100%; text-align:left; background:none; border:0; color:var(--text); font:inherit;
             font-size:13.5px; padding:8px 10px; border-radius:7px; cursor:pointer; min-height:36px; }
  .whomenu button:hover, .whomenu button:focus-visible { background:var(--panel2); outline:none; }
  .whomenu button.on { font-weight:650; }
  .whomenu button .on-dot { width:7px; height:7px; border-radius:50%; background:var(--green); flex:none; }
  .whomenu button .off-dot { width:7px; height:7px; border-radius:50%; background:var(--border2); flex:none; }
  .whomenu .whohead { font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted); padding:6px 10px 2px; }
  .cpsec .rr { font-size:12.5px; padding:5px 0; border-top:1px solid var(--hairline); }
  .cpsec .rr:first-of-type { border-top:0; }
  .cpsec .rr .did { color:var(--muted); }
  .cpsec .rr .did .no { color:var(--amber-ink, var(--amber)); }
  /* ── 6c: tags. One chip shape everywhere; the colour is a dot, so a chip reads the same in both themes. ── */
  .tdot { display:inline-block; width:8px; height:8px; border-radius:50%; flex:none; background:var(--muted); vertical-align:middle; }
  .tdot.c-violet { background:#7c3aed; } .tdot.c-blue { background:#2563eb; } .tdot.c-teal { background:#0d9488; } .tdot.c-green { background:#16a34a; }
  .tdot.c-amber { background:#d97706; } .tdot.c-red { background:#dc2626; } .tdot.c-pink { background:#db2777; } .tdot.c-grey { background:#6b7280; }
  .tagrow { display:flex; flex-wrap:wrap; align-items:center; gap:6px; position:relative; }
  .tagchip { display:inline-flex; align-items:center; gap:6px; padding:2px 6px 2px 8px; border-radius:999px; border:1px solid var(--border);
             background:var(--panel2); color:var(--text); font-size:12.5px; font-weight:600; line-height:1.4; }
  .tagchip button { border:0; background:none; color:var(--muted); font:inherit; font-size:13.5px; line-height:1; padding:0 2px; cursor:pointer; border-radius:999px; min-height:0; }
  .tagchip button:hover { color:var(--red); }
  .tagadd { border:1px dashed var(--border2); background:none; color:var(--muted); border-radius:999px; padding:2px 10px; font:inherit; font-size:12.5px;
            font-weight:600; cursor:pointer; min-height:24px; }
  .tagadd:hover { color:var(--accent2); border-color:var(--accent); }
  .tagpick { position:absolute; left:0; top:calc(100% + 6px); z-index:30; width:min(300px, 90vw); background:var(--panel); border:1px solid var(--border2);
             border-radius:var(--r-md); box-shadow:var(--shadow-menu); padding:8px; }
  .tagpick input { width:100%; background:var(--panel2); border:1px solid var(--border); color:var(--text); border-radius:8px; padding:7px 9px; font:inherit; font-size:13.5px; }
  .tagpick .tagcolors { display:flex; gap:7px; padding:8px 4px 2px; }
  .tagpick .tagcolors button { width:18px; height:18px; border-radius:50%; border:2px solid transparent; padding:0; cursor:pointer; min-height:0; }
  .tagpick .tagcolors button.on { border-color:var(--text); }
  .tagpick .tagopts { max-height:220px; overflow:auto; margin-top:6px; display:flex; flex-direction:column; gap:2px; }
  .tagpick .tagopts button { display:flex; align-items:center; gap:8px; width:100%; text-align:left; background:none; border:0; color:var(--text); font:inherit;
             font-size:13.5px; padding:7px 8px; border-radius:7px; cursor:pointer; min-height:32px; }
  .tagpick .tagopts button:hover, .tagpick .tagopts button:focus-visible { background:var(--panel2); outline:none; }
  .tagpick .tagopts button.new { color:var(--accent2); font-weight:600; }
  .tagpick .tagmsg { font-size:12.5px; color:var(--red); padding:4px 8px 0; }
  .tagpick .tagmsg:empty { display:none; }
  .thead .tagrow { flex:1 0 100%; margin-top:2px; }
  .conv .tagrow { margin-top:4px; gap:4px; }
  .conv .tagchip, .ctbl .tagchip { font-size:11px; padding:1px 7px; }
  .ctbl .tagrow { margin-top:4px; }
  .irail button .tdot { margin-right:7px; }
  .tagtbl { display:flex; flex-direction:column; margin-top:8px; }
  .tagtbl .trow { display:grid; grid-template-columns:auto minmax(0,1fr) auto auto auto; gap:10px; align-items:center; padding:7px 0; border-top:1px solid var(--hairline); }
  .tagtbl .trow:first-child { border-top:0; }
  .tagtbl .cnt { font-size:12.5px; color:var(--muted); white-space:nowrap; }
  .pcard .tagnew { display:flex; gap:8px; margin-top:10px; flex-wrap:wrap; align-items:center; }
  .pcard .tagnew input[type=text] { flex:1; min-width:160px; width:auto; }
  .pcard .tagnew select, .pcard .tagtbl select { width:auto; }
  .pcard .tagtbl button.ghost, .pcard .tagnew button.ghost { background:var(--panel2); color:var(--text); border:1px solid var(--border); border-radius:8px;
            padding:6px 12px; min-height:32px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
  .pcard .tagtbl button.ghost:hover, .pcard .tagnew button.ghost:hover { border-color:var(--accent); color:var(--accent2); }
  #tagMsg { font-size:12.5px; margin:8px 0 0; min-height:1em; }
  #ctTag { background:var(--panel2); border:1px solid var(--border); color:var(--text); border-radius:8px; padding:7px 9px; font:inherit; font-size:13.5px; max-width:200px; }
  .crchips { display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
  .crstage { display:flex; flex-wrap:wrap; gap:10px; align-items:center; }
  .crstage b { font-size:16px; }
  .crlist { display:grid; gap:6px; }
  .critem { background:var(--panel2); border:1px solid var(--border); border-radius:var(--r-md); padding:9px 11px;
            display:flex; gap:10px; align-items:flex-start; }
  .critem .main { flex:1; min-width:0; }
  .critem .t { font-size:13.5px; font-weight:600; }
  .critem .s { color:var(--muted); font-size:12.5px; margin-top:2px; display:flex; flex-wrap:wrap; gap:6px 10px; }
  .critem .q { color:var(--muted); font-size:12.5px; margin-top:4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .critem.done .t { text-decoration:line-through; color:var(--muted); }
  .critem .rowact { min-height:34px; }
  .crnote { white-space:pre-wrap; font-size:13.5px; }
  .crform { display:flex; flex-direction:column; gap:8px; margin-bottom:8px; }
  .crform textarea { background:var(--panel2); border:1px solid var(--border); color:var(--text); border-radius:var(--r-sm);
                     padding:9px 10px; font:inherit; font-size:13.5px; min-height:64px; resize:vertical; }
  .crform .pbtn { align-self:flex-start; }
  .crtime { display:grid; gap:0; border-left:2px solid var(--border); margin-left:4px; }
  .crtime div { position:relative; padding:4px 0 8px 14px; font-size:12.5px; }
  .crtime div::before { content:""; position:absolute; left:-6px; top:8px; width:10px; height:10px; border-radius:50%;
                        background:var(--panel); border:2px solid var(--border2); }
  .crtime b { display:block; color:var(--muted); font-weight:600; font-size:11px; }
  /* #93: setup progress that FOLLOWS you. The step list already existed on the
     Dashboard, but an operator two tabs deep had no idea a client was half
     built — so a business could sit at "profile written, nothing installed"
     for days with nothing on screen saying so. Same derived steps, same
     numbers; this is only ever a summary of them, never a second source of
     truth. Removes itself at 100% — a permanent "you're done" badge is
     furniture, and the one thing worse than no progress bar is one that is
     always full. */
  .setupmini { display:flex; flex-direction:column; gap:6px; width:100%; text-align:left;
               margin:10px 0 2px; padding:9px 10px; border-radius:10px; cursor:pointer;
               background:var(--accent-soft); border:1px solid var(--border);
               color:var(--accent2); font:inherit; }
  .setupmini:hover { border-color:var(--accent); }
  .setupmini:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  .setupmini .smtop { display:flex; align-items:baseline; justify-content:space-between; gap:8px; }
  .setupmini .smlabel { font-size:11px; font-weight:700; letter-spacing:.07em;
                        text-transform:uppercase; }
  .setupmini .smpct { font-size:13.5px; font-weight:700; font-variant-numeric:tabular-nums; }
  /* The track keeps its own contrast in both themes — a bar drawn only in the
     accent vanishes against accent-soft in dark mode. */
  .setupmini .smbar { display:block; height:5px; border-radius:999px; overflow:hidden;
                      background:var(--border); }
  .setupmini .smfill { display:block; height:100%; border-radius:999px;
                       background:var(--accent); transition:width .35s ease; }
  .setupmini .smleft { font-size:11px; color:var(--muted); }
  /* An account with no business attached used to get the whole instrument
     panel: five stat cards reading 0, a live chart flat at zero, "Nobody on
     your sites right now". Every number true, the overall impression false —
     it reads as a working-but-quiet product when in fact nothing can EVER
     appear here. Hide the instruments and say the one true thing instead.
     Scoped to #view-dash only: an admin with no properties still needs the
     Clients tab to create one. */
  #app.noprops #view-dash > * { display:none !important; }
  .emptyacct { display:flex; flex-direction:column; gap:6px; }
  .emptyacct b { font-size:13.5px; color:var(--text); }
  .emptyacct span { color:var(--muted); font-size:13.5px; max-width:62ch; line-height:1.5; }
  /* B5 — first-run. One centered column; generous air on purpose: the page is
     empty because nothing has happened yet, and the layout should own that
     instead of apologising for it. */
  .frun { max-width: 640px; margin: 6vh auto 4rem; display:flex; flex-direction:column; gap:28px; }
  .frun-hero { text-align:center; display:flex; flex-direction:column; align-items:center; gap:10px; }
  .frun-glyph { width:44px; height:44px; color:var(--accent, #7c3aed); opacity:.9; }
  .frun-hero h2 { font-size:20px; font-weight:700; color:var(--text); margin:0; }
  .frun-hero p { color:var(--muted); font-size:13.5px; line-height:1.6; max-width:52ch; margin:0; }
  .frun-steps { display:flex; flex-direction:column; gap:14px; }
  .fstep { display:flex; gap:14px; align-items:flex-start; background:var(--panel2, rgba(255,255,255,.03));
           border:1px solid var(--line, rgba(255,255,255,.07)); border-radius:12px; padding:14px 16px; }
  .fnum { flex:none; width:26px; height:26px; border-radius:50%; display:flex; align-items:center;
          justify-content:center; font-size:13.5px; font-weight:700; color:var(--accent, #7c3aed);
          background:color-mix(in srgb, var(--accent, #7c3aed) 14%, transparent); }
  .fstep b { display:block; font-size:13.5px; color:var(--text); margin-bottom:2px; }
  .fstep span { color:var(--muted); font-size:13.5px; line-height:1.55; }
  /* The relocated two-step card keeps its own styling; just give it room. */
  #frunMfa:empty { display:none; }
  .frun-foot { display:flex; flex-direction:column; gap:6px; text-align:center; }
  .frun-foot a { color:var(--accent, #7c3aed); font-size:13.5px; font-weight:650; text-decoration:none; }
  .frun-foot a:hover { text-decoration:underline; }
  .frun-foot span { color:var(--muted); font-size:12.5px; }
  /* In the horizontal strip it becomes a compact pill beside the tabs — the
     stacked bar would break the row the same way .navsec does. */
  @media (max-width: 900px) {
    header .setupmini { order:2; width:auto; flex:none; margin:0; padding:6px 10px;
                        flex-direction:row; align-items:center; gap:8px; }
    header .setupmini .smbar { width:54px; }
    header .setupmini .smleft { display:none; }
  }
  /* Echo of the picked business on each scoped editor page — "Settings" alone
     reads as global; "Settings · BEM Solutions" cannot. */
  .scopechip { margin-left:10px; font-size:12.5px; font-weight:600; color:var(--accent2);
               background:var(--accent-soft); border:1px solid var(--border); border-radius:999px;
               padding:3px 10px; vertical-align:3px; }
  /* Channel pills + rail icons. Colors are the channels' own brand hues, not
     theme tokens — a WhatsApp row should read WhatsApp in either theme. */
  .pill.chan { display:inline-flex; align-items:center; gap:4px; }
  .chi { width:12px; height:12px; flex:none; vertical-align:-2px; }
  .pill.ch-whatsapp  { color:#25d366; background:rgba(37,211,102,.12);  border-color:rgba(37,211,102,.35); }
  .pill.ch-messenger { color:#3b9cff; background:rgba(59,156,255,.12);  border-color:rgba(59,156,255,.35); }
  .pill.ch-telegram  { color:#33a8dd; background:rgba(51,168,221,.12);  border-color:rgba(51,168,221,.35); }
  .pill.ch-email     { color:#fbbf24; background:rgba(251,191,36,.12);  border-color:rgba(251,191,36,.35); }
  .pill.ch-instagram { color:#e1306c; background:rgba(225,48,108,.12);  border-color:rgba(225,48,108,.35); }
  .irail .chi { margin-right:5px; }
  /* #88: blocked discount attempts */
  .proberow { padding:9px 0; border-top:1px solid var(--border); font-size:12.5px; line-height:1.55; }
  .proberow:first-child { border-top:none; }
  .proberow .muted { display:block; font-size:11px; margin-bottom:2px; }
  /* Costs card (Clients tab) */
  .costhead { display:flex; align-items:center; justify-content:space-between; gap:12px;
              flex-wrap:wrap; margin:10px 0 12px; }
  .costwin button { min-height:36px; }
  .costtbl { width:100%; border-collapse:collapse; font-size:13.5px; }
  .costtbl .num { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
  .costtbl td .sub { display:block; color:var(--muted); font-size:11px; }
  .costtbl .neg { color:var(--red, #dc2626); }
  .costnote { color:var(--muted); font-size:12.5px; margin:10px 0 0; line-height:1.5; }
  .costsub { margin:18px 0 6px; font-size:11px; font-weight:700; letter-spacing:.08em;
             text-transform:uppercase; color:var(--muted); }
  .costtop .billrow { gap:12px; }
  .costtop .who { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .costtop .rowact { margin-left:auto; }
  /* Channels card (#79) */
  .chanrow { padding:10px 0 2px; }
  .chanrow + .chanrow { border-top:1px solid var(--border); margin-top:10px; }
  .chanrow .chanok { font-size:11px; font-weight:700; color:var(--green-ink, var(--green)); margin-left:6px;
                     text-transform:uppercase; letter-spacing:.04em; }
  .chansteps { margin:10px 0 8px; padding-left:20px; font-size:12.5px; color:var(--muted);
               line-height:1.7; }
  .chansteps code { background:var(--panel2); border:1px solid var(--border); border-radius:4px;
                    padding:1px 5px; font-size:11px; }
  .chanrow .chantoken { max-width:340px; }
  .chanbar { position:static; border-top:none; padding:12px 0 0; background:transparent; }
  /* One-of-one switch (#107). The whole sentence is the tap target (44px floor
     via padding), because the checkbox alone is a 13px square. */
  .wooLive { display:flex; gap:10px; align-items:flex-start; cursor:pointer;
             margin:12px 0 2px; padding:12px; border:1px solid var(--border);
             border-radius:10px; background:var(--panel2);
             font-size:12.5px; color:var(--muted); line-height:1.6; }
  .wooLive input { margin-top:3px; flex:none; accent-color:var(--accent); }
  .wooLive b { color:var(--text); }
  .wooLive input:disabled + span { opacity:.6; }
  /* #82: WhatsApp's three credential fields + the one-time Meta setup panel. */
  .chanfields { display:flex; flex-direction:column; gap:8px; max-width:460px; }
  .chanfields input { width:100%; }
  /* the provider picker: the settings form styles inputs, not selects */
  .chanfields select { width:100%; background:var(--panel2); border:1px solid var(--border); color:var(--text);
    border-radius:8px; padding:10px; font:inherit; font-size:13.5px; line-height:1.5; }
  .chanfields select:focus { outline:none; border-color:var(--accent); }
  .tsrow { display:flex; gap:8px; align-items:center; padding:10px 0; border-top:1px solid var(--border); font-size:13.5px; }
  .tsrow:first-child { border-top:none; }
  /* UX28 (batch 46): one person's permissions, under their row */
  .tscaps { margin:0 0 12px; padding:10px 12px; border:1px solid var(--border); border-radius:10px; background:var(--panel2); }
  .tscaps .tscap { display:flex; gap:8px; align-items:flex-start; margin:8px 0; font-size:13.5px; line-height:1.45; cursor:pointer; }
  .tscaps .tscap input { margin-top:3px; flex:none; }
  .tscaps .savebar { margin-top:10px; flex-wrap:wrap; }
  .tsrow .tswho { flex:1; min-width:0; line-height:1.5; }
  /* quiet: the card's one filled button is Add (.setgrid button fills every button otherwise) */
  .setgrid .tsrow button { background:none; border:1px solid var(--border); color:var(--text); }
  .setgrid .tsrow button:hover { border-color:var(--accent); color:var(--accent2); }
  .pcard.suflash { box-shadow:0 0 0 2px var(--accent); transition:box-shadow .25s; }
  .chansteps .mnote { list-style:none; margin-left:-20px; padding-top:4px; color:var(--text); }
  .chancopy { display:flex; gap:6px; }
  .chancopy input { flex:1; font-size:12.5px; }
  .copybtn { flex:none; background:none; border:1px solid var(--border); color:var(--text);
             border-radius:8px; padding:0 12px; cursor:pointer; font-size:12.5px; }
  .copybtn:hover { border-color:var(--accent); color:var(--accent2); }
  /* ── inbox ── */
  .ppill { background:var(--panel); border:1px solid var(--border); color:var(--muted);
           padding:5px 14px; border-radius:999px; cursor:pointer; font-size:12.5px; }
  .ppill.on { color:var(--accent2); border-color:var(--accent); background:var(--panel2); }
  .split { display:grid; grid-template-columns:340px 1fr; gap:14px; align-items:start; }
  @media (max-width:820px){ .split { grid-template-columns:1fr; } }
  /* Conversation rows: flush list rows with hairline dividers and an identity
     avatar — a row per PERSON, not a floating card per URL. */
  .convlist { display:flex; flex-direction:column; }
  .conv { display:grid; grid-template-columns:34px minmax(0,1fr); gap:4px 10px;
          padding:11px 12px; cursor:pointer; border-bottom:1px solid var(--hairline);
          border-left:3px solid transparent; }
  .conv:hover { background:var(--panel2); }
  .conv.sel { background:var(--accent-soft); border-left-color:var(--accent); }
  .conv .cav { grid-row:1 / span 3; grid-column:1; width:34px; height:34px; border-radius:50%;
               margin-top:2px; display:flex; align-items:center; justify-content:center;
               font-size:13.5px; font-weight:700; color:#fff; position:relative; }
  /* Presence pip — only ever rendered when the visitor is on the site NOW. */
  .conv .cav.on::after { content:""; position:absolute; right:-1px; bottom:-1px;
               width:10px; height:10px; border-radius:50%; background:var(--green);
               border:2px solid var(--panel); }
  .conv .c1, .conv .c2, .conv .meta { grid-column:2; }
  .conv .c1 { display:flex; justify-content:space-between; gap:8px; font-size:13.5px; }
  .conv .c1 b { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .conv .c1 .muted { flex:none; font-size:11px; }
  /* The preview line is what the operator PICKS BY — it was the same muted
     gray as the meta chips below it, so the one line that matters carried the
     least weight on the card (2026-08-28 polish). Near-text, not muted; the
     "no message yet" italic keeps its own muted class, so empty rows still
     read quiet automatically. */
  /* No opacity here: it was inherited by the italic "no message yet" line
     and dragged its muted colour to 2.92:1 (audit 2026-09-03). */
  .conv .c2 { color:var(--text); font-size:12.5px;
              overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .conv .c3 { font-size:11px; }
  .pill.lead { color:var(--green-ink, var(--green)); }
  .thread { display:flex; flex-direction:column; min-height:420px; }
  .thead { padding:12px 14px; border-bottom:1px solid var(--border); font-size:13.5px;
           background:var(--panel); }
  /* The transcript sits one surface step BELOW its chrome, so the reading area
     reads as a canvas between the header and the composer. */
  .tmsgs { flex:1; overflow-y:auto; padding:16px 18px; display:flex; flex-direction:column;
           gap:10px; background:var(--bg); }
  .m { max-width:78%; }
  .m.v { align-self:flex-start; } .m.a { align-self:flex-start; } .m.h { align-self:flex-end; }
  .m .mb { padding:9px 13px; border-radius:14px; font-size:13.5px; line-height:1.45; white-space:pre-wrap; word-break:break-word; }
  .m.v .mb { background:var(--panel2); border:1px solid var(--border); border-bottom-left-radius:5px; }
  .m.a .mb { background:transparent; border:1px dashed var(--border2); color:var(--muted); }
  .m.h .mb { background:linear-gradient(135deg, var(--accent), #6d28d9); color:#fff;
             border-bottom-right-radius:5px; }
  .m .mw { font-size:11px; margin-top:3px; color:var(--muted); }
  .m.h .mw { text-align:right; }
  #replyErr { display:none; background:rgba(248,113,113,.12); color:var(--red);
              font-size:13.5px; font-weight:600; padding:8px 12px;
              border-top:1px solid var(--border); }
  #replyErr.on { display:block; }
  #replyErr.note { background:rgba(148,163,184,.14); color:inherit; opacity:.85; }
  /* A one-time link that needs its two-step code: only the code box is relevant. */
  #loginForm.magic #u, #loginForm.magic #p, #loginForm.magic .flabel[for="u"], #loginForm.magic .flabel[for="p"] { display:none; }
  .treply { display:flex; gap:8px; padding:12px; border-top:1px solid var(--border);
            background:var(--panel); }
  /* ── dashboard ── */
  /* EXPLICIT area plan, not nested auto-fit. The auto-fit version formed four
     top-level columns on the operator's 1730px monitor and stuffed the whole
     stat grid into ONE ~360px track — the four KPI cards stacked as tall
     blocks down the right edge (operator screenshot, 2026-07-28). Areas make
     the hierarchy fixed at every width: KPIs read first, then trend + pages,
     then the visitor table across the full row. DOM order is unchanged —
     grid-area does the reordering, so the census and tab logic see the same
     tree. */
  .dashgrid { display:grid; gap:14px; align-items:start;
              grid-template-columns:minmax(0,1.7fr) minmax(0,1fr);
              grid-template-areas: "stats stats"; }   /* MN1: period/chart/pages/visitors moved to Reports and Live */
  .dashgrid .periodcard { grid-area:period; }
  .dashgrid .chartcard { grid-area:chart; }
  .dashgrid .statwrap { grid-area:stats; }
  .gridhead { font-size:11px; font-weight:700; letter-spacing:.6px; text-transform:uppercase;
              color:var(--muted); margin:0 0 8px 2px; }
  .statgrid + .gridhead { margin-top:16px; }
  .dashgrid .card:has(#topPages) { grid-area:pages; }
  .dashgrid .card:has(#visitors) { grid-area:visitors; }
  @media (max-width:900px) {
    .dashgrid { grid-template-columns:minmax(0,1fr);
                grid-template-areas: "stats"; }
  }
  .card { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg); padding:16px 18px 18px; }
  .cardhead { display:flex; align-items:baseline; justify-content:space-between; gap:10px; margin-bottom:12px; }
  .cardhead h3 { margin:0; font-size:13.5px; font-weight:600; display:flex; align-items:center; gap:7px; }
  .cardhead h3 .ico { width:15px; height:15px; color:var(--muted); }
  .cardhead .dim { font-size:11px; }
  .livedot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--muted);
             margin:0 7px 0 8px; vertical-align:middle; }
  .livedot.on { background:var(--green); box-shadow:0 0 0 3px rgba(52,211,153,.18); }
  .chartwrap { height:190px; position:relative; }
  /* Axis furniture in HTML around the stretched SVG plot. */
  .chartrow { display:flex; gap:8px; height:100%; }
  .chartrow .yaxis { display:flex; flex-direction:column; justify-content:space-between;
                     padding-bottom:20px; font-size:11px; color:var(--muted);
                     font-variant-numeric:tabular-nums; text-align:right; min-width:16px; }
  .chartrow .plot { flex:1; min-width:0; display:flex; flex-direction:column; min-height:0; }
  /* The SVG needs a DEFINITE box: with preserveAspectRatio="none" and an auto
     height it fell back to the viewBox ratio and drew straight out of the card
     over the panel below (caught on screen). Absolute inside a relative track
     pins it to exactly the space left above the axis labels. */
  .chartrow .plotbox { position:relative; flex:1; min-height:0; }
  .chartrow .plotbox svg { position:absolute; inset:0; width:100%; height:100%;
                           display:block; overflow:hidden; }
  .chartrow .xaxis { display:flex; justify-content:space-between; font-size:11px;
                     color:var(--muted); padding-top:6px; flex:none; }
  .peakchip { position:absolute; top:6px; right:6px; background:var(--panel2);
              border:1px solid var(--border); color:var(--muted); border-radius:999px;
              padding:2px 9px; font-size:11px; font-variant-numeric:tabular-nums; }
  /* stat cards — number first, context underneath; never a number with no baseline.
     Trends are CHIPS (tinted pills), not loose arrow glyphs: "7d ↑1 ↓0" read as
     debug output on every card of the shipped dashboard. */
  /* KPI strip: as many tracks as fit; the hero takes two, so at full width the
     row reads hero + four peers, and at narrow widths it wraps to 2-up. */
  .statgrid { display:grid; grid-template-columns:repeat(auto-fit, minmax(170px, 1fr)); gap:12px; }
  /* Today = hero (2 tracks) + 5 cards = 7 tracks: at desktop width give it exactly 7 so
     it is one row, never 6 + 1. The week row has 2 cards; cap their width so they read
     as cards, not banners. */
  @media (min-width:1100px) { .statgrid:not(.week) { grid-template-columns:repeat(7, minmax(0,1fr)); } }
  .statgrid.week { grid-template-columns:repeat(auto-fill, minmax(170px, 260px)); }
  .stat { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg); padding:14px 16px; }
  .stat .k { color:var(--muted); font-size:12.5px; display:flex; align-items:center; gap:7px; }
  .stat .k .ico { width:15px; height:15px; color:var(--muted); }
  .stat .v { font-size:28px; font-weight:650; letter-spacing:-.02em; margin:2px 0 4px;
             font-variant-numeric:tabular-nums; }
  .stat .per { font-size:11px; color:var(--muted); margin-top:6px; }
  .stat .sub { font-size:11px; color:var(--muted); display:flex; gap:7px; flex-wrap:wrap; align-items:center; }
  .wk { color:var(--muted); font-size:11px; display:inline-flex; gap:4px; align-items:center; }
  .wk b { font-weight:700; font-variant-numeric:tabular-nums; }
  .wk b.zero { color:var(--muted); font-weight:600; }
  .stat.hero { grid-column:span 2; border-color:rgba(124,58,237,.5);
               background:linear-gradient(180deg, rgba(124,58,237,.13), var(--panel) 70%); }
  .stat.hero .v { font-size:28px; }
  .stat.warn { border-color:rgba(248,113,113,.45); }
  .chip { display:inline-flex; align-items:center; gap:3px; padding:2px 8px; border-radius:999px;
          font-size:11px; font-weight:600; font-variant-numeric:tabular-nums; }
  .chip.up { background:rgba(52,211,153,.12); color:var(--green-ink, var(--green)); }
  .chip.down { background:rgba(248,113,113,.12); color:var(--red); }
  .chip.flat { background:var(--panel2); color:var(--muted); font-weight:500; }
  .up { color:var(--green-ink, var(--green)); } .down { color:var(--red); } .flat { color:var(--muted); }
  /* page list — a bar you can read at a glance, not a table to parse.
     Zero-chat pages keep their warning (that IS the actionable fact here), but
     as an amber label on a muted bar — the shipped version painted every bar
     red, which made a healthy dashboard read as an incident. */
  .pagerow { display:grid; grid-template-columns:1fr auto; gap:4px 12px; padding:9px 0;
             border-bottom:1px solid var(--hairline); font-size:13.5px; }
  .pagerow:last-child { border-bottom:none; }
  .pagerow .p { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .pagerow .n { color:var(--muted); font-variant-numeric:tabular-nums; font-size:12.5px; }
  .pagerow .bar { grid-column:1 / -1; height:5px; border-radius:3px; background:var(--panel2); overflow:hidden; }
  .pagerow .bar i { display:block; height:100%; border-radius:3px;
                    background:linear-gradient(90deg, var(--accent), var(--accent2)); }
  .pagerow .bar i.zero { background:var(--panel3); }
  .chatyes { color:var(--green-ink, var(--green)); } .chatno { color:var(--amber); }

  /* ── business profile form ── */
  .agentform { max-width:820px; }
  .pcard { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg);
           padding:16px 18px 18px; margin-bottom:14px; }
  .pcard h3 { margin:0 0 4px; font-size:11px; font-weight:700; letter-spacing:.08em;
              text-transform:uppercase; color:var(--accent2); }
  .pcard label, .seglabel { display:block; font-weight:600; margin:14px 0 2px; font-size:13.5px; }
  .pcard h3 + label { margin-top:10px; }
  /* Global, NOT scoped to .agentform: the Greeting tab's help copy fell outside
     that scope and rendered at the 16px browser default — explanatory text
     LARGER than the headings above it (seen live). */
  .fieldhelp { margin:0 0 6px; color:var(--muted); font-size:12.5px; line-height:1.5; }
  .pcard > p:not([class]) { margin:0 0 6px; color:var(--muted); font-size:12.5px; line-height:1.5; }
  .agentform textarea, .agentform input[type=text], .agentform input[type=email],
  .agentform input[type=password], .agentform input[type=number] {
    width:100%; background:var(--panel2); border:1px solid var(--border); color:var(--text);
    border-radius:8px; padding:10px; font:inherit; font-size:13.5px; line-height:1.5; }
  .agentform textarea { resize:vertical; }
  .agentform textarea:focus, .agentform input[type=text]:focus, .agentform input[type=email]:focus,
  .agentform input[type=password]:focus, .agentform input[type=number]:focus {
    outline:none; border-color:var(--accent); }
  .seg { display:flex; flex-wrap:wrap; gap:6px; margin:4px 0 6px; }
  .seg button { background:var(--panel2); border:1px solid var(--border); color:var(--muted);
                padding:7px 14px; border-radius:8px; cursor:pointer; font-size:13.5px; }
  .seg button.on { background:var(--accent); border-color:var(--accent); color:#fff; font-weight:600; }
  .seg button:hover:not(.on) { color:var(--text); border-color:var(--accent); }
  #pricingNoteWrap.inert { opacity:.45; }
  #pricingNoteWrap.inert textarea { pointer-events:none; }
  /* Collapsible (#86). Closed is the default: twenty answers used to be a
     scroll marathon, and the question alone is what an operator scans for. */
  /* F1: questions the chat couldn't answer. One row per question, the count
     up front — the owner's job here is ten seconds per row, so every control
     sits on the row and the editor opens in place. */
  .gaprow { padding:12px 0; border-top:1px solid var(--border); }
  .gaprow:first-child { border-top:none; padding-top:4px; }
  .gaphead { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; font-size:13.5px; }
  .gaphead .gapn { flex:none; font-size:11px; font-weight:700; padding:2px 8px; border-radius:999px;
                   background:var(--accent-soft); color:var(--accent2); }
  .gaphead .dim { font-size:11px; }
  .gapreply { margin:4px 0 0; font-size:12.5px; color:var(--muted); line-height:1.5; }
  .gapact { display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-top:8px; }
  .gapact button { padding:7px 12px; font-size:12.5px; }
  .gaped { margin-top:10px; padding:10px; background:var(--panel2); border:1px solid var(--border);
           border-radius:10px; }
  .gaped input, .gaped textarea { width:100%; background:var(--bg); }
  .gaped textarea { min-height:84px; margin-top:6px; }
  .gapnote { margin-top:6px; font-size:12.5px; color:var(--muted); line-height:1.5; }
  .gapnote.warn { color:var(--amber, #d97706); }
  .gaphead .gapn.ready { background:rgba(52,211,153,.14); color:var(--green-ink, var(--green)); }
  .segpills { display:flex; gap:6px; margin:6px 0 10px; }
  /* Batch 1: the alert-choices grid. Native checkboxes in a small table — the
     page's own table style, accent-coloured boxes, 44px rows for the trackpad. */
  .prefgrid { width:100%; border-collapse:collapse; margin:8px 0 4px; font-size:13.5px; }
  .prefgrid th { text-align:left; font-weight:600; font-size:11px; color:var(--muted);
                 text-transform:uppercase; letter-spacing:.06em; padding:6px 8px; }
  .prefgrid th:not(:first-child), .prefgrid td:not(:first-child) { text-align:center; width:96px; }
  .prefgrid td { padding:0 8px; height:44px; border-top:1px solid var(--hairline, var(--border)); }
  .prefgrid input[type=checkbox] { width:18px; height:18px; accent-color:var(--accent); cursor:pointer; }
  .prefgrid .grp td { height:auto; padding:12px 8px 4px; border-top:none; font-weight:700; font-size:12.5px;
                      color:var(--muted); text-transform:uppercase; letter-spacing:.06em; }
  .prefrow { display:grid; grid-template-columns:1fr auto; gap:8px 12px; align-items:center; margin-top:10px; }
  .prefrow label { margin:0; font-size:13.5px; }
  .prefrow input[type=time] { width:110px; }
  .prefrow .two { display:flex; gap:8px; align-items:center; }
  /* Batch 3: feature cards. A code row and a report block reuse the page's own
     hairlines and mono; the report is the exact text the owner gets by email. */
  .coderow { display:flex; align-items:center; gap:10px; padding:9px 0; border-top:1px solid var(--hairline, var(--border)); font-size:13.5px; }
  .coderow:first-child { border-top:none; }
  .coderow code { font-size:12.5px; background:var(--panel2); border:1px solid var(--border); border-radius:6px; padding:2px 7px; }
  .coderow .offer { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .coderow.off .offer, .coderow.off code { opacity:.55; text-decoration:line-through; }
  .coderow .fx { background:none; border:none; color:var(--muted); cursor:pointer; font-size:12.5px; padding:6px 8px; min-height:32px; }
  .coderow .fx:hover { color:var(--text); }
  .reportbox { white-space:pre-wrap; font:12.5px/1.6 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
               background:var(--panel2); border:1px solid var(--border); border-radius:10px; padding:12px 14px; margin-top:8px; }
  .mailslot { margin-top:14px; padding-top:12px; border-top:1px dashed var(--border); }
  .slothead { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:4px; }
  .slotname { font-size:12.5px; font-weight:700; }
  .slotstate { font-size:12.5px; color:var(--muted); }
  .slotstate.ok { color:var(--green-ink, var(--green)); } .slotstate.bad { color:var(--amber); }
  .mailorder { margin-top:12px; }
  .mailorder b { color:var(--text); font-weight:600; }
  .mailprev { border:1px solid var(--border); border-radius:10px; background:var(--panel2); padding:12px 14px; margin-top:10px; font-size:13.5px; line-height:1.55; }
  .mailprev .subj { font-weight:700; margin-bottom:6px; }
  .mailprev .body { white-space:pre-wrap; color:var(--muted); }
  .faqrow { margin-bottom:8px; padding:8px 10px; background:var(--panel2);
            border:1px solid var(--border); border-radius:8px; }
  .faqhead { display:flex; align-items:center; gap:8px; }
  /* 22px and 16px controls in a dense row (checklist, 2026-09-04): a desktop minimum. */
  .faqhead .fchip, .faqhead .fx { min-height:28px; }
  .faqhead .fx { min-width:28px; }
  .faqrow input, .faqrow textarea { background:var(--bg); }
  .faqrow input { flex:1; min-width:0; }
  .faqrow .fchip { flex:none; background:none; border:1px solid var(--edge, #ddd); border-radius:999px;
    color:var(--muted); cursor:pointer; font-size:12.5px; padding:3px 9px; line-height:1.2; white-space:nowrap; }
  .faqrow .fchip.on { color:var(--accent, #7c3aed); border-color:var(--accent, #7c3aed); font-weight:600; }
  .faqrow .flang { flex:none; font-size:12.5px; padding:3px 4px; border:1px solid var(--edge, #ddd);
    border-radius:6px; background:none; color:var(--muted); }
  .faqrow .fx { flex:none; background:none; border:none; color:var(--muted);
                font-size:16px; cursor:pointer; padding:0 2px; line-height:1; }
  .faqrow .fx:hover { color:var(--red); }
  .faqtog { flex:none; background:none; border:none; color:var(--muted); cursor:pointer;
            padding:0 2px; line-height:1; font-size:16px; }
  .faqtog .chev { display:inline-block; transition:transform .15s ease; }
  .faqrow.open .faqtog .chev { transform:rotate(90deg); }
  .faqtog:hover { color:var(--accent2); }
  /* The closed row still says what the answer IS — one line, clickable. */
  .faqpeek { font-size:12.5px; color:var(--muted); margin:5px 0 0 26px; cursor:pointer;
             overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .faqpeek:hover { color:var(--text); }
  .faqrow textarea { display:none; width:100%; margin-top:7px; }
  .faqrow.open textarea { display:block; }
  .faqempty { color:var(--muted); font-size:12.5px; padding:6px 0; }
  /* UX13: a closed saved answer is one button; the editors show on the open row only */
  .faqsum { display:flex; align-items:center; gap:8px; width:100%; min-height:40px; padding:4px 6px; background:none; border:0;
    border-radius:8px; color:var(--text); font:inherit; text-align:left; cursor:pointer; box-shadow:none; }
  .faqsum:hover, .faqsum:focus-visible { background:var(--accent-soft); }
  .faqsum .chev { display:inline-block; color:var(--muted); }
  .faqsum .fq { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:500; }
  .faqrow.off .faqsum .fq { color:var(--muted); }
  .fbadge { flex:none; font-size:12.5px; color:var(--muted); border:1px solid var(--border2); border-radius:999px; padding:1px 7px; }
  .fbadge.on { color:var(--accent, #7c3aed); border-color:var(--accent, #7c3aed); }
  .faqadd { margin-top:2px; min-height:28px; padding:4px 10px; }
  /* Reorder arrows were 22x18 with no pointer, and `.up` collided with the trend-mark
     rule (green arrows). Scoped, sized, quiet (checklist, 2026-09-05). */
  .grule .ord .up, .grule .ord .dn { min-width:28px; min-height:28px; cursor:pointer;
                                     color:var(--muted); font-size:12.5px; }
  .grule .ord .up:hover, .grule .ord .dn:hover { color:var(--accent2); }
  .grule .ord button:disabled { opacity:.4; cursor:default; }
  /* On/Off per answer (activity 2345). Green pill = the chat uses it; grey = saved, unused. */
  .faqrow .fon { flex:none; min-height:28px; min-width:44px; background:none; border:1px solid var(--green);
    border-radius:999px; color:var(--green-ink, var(--green)); cursor:pointer; font:inherit; font-size:11px; font-weight:700;
    padding:3px 9px; line-height:1.2; }
  .faqrow .fon.off { border-color:var(--border2); color:var(--muted); }
  .faqrow.off { border-style:dashed; }
  .faqrow.off .faqhead input, .faqrow.off .faqpeek, .faqrow.off textarea { opacity:.55; }
  .anspoint .fieldhelp { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
  .faqbar { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:4px; }

  /* ── Scenarios ──
     A saved scenario reads as a RULE, not a form: name, when it fires, what it
     does. The editor only opens when you are editing one — a permanently-open
     form of empty chip inputs is how this card would read as homework. */
  .scnrow { display:flex; align-items:flex-start; gap:11px; padding:11px 0;
            border-bottom:1px solid var(--border); }
  .scnrow:last-of-type { border-bottom:none; }
  .scnmain { flex:1; min-width:0; }
  .scnname { font-weight:650; font-size:13.5px; }
  .scnname .off { color:var(--muted); font-weight:500; font-size:11px;
                  border:1px solid var(--border); border-radius:999px;
                  padding:1px 7px; margin-left:7px; vertical-align:1px; }
  .scnwhen { color:var(--muted); font-size:12.5px; margin-top:3px; line-height:1.5; }
  /* Department voice (#109) */
  .dpv { margin-top:6px; }
  .dpv summary { cursor:pointer; font-size:12.5px; color:var(--accent2); font-weight:600;
                 list-style:none; }
  .dpv summary::before { content:'\25B8  '; }
  .dpv[open] summary::before { content:'\25BE  '; }
  .dpv textarea { display:block; width:100%; margin:8px 0 6px; font:inherit; font-size:13.5px;
                  padding:9px 11px; border:1px solid var(--border); border-radius:8px;
                  background:var(--bg); color:var(--text); resize:vertical; min-height:64px; }
  .dpv textarea:focus { outline:none; border-color:var(--accent); }
  .dpv .dim { font-size:11px; margin-bottom:8px; }
  .dpv button { min-height:34px; padding:0 14px; }
  .dpv [data-dpvmsg] { margin-left:10px; }
  .scnwhen b { color:var(--text); font-weight:600; }
  .scnacts { display:flex; gap:6px; flex:none; }
  .scnacts button { background:var(--panel2); border:1px solid var(--border);
                    color:var(--muted); font:inherit; font-size:12.5px; font-weight:500;
                    padding:5px 11px; border-radius:999px; cursor:pointer; }
  .scnacts button:hover { border-color:var(--accent); color:var(--accent2); }
  .scned { background:var(--panel2); border:1px solid var(--border); border-radius:12px;
           padding:14px; margin-top:12px; }
  .scned label { display:block; font-size:12.5px; font-weight:600; margin:12px 0 3px; }
  .scned label:first-of-type { margin-top:0; }
  .scned input[type=text] { width:100%; }
  /* Chip input: the phrases are the data, the text box is just the way in. */
  .chipbox { display:flex; flex-wrap:wrap; gap:6px; align-items:center;
             background:var(--bg); border:1px solid var(--border); border-radius:10px;
             padding:7px 8px; min-height:40px; }
  .chipbox:focus-within { border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .chipbox input { flex:1; min-width:130px; background:none; border:none; color:var(--text);
                   font:inherit; font-size:13.5px; padding:3px 2px; }
  .chipbox input:focus { outline:none; }
  .chip { display:inline-flex; align-items:center; gap:6px; background:var(--accent-soft);
          color:var(--accent2); border:1px solid rgba(124,58,237,.35); border-radius:999px;
          font-size:12.5px; padding:3px 5px 3px 11px; }
  .chip.neg { background:rgba(248,113,113,.1); color:var(--red);
              border-color:rgba(248,113,113,.35); }
  .chip button { background:none; border:none; color:inherit; cursor:pointer;
                 font-size:13.5px; line-height:1; padding:0 4px; opacity:.7; }
  .chip button:hover { opacity:1; }
  /* The live count is the whole point of the minimum — it must move as you type,
     not appear as a 400 after you press Save. */
  .chipcount { font-size:11px; color:var(--muted); margin-top:4px; }
  .chipcount.bad { color:var(--red); font-weight:600; }
  .stepline { display:flex; gap:8px; align-items:flex-start; margin-bottom:7px; }
  .stepnum { flex:none; width:22px; height:22px; border-radius:50%; margin-top:7px;
             background:var(--accent-soft); color:var(--accent2); font-size:11px;
             font-weight:700; display:grid; place-items:center; }
  .stepline input { flex:1; }
  .stepline .fx { flex:none; background:none; border:none; color:var(--muted);
                  font-size:16px; cursor:pointer; padding:6px 4px; }
  .stepline .fx:hover { color:var(--red); }
  /* Destructive, and deliberately not styled like the helpful buttons above it. */
  .teamtbl { width:100%; border-collapse:collapse; font-size:13.5px; }
  .teamtbl th { text-align:left; font-size:11px; text-transform:uppercase;
                letter-spacing:.06em; color:var(--muted); font-weight:700;
                padding:0 0 8px; border-bottom:1px solid var(--border); }
  .teamtbl th.num, .teamtbl td.num { text-align:right; font-variant-numeric:tabular-nums; }
  .teamtbl td { padding:10px 0; border-bottom:1px solid var(--border); }
  .teamtbl tr:last-child td { border-bottom:none; }
  .teamtbl .sub { display:block; font-size:11px; color:var(--muted); }
  /* Queue picker in the thread details. */
  .deptsel { width:100%; background:var(--panel2); border:1px solid var(--border);
             color:var(--text); font:inherit; font-size:13.5px; padding:8px 10px;
             border-radius:9px; }
  .deptsel:focus { outline:none; border-color:var(--accent); }
  .blockbtn { background:none; border:1px solid rgba(248,113,113,.4); color:var(--red);
              font:inherit; font-size:12.5px; font-weight:600; padding:7px 14px;
              border-radius:999px; cursor:pointer; }
  .blockbtn:hover:not(:disabled) { background:rgba(248,113,113,.1); }
  .blockbtn:disabled { opacity:.55; cursor:default; border-color:var(--border);
                       color:var(--muted); }
  .savebar { position:sticky; bottom:0; display:flex; align-items:center; gap:10px;
             background:var(--bg); border-top:1px solid var(--border);
             padding:12px 2px; margin-top:4px; }
  /* A sticky bar necessarily overlays whatever scrolls beneath it. Two softeners
     (audit finding: the BEHAVIOR tone row was cut mid-scroll, which read as
     clipped, not "behind"): translucency + blur make occluded content legible
     as passing UNDER a surface, and scroll-padding on the container keeps
     focus/tab navigation from ever parking a control beneath the bar. */
  @supports (backdrop-filter: blur(10px)) {
    .savebar { background:color-mix(in srgb, var(--bg) 78%, transparent);
               backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px); }
  }
  /* Primary/ghost pair, styled GLOBALLY: the Greeting save bar sat outside
     .agentform and shipped as white browser-default buttons (seen live). */
  .agentform button, .savebar button { background:var(--accent); border:none; color:#fff;
                      padding:9px 18px; border-radius:var(--r-sm); cursor:pointer;
                      font:inherit; font-size:13.5px; font-weight:600; }
  .agentform button:hover:not(.ghost), .savebar button:hover:not(.ghost) { background:#6d28d9; }
  .agentform button.ghost, .savebar button.ghost { background:var(--panel2);
                            border:1px solid var(--border); color:var(--muted); font-weight:500; }
  .agentform button.ghost:hover, .savebar button.ghost:hover { color:var(--text); border-color:var(--border2); }
  /* Segments must NOT inherit the primary-button purple: `.agentform button`
     ties them on specificity and later source order was winning — every
     pricing/tone segment rendered as an active primary (seen live). */
  .seg button:not(.on) { background:var(--panel2); border:1px solid var(--border);
                         color:var(--muted); font-weight:500; }
  .seg button:not(.on):hover { color:var(--text); border-color:var(--accent); }
  /* Ghost styling for ghosts OUTSIDE .agentform/.savebar — "Start over" in the
     Try-it panel shipped as a white browser-default button (seen live). */
  button.ghost { background:var(--panel2); border:1px solid var(--border);
                 color:var(--muted); font-weight:500; cursor:pointer; border-radius:var(--r-sm); }
  button.ghost:hover { color:var(--text); border-color:var(--border2); }
  .treply textarea { flex:1; background:var(--panel2); border:1px solid var(--border); color:var(--text);
                     border-radius:10px; padding:9px 12px; font:inherit; font-size:13.5px; resize:none; }
  .treply textarea:focus { outline:none; border-color:var(--accent);
                           box-shadow:0 0 0 3px var(--accent-soft); }
  /* #99: Draft is the QUIET button — Send stays the only loud one in the row.
     A first draft is an assist, not the action, and two solid-accent buttons
     side by side would make "which one talks to the customer" a guess.
     Product joined the row (#116b) with the generic solid style and broke this
     exact rule — the operator's 2026-08-28 screenshot shows two loud purple
     buttons flanking a quiet one. Product is an assist too: quiet pair. */
  .treply #replyDraft, .treply #prodBtn {
                        background:var(--panel2); border:1px solid var(--border);
                        color:var(--accent2); font-weight:600; }
  .treply #replyDraft:hover, .treply #prodBtn:hover {
                        border-color:var(--accent); background:var(--panel2); }
  .treply #replyDraft:disabled { opacity:.6; cursor:default; }
  #draftNote { margin:0 12px 0; }
  /* #100: the setup key and recovery codes. Mono and grouped because both get
     TYPED — the key into an authenticator, a recovery code into a login box,
     possibly read aloud down a phone. */
  .mfakey { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
            font-size:16px; letter-spacing:.12em; background:var(--panel2);
            border:1px solid var(--border); border-radius:8px; padding:10px 12px;
            display:inline-block; user-select:all; }
  .mfacodes { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
              gap:6px 14px; margin:10px 0;
              font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
              font-size:13.5px; letter-spacing:.06em; }
  .mfacodes code { background:var(--panel2); border:1px solid var(--border);
                   border-radius:6px; padding:6px 10px; user-select:all; }
  /* The save-confirmation row gates the Done button: these codes are shown
     exactly once and the design's job is to make walking away feel wrong. */
  .mfasave { display:flex; align-items:center; gap:8px; margin:10px 0 4px;
             font-size:13.5px; color:var(--text); }
  .mfasave input { width:18px; height:18px; accent-color:var(--accent); }
  #mfaCard input[type="text"] { font-size:16px; letter-spacing:.15em;
                                max-width:200px; }
  /* #97: the drop-zone reads as a PLACE, not a button — dashed border is the
     one visual idiom everybody already knows means "put a file here". */
  #kbDrop { border:1.5px dashed var(--border); border-radius:10px; padding:12px 14px;
            margin:0 0 10px; font-size:13.5px; color:var(--muted); min-height:44px;
            display:flex; align-items:center; gap:4px; flex-wrap:wrap; cursor:default; }
  #kbDrop b { color:var(--text); }
  #kbDrop.over { border-color:var(--accent); background:var(--accent-soft); }
  #kbDrop:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  .kbpick { color:var(--accent2); font-weight:600; cursor:pointer; text-decoration:underline; }
  /* #98: one claim per row — the pill says what KIND of promise their site is
     making, the text is the site's own sentence, the link is the receipt. */
  .watchrow { display:flex; align-items:baseline; gap:10px; padding:9px 0;
              border-bottom:1px solid var(--border); font-size:13.5px; }
  .watchrow:last-child { border-bottom:none; }
  .watchrow .pill { flex:none; text-transform:none; }
  .watchrow .wtext { flex:1; color:var(--text); }
  .watchrow .wsrc { flex:none; color:var(--accent2); font-size:12.5px;
                    text-decoration:none; white-space:nowrap; }
  .watchrow .wsrc:hover { text-decoration:underline; }
  /* #96: a fact about the thread, not an alarm — dim, small, above the box. */
  .langnote { margin:0 12px; padding:6px 2px 0; font-size:12.5px; color:var(--muted); }
  /* UX14: the translation under a visitor line, the "Sent as" under a reply, the switch in the language note */
  .m .mtr { font-size:12.5px; color:var(--muted); margin-top:4px; border-left:2px solid var(--border2); padding-left:8px; }
  .langnote .linkbtn { background:none; border:0; color:var(--accent2); cursor:pointer; font:inherit; padding:0 2px; text-decoration:underline; min-height:0; box-shadow:none; }
  /* Settings IA: ten cards had accreted into one undifferentiated stack. The
     groups answer WHEN you need a thing, and each carries its own reason — a
     bare divider just moves the guessing up a level. Same visual language as
     the sidebar's .navsec so the page reads as part of the same product. */
  .setsec { font-size:11px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
            color:var(--muted); margin:26px 0 -2px; padding:0 2px; }
  .setsec:first-child { margin-top:4px; }
  /* #91: the visitor's verdict. Green/amber rather than green/red — a thumbs
     down is a signal to read the thread, not an incident. */
  /* UX9 (batch 27): one pill scheme - the green / amber token inks every other pill uses, no bespoke hex */
  .pill.rateup { background:rgba(52,211,153,.13); color:var(--green-ink, var(--green)); border-color:rgba(52,211,153,.32); }
  .pill.ratedown { background:rgba(251,191,36,.14); color:var(--amber-ink, var(--amber)); border-color:rgba(251,191,36,.35); }
  :root[data-theme="dark"] .pill.rateup { color:#34d399; }
  :root[data-theme="dark"] .pill.ratedown { color:#fbbf24; }
  /* Tickets (#108): open = blue (an obligation), waiting = amber (their move),
     closed = plain (renders only inside the thread panel, never on rows). */
  .pill.tk-open { background:rgba(59,130,246,.13); color:#1d4ed8; border-color:rgba(59,130,246,.32); }
  .pill.tk-waiting { background:rgba(251,191,36,.16); color:#b45309; border-color:rgba(251,191,36,.35); }
  .pill.tk-closed { background:var(--panel2); color:var(--muted); border-color:var(--border); }
  :root[data-theme="dark"] .pill.tk-open { color:#60a5fa; }
  :root[data-theme="dark"] .pill.tk-waiting { color:#fbbf24; }
  /* Incoming call (#110). The only element in the inbox with a countdown, so
     it is allowed to be louder than everything else — but it is a band, not a
     modal: the operator must still be able to read the transcript while it
     rings, because "what did they ask?" is what they need before picking up. */
  .callbar { display:flex; align-items:center; gap:12px; flex-wrap:wrap;
             padding:12px 16px; border-radius:12px; margin:0 0 10px;
             background:rgba(16,185,129,.12); border:1px solid rgba(16,185,129,.4); }
  .callbar.ringing { animation:callpulse 1.5s ease-in-out infinite; }
  @keyframes callpulse { 0%,100% { border-color:rgba(16,185,129,.4); }
                         50% { border-color:rgba(16,185,129,.95); } }
  @media (prefers-reduced-motion: reduce) { .callbar.ringing { animation:none; } }
  .callbar b { font-size:13.5px; }
  .callbar .grow { flex:1; min-width:120px; }
  .callbar button { min-height:40px; padding:0 18px; border-radius:999px; border:none;
                    font:inherit; font-weight:650; font-size:13.5px; cursor:pointer; }
  .callbar .ans { background:#059669; color:#fff; }
  .callbar .dec { background:var(--panel2); color:var(--text); border:1px solid var(--border); }
  .callbar .end { background:#dc2626; color:#fff; }
  .callbar .dim { font-size:12.5px; }
  .pill.ring { background:rgba(52,211,153,.13); color:var(--green-ink, var(--green));
               border-color:rgba(16,185,129,.45); }
  :root[data-theme="dark"] .pill.ring { color:#34d399; }
  .tkrow { display:flex; align-items:center; gap:8px; margin-bottom:4px; }
  .tkrow b { font-size:13.5px; }
  .tkacts { margin-top:6px; display:flex; gap:14px; flex-wrap:wrap; }
  .setsec span { display:block; text-transform:none; letter-spacing:0; font-size:12.5px;
                 font-weight:500; color:var(--muted); margin-top:3px; }
  /* Fixed height + bottom-aligned: the buttons used to stretch to the full
     two-row composer height, which made three tall slabs dominate the row the
     operator types in. Anchoring them to the baseline of the text entry is the
     messenger pattern every operator already knows. */
  .treply button { background:var(--accent); border:none; color:#fff; padding:0 18px;
                   border-radius:10px; font-weight:600; cursor:pointer;
                   height:42px; flex:none; align-self:flex-end; }
  /* brightness, not a second hex: the old hover was #6d28d9, which IS the
     light theme's resting accent — hovering Send in light mode changed
     nothing. A filter reads in both themes. */
  .treply button:hover { filter:brightness(1.12); }
  .treply #replySend { min-width:88px; box-shadow:0 1px 3px rgba(0,0,0,.22); }
  .treply #replySend:active { transform:translateY(1px); }
  /* Saved-reply picker. Anchored ABOVE the composer: it must never cover the
     line the operator is typing, and on a short thread there is no room below. */
  .treply { position:relative; }
  .cannedpick { position:absolute; left:12px; right:12px; bottom:calc(100% - 6px);
                background:var(--panel); border:1px solid var(--border2);
                border-radius:10px; box-shadow:0 -8px 28px rgba(0,0,0,.24);
                max-height:250px; overflow-y:auto; z-index:5; padding:5px; }
  .cnrow { display:block; width:100%; text-align:left; background:none; border:none;
           color:var(--text); padding:8px 10px; border-radius:7px; cursor:pointer;
           font:inherit; }
  .cnrow:hover, .cnrow.on { background:var(--accent-soft); }
  .cnrow .cnsc { font-weight:700; font-size:12.5px; color:var(--accent2);
                 font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
  .cnrow .cnbody { display:block; font-size:12.5px; color:var(--muted); line-height:1.45;
                   margin-top:2px; overflow:hidden; text-overflow:ellipsis;
                   display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
  .cnempty { padding:9px 10px; font-size:12.5px; color:var(--muted); }
  .cnempty b { color:var(--text); }
  /* #116b: product picker — the saved-replies panel's sibling, anchored the
     same way for the same reason (never cover the line being typed). */
  .prodpick { position:absolute; left:12px; right:12px; bottom:calc(100% - 6px);
              background:var(--panel); border:1px solid var(--border2);
              border-radius:10px; box-shadow:0 -8px 28px rgba(0,0,0,.24);
              z-index:6; padding:8px; display:flex; flex-direction:column; gap:7px; }
  .prodpick input { background:var(--panel2); border:1px solid var(--border2);
                    border-radius:8px; color:var(--text); font:inherit;
                    font-size:13.5px; padding:7px 10px; width:100%; }
  #prodResults { max-height:230px; overflow-y:auto; display:flex;
                 flex-direction:column; gap:2px; }
  /* A row is scanned, not read: image · name+price · stock. */
  .prow { display:flex; align-items:center; gap:10px; width:100%; text-align:left;
          background:none; border:none; color:var(--text); padding:6px 8px;
          border-radius:8px; cursor:pointer; font:inherit; }
  .prow:hover { background:var(--accent-soft); }
  .prow.on { background:var(--accent-soft); outline:1px solid var(--accent2); }
  /* PICK (ux49): the rows are <button>s inside .treply, so the Send rule above (.treply button) painted them solid
     accent with white text. Their own look again, at a specificity that beats it; hover / selected unchanged. */
  .treply button.cnrow, .treply button.prow { background:none; color:var(--text); height:auto; font-weight:inherit;
                                              align-self:auto; flex:none; box-shadow:none; }
  .treply button.cnrow { padding:8px 10px; border-radius:7px; }
  .treply button.prow { padding:6px 8px; border-radius:8px; }
  .treply button.cnrow:hover, .treply button.cnrow.on,
  .treply button.prow:hover, .treply button.prow.on { background:var(--accent-soft); filter:none; }
  .prow img { width:34px; height:34px; border-radius:6px; object-fit:cover;
              background:var(--panel2); flex:none; }
  .prow .pn { flex:1; min-width:0; }
  .prow .pn b { display:block; font-size:13.5px; font-weight:600;
                white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .prow .pn span { font-size:12.5px; color:var(--muted); }
  .prow .pstock { flex:none; font-size:11px; font-weight:650; }
  .prow .pstock.in { color:var(--green,#34d399); }
  .prow .pstock.out { color:var(--muted); }
  .prodfoot { display:flex; gap:7px; }
  .prodfoot input { flex:1; }
  #prodSend { background:var(--accent); color:#fff; border:none; border-radius:8px;
              font:inherit; font-size:13.5px; font-weight:650; padding:7px 14px;
              cursor:pointer; flex:none; }
  #prodSend:disabled { opacity:.45; cursor:default; }
  #prodMsg { font-size:12.5px; color:var(--muted); min-height:0; }
  #prodMsg.bad { color:#fbbf24; }

  /* ── Inbox ─────────────────────────────────────────────────────────────────
     Three columns: triage rail · conversation list · thread + details.
     The rail deliberately does NOT copy tawk.to's Tickets/Trash/Spam folders —
     we have no ticket model and no soft-delete, so those would be chrome with
     nothing behind them. What replaces them is the filter an operator actually
     needs: "who is waiting on me right now".

     The three panes are ONE bordered surface with internal dividers, not three
     rounded boxes floating in the canvas — contiguous surfaces are what makes
     an inbox read as an application (measured against tawk.to and Intercom,
     both of which do exactly this). */
  .ibx { display:grid; grid-template-columns:190px 340px minmax(0,1fr); gap:0;
         background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg);
         overflow:hidden; }

  .irail { padding:10px 8px; border-right:1px solid var(--border); }
  .irail button { display:flex; width:100%; align-items:center; gap:8px; background:none; border:none;
                  color:var(--muted); font:inherit; font-size:13.5px; text-align:left; cursor:pointer;
                  padding:8px 9px; border-radius:var(--r-sm); white-space:nowrap; }
  .irail button:hover { background:var(--panel2); color:var(--text); }
  .irail button.on { background:var(--accent-soft); color:var(--text); font-weight:600; }
  .irail button:focus-visible { outline:3px solid var(--accent2); outline-offset:1px; }
  /* Waiting-on-us count on the Inbox nav tab; hidden at zero (jump-in flow, 2026-09-04). */
  .navcnt { margin-left:auto; min-width:20px; height:20px; padding:0 6px; border-radius:999px;
            background:var(--accent); color:#fff; font-size:11px; font-weight:700;
            display:inline-grid; place-items:center; font-variant-numeric:tabular-nums; }
  .navcnt[hidden] { display:none; }
  /* 44px: these are the only controls in a table row, and they were 28px (census
     2026-09-08). inline-flex centres the label; the row grows, the width does not. */
  .rowact { background:var(--panel2); border:1px solid var(--border); color:var(--text);
            font:inherit; font-size:12.5px; font-weight:600; padding:0 12px; border-radius:7px;
            cursor:pointer; white-space:nowrap; min-height:44px; display:inline-flex;
            align-items:center; }
  .rowact:hover { border-color:var(--accent); color:var(--accent2); }
  .rowact.go { background:var(--accent); border-color:var(--accent); color:#fff; }
  .rowact.go:hover { background:#6d28d9; color:#fff; }
  .helloform { display:flex; gap:6px; align-items:center; min-width:260px; }
  .helloform input { flex:1; min-width:0; min-height:44px; background:var(--panel2); border:1px solid var(--border);
                     color:var(--text); border-radius:7px; padding:6px 9px; font:inherit; font-size:12.5px; }
  .helloform input:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); }
  .irail .railtog { color:var(--muted); font-size:11px; }
  .irail .cnt { margin-left:auto; font-size:11px; font-variant-numeric:tabular-nums;
                background:var(--panel2); color:var(--muted); border-radius:9px; padding:1px 7px; }
  .irail button.on .cnt { background:var(--accent); color:#fff; }
  .irail .rhead { font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted);
                  padding:8px 9px 6px; }
  /* Navigation, not a filter: it leaves this screen, so it must not dress like
     the filter buttons above it. Accent text, hairline top rule, no count. */
  .irail button.railgo { margin-top:10px; border-top:1px solid var(--border); border-radius:0;
                         padding-top:12px; color:var(--accent2); font-size:12.5px;
                         /* The channel names are the pitch — wrap rather than clip them
                            in the 190px rail (nowrap comes from .irail button above). */
                         white-space:normal; line-height:1.35; }
  .irail button.railgo:hover { background:none; text-decoration:underline; color:var(--text); }

  .isearch { display:flex; gap:8px; padding:10px; border-bottom:1px solid var(--border);
             background:var(--panel); }
  .isearch input, .isearch select { background:var(--panel2); border:1px solid var(--border);
      color:var(--text); border-radius:var(--r-sm); padding:8px 10px; font:inherit; font-size:13.5px; }
  .isearch input { flex:1; min-width:0; }
  .isearch input:focus, .isearch select:focus { outline:none; border-color:var(--accent);
      box-shadow:0 0 0 3px rgba(124,58,237,.25); }

  .conv { position:relative; }
  /* Needs-reply marker. A dot alone would be colour-only information, which
     fails 1.4.1 — the row also carries the word "Waiting" in its status line. */
  .conv.wait { border-left:3px solid var(--amber); }
  .conv .c1 b { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .conv .meta { display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-top:5px; font-size:11px; }
  .conv .dev { color:var(--muted); display:inline-flex; align-items:center; gap:4px; }
  .ico.dvi { width:13px; height:13px; vertical-align:-2px; }
  /* The page they're on — context, not identity, so it reads as a quiet path. */
  .conv .onpage { color:var(--muted); font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
                  font-size:11px; max-width:150px; overflow:hidden; text-overflow:ellipsis;
                  white-space:nowrap; }
  /* Identity line (2026-09-03): the name carries the weight; the handle is a
     quiet mono ID beside it (kept so an alert's "Visitor 071E0A" still finds
     its card); the time keeps its right-hand slot. */
  .conv .c1 .cid { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11px;
                   color:var(--muted); margin-left:6px; margin-right:auto; align-self:center;
                   letter-spacing:.02em; }
  .conv .cgeo { color:var(--muted); font-size:11px; }
  /* "returning" reads as a fact, not an alarm: neutral, not amber. */
  .pill.ret { color:var(--accent2); }
  /* No opacity: at .85 the muted "no message yet" line measured 4.45:1 on a
     plain card and 3.93:1 on the selected (accent-tinted) card — both under
     4.5 (audit 2026-09-03). --muted alone clears it on both backgrounds. */
  .conv .c2 i { font-style:normal; }
  .conv .c2 .hit { color:var(--accent2); font-weight:600; }
  .pill.wait { background:rgba(251,191,36,.14); color:var(--amber-ink, var(--amber)); border-color:rgba(251,191,36,.35); }
  .pill.late { background:rgba(248,113,113,.14); color:var(--red); border-color:rgba(248,113,113,.4); font-weight:700; }  /* UX7: past the reply target */
  .pill.live { background:rgba(52,211,153,.13); color:var(--green-ink, var(--green)); border-color:rgba(52,211,153,.32); }

  /* Thread */
  .tsys { display:flex; align-items:center; gap:8px; margin:12px 0; color:var(--muted); font-size:11px; }
  .tsys::before, .tsys::after { content:""; flex:1; height:1px; background:var(--border); }
  .tsys span { flex:none; }
  /* Navigation reads as movement, not as a system notice: tinted, with the
     chevron pointing the way they went. Still a divider row, so it never
     competes with an actual message for attention. */
  .tnav span { display:inline-flex; align-items:center; gap:6px; color:var(--nav-ink, var(--accent2));
               background:var(--accent-soft); border-radius:999px; padding:3px 11px; }
  .tnav b { color:var(--text); font-weight:650; }
  .tnav svg { width:13px; height:13px; flex:none; fill:none; stroke:currentColor;
              stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round; }
  .tnav::before, .tnav::after { background:var(--hairline); }
  /* Attachments (#92) read like navigation — a thing that happened, not a
     message — but warmer, because unlike a page view it is waiting for a
     person to do something about it. */
  .tup span { display:inline-flex; align-items:center; gap:6px; color:var(--accent2);
              background:var(--accent-soft); border-radius:999px; padding:3px 11px; }
  .tup b { color:var(--text); font-weight:650; }
  .tup svg { width:13px; height:13px; flex:none; fill:currentColor; }
  .tup::before, .tup::after { background:var(--hairline); }
  .linkbtn { background:none; border:0; padding:0 0 0 4px; margin:0; font:inherit;
             color:var(--accent2); font-weight:650; cursor:pointer;
             text-decoration:underline; min-height:0; }
  .linkbtn:hover { color:var(--text); }
  /* The preview is capped rather than natural-size: a 4000px phone photo would
     push the whole transcript off the screen it is supposed to be read in. */
  .upshot:empty { display:none; }
  .upshot { margin:-4px 0 12px; text-align:center; color:var(--muted); font-size:11px; }
  .upshot img { max-width:min(320px, 100%); max-height:320px; border-radius:12px;
                border:1px solid var(--border); }

  /* ── Operator notes ── */
  .ntlist { display:flex; flex-direction:column; gap:8px; margin-bottom:9px; }
  .ntrow { background:var(--panel2); border:1px solid var(--border); border-left:3px solid var(--amber);
           border-radius:0 8px 8px 0; padding:8px 10px; font-size:12.5px; line-height:1.5;
           color:var(--text); position:relative; }
  .ntrow .ntmeta { display:block; margin-top:4px; color:var(--muted); font-size:11px; }
  .ntrow .ntx { position:absolute; top:5px; right:6px; background:none; border:none;
                color:var(--muted); cursor:pointer; font-size:16px; line-height:1; padding:2px 4px; }
  .ntrow .ntx:hover { color:var(--red); }
  .ntadd { display:flex; flex-direction:column; gap:6px; }
  .ntadd textarea { width:100%; background:var(--panel2); border:1px solid var(--border);
                    color:var(--text); border-radius:8px; padding:8px 10px; font:inherit;
                    font-size:12.5px; line-height:1.5; resize:vertical; scrollbar-width:none; }
  .ntadd textarea::-webkit-scrollbar { display:none; }
  .ntadd textarea:focus { outline:none; border-color:var(--accent); }
  .ntadd .ntbar { display:flex; align-items:center; gap:8px; }
  .ntadd button { background:var(--accent); border:none; color:#fff; padding:6px 14px;
                  border-radius:var(--r-sm); font:inherit; font-size:12.5px; font-weight:600;
                  cursor:pointer; }
  .ntadd button:hover:not(:disabled) { background:#6d28d9; }
  .ntadd button:disabled { opacity:.5; cursor:default; }
  .tdate { text-align:center; margin:14px 0 10px; }
  .tdate span { background:var(--panel2); border:1px solid var(--border); color:var(--muted);
                border-radius:999px; padding:3px 12px; font-size:11px; }
  .m .mw { font-size:11px; }

  .thead { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
  .thead .tgrow { flex:1; min-width:0; }
  .thead .twho { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
  .thead .twho b { font-size:13.5px; font-weight:650; letter-spacing:-.01em; }
  .thead .tpage { font-size:12.5px; color:var(--muted); white-space:nowrap; overflow:hidden;
                  text-overflow:ellipsis; margin-top:1px; }
  .thead button { background:var(--panel2); border:1px solid var(--border); color:var(--muted);
                  border-radius:8px; padding:5px 10px; font:inherit; font-size:12.5px; cursor:pointer; }
  .thead button:hover { color:var(--text); border-color:var(--accent); }
  /* UX2: the rare conversation actions under one button (research 2026-10-10: Front, Help Scout, NN/g progressive disclosure) */
  .thead .more { position:relative; }
  .thead .moremenu { position:absolute; right:0; top:calc(100% + 4px); z-index:50; min-width:170px; display:flex; flex-direction:column; gap:2px;
    background:var(--panel); border:1px solid var(--border); border-radius:10px; box-shadow:var(--shadow-menu); padding:4px; }
  .thead .moremenu[hidden] { display:none; }
  /* UX9 (batch 27): the composer "+" and its menu (opens upward: it sits at the bottom of the screen) */
  .treply .more { position:relative; align-self:flex-end; }
  .treply #replyMore { min-width:42px; padding:0 13px; font-size:20px; line-height:1; font-weight:500;
                       background:var(--panel2); color:var(--accent2); border:1px solid var(--border); }
  .treply #replyMore[aria-expanded="true"] { background:var(--accent-soft); border-color:var(--accent); }
  .treply .moremenu { position:absolute; right:0; bottom:calc(100% + 6px); z-index:50; min-width:200px; display:flex; flex-direction:column; gap:2px;
                      background:var(--panel); border:1px solid var(--border); border-radius:10px; padding:5px; box-shadow:0 10px 28px rgba(0,0,0,.18); }
  .treply .moremenu[hidden] { display:none; }
  .treply .moremenu button { background:none; border:0; text-align:left; width:100%; height:auto; padding:9px 11px; border-radius:7px; color:var(--text); font-weight:500; box-shadow:none; }
  .treply .moremenu button:hover, .treply .moremenu button:focus-visible { background:var(--accent-soft); color:var(--accent2); filter:none; }
  /* UX9: 13 sidebar items need no section headings; the groups keep their gap. The agency heading stays (it is a divider). */
  .navsec:not(.navsec-agency) { display:none; }
  .navsec:not(.navsec-agency) + [role=tab] { margin-top:10px; }
  .thead .moremenu button { background:none; border:0; text-align:left; width:100%; padding:7px 10px; border-radius:7px; color:var(--text); }
  .thead .moremenu button:hover { background:var(--accent-soft); color:var(--accent2); }
  .thead #ibxMore[aria-expanded="true"] { border-color:var(--accent); color:var(--text); }
  /* UX2: the reply bar's three buttons had no size rule at all (the browser default, 13.33 px) */
  #prodBtn, #replyDraft, #replySend { font-size:13.5px; }
  .thead button[aria-pressed="true"] { background:var(--accent-soft); border-color:var(--accent); color:var(--accent2); }

  /* Details panel — every field below is real data we already store. Nothing
     here is a placeholder for a schema we do not have. */
  .idetails { border-top:1px solid var(--border); padding:12px 14px; background:var(--panel); }
  .idetails h4 { margin:0 0 8px; font-size:11px; text-transform:uppercase; letter-spacing:.07em;
                 color:var(--muted); font-weight:600; }
  .idl { display:grid; grid-template-columns:104px minmax(0,1fr); gap:6px 12px; font-size:12.5px; }
  .idl dt { color:var(--muted); }
  .idl dd { margin:0; overflow-wrap:anywhere; color:var(--text); }
  .idl dd a { color:var(--accent2); }
  /* Second list in the same section = the thread's own stats (duration,
     messages, status, IP) — separated from the WHERE facts above it by a
     hairline, because "what page did they come from" and "how long has this
     thread run" are different questions the eye should not have to unbraid. */
  .idl + .idl { margin-top:8px; padding-top:8px; border-top:1px solid var(--border); }

  /* Focus indicators. Audited 2026-07-27: nine controls here were keyboard
     reachable with NO visible focus style — including the conversation rows,
     which this pass made tabbable. A focusable row with no indicator is worse
     than a non-focusable one: the keyboard user is somewhere they cannot see
     (WCAG 2.4.7). The property pills and Send button predate this pass and are
     fixed in the same sweep rather than left for a later "accessibility task". */
  .conv:focus-visible, .ppill:focus-visible, .thead button:focus-visible,
  .treply button:focus-visible, .tabs button:focus-visible {
    outline:3px solid var(--accent2); outline-offset:2px; }

  /* ── Greeting tab ──────────────────────────────────────────────────────────
     The hard problem here is that rule order IS the behaviour: matching is
     server-side, path-prefix, FIRST MATCH WINS. A form that renders rules as an
     unordered pile hides the one thing that decides what a visitor sees, so
     order is explicit, reorderable, and rules that can never fire are drawn as
     dead rather than left looking healthy. */
  /* Visible to screen readers, not to sighted users. Used where the visual
     design already labels a control by context but the accessible name would
     otherwise be empty. */
  .visually-hidden { position:absolute; width:1px; height:1px; margin:-1px; padding:0;
                     overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
  .greetgrid { display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:16px; align-items:start; }
  @media (max-width:1000px) { .greetgrid { grid-template-columns:minmax(0,1fr); } }

  /* Master switch. A real checkbox underneath — it must be tabbable, toggle on
     Space, and report checked state to a screen reader. */
  /* label.gswitch, not .gswitch: `.pcard label` is (0,1,1) and this must be too,
     or display:block wins and the whole switch renders as unstyled inline spans
     with the knob painted over the label text — which is exactly how it
     shipped (seen live, diagnosed via getComputedStyle). */
  label.gswitch { display:flex; align-items:center; gap:12px; position:relative;
                  font-weight:400; margin:0; }
  .gswitch input { position:absolute; opacity:0; width:44px; height:26px; margin:0; cursor:pointer;
                   left:0; top:50%; transform:translateY(-50%); }
  .gswitch .track { display:block; width:44px; height:26px; border-radius:13px; background:var(--panel3);
                    border:1px solid var(--border2); position:relative; flex:none; }
  .gswitch .track::after { content:""; position:absolute; top:3px; left:3px; width:18px; height:18px;
                           border-radius:50%; background:var(--muted); }
  @media (prefers-reduced-motion: no-preference) {
    .gswitch .track, .gswitch .track::after { transition:background .18s ease, transform .18s ease; }
  }
  .gswitch input:checked + .track { background:var(--accent); border-color:var(--accent); }
  .gswitch input:checked + .track::after { background:#fff; transform:translateX(18px); }
  .gswitch input:focus-visible + .track { outline:3px solid var(--accent2); outline-offset:2px; }
  .gswitch .lbl { font-weight:600; font-size:13.5px; }
  .gswitch .sub { color:var(--muted); font-size:12.5px; }

  /* When the master switch is off, the rules below are inert. Say so visually
     instead of letting an operator edit rules that cannot fire. */
  .gdisabled { opacity:.45; pointer-events:none; }

  .grule { background:var(--panel2); border:1px solid var(--border); border-radius:10px;
           padding:10px 10px 12px; margin-bottom:10px; display:grid;
           grid-template-columns:28px minmax(0,1fr) auto; gap:8px 10px; align-items:start; }
  .grule .ord { display:flex; flex-direction:column; align-items:center; gap:2px; padding-top:2px; }
  .grule .ord .num { font-size:11px; color:var(--muted); font-variant-numeric:tabular-nums; }
  .grule .ord button { background:none; border:1px solid transparent; color:var(--muted);
                       cursor:pointer; border-radius:5px; width:22px; height:18px; line-height:1;
                       font-size:11px; padding:0; }
  .grule .ord button:hover:not(:disabled) { color:var(--accent2); border-color:var(--border); }
  .grule .ord button:disabled { opacity:.28; cursor:default; }
  .grule .fields { display:grid; gap:6px; min-width:0; }
  .grule .frow { display:grid; grid-template-columns:minmax(0,1fr) 118px; gap:8px; }
  @media (max-width:620px) { .grule .frow { grid-template-columns:minmax(0,1fr); } }
  .grule input[type=text], .grule input[type=number] {
      width:100%; background:var(--bg); border:1px solid var(--border); color:var(--text);
      border-radius:8px; padding:8px 10px; font:inherit; font-size:13.5px; }
  .grule input:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .grule .gx { background:none; border:none; color:var(--muted); cursor:pointer; font-size:16px;
               border-radius:6px; width:26px; height:26px; }
  .grule .gx:hover { color:var(--red); }
  .grule .cnt { font-size:11px; color:var(--muted); text-align:right; font-variant-numeric:tabular-nums; }
  .grule .cnt.over { color:var(--red); font-weight:600; }

  /* The catch-all fires on EVERY page — including on a real prospect mid-purchase.
     It gets its own colour so it can never be mistaken for a scoped rule. */
  .grule.catchall { border-color:var(--amber); background:rgba(245,158,11,.06); }
  .grule.catchall .tagline { color:var(--amber); }
  /* Unreachable: an earlier rule already matches everything this one would. */
  .grule.dead { opacity:.6; border-style:dashed; }
  .grule .tagline { grid-column:2 / -1; font-size:11px; color:var(--muted); margin:0; }
  .grule.dead .tagline { color:var(--red); }

  /* ── Business Profile: "Try it" preview ────────────────────────────────────
     Sits beside the editor because the question it answers is "did my edit
     work?" — and that question is worthless once you have already saved and
     shipped the edit to real traffic. */
  .agentgrid { display:grid; grid-template-columns:minmax(0,1fr) 340px; gap:16px; align-items:start; }
  @media (max-width:1100px) { .agentgrid { grid-template-columns:minmax(0,1fr); } }
  .pvwrap { background:var(--panel); border:1px solid var(--border); border-radius:12px;
            padding:14px; position:sticky; top:14px; display:flex; flex-direction:column; gap:10px; }
  .pvhead { display:flex; align-items:center; gap:10px; }
  .pvhead h3 { margin:0; font-size:13.5px; color:var(--accent2); flex:1; }
  .pvhead button { padding:5px 10px; font-size:12.5px; border-radius:7px; }
  .pvdraft { display:flex; align-items:flex-start; gap:8px; font-size:12.5px; cursor:pointer; }
  .pvdraft input { margin-top:2px; }
  .pvdraft .dim { display:block; font-size:11px; color:var(--muted); }
  .pvlist { min-height:150px; max-height:44vh; overflow-y:auto; overscroll-behavior:contain;
            display:flex; flex-direction:column; gap:8px; padding:4px 2px; }
  /* Beside the editor, the panel fills the viewport column instead of floating
     as a 349px island over ~2000px of empty rail (audit finding 2 — the same
     shape the Inbox had before its full-height pass). The transcript takes the
     slack, which is also just better: a test conversation longer than three
     turns no longer lives in a letterbox. Stacked (≤1100px) it stays compact. */
  @media (min-width:1101px) {
    .pvwrap { height:calc(100vh - 28px); max-height:calc(100vh - 28px); }
    .pvwrap .pvlist { flex:1; min-height:0; max-height:none; }
  }
  .pvmsg { max-width:88%; padding:8px 11px; border-radius:12px; font-size:13.5px; line-height:1.5;
           white-space:pre-wrap; word-wrap:break-word; }
  .pvmsg.you { align-self:flex-end; background:var(--accent); color:#fff; border-bottom-right-radius:4px; }
  .pvmsg.bot { align-self:flex-start; background:var(--panel2); border:1px solid var(--border);
               border-bottom-left-radius:4px; }
  .pvmsg.err { align-self:center; background:rgba(248,113,113,.12); border:1px solid rgba(248,113,113,.4);
               color:var(--red); font-size:12.5px; text-align:center; }
  /* Empty state (audit finding 3: helper text floating over a blank band read
     as a broken panel). Modeled on the FREQUENTLY ASKED empty state: say what
     the space is for, then hand the operator a first move. The three starter
     questions are not filler — they are the product's three genuinely dangerous
     behaviours (invented prices, wrong-hours promises, human handoff), i.e. the
     exact answers an operator should read BEFORE a visitor does. */
  .pvempty { flex:1; display:flex; flex-direction:column; align-items:center;
             justify-content:center; gap:5px; color:var(--muted); font-size:12.5px;
             text-align:center; padding:22px 8px; line-height:1.6; }
  .pveico { width:38px; height:38px; border-radius:12px; display:grid; place-items:center;
            background:rgba(124,58,237,.12); color:var(--accent2); margin-bottom:3px; }
  .pveico svg { width:19px; height:19px; }
  .pveh { font-size:13.5px; font-weight:650; color:var(--text); }
  .pves { max-width:240px; font-size:12.5px; }
  .pvchips { display:flex; flex-direction:column; gap:7px; margin-top:11px;
             width:100%; max-width:250px; }
  .pvchip { background:var(--panel2); border:1px solid var(--border); color:var(--text);
            font:inherit; font-size:12.5px; padding:8px 13px; border-radius:999px;
            cursor:pointer; transition:border-color .12s, color .12s; }
  .pvchip:hover { border-color:var(--accent); color:var(--accent2); }
  .pvchip:focus-visible { outline:3px solid var(--accent2); outline-offset:2px; }
  .pvrow { display:flex; gap:8px; align-items:flex-end; }
  .pvrow textarea { flex:1; background:var(--bg); border:1px solid var(--border); color:var(--text);
                    border-radius:10px; padding:8px 10px; font:inherit; font-size:13.5px; resize:none; }
  .pvrow textarea:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .pvrow button { background:var(--accent); border:none; color:#fff; padding:9px 15px; border-radius:9px;
                  font-weight:600; cursor:pointer; }
  .pvrow button:disabled { opacity:.55; cursor:default; }
  .pvnote { margin:0; font-size:11px; color:var(--muted); line-height:1.5; }


  /* ── Full-height panes ─────────────────────────────────────────────────────
     The shell owns the viewport, so each view fills it and scrolls INSIDE its
     own panes. Before this the Inbox was a small box in the corner of a large
     black rectangle: the list had no height and the thread pane had nothing to
     fill, so ~60% of the screen was empty. */
  .viewhead { display:flex; align-items:baseline; gap:10px; margin:0 0 14px; flex-wrap:wrap; }
  .viewhead h2 { margin:0; }

  .ibx { height:calc(100vh - 54px); grid-template-rows:minmax(0,1fr); align-items:stretch; }
  /* Placeholder and thread occupy the SAME grid cell so the column is filled
     whichever one is showing. */
  .ibx > .threadempty, .ibx > .thread { grid-column:3; grid-row:1; border-left:1px solid var(--border); }
  .irail { height:100%; overflow-y:auto; overscroll-behavior:contain; }
  .ibx > div:nth-child(2) { display:flex; flex-direction:column; min-height:0; }
  .convlist { flex:1; min-height:0; overflow-y:auto; overscroll-behavior:contain; }
  .thread { height:100%; display:flex; flex-direction:column; min-height:0; }
  .tmsgs { flex:1; min-height:0; overflow-y:auto; overscroll-behavior:contain; }
  .cprof { max-height:none; flex:none; }

  /* On a wide screen the visitor details belong BESIDE the transcript, not
     stacked under the composer — at 1810px they pushed the reply box up and
     left the profile as a long scroll below it (operator screenshot). Grid
     areas rather than a DOM move: same tree, same census hooks.
     1280, not 1500: the operator's real window measured 1489px — ELEVEN px
     under the old breakpoint — and got the stacked layout this rule exists to
     avoid (second operator screenshot, 2026-08-27). MEASURED, not derived: the
     shell's own left nav eats ~295px before .ibx ever divides the rest, so at
     1489 the thread column is 661px → a 331px transcript beside 330px details.
     Tall-and-narrow reads fine for chat bubbles; what did NOT survive was the
     composer sharing the 331px column with three buttons — the textarea
     measured 58px. So the composer spans BOTH columns instead. */
  @media (min-width:1280px) {
    /* Four rows, not three: #replyErr needs its own or it auto-places into the
       details column. It is display:none until a send fails, so the extra auto
       row collapses to 0 and the resting layout is unchanged. */
    .thread { display:grid; grid-template-columns:minmax(0,1fr) 330px;
              grid-template-rows:auto minmax(0,1fr) auto auto; }
    .thead { grid-column:1 / -1; }
    .tmsgs { grid-column:1; grid-row:2; }
    #replyErr { grid-column:1; grid-row:3; }
    /* Full-width: the reply box is where the operator WORKS; it gets the
       whole thread width, under both the transcript and the details. */
    .treply { grid-column:1 / -1; grid-row:4; }
    .idetails { grid-column:2; grid-row:2 / span 2; border-top:none;
                border-left:1px solid var(--border); overflow-y:auto;
                overscroll-behavior:contain; }
  }

  /* Below the side-by-side breakpoint the details stack UNDER the composer in
     the same flex column — and until 2026-08-27 they had no height limit while
     .tmsgs had min-height:0, so the details always won and the transcript
     always lost: at 1489px the whole conversation was one clipped line behind
     the reply box, and in a half-screen window it was invisible outright
     (operator screenshots — "the UI… can't even read it"). The chat is the
     point of this screen; the details scroll inside themselves instead.
     flex:0 1 auto (not none) so on short viewports they shrink further rather
     than shoving the composer off-screen. */
  @media (max-width:1279.98px) {
    .idetails { flex:0 1 auto; min-height:0; max-height:40vh;
                overflow-y:auto; overscroll-behavior:contain; }
    .tmsgs { min-height:160px; }
  }

  /* A conversation with no messages is common (they opened the bubble and
     left) — say so instead of showing a tall blank panel. */
  .tempty { margin:auto; text-align:center; color:var(--muted); font-size:13.5px;
            line-height:1.6; padding:24px; max-width:320px; }
  .tempty b { display:block; color:var(--text); font-size:13.5px; margin-bottom:4px; }

  /* Between 780 and 1180px the shipped layout collapsed to height:auto — the
     transcript became a 60px sliver with its own scrollbar and the bottom half
     of the screen went black (seen live at 1134px). Instead: the triage rail
     becomes a horizontal strip and the surface keeps FULL height. */
  @media (max-width:1180px) {
    .ibx { grid-template-columns:300px minmax(0,1fr); grid-template-rows:auto minmax(0,1fr); }
    .irail { grid-column:1 / -1; grid-row:1; height:auto; display:flex; gap:2px;
             overflow-x:auto; overflow-y:hidden; border-right:none;
             border-bottom:1px solid var(--border); padding:8px; }
    .irail button { width:auto; flex:none; }
    .irail .rhead { display:none; }
    .ibx > div:nth-child(2) { grid-column:1; grid-row:2; }
    .ibx > .threadempty, .ibx > .thread { grid-column:2; grid-row:2; }
  }
  /* Phones: the surface becomes a scrolling document again — list first, thread
     under it at a workable fixed height. */
  @media (max-width:780px) {
    .ibx { grid-template-columns:minmax(0,1fr); grid-template-rows:auto auto auto; height:auto; }
    .ibx > div:nth-child(2) { grid-column:1; grid-row:2; }
    .ibx > .threadempty, .ibx > .thread { grid-column:1; grid-row:3; border-left:none;
                                          border-top:1px solid var(--border); }
    .convlist { max-height:44vh; }
    .thread { height:70vh; }
    .threadempty { min-height:200px; height:auto; }
  }

  /* (Dashboard layout lives in the explicit grid-areas block above — the
     auto-fit version that used to sit here is what broke at 1730px.) */

  /* Editors read better bounded than stretched to 1600px — but bounded by
     CONTENT width, not by a centred document column. */
  .agentform { max-width:none; }
  .agentgrid { max-width:1320px; }
  /* Eleven groups over ~7,000px. From 1500px the grid takes a third, 220px column for a
     sticky index; the form and the Try-it panel keep their widths (2026-09-05). */
  .agentnav { display:none; }
  @media (min-width:1500px) {
    .agentgrid { grid-template-columns:minmax(0,1fr) 340px 220px; max-width:1572px; }
    .agentnav { display:flex; flex-direction:column; gap:2px; position:sticky; top:14px; }
  }
  .greetgrid { max-width:1320px; }
  /* The third column must never be an empty rectangle. Before this, opening the
     Inbox with nothing selected left most of the viewport as blank black — the
     single biggest reason the console read as broken rather than empty. */
  .threadempty { height:100%; display:flex; flex-direction:column; align-items:center;
                 justify-content:center; gap:8px; text-align:center; padding:30px;
                 background:var(--bg); }
  .threadempty.hidden { display:none !important; }
  .threadempty .temoji { width:52px; height:52px; border-radius:16px; background:var(--panel2);
                         border:1px solid var(--border); color:var(--accent2); margin-bottom:4px;
                         display:flex; align-items:center; justify-content:center; }
  .threadempty .temoji .ico { width:24px; height:24px; }
  .threadempty b { font-size:16px; }
  .threadempty span { color:var(--muted); font-size:13.5px; max-width:290px; line-height:1.55; }
  /* ── Contact profile ───────────────────────────────────────────────────────
     Who this person is, where they came from, and what happened — beside the
     transcript rather than instead of it. Deliberately NOT tawk.to's
     Timeline/Conversations/Notes tab set: we have no notes table, no
     organisations and no custom attributes, and one conversation per visitor per
     property, so those tabs would be four labels over one populated pane. */
  .cprof { border-top:1px solid var(--border); background:var(--panel); padding:14px;
           max-height:52vh; overflow-y:auto; overscroll-behavior:contain; }
  .cphead { display:flex; align-items:center; gap:11px; margin-bottom:12px; }
  .cpav { width:38px; height:38px; border-radius:50%; flex:none; display:flex;
          align-items:center; justify-content:center; font-weight:700; font-size:13.5px;
          background:var(--accent); color:#fff; }
  .cpav.anon { background:var(--panel2); color:var(--muted); border:1px solid var(--border); }
  .cpid { min-width:0; }
  .cpid b { display:block; font-size:13.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .cpid .sub { color:var(--muted); font-size:11px; }
  /* .bklink was written on "Make this a ticket" and "Email transcript…" but
     the rule itself was never authored, so both rendered as NATIVE browser
     buttons — invisible-ish in light mode, a white bevel bar in dark (caught
     in the 2026-08-28 polish pass, dark-mode screenshot). Quiet bordered
     button, same family as the composer's assist pair. */
  .bklink { display:inline-block; background:var(--panel2); color:var(--text);
            border:1px solid var(--border); border-radius:8px; padding:7px 12px;
            font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
  .bklink:hover { border-color:var(--accent); color:var(--accent2); }
  /* A hairline above each section: the panel used to be one continuous wall
     of label/value rows where TICKET, CONTACT and WHERE THEY CAME FROM ran
     together — the rules turn a scroll of facts into scannable groups. */
  .cpsec { margin-top:12px; padding-top:12px; border-top:1px solid var(--border); }
  .cpsum { margin:0; font-size:13.5px; line-height:1.5; color:var(--text); }   /* SUM (batch 55) */
  .cpsec h4 { margin:0 0 7px; font-size:11px; text-transform:uppercase; letter-spacing:.07em;
              color:var(--muted); font-weight:600; }
  .cpcontact { display:flex; flex-direction:column; gap:5px; }
  .cpcontact a { color:var(--accent2); font-size:13.5px; text-decoration:none; word-break:break-all; }
  .cpcontact a:hover { text-decoration:underline; }
  .cpcontact .none { color:var(--muted); font-size:12.5px; }

  /* Journey — the visit, not the transcript. Complementary to the thread on the
     left: that shows what was SAID, this shows what HAPPENED. */
  .cptl { position:relative; padding-left:16px; }
  .cptl::before { content:""; position:absolute; left:4px; top:4px; bottom:4px; width:1px;
                  background:var(--border); }
  .cpev { position:relative; padding:0 0 12px; }
  .cpev::before { content:""; position:absolute; left:-16px; top:4px; width:9px; height:9px;
                  border-radius:50%; background:var(--panel); border:2px solid var(--border); }
  .cpev.key::before { background:var(--accent); border-color:var(--accent); }
  .cpev.win::before { background:var(--green); border-color:var(--green); }
  .cpev .t { font-size:12.5px; }
  .cpev .w { font-size:11px; color:var(--muted); margin-top:1px; }
  .cpday { font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted);
           margin:2px 0 8px; }

  /* Stated limits beat an empty tab that implies a feature exists. */
  .cplimit { margin-top:14px; border-left:3px solid var(--border); padding:8px 11px;
             color:var(--muted); font-size:11px; line-height:1.5; }

  /* ── Business switcher ─────────────────────────────────────────────────────
     The property an operator is working on is GLOBAL CONTEXT, not per-tab state.
     Before this there were three independent selectors (Inbox, Business Profile,
     Greeting) that could and did disagree — measured live showing infamouz, bem
     and BEM Solutions simultaneously, in two different labelling conventions,
     with nothing on screen saying which business you were editing. Harmless with
     one client; with client companies it means editing the wrong company's AI
     instructions because a tab you were not looking at stayed behind. */
  .switch { position:relative; }
  .switch > button { display:flex; align-items:center; gap:9px; background:var(--panel);
      border:1px solid var(--border); color:var(--text); border-radius:10px;
      padding:7px 11px; font:inherit; font-size:13.5px; cursor:pointer; max-width:280px; }
  .switch > button:hover { border-color:var(--accent); }
  .switch > button:focus-visible { outline:3px solid var(--accent2); outline-offset:2px; }
  .switch .swlabel { display:flex; flex-direction:column; align-items:flex-start; min-width:0; }
  .switch .swkey { font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted); }
  .switch .swname { font-weight:600; max-width:210px; overflow:hidden; text-overflow:ellipsis;
                    white-space:nowrap; }
  .switch .chev { color:var(--muted); font-size:11px; margin-left:auto; flex:none; }
  /* Position is set inline (fixed, from the button's rect) by openSwitch() —
     see the comment there. Everything visual lives here. */
  .swmenu { position:absolute; top:calc(100% + 6px); left:0; z-index:60;
            width:min(320px, calc(100vw - 24px));
            background:var(--panel2); border:1px solid var(--border2); border-radius:12px;
            box-shadow:var(--shadow-menu); padding:8px; }
  .swmenu[hidden] { display:none; }
  /* UX1 (batch 17): jump box, unsaved chip, fix-this-answer link. Tokens only; nothing else restyled. */
  .jump { position:relative; margin:8px 0 2px; }
  .jump input { width:100%; background:var(--bg); border:1px solid var(--border); color:var(--text); border-radius:9px;
    padding:8px 54px 8px 30px; font:inherit; font-size:12.5px; }
  .jump input:focus { padding-right:10px; }
  .jump input:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .jump .jico { position:absolute; left:10px; top:50%; transform:translateY(-50%); width:14px; height:14px; color:var(--muted); pointer-events:none; }
  .jump kbd { position:absolute; right:8px; top:50%; transform:translateY(-50%); font:inherit; font-size:11px; color:var(--muted);
    border:1px solid var(--border); border-radius:5px; padding:1px 5px; pointer-events:none; }
  .jump input:focus ~ kbd { display:none; }
  #jumpList { position:fixed; width:max-content; max-width:380px; z-index:40;   /* ux1c: fixed, so the scrolling rail cannot clip it */ background:var(--panel); border:1px solid var(--border);
    border-radius:10px; box-shadow:var(--shadow-menu); padding:4px; max-height:320px; overflow:auto; }
  #jumpList[hidden] { display:none; }
  #jumpList .jrow { display:flex; align-items:baseline; gap:8px; width:100%; text-align:left; background:none; border:0; color:var(--text);
    padding:7px 9px; border-radius:7px; font:inherit; font-size:12.5px; cursor:pointer; }
  #jumpList .jrow .jk { margin-left:auto; color:var(--muted); font-size:11px; white-space:nowrap; }
  #jumpList .jrow .jl { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:230px; }
  #jumpList .jrow:hover, #jumpList .jrow.on { background:var(--accent-soft); color:var(--accent2); }
  #jumpList .jnone { padding:8px 9px; color:var(--muted); font-size:12.5px; }
  .jumped { outline:3px solid var(--accent2); outline-offset:3px; }
  .jumped.jfade { outline-color:transparent; transition:outline-color 1.2s ease .9s; }   /* fades out only; snaps in */
  .unsavedchip { display:inline-block; margin-left:8px; padding:2px 7px; border-radius:999px; font-size:11px; font-weight:600; letter-spacing:0;
    text-transform:none; background:var(--warn-bg); color:var(--warn-text); border:1px solid var(--warn-border); vertical-align:middle; }
  .fixans { background:none; border:0; padding:0; margin:0; font:inherit; font-size:inherit; color:var(--accent2); cursor:pointer; text-decoration:underline; }
  .fixans:hover { color:var(--accent); }
  .fixans:focus-visible { outline:2px solid var(--accent2); outline-offset:2px; border-radius:3px; }
  .swmenu input { width:100%; background:var(--bg); border:1px solid var(--border); color:var(--text);
      border-radius:8px; padding:8px 10px; font:inherit; font-size:13.5px; margin-bottom:6px; }
  .swmenu input:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .swlist { max-height:320px; overflow-y:auto; overscroll-behavior:contain; }
  .swgroup { font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted);
             padding:8px 8px 4px; }
  .switem { display:flex; align-items:center; gap:9px; width:100%; background:none; border:none;
            color:var(--text); font:inherit; font-size:13.5px; text-align:left; cursor:pointer;
            padding:8px 9px; border-radius:8px; }
  .switem:hover, .switem.cursor { background:var(--panel2); }
  .switem[aria-selected="true"] { color:var(--accent2); font-weight:600; }
  .switem .tick { width:14px; flex:none; color:var(--accent2); }
  .switem .sub { color:var(--muted); font-size:11px; margin-left:auto; }
  .switem:focus-visible { outline:3px solid var(--accent2); outline-offset:-2px; }
  .swempty { color:var(--muted); font-size:12.5px; padding:10px 9px; }

  /* Shown in a per-property tab when the scope is "All businesses". These
     screens edit ONE business's settings, so there is no honest way to render
     them for "all" — say so and offer the fix rather than silently picking one. */
  .needprop { background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg);
              padding:48px 26px; text-align:center; color:var(--muted); font-size:13.5px;
              max-width:520px; margin:8vh auto 0; }
  .needprop b { color:var(--text); display:block; margin-bottom:6px; font-size:16px; }
  .needprop button { margin-top:14px; background:var(--accent); border:none; color:#fff;
                     padding:9px 16px; border-radius:var(--r-sm); font:inherit; font-weight:600; cursor:pointer; }
  .needprop button:hover { background:#6d28d9; }
  /* max-width, not 1fr 1fr: on a wide screen equal fractions gave each field a
     600px column that the input did not fill, so three tiny boxes floated in a
     row of whitespace. Cap the row and let the inputs actually fill their cell. */
  /* ── getting started ── */
  /* ── Scan website & set up (activity 2341) ── */
  .obwrap { max-width:840px; }
  .obhead { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:10px; }
  .obhead h2 { margin:0; flex:1; min-width:180px; }
  .obhead button { padding:7px 13px; font-size:12.5px; }
  .obstatus { font-size:12.5px; color:var(--muted); min-height:18px; margin-bottom:12px; }
  .obfacts { display:grid; grid-template-columns:160px 1fr; gap:7px 14px; font-size:13.5px; line-height:1.45; }
  .obfacts .k { color:var(--muted); }
  .obfacts .v b { font-weight:650; }
  .obgate { color:var(--amber-ink); }
  .obreg { color:var(--red); font-weight:650; }
  .obsrc { font-size:11px; color:var(--muted); margin-top:2px; }
  .obrow { display:flex; gap:11px; align-items:flex-start; padding:10px 0; border-top:1px solid var(--hairline); }
  .obrow:first-of-type { border-top:none; }
  .obrow .obck { width:17px; height:17px; margin:2px 0 0; flex:none; accent-color:var(--accent); }
  .obrow .sutick { margin-top:1px; }
  .obrow.done .sutick { background:var(--green); border-color:var(--green); color:#fff; }
  .obrow .obb { flex:1; min-width:0; }
  .obrow .obt { display:block; font-size:13.5px; font-weight:650; }
  .obrow.done .obt { color:var(--muted); }
  .obrow .obd { display:block; font-size:12.5px; color:var(--muted); margin-top:2px; line-height:1.45; }
  .obfield label { display:block; font-size:12.5px; font-weight:600; margin:9px 0 3px; }
  .obfield input, .obfield textarea, .obfield select { width:100%; background:var(--panel2); border:1px solid var(--border);
    color:var(--text); border-radius:8px; padding:9px 10px; font:inherit; font-size:13.5px; line-height:1.45; }
  .obfield textarea { resize:vertical; min-height:60px; }
  .obtwo { display:grid; grid-template-columns:1fr 1fr; gap:0 12px; }
  .obinline { display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-top:9px; }
  .obinline .dim { font-size:12.5px; }
  .obarow { display:grid; grid-template-columns:20px 1fr; gap:8px; padding:8px 10px; margin-top:6px;
            background:var(--panel2); border:1px solid var(--border); border-radius:8px; }
  .obarow.dropped { opacity:.62; }
  .obarow .obwhy { font-size:11px; color:var(--amber-ink); margin-top:4px; }
  .obarow input, .obarow textarea { width:100%; background:var(--bg); border:1px solid var(--border); color:var(--text);
    border-radius:6px; padding:7px 9px; font:inherit; font-size:12.5px; line-height:1.45; }
  .obarow textarea { margin-top:5px; resize:vertical; min-height:46px; }
  .obcomp { margin-top:10px; background:rgba(248,113,113,.08); border:1px solid rgba(248,113,113,.35);
            border-radius:var(--r-sm); padding:11px 13px; font-size:12.5px; line-height:1.55; }
  .obcomp b { color:var(--red); }
  .obcomp.ok { background:rgba(52,211,153,.08); border-color:rgba(52,211,153,.35); }
  .obcomp.ok b { color:var(--green-ink, var(--green)); }
  .obsnip pre { white-space:pre-wrap; word-break:break-all; background:var(--panel2); border:1px solid var(--border);
                border-radius:8px; padding:10px 12px; font-size:12.5px; line-height:1.5; margin:8px 0; }
  .obhold { background:var(--panel2); border:1px solid var(--border); border-left:3px solid var(--red);
            border-radius:8px; padding:10px 12px; margin-top:8px; font-size:12.5px; line-height:1.5; }
  .obhold b { color:var(--red); }
  .obapply { position:sticky; bottom:0; display:flex; align-items:center; gap:10px; background:var(--bg);
             border-top:1px solid var(--border); padding:12px 2px; margin-top:4px; }
  .obapply button { background:var(--accent); border:none; color:#fff; padding:9px 18px; border-radius:var(--r-sm);
                    cursor:pointer; font:inherit; font-size:13.5px; font-weight:600; }
  .obapply button:hover { background:#6d28d9; }
  .obapply button[disabled] { opacity:.6; cursor:default; }
  .obapply .dim { font-size:12.5px; }
  .setupscan { background:var(--accent); border:none; color:#fff; border-radius:8px; padding:7px 13px;
               font:inherit; font-size:12.5px; font-weight:650; cursor:pointer; flex:none; }
  .setupscan:hover { background:#6d28d9; }
  @media (max-width:640px) {
    .obfacts { grid-template-columns:1fr; gap:2px 0; }
    .obfacts .k { margin-top:7px; }
    .obtwo { grid-template-columns:1fr; }
  }
  .setupcard { margin-bottom:14px; border-color:var(--accent); }
  .sustep { display:flex; gap:11px; align-items:flex-start; padding:11px 16px;
            border-top:1px solid var(--border); }
  .sustep:first-child { border-top:none; }
  .sutick { width:20px; height:20px; flex:none; border-radius:50%; margin-top:1px;
            display:grid; place-items:center; font-size:12.5px; font-weight:800;
            border:1.5px solid var(--border2); color:var(--muted); }
  .sustep.done .sutick { background:var(--green); border-color:var(--green); color:#fff; }
  /* Muted, but NOT struck through. The green tick already says "done"; the
     line-through additionally said "dead", which is the wrong signal now that a
     finished step is still a working link to its screen. */
  .sustep.done .sut { color:var(--muted); }
  /* Quieter than an outstanding step's button, still obviously a control. */
  .sustep.done .go { color:var(--muted); font-weight:500; }
  .sustep.done .go:hover { color:var(--accent2); }
  /* display:block on the spans — inline they ran the title and its reason into
     one sentence ("Tell the chat what you sellWithout this it can only…"). */
  .sub { flex:1; min-width:0; }
  .sut { display:block; font-size:13.5px; font-weight:650; }
  .suw { display:block; font-size:12.5px; color:var(--muted); margin-top:2px; line-height:1.45; }
  .sustep .go { background:var(--panel2); border:1px solid var(--border); color:var(--text);
                border-radius:8px; padding:5px 11px; font:inherit; font-size:12.5px;
                font-weight:650; cursor:pointer; flex:none; }
  .sustep .go:hover { border-color:var(--accent); color:var(--accent2); }
  /* ── over-time strip ── */
  .periodcard { margin-bottom:14px; }
  .segs { display:flex; gap:6px; }
  .segs button { background:var(--panel2); border:1px solid var(--border); color:var(--muted);
                 border-radius:999px; padding:5px 12px; font:inherit; font-size:12.5px;
                 font-weight:650; cursor:pointer; }
  .segs button:hover { color:var(--text); }
  .segs button.on { background:var(--accent-soft); border-color:var(--accent);
                    color:var(--accent2); }
  .pergrid { display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
             gap:12px; padding:14px 16px 16px; }
  .perstat .pv { font-size:20px; font-weight:700; letter-spacing:-.4px; }  /* was 26/800: context, not headline (2026-09-04) */
  .perstat .pl { font-size:12.5px; color:var(--muted); margin-top:2px; }
  .perstat .ps { font-size:11px; color:var(--muted); margin-top:3px; }
  /* Deltas as the same quiet pills the stat cards below use — the strip and
     the cards describe the same business, so their vocabulary should match.
     Bold bare text here read as a THIRD style for the same idea. */
  .perstat .up, .perstat .dn, .perstat .flat {
    display:inline-block; font-size:11px; font-weight:650; border-radius:999px;
    padding:2px 9px; margin-top:2px; }
  .perstat .up { color:var(--green-ink, var(--green)); background:rgba(52,211,153,.10); }
  .perstat .dn { color:var(--red); background:rgba(248,113,113,.10); }
  .perstat .flat { color:var(--muted); background:var(--panel2); font-weight:550; }
  .npgrid2 { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr) 150px;
             gap:10px; align-items:end; max-width:760px; }
  .npgrid2 input, #newPropCard > input { width:100%; }
  #newPropCard > input { max-width:760px; }
  /* The fields themselves. Without this they shipped as WHITE browser-default
     boxes on the dark theme — the third instance of the documented trap where
     a control outside a styled scope (.agentform / .orgform) falls back to
     UA styles. The width rules above styled the LAYOUT and nothing else. */
  #newPropCard input { background:var(--panel2); border:1px solid var(--border);
      color:var(--text); border-radius:8px; padding:9px 11px; font:inherit; font-size:13.5px; }
  #newPropCard input:focus { outline:none; border-color:var(--accent);
      box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  #newPropCard input::placeholder { color:var(--muted); }
  @media (max-width:820px) { .npgrid2 { grid-template-columns:minmax(0,1fr); } }
  /* ── New-client wizard ─────────────────────────────────────────────────────
     The rail is a statement of WHERE YOU ARE, not navigation — steps are not
     clickable, because jumping ahead would skip the creation the later steps
     depend on. Done-ness is shown, never assumed. */
  .wizrail { display:flex; gap:8px; list-style:none; margin:14px 0 18px; padding:0; flex-wrap:wrap; }
  .wizrail li { display:flex; align-items:center; gap:8px; padding:5px 14px 5px 6px;
    border-radius:999px; border:1px solid var(--border); background:var(--panel2);
    color:var(--muted); font-size:12.5px; font-weight:600; }
  .wizrail li .wn { width:22px; height:22px; border-radius:50%; display:grid; place-items:center;
    background:var(--panel); border:1px solid var(--border); font-size:11px; }
  .wizrail li.on { color:var(--text); border-color:var(--accent); background:rgba(124,58,237,.08); }
  .wizrail li.on .wn { background:var(--accent); border-color:var(--accent); color:#fff; }
  .wizrail li.done { color:var(--green-ink, var(--green)); border-color:rgba(52,211,153,.35); }
  .wizrail li.done .wn { background:rgba(52,211,153,.12); border-color:transparent; color:var(--green-ink, var(--green)); }
  /* Same input treatment as #newPropCard — these fields sit outside .orgform /
     .agentform, the documented white-box trap. */
  #wizCard input, #wizCard select { background:var(--panel2); border:1px solid var(--border);
    color:var(--text); border-radius:8px; padding:9px 11px; font:inherit; font-size:13.5px; }
  #wizCard input:focus, #wizCard select:focus { outline:none; border-color:var(--accent);
    box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  #wizCard input::placeholder { color:var(--muted); }
  #wizCard .npgrid2 input { width:100%; }
  .wizrow { display:flex; gap:10px; flex-wrap:wrap; align-items:end; }
  .wizrow > div { display:flex; flex-direction:column; gap:4px; }
  .wizbar { display:flex; gap:10px; align-items:center; margin-top:14px; flex-wrap:wrap; }
  .wizbar .ghost { background:transparent; border:1px solid var(--border); color:var(--muted); }
  .wizbar .ghost:hover { color:var(--text); border-color:var(--muted); }
  /* The folded à-la-carte forms under the wizard. */
  /* Knowledge editor. Monospace because it is markdown the operator structures
     with headings, and proportional text hides whether a "##" is at line start. */
  #kbText { width:100%; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:12.5px; line-height:1.6; resize:vertical; min-height:220px; }
  .kbfoot { display:flex; justify-content:space-between; gap:12px; margin-top:6px;
    font-size:11px; flex-wrap:wrap; }
  .kbnote { background:var(--panel2); border:1px solid var(--border); border-left:3px solid var(--amber);
    border-radius:8px; padding:10px 12px; margin:0 0 10px; font-size:12.5px; line-height:1.55;
    color:var(--muted); }
  .kbnote b { color:var(--text); }
  #kbSrc { font-weight:500; }
  #kbSrc .kbtag { display:inline-block; font-size:11px; font-weight:650; border-radius:999px;
    padding:2px 9px; margin-left:2px; }
  #kbSrc .kbtag.saved { color:var(--green-ink, var(--green)); background:rgba(52,211,153,.10); }
  #kbSrc .kbtag.file  { color:var(--muted); background:var(--panel2); }
  #kbSrc .kbtag.none  { color:var(--amber); background:rgba(251,191,36,.10); }
  /* Outage bank rows — read like a Q&A list, not a form. */
  .obrow { position:relative; padding:10px 34px 10px 0; border-bottom:1px solid var(--hairline); }
  .obrow:last-child { border-bottom:none; }
  .obq { font-size:13.5px; font-weight:650; margin-bottom:3px; }
  .oba { font-size:12.5px; color:var(--muted); line-height:1.55; }
  .obtag { display:inline-block; font-size:11px; font-weight:650; border-radius:999px;
    padding:1px 7px; margin-left:6px; color:var(--amber); background:rgba(251,191,36,.12);
    vertical-align:middle; }
  .obx { position:absolute; top:8px; right:0; }
  #obCount { font-weight:500; }
  .advfold { margin:4px 0 16px; }
  .advfold > summary { cursor:pointer; color:var(--muted); font-size:12.5px; font-weight:600;
    padding:6px 2px; user-select:none; }
  .advfold > summary:hover { color:var(--text); }
  .advfold[open] > summary { margin-bottom:10px; }
  .npgrid { display:grid; gap:8px; margin-top:16px; text-align:left; }
  .needprop .nppick { margin:0; background:var(--panel2, var(--bg)); border:1px solid var(--border);
                      color:var(--text); padding:12px 14px; border-radius:var(--r-sm);
                      display:flex; flex-direction:column; gap:2px; font-weight:600; }
  .needprop .nppick:hover { background:var(--accent); border-color:var(--accent); color:#fff; }
  .needprop .nppick .nph { font-size:12.5px; font-weight:400; color:var(--muted); }
  .needprop .nppick:hover .nph { color:rgba(255,255,255,.85); }
  .npnone { margin-top:14px; color:var(--muted); }
  /* When the scope gate is up, the gated editor does not render half-dead
     beside it — the Try-it panel floating next to a "Choose a business" card
     was the shipped behaviour (seen live). */
  #agentScope:not(:empty) ~ .agentgrid { display:none; }
  #greetScope:not(:empty) ~ .greetgrid { display:none; }
  #setScope:not(:empty) ~ .setgrid { display:none; }

  /* ── Settings ──
     Field styling is repeated here rather than inherited: the input/textarea
     rules above are scoped to `.agentform`, and the documented consequence of
     falling outside that scope is shipping white browser-default controls. The
     alert card moved into this tab, so it would have hit exactly that. */
  .setgrid { max-width:820px; }
  .lookbrand { display:flex; align-items:center; gap:8px; margin-top:16px; font-size:13.5px; }
  .lookbrand input { width:16px; height:16px; flex:none; }
  .bdplan { font-size:16px; margin-bottom:4px; }
  .bdmeter { margin:10px 0 4px; font-size:13.5px; }
  .bdbar { height:8px; border-radius:999px; background:var(--panel2); border:1px solid var(--border); overflow:hidden; margin-top:6px; }
  .bdbar span { display:block; height:100%; background:var(--accent); }
  .bdbar span.warn { background:#fbbf24; } .bdbar span.bad { background:var(--red); }
  .bdplans { display:flex; gap:8px; flex-wrap:wrap; margin:6px 0 4px; }
  /* #billCard-scoped: the console paints every button in a card solid accent, which
     made the four plan choices look identical. The chosen one is the only tinted one. */
  #billCard button.bdp { background:var(--panel2); border:1px solid var(--border); border-radius:9px; padding:10px 12px;
         text-align:left; min-width:140px; min-height:44px; display:flex; flex-direction:column; gap:2px; color:var(--text); }
  #billCard button.bdp span { font-size:12.5px; color:var(--muted); }
  #billCard button.bdp.on { border-color:var(--accent); background:var(--accent-soft); color:var(--accent2); }
  #billCard button.bdp:disabled { opacity:.6; cursor:default; }
  #billCard button.ghost { background:var(--panel2); color:var(--text); border:1px solid var(--border); }
  #billCard button.ghost:hover { border-color:var(--accent); }
  .bdupg { display:flex; gap:12px; align-items:flex-start; padding:10px 0; border-top:1px solid var(--border); font-size:13.5px; cursor:pointer; }
  .bdupg input { width:20px; height:20px; margin-top:2px; flex:none; accent-color:var(--accent); }
  .bdupg > span { flex:1; } .bdupg button { flex:none; }
  .bdrow { display:flex; gap:8px; flex-wrap:wrap; margin-top:6px; }
  .allast { margin-top:12px; padding:10px 12px; border-radius:9px; font-size:12.5px;
            border:1px solid var(--border); background:var(--panel2); }
  .allast.good { border-color:rgba(16,185,129,.45); }
  .allast.bad { border-color:rgba(248,113,113,.5); background:rgba(248,113,113,.08); }
  .allast .alwhy { color:var(--muted); margin-top:4px; word-break:break-word; }
  .alertban { border-color:rgba(248,113,113,.55); background:rgba(248,113,113,.08); }
  .alertban h3 { margin:0 0 4px; }
  .alertban ul { margin:10px 0; padding-left:18px; }
  .alertban li { margin:6px 0; }
  .alertban .dim { color:var(--muted); }
  /* Settings index (2026-09-04): twelve cards in five groups ran 820px wide down a
     1600px view. Two-column cards would scramble the group order, so the empty side
     carries a sticky jump list instead. Hidden below 1200px. */
  /* Settings sub-pages (batch 6a): the five groups are pages picked from the rail on the left; on a narrow
     screen the rail is a pill row above the cards. A group with no card this seat may see is not offered. */
  #view-settings { display:grid; grid-template-columns:196px minmax(0,820px); column-gap:28px; align-items:start; }
  #view-settings > h2, #view-settings > #setScope { grid-column:1 / -1; }
  #view-settings > .setgrid { grid-column:2; grid-row:3; }
  .setnav { grid-column:1; grid-row:3; position:sticky; top:18px; display:flex; flex-direction:column; gap:2px; }
  #setScope:not(:empty) ~ .setnav { display:none; }
  .setgrid > .sg-off { display:none !important; }
  @media (max-width:900px) {
    #view-settings { display:flex; flex-direction:column; }
    #view-settings > h2 { order:-3; } #view-settings > #setScope { order:-2; } .setnav { order:-1; }
    .setnav { position:static; flex-direction:row; gap:6px; margin:0 0 14px; overflow-x:auto; scrollbar-width:none; padding-bottom:2px; }
    .setnav::-webkit-scrollbar { display:none; }
    .setnav .navhead { display:none; }
    .setnav a { flex:none; border:1px solid var(--border); border-radius:999px; padding:9px 13px; white-space:nowrap; min-height:40px; display:inline-flex; align-items:center; }
    .setnav a.on { border-color:var(--accent); }
  }
  .setnav .navhead, .agentnav .navhead { font-size:11px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
                     color:var(--muted); padding:0 10px 6px; }
  .setnav a, .agentnav a { display:block; padding:7px 10px; border-radius:8px; font-size:12.5px;
              color:var(--muted); text-decoration:none; border-left:2px solid transparent;
              transition:background-color .18s ease, color .18s ease; }
  .setnav a:hover, .agentnav a:hover { color:var(--text); background:var(--panel2); }
  .setnav a.on, .agentnav a.on { color:var(--accent2); border-left-color:var(--accent); background:var(--accent-soft); }
  .setnav a:focus-visible, .agentnav a:focus-visible { outline:3px solid var(--accent2); outline-offset:2px; }
  .setgrid textarea, .setgrid input[type=text], .setgrid select {
    width:100%; background:var(--panel2); border:1px solid var(--border); color:var(--text);
    border-radius:8px; padding:10px; font:inherit; font-size:13.5px; line-height:1.5; }
  .setgrid textarea { resize:vertical; }
  .setgrid textarea:focus, .setgrid input[type=text]:focus, .setgrid select:focus {
    outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .setgrid button { background:var(--accent); border:none; color:#fff; padding:9px 18px;
                    border-radius:var(--r-sm); cursor:pointer; font:inherit; font-size:13.5px;
                    font-weight:600; }
  .setgrid button:hover:not(.ghost) { background:#6d28d9; }
  .setgrid .seg button:not(.on) { background:var(--panel2); border:1px solid var(--border);
                                  color:var(--muted); font-weight:500; }

  /* ── Appearance editor ── */
  .lookrow { display:grid; grid-template-columns:minmax(0,1fr) 232px; gap:20px; align-items:start; }
  @media (max-width:900px){ .lookrow { grid-template-columns:1fr; } }
  .swatchrow { display:flex; gap:8px; align-items:center; }
  .swatchrow input[type=color] { width:46px; height:38px; padding:2px; border:1px solid var(--border);
                                 border-radius:8px; background:var(--panel2); cursor:pointer; flex:none; }
  /* Explicit width — in a flex row the hex field stretched the whole way. */
  .setgrid .swatchrow input[type=text] { width:120px; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
  .presets { display:flex; gap:6px; flex-wrap:wrap; margin:9px 0 2px; }
  .setgrid .presets button { width:26px; height:26px; padding:0; border-radius:50%;
                             border:2px solid transparent; cursor:pointer; }
  .setgrid .presets button:hover { border-color:var(--text); }
  .setgrid .presets button.on { border-color:var(--text); }

  /* Preview. Scaled-down but built from the SAME tokens the widget uses, so what
     it shows is the decision being made, not a drawing of it. */
  .lookprev { position:sticky; top:0; }
  .lpsub { font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
           color:var(--muted); margin-bottom:8px; }
  .lpstage { position:relative; height:290px; border:1px solid var(--border); border-radius:12px;
             background:var(--panel2); overflow:hidden; padding:12px; }
  .lppanel { position:absolute; left:12px; right:12px; top:12px; border-radius:12px;
             overflow:hidden; box-shadow:0 8px 24px rgba(0,0,0,.18); }
  .lphdr { padding:9px 11px; color:#fff; font-size:12.5px; font-weight:600;
           display:flex; align-items:center; gap:7px; }
  .lpdot { width:7px; height:7px; border-radius:50%; background:#34d399; flex:none; }
  .lpbody { padding:10px; display:flex; flex-direction:column; gap:7px; }
  .lpmsg { max-width:82%; padding:7px 10px; border-radius:11px; font-size:12.5px; line-height:1.4; }
  .lpmsg.me { align-self:flex-end; color:#fff; }
  .lplaunch { position:absolute; bottom:12px; display:flex; align-items:center; gap:8px; }
  .lpbub { width:38px; height:38px; border-radius:50%; flex:none;
           box-shadow:0 4px 14px rgba(0,0,0,.28); }
  .lplbl { font-size:11px; font-weight:600; padding:6px 10px; border-radius:999px;
           white-space:nowrap; max-width:132px; overflow:hidden; text-overflow:ellipsis; }
  .lplbl:empty { display:none; }
  /* The pop-up teaser, as an example — so "what does the bubble look like"
     is answered here instead of on a client's live site. Copy is a sample;
     the real text comes from the Greeting rules. */
  .lpteaser { position:absolute; bottom:64px; right:12px; max-width:170px;
              font-size:11px; line-height:1.45; padding:8px 24px 8px 11px;
              border-radius:11px; box-shadow:0 6px 20px rgba(0,0,0,.16);
              border:1px solid transparent; }
  .lpteaser .lptx { position:absolute; top:3px; right:6px; font-size:12.5px; opacity:.55; }

  /* Saved replies manager */
  .cnitem { display:flex; gap:10px; align-items:flex-start; padding:9px 0;
            border-bottom:1px solid var(--hairline); }
  .cnitem:last-of-type { border-bottom:none; }
  .cnitem .k { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12.5px;
               font-weight:700; color:var(--accent2); flex:none; min-width:96px; }
  .cnitem .v { flex:1; min-width:0; font-size:12.5px; line-height:1.5; color:var(--text); }
  .cnitem .x { background:none; border:none; color:var(--muted); cursor:pointer;
               font-size:16px; line-height:1; padding:0 4px; flex:none; }
  .cnitem .x:hover { color:var(--red); }
  .cnnone { color:var(--muted); font-size:12.5px; padding:4px 0 8px; }
  .cnaddrow { display:grid; grid-template-columns:150px minmax(0,1fr); gap:10px;
              align-items:start; }
  @media (max-width:700px){ .cnaddrow { grid-template-columns:1fr; } }

  /* Open/closed banner. This is the one place the operator can check that what
     they configured is what the agent is actually being told. */
  .hstatus { display:flex; align-items:center; gap:9px; margin:2px 0 6px; padding:10px 13px;
             border-radius:10px; font-size:13.5px; background:var(--panel2);
             border:1px solid var(--border); }
  .hstatus .dot { width:9px; height:9px; border-radius:50%; flex:none; background:var(--dim); }
  .hstatus.open .dot { background:var(--green); }
  .hstatus.shut .dot { background:var(--amber); }
  .hstatus b { font-weight:700; }
  .hstatus .sub { color:var(--muted); }

  /* One row per day. The checkbox is the "open at all" switch — a day with no
     hours is closed, which is how people describe a week out loud. */
  .hdays { margin:10px 0 4px; border:1px solid var(--border); border-radius:10px;
           overflow:hidden; }
  .hrow { display:grid; grid-template-columns:118px 1fr; gap:10px; align-items:center;
          padding:9px 12px; border-top:1px solid var(--border); }
  .hrow:first-child { border-top:none; }
  .hrow.off { background:rgba(127,127,127,.05); }
  .hday { display:flex; align-items:center; gap:9px; font-size:13.5px; font-weight:600; }
  .hday input { width:15px; height:15px; accent-color:var(--accent); cursor:pointer; }
  .htimes { display:flex; align-items:center; gap:8px; font-size:13.5px; color:var(--muted); }
  /* Explicit width — inside a 1fr cell a bare time input stretched to 500px. */
  .htimes input[type=time] { width:120px; background:var(--panel2); border:1px solid var(--border);
                             color:var(--text); border-radius:8px; padding:7px 9px;
                             font:inherit; font-size:13.5px; }
  .htimes input[type=time]:focus { outline:none; border-color:var(--accent);
                                   box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .hrow.off .htimes { opacity:.4; }
  .hrow.off .htimes input { pointer-events:none; }
  /* `.setgrid button` is (0,1,1) and would otherwise paint this the primary
     purple on later source order — the exact trap the `.seg button` comment
     above records. Scoped here so it actually wins. */
  .setgrid button.hcopy { background:var(--panel2); border:1px solid var(--border);
           color:var(--muted); cursor:pointer; border-radius:6px; padding:4px 10px;
           font:inherit; font-size:12.5px; font-weight:500; margin-left:auto; }
  .setgrid button.hcopy:hover { background:var(--panel2); color:var(--text); border-color:var(--accent); }

  .gnote { border-left:3px solid var(--amber); background:rgba(245,158,11,.08);
           padding:9px 12px; border-radius:0 8px 8px 0; font-size:12.5px; line-height:1.5;
           margin:0 0 12px; color:var(--text); }
  .gnote b { color:var(--amber); }

  /* Path tester — turns "first match wins" from a rule you must remember into
     something you can watch happen. */
  .gtest { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
  .gtest input { flex:1; min-width:180px; background:var(--bg); border:1px solid var(--border);
                 color:var(--text); border-radius:8px; padding:8px 10px; font:inherit; font-size:13.5px; }
  .gtest input:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  .gtestout { margin-top:9px; font-size:12.5px; line-height:1.5; }
  .gtestout .hit { color:var(--green-ink, var(--green)); font-weight:600; }
  .gtestout .miss { color:var(--muted); }
  .gtestout code { background:var(--panel2); border:1px solid var(--border); border-radius:4px;
                   padding:1px 5px; font-size:11px; }

  /* Preview mirrors the widget's real teaser (light card, 280px, close affordance)
     rather than restyling it in console colours — an operator approving a teaser
     should be approving the thing that actually ships. */
  .gpreview { background:var(--panel); border:1px solid var(--border); border-radius:12px;
              padding:14px; position:sticky; top:14px; }
  .gpreview h3 { margin:0 0 2px; font-size:13.5px; color:var(--accent2); }
  .gpreview .dim { font-size:12.5px; color:var(--muted); }
  .gstage { margin-top:12px; border-radius:10px; padding:16px 14px 68px; position:relative;
            background:repeating-linear-gradient(45deg,#f4f4f7,#f4f4f7 10px,#ececf2 10px,#ececf2 20px);
            min-height:150px; }
  .gbubblefake { position:absolute; right:14px; bottom:14px; width:44px; height:44px; border-radius:50%;
                 background:var(--accent); box-shadow:0 6px 18px rgba(0,0,0,.28); }
  .gteaser { max-width:230px; margin-left:auto; background:#fff; color:#16161a;
             border:1px solid rgba(0,0,0,.10); border-radius:14px;
             box-shadow:0 10px 34px rgba(0,0,0,.22); padding:11px 30px 11px 13px;
             font-size:13.5px; line-height:1.45; text-align:left; position:relative; }
  .gteaser .x { position:absolute; top:5px; right:5px; width:20px; height:20px; color:#8b8b98;
                font-size:16px; line-height:20px; text-align:center; }
  .gteaser.none { background:transparent; border:1px dashed rgba(0,0,0,.22); box-shadow:none;
                  color:#5f5f6b; font-style:italic; text-align:center; padding:11px 13px; }
  .gmeta { margin-top:10px; font-size:11px; color:var(--muted); line-height:1.5; }

  /* UX3: ux3 (ai-chat-bot batch 19, Fable 2026-10-11): three columns; the folders are chips + a Filter menu above the
     list. The rail still renders, hidden, and keeps every handler; see patch_ux3.py. */
  .irail { display:none !important; }
  .ibx { grid-template-columns:340px minmax(0,1fr); grid-template-rows:minmax(0,1fr); }
  .ibx > div:nth-child(2) { grid-column:1; grid-row:1; }
  .ibx > .threadempty, .ibx > .thread { grid-column:2; grid-row:1; }
  /* Under the side-by-side breakpoint the composer shared its width with three buttons: a 130 px reply box at 1024.
     The box takes the whole row; the buttons sit under it. */
  @media (max-width:1279.98px) {
    .treply { flex-wrap:wrap; }
    .treply textarea { flex:1 1 100%; }
    .treply button { min-height:36px; }
  }
  @media (max-width:1180px) {
    .ibx { grid-template-columns:280px minmax(0,1fr); grid-template-rows:minmax(0,1fr); }
    .ibx > div:nth-child(2) { grid-column:1; grid-row:1; }
    .ibx > .threadempty, .ibx > .thread { grid-column:2; grid-row:1; }
  }
  @media (max-width:780px) {
    .ibx { grid-template-columns:minmax(0,1fr); grid-template-rows:auto auto; }
    .ibx > div:nth-child(2) { grid-column:1; grid-row:1; }
    .ibx > .threadempty, .ibx > .thread { grid-column:1; grid-row:2; }
  }
  .ichips { display:flex; flex-wrap:wrap; gap:6px; align-items:center; padding:10px 10px 0; }
  .ichips > button, .ichips .ifbtn { background:var(--panel2); border:1px solid var(--border); color:var(--muted); border-radius:999px;
    padding:4px 10px; font:inherit; font-size:12.5px; cursor:pointer; display:inline-flex; align-items:center; gap:6px; min-height:30px; }
  .ichips > button:hover, .ichips .ifbtn:hover { color:var(--text); border-color:var(--accent); }
  .ichips > button:focus-visible, .ichips .ifbtn:focus-visible { outline:3px solid var(--accent2); outline-offset:1px; }
  .ichips .cnt { font-size:11px; font-variant-numeric:tabular-nums; background:var(--panel3); color:var(--muted); border-radius:999px; padding:1px 6px; }
  .ichips > button.on, .ichips .ifbtn.on { background:var(--accent-soft); border-color:var(--accent); color:var(--accent2); font-weight:600; }
  .ichips > button.on .cnt { background:var(--accent); color:#fff; }
  .ichips .ifilter { position:relative; margin-left:auto; display:inline-flex; gap:4px; }
  .ichips .ifx { background:none; border:1px solid var(--border); color:var(--muted); border-radius:999px; width:30px; min-height:30px; font:inherit; cursor:pointer; }
  .ichips .ifx:hover { color:var(--text); border-color:var(--accent); }
  .ifmenu { position:fixed; z-index:50; min-width:240px; max-width:320px; max-height:60vh; overflow-y:auto; background:var(--panel); border:1px solid var(--border);
    border-radius:10px; box-shadow:var(--shadow-menu); padding:6px; }
  .ifmenu[hidden] { display:none; }
  .ifmenu .rhead { font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--muted); padding:8px 10px 4px; }
  .ifmenu button { display:flex; align-items:center; gap:8px; width:100%; background:none; border:0; border-radius:7px; padding:7px 10px; text-align:left;
    font:inherit; font-size:12.5px; color:var(--text); cursor:pointer; min-height:32px; }
  .ifmenu button:hover { background:var(--accent-soft); color:var(--accent2); }
  .ifmenu button.on { color:var(--accent2); font-weight:600; }
  .ifmenu button .cnt { margin-left:auto; font-size:11px; font-variant-numeric:tabular-nums; background:var(--panel3); color:var(--muted); border-radius:999px; padding:1px 6px; }
  .ifmenu button.on .cnt { background:var(--accent); color:#fff; }
  .ifmenu button.railgo { color:var(--accent2); }
  .ifmenu .tdot { margin-right:4px; }

  /* UX4b (ai-chat-bot batch 20, Fable 2026-10-11): Settings password fields (store keys, channel tokens, mail
     password) had only the browser's default box - white on the dark theme. Same box as a text field. */
  .setgrid input[type=password] { width:100%; background:var(--panel2); border:1px solid var(--border); color:var(--text);
    border-radius:8px; padding:10px; font:inherit; font-size:13.5px; line-height:1.5; }
  .setgrid input[type=password]:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px rgba(124,58,237,.25); }
  /* UX27 (batch 45): a card this person may see but not change */
  .pcard.ux27ro .ux27hide { display:none !important; }
  .pcard .ronote { margin:2px 0 8px; font-size:12.5px; color:var(--muted); }
  /* LQ (batch 49): questions for new leads, and the answers on a lead */
  .lqrow { display:flex; gap:8px; align-items:center; margin:6px 0; }
  .lqrow .lqtext { flex:1; min-width:0; }
  dl.lqans { margin:0; }
  dl.lqans dt { font-size:12.5px; color:var(--muted); margin-top:8px; }
  dl.lqans dt:first-child { margin-top:0; }
  dl.lqans dd { margin:2px 0 0; }
  /* PROC (batch 57): procedures */
  .procitem { border:1px solid var(--hairline); border-radius:10px; padding:8px 12px; margin:8px 0; }
  .procitem summary { cursor:pointer; display:flex; gap:8px; align-items:center; min-height:32px; }
  .procitem label { display:block; margin:10px 0 4px; font-size:12.5px; color:var(--muted); }
  .procitem input[type=text], .procitem textarea, .procitem select { width:100%; }
  .cpproc .pst { margin:0 0 6px; font-size:12.5px; color:var(--muted); }
  /* PHOTO (batch 58): a photo's note under its attachment line */
  .upnote { margin:-4px auto 10px; max-width:560px; font-size:12.5px; color:var(--muted); text-align:center; line-height:1.45; }
  .upnote b { color:var(--text); font-weight:600; margin-right:4px; }
  /* ART (batch 59): help articles */
  .artrow { display:flex; gap:10px; align-items:center; padding:9px 0; border-bottom:1px solid var(--hairline); }
  .artrow .artt { flex:1; min-width:0; display:flex; flex-direction:column; }
  .arted label { display:block; margin:10px 0 4px; font-size:12.5px; color:var(--muted); }
  .arted input[type=text], .arted textarea, .arted select { width:100%; }
  .arted label.chk { display:flex; gap:8px; align-items:center; color:var(--text); font-size:13.5px; }
  /* ── a11y + phone-width pass (cloud/a11y-phone-pass, 2026-10-18) ─────────────────────────────────────────────
     No redesign: layout fixes that stop the page scrolling sideways on a phone, and 44px hit areas nobody sees. */
  /* Live visitors: the moved cards sat in an implicit auto grid track that grew to their content (568px on a
     390px phone) and pushed the whole page sideways. One column that may shrink. */
  .vhost { grid-template-columns:minmax(0,1fr); }
  @media (max-width:900px) {
    /* The Settings page rail is a sideways-scrolling row here, but as a grid item its automatic minimum was its
       content (694px), so it scrolled the page instead of itself. */
    .setnav { min-width:0; max-width:100%; }
    /* ...and on the Automations page an unbreakable example address in a <code> made the cards' column 399px
       wide on a 390px phone. It may break where it must. */
    #view-settings .setgrid code { overflow-wrap:anywhere; }
    /* The rail scrolls, so it clips: 2px of padding (given back by the margin) lets its links' 44px hit areas
       through without moving anything. */
    .setnav { padding-top:2px; margin-top:-2px; }
  }
  @media (max-width:767px) {
    /* Contacts: a 6-column table cannot fit a phone; it scrolls inside its card instead of dragging the page. */
    #contacts { overflow-x:auto; }
    /* a phone number wrapped one digit-group per line in its squeezed column (30px wide, 3 lines) */
    .ctbl td a[href^="tel:"] { white-space:nowrap; }
    /* 44x44 hit areas without a bigger visual (the widget does the same): an empty ::after reaching past a
       short control. min(0px, 50% - 22px) is 0 on any side that is already 44px, so nothing grows that does not
       need to. :where() keeps it at zero specificity, so any rule that already positions a control wins.
       .rsw, .tsys, .tnav and .tup draw with their own ::after and are left alone. */
    :where(button, [role=button], summary, .setnav a, .ctbl td a):where(:not(.rsw, .tsys, .tnav, .tup)) { position:relative; }
    :where(button, [role=button], summary, .setnav a, .ctbl td a):where(:not(.rsw, .tsys, .tnav, .tup))::after { content:'';
      position:absolute; top:min(0px, calc(50% - 22px)); bottom:min(0px, calc(50% - 22px));
      left:min(0px, calc(50% - 22px)); right:min(0px, calc(50% - 22px)); }
  }
