/* Operator dashboard.
 *
 * Every brand-specific value is a token in this block. The product is expected
 * to be renamed and recoloured, and eventually white-labelled per reseller, so
 * nothing below this block should hard-code a colour, a radius or the name.
 */

:root {
  /* --- brand: the only values that change per customer ---
     Graphite. The product used to be green throughout, which put the brand in
     direct competition with the three things green already means in an
     operator console: a visitor is online, a check passed, a conversation is
     live. A neutral brand gives every one of those its colour back, and it is
     the palette an operator can sit in front of for eight hours.

     Each value carries the relative luminance of the green it replaced, to
     roughly four decimal places. Contrast is a ratio between two luminances,
     so holding luminance fixed means every contrast measurement already made
     against this palette -- in this stylesheet, in the contract checks and in
     the acceptance suite -- still holds, and nothing had to be re-proved by
     eye. Where a pair is different below, it is because it was measured and
     found wanting, not because the recolour moved it. */
  --brand:          #35373b;
  --brand-deep:     #252629;
  --brand-contrast: #ffffff;
  --accent:         #7a7e84;
  --accent-bright:  #d4d6d9;
  --accent-ink:     #333538;
  --accent-wash:    #eceef1;

  /* The conversation an operator is currently working in. One property; the
     ring, the border and the rail marker are all derived from it, so an
     operator who changes it changes one value rather than a stylesheet. Overridden per operator at
     runtime from a preference validated to six hex digits — never from
     arbitrary CSS.

     Graphite, not the lime it was. WCAG 2.1 SC 1.4.11 asks 3:1 of a UI
     boundary against what it sits on; #74f06a measures 1.46:1 against the card
     and 1.37:1 against the canvas, so the ring that answers "which window am I
     typing in" was the least visible thing on the screen. It was compensated
     for with seven stacked coloured shadows, which is what made it look cheap
     rather than making it legible. This measures 14.84:1 and needs one ring.

     Not red and not green, whatever the contrast: --danger is red and means a
     destructive action, --warn is amber and already marks unread on this very
     window, --good is green and means the visitor is online. The most ordinary
     state an operator is ever in must not wear the colour of the most
     dangerous one, and red/green is the pair the most people cannot separate. */
  --active-chat-color: #1f2124;

  /* --- neutrals ---
     A cool cast of at most five RGB steps, tapering to nothing at both ends of
     the ramp: an off-white has no headroom to carry a cast and picks it up as
     a visible blue tint rather than reading as paper. */
  --ink:        #171819;
  --ink-soft:   #60636a;
  --ink-faint:  #8a8d94;
  --line:       #e6e7e9;
  --line-strong:#d3d5d7;
  --surface:    #ffffff;
  --surface-sunk: #f3f3f4;
  --canvas:     #f7f7f8;

  /* --- chart series ---
     Four hues, none of them a red/green pair, each measured at 3:1 or better
     against both surfaces a chart is ever drawn on -- the card and the sunken
     panel -- because a line a reader cannot find is a line that is not there.
     The two the Home chart stacks, --series-1 and --series-2, are also 3.33:1
     apart from EACH OTHER, so new and returning separate by lightness as well
     as by hue. The analytics chart's four do not all separate that way: three
     of them sit within 1.4:1. It therefore does not rely on colour alone --
     every series is named in the legend and again in the tooltip, which is
     what WCAG 2.1 SC 1.4.1 asks for. Kept here rather than in the chart module
     because a reseller recolouring the product recolours these too. */
  --series-1: #35373b;
  --series-2: #3f8ada;
  --series-3: #c97314;
  --series-4: #8b5cc7;

  /* --- semantic, deliberately separate from the accent --- */
  --danger:     #c2402f;
  --danger-wash:#fbeae7;
  --warn:       #9d610f;
  --warn-wash:  #fdf3e2;
  --good:       #1d7a3c;
  --good-wash:  #e6f6ea;

  /* --- the assistant ---
     Blue is the only hue this palette has not already spoken for: red is
     destructive, amber is unread, green is online, graphite is the brand. It
     therefore carries "the assistant is answering this one" everywhere that
     state appears -- the mode chip in the rail, the same chip on the dark
     dock header, and the assistant's own bubbles -- so the answer is the same
     colour wherever the operator happens to be looking. */
  --ai:      #1b5c9c;
  --ai-wash: #eaf4ff;
  --ai-edge: #c3dcf7;

  /* --- form --- */
  --radius:    12px;
  --radius-sm: 8px;
  --radius-lg: 18px;
  --shadow:    0 1px 2px rgba(23, 24, 25, .05), 0 8px 24px rgba(23, 24, 25, .06);
  --shadow-lift: 0 2px 6px rgba(23, 24, 25, .07), 0 18px 44px rgba(23, 24, 25, .10);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* --- motion ---
     Two durations and one curve, so everything that moves moves the same way.
     The curve is fast at the start and settles without bouncing: a chat window
     is a tool, and a tool that springs is a tool that is still moving when you
     try to click it. Anything longer than --motion-slow on an interface this
     dense reads as lag rather than polish. */
  --motion-fast: 120ms;
  --motion-slow: 220ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* --- rhythm --- */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
  --space-4: 16px; --space-5: 24px; --space-6: 32px; --space-7: 48px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--canvas);
  font-size: 14px;
  line-height: 1.5;
}

.hidden { display: none !important; }
.muted { color: var(--ink-soft); }
.small { font-size: 12px; }
.wrap { overflow-wrap: anywhere; }
.error-text { color: var(--danger); }
.success { color: #1d7a3c; }
h1, h2, h3, h4 { margin: 0 0 8px; line-height: 1.25; }
h3 { font-size: 15px; }
h4 { font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft); }
a { color: var(--brand); }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; background: var(--canvas); padding: 1px 5px; border-radius: 4px; }

/* -------------------------------------------------------------------- Shell */
/* One viewport, divided. `dvh` rather than `vh` so a phone's collapsing
   address bar does not leave a strip of nothing at the bottom. */
.shell {
  position: relative;
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr) 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  background: var(--canvas);
}
.shell.hidden { display: none; }

/* The Chats rail is a column of the shell, so opening it makes room in the
   workspace instead of covering what the operator is reading. */
body.rail-open .shell { grid-template-columns: 232px minmax(0, 1fr) var(--rail-width, 372px); }

.sidebar {
  background: var(--brand-deep); color: #f1f2f3; display: flex; flex-direction: column;
  padding: 20px 14px; gap: 20px; height: 100%; min-height: 0; overflow-y: auto;
}
.brand { display: flex; align-items: center; gap: 8px; font-size: 16px; padding: 0 8px; }
.brand span { color: var(--accent); }
.sidebar nav { display: grid; gap: 2px; }
.sidebar nav a {
  display: block; padding: 9px 12px; border-radius: 9px; color: #dedfe1;
  text-decoration: none; font-weight: 500; position: relative;
}
.sidebar nav a:hover { background: rgba(255, 255, 255, .07); color: #fff; }
.sidebar nav a.active { background: var(--brand); color: #fff; }
.sidebar nav a.has-activity::after {
  content: ''; position: absolute; right: 12px; top: 50%; width: 7px; height: 7px;
  margin-top: -3px; border-radius: 50%; background: var(--accent);
}
.sidebar-foot { margin-top: auto; display: grid; gap: 10px; padding: 0 8px; }
#identity { display: grid; gap: 6px; }
#identity .who strong { display: block; font-size: 13px; }
#identity .who .muted { color: #b2b5ba; }
#identity select {
  background: rgba(255, 255, 255, .08); color: #f1f2f3;
  border: 1px solid rgba(255, 255, 255, .15); border-radius: 8px; padding: 6px 8px;
}
/* Only ever shown at the width where the navigation collapses. */
.nav-toggle { display: none; }

.link-button { background: none; border: 0; color: #b2b5ba; text-align: left; cursor: pointer; padding: 0; font-size: 13px; }
.link-button:hover { color: #fff; }

/* `min-height: 0` is what allows the children of a flex column to scroll
   rather than growing the column past the viewport. Without it every nested
   overflow is ignored and the page scrolls instead. */
main { display: flex; flex-direction: column; min-width: 0; min-height: 0; position: relative; }
.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 20px 24px 14px; background: var(--canvas); flex: 0 0 auto; z-index: 5;
}
.topbar-heading { min-width: 0; }
.topbar h1 { font-size: 22px; }
.topbar p { margin: 0; }
/* The view scrolls, not the document. Every screen therefore keeps its
   navigation and its chats in place, and no screen can trap the application. */
.view {
  padding: 0 24px 32px; display: grid; gap: 16px; align-content: start;
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  /* A layout inside a view has to respond to the width it ACTUALLY has, which
     is not the width of the window: the Chats rail takes 372px of it, and the
     operator can have it open or closed on any screen. Measured with the rail
     open at a 1440px window, a three-column layout using viewport breakpoints
     gave its middle column 124px, and 16px at 1280 — the media query never
     fired because the WINDOW was still wide. Naming this a container lets the
     layouts inside ask about their own space instead. Nothing positioned
     `fixed` lives in here — the dock, the modals and the toasts are all
     siblings of <main> or children of <body> — so the containing-block change
     containment brings with it has nothing to act on. */
  container-type: inline-size;
  container-name: view;
  /* A grid column defaults to being as wide as its widest child needs, and
     every sibling then stretches to match. One wide table was therefore making
     every card on the screen 487px wide inside a 390px phone — the account
     card, the tags, everything. Capping the track at the container's width
     confines the problem to the element that actually has one. */
  grid-template-columns: minmax(0, 1fr);
}

/* For the element that actually is wider than a phone: it scrolls, the page
   does not. Never applied to a card, which would clip the chart tooltip. */
.scroll-x { overflow-x: auto; }

.pill {
  border-radius: 999px; padding: 4px 12px; font-size: 12px; font-weight: 600;
  background: #ececec; color: #666;
}
.pill.live { background: #e2f8e0; color: #1d7a3c; }

/* Trial state: one compact pill beside the connection state. A running trial
   is information, not an interruption, so it never becomes a banner. */
.topbar-status { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }
.trial-pill {
  background: var(--warn-wash); color: var(--warn); text-decoration: none;
  border: 1px solid #f0d9a8; white-space: nowrap;
}
.trial-pill:hover { border-color: var(--warn); }
.trial-pill.urgent { background: var(--danger-wash); color: var(--danger); border-color: #eccbc5; }

/* An ended trial changes what the product will do, so it is stated once, at
   the top of every screen, and says plainly that nothing has been deleted. */
.billing-notice {
  margin: 0 var(--space-5) var(--space-4);
  padding: var(--space-3) var(--space-4);
  display: grid; gap: var(--space-1);
  background: var(--warn-wash);
  border: 1px solid #f0d9a8;
  border-radius: var(--radius);
  font-size: 13px; color: var(--ink);
}
.billing-notice strong { color: var(--warn); }

/* A stylesheet's display rule outranks the browser's own [hidden] rule, so
   both of these must say so explicitly or they show while hidden. */
.billing-notice[hidden], .trial-pill[hidden] { display: none !important; }

/* A card that is reporting a real constraint, not decorating one. */
.card-attention { border-color: #f0d9a8; background: var(--warn-wash); }
.field-note.warn { color: var(--warn); }
.field-note.ok { color: var(--good); }

/* Configured email recipients. Deliberately not the .chip used by the AI
   try-panel: that one is a button you press, this one is a value you remove. */
.recipient-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 var(--space-3); }
.recipient {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; background: var(--accent-wash); color: var(--accent-ink);
  border: 1px solid #dfe0e2; border-radius: 999px; padding: 5px 6px 5px 12px;
}
.recipient-remove {
  border: 0; background: none; font: inherit; font-size: 15px; line-height: 1;
  color: inherit; opacity: .6; cursor: pointer; padding: 0 4px; border-radius: 50%;
}
.recipient-remove:hover { opacity: 1; background: rgba(53, 55, 59, .12); }

/* What the visitor is looking at right now — the one piece of live context a
   profile page was missing, and the first thing an operator asks. */
.profile-now { margin: 6px 0 0; font-size: 13px; color: var(--ink-soft); }
.profile-now b { color: var(--ink); }

/* --- country flags ------------------------------------------------------
 *
 * Images this installation serves, not emoji. A regional-indicator pair only
 * becomes a flag where the platform's emoji font carries the ligature, and
 * Windows has never shipped one, so Chrome and Edge there drew "PK" and "US".
 *
 * One rule set, used on every surface, so a flag is the same size and sits on
 * the same baseline in the rail, the dock, the Inbox, Home, a profile and a
 * lead.
 */
.flag {
  display: inline-block; vertical-align: -3px; margin-right: 7px;
  width: 20px; height: 15px; flex: 0 0 auto;
  border-radius: 2px; box-shadow: 0 0 0 1px rgba(23, 24, 25, .10) inset;
  object-fit: cover; background: var(--surface-sunk);
}
.flag-unknown {
  display: inline-grid; place-items: center; box-shadow: none;
  color: var(--ink-faint);
}
.flag-unknown svg {
  width: 15px; height: 15px; fill: none;
  stroke: currentColor; stroke-width: 1.5; stroke-linecap: round;
}

/* In a circular avatar the flag is the avatar, so it loses its margin — but
   not its size. One flag is one size everywhere, or the eye has to relearn it
   on every surface. */
.chat-row-avatar .flag { margin: 0; vertical-align: 0; }

/* The sending provider and the alert recipients are two independent things,
   and a shared two-column list read them as one contradictory sentence:
   "Provider: Not configured / Recipients: 1 address". Side by side, each with
   its own heading, they read as the two halves they are. */
.status-split {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: var(--space-3); margin-bottom: var(--space-3);
}
.status-block {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 12px 14px; background: var(--surface-sunk);
}
.status-block h4 {
  margin: 0 0 6px; font-size: 11.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-soft);
}
.status-block .status-value { margin: 0 0 6px; font-weight: 600; }
.status-block .field-note { margin: 0; }

.status-ok { color: var(--good); }
.status-warn { color: var(--warn); }
.setup-card-trial { margin: var(--space-2) 0 0; font-size: 12px; font-weight: 600; color: var(--warn); }

/* ------------------------------------------------------------------- Blocks */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow); }
.card.wide { grid-column: 1 / -1; }
.card.danger { border-color: #f0d3ce; }
.empty { color: var(--ink-soft); padding: 24px; text-align: center; }
.empty-state { display: grid; place-content: center; text-align: center; gap: 4px; height: 100%; color: var(--ink-soft); }
.two-column { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.back { display: inline-block; margin-bottom: 8px; text-decoration: none; font-size: 13px; }

.toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.button-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.sticky-save { position: sticky; bottom: 12px; display: flex; justify-content: flex-end; }

/* ------------------------------------------------------------------ Controls */
input, select, textarea {
  font: inherit; color: inherit; background: var(--surface);
  border: 1px solid var(--line); border-radius: 9px; padding: 8px 10px; width: 100%;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--accent); }
input:disabled, select:disabled, textarea:disabled { background: var(--canvas); color: var(--ink-soft); }
textarea { resize: vertical; }

.btn {
  font: inherit; font-weight: 600; cursor: pointer; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); border-radius: 9px; padding: 8px 14px; white-space: nowrap;
}
.btn:hover { border-color: #cdced2; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-deep); }
.btn.small { padding: 5px 10px; font-size: 12px; }
.btn-block { width: 100%; margin-bottom: 12px; }
.btn.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn.danger-outline { color: var(--danger); border-color: #eccbc5; }

/* `overflow: hidden` is here to keep the group's corners rounded, and on a
   390px phone it was also quietly amputating the last filter: the Leads status
   row is six buttons wide, so "Lost" ended 31px past the edge of the screen
   with nothing to scroll and no way to reach it. Wrapping keeps every filter
   reachable; the radius moves onto the buttons so the group still reads as one
   control on the rows where it does fit. */
.segmented {
  display: inline-flex; flex-wrap: wrap; max-width: 100%;
  background: var(--surface); border: 1px solid var(--line); border-radius: 9px;
}
.segmented > :first-child { border-top-left-radius: 8px; border-bottom-left-radius: 8px; }
.segmented > :last-child { border-top-right-radius: 8px; border-bottom-right-radius: 8px; }
.segmented button {
  font: inherit; font-weight: 600; border: 0; background: none; color: var(--ink-soft);
  padding: 8px 13px; cursor: pointer; border-right: 1px solid var(--line);
}
.segmented button:last-child { border-right: 0; }
.segmented button.active { background: var(--brand); color: #fff; }
.segmented .count { font-weight: 500; opacity: .8; }

.field { display: grid; gap: 4px; }
.field > span { font-size: 12px; font-weight: 600; color: var(--ink-soft); }
.field.wide { grid-column: 1 / -1; }
.field.checkbox { grid-template-columns: auto 1fr; align-items: center; gap: 8px; }
.field.checkbox input { width: auto; }
.field.checkbox span { font-weight: 500; color: var(--ink); font-size: 13px; }
.field.checkbox.inline { display: inline-grid; }
.field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; }
.inline-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.inline-form input, .inline-form select { width: auto; flex: 1 1 180px; }
.test-email-form { align-items: flex-end; }
.test-email-form .field { flex: 1 1 260px; }
.test-email-form select { width: 100%; }

.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .03em; color: var(--ink-soft); padding: 8px 10px; border-bottom: 1px solid var(--line); }
.table td { padding: 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
.table tr:last-child td { border-bottom: 0; }
.row-actions { display: flex; gap: 6px; flex-wrap: wrap; }

.badge {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600;
  border: 1px solid var(--line); border-radius: 999px; padding: 2px 8px; color: var(--ink-soft);
}
.badge.ok { background: #e2f8e0; border-color: #b7e6b0; color: #1d7a3c; }
.badge.warn { background: #fdf2df; border-color: #f0d9a8; color: var(--warn); }
.badge.muted-badge { background: var(--canvas); }
.badge.intent-high_intent { background: #fdeceb; border-color: #f3c6c1; color: #a53527; }
.badge.intent-engaged { background: #eaf4ff; border-color: #c3dcf7; color: #1b5c9c; }
.badge.mode-human { background: var(--brand); border-color: var(--brand); color: #fff; }
.badge.priority-high, .badge.priority-urgent { background: #fdeceb; border-color: #f3c6c1; color: #a53527; }
.badge.availability-online { background: #e2f8e0; border-color: #b7e6b0; color: #1d7a3c; }
.badge.availability-away { background: #fdf2df; border-color: #f0d9a8; color: var(--warn); }
.tag-remove { border: 0; background: none; cursor: pointer; color: inherit; font-size: 14px; line-height: 1; padding: 0 0 0 2px; }

.dot { width: 8px; height: 8px; border-radius: 50%; background: #d0d1d4; display: inline-block; margin-right: 6px; }
.dot.online { background: var(--good); box-shadow: 0 0 0 3px rgba(29, 122, 60, .25); }

.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; display: grid; gap: 2px; }
.stat span { font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.stat b { font-size: 22px; }
/* The breakdown under a figure, when the figure alone would be ambiguous —
   "median first response" means something different for the AI than it does
   for the team, and both are worth seeing at once. */
.stat-note { font-size: 11.5px; color: var(--ink-faint); font-style: normal; }

.context-block { display: grid; gap: 6px; margin-bottom: 12px; }
.context-row { display: grid; grid-template-columns: 110px 1fr; gap: 8px; align-items: baseline; font-size: 13px; }
.context-row span { color: var(--ink-soft); font-size: 12px; }
.context-row .status-ok { color: var(--good); }
.context-row .status-warn { color: var(--warn); }
.quote { border-left: 3px solid var(--line); padding-left: 10px; color: var(--ink-soft); margin: 10px 0 0; }
.warning { background: #fdf2df; border: 1px solid #f0d9a8; border-radius: 9px; padding: 10px; color: #7a5411; }

.simple-list, .link-list, .doc-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }
.simple-list li, .link-list li { display: flex; justify-content: space-between; gap: 12px; align-items: center; border-bottom: 1px solid var(--line); padding-bottom: 8px; }
.simple-list li p { margin: 2px 0 0; }
.tag-cloud { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }

/* -------------------------------------------------------------------- Inbox */
.inbox-focus { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 16px; min-height: 0; height: 100%; }
.inbox-empty {
  display: grid; place-content: center; justify-items: center; gap: 12px;
  text-align: center; padding: 48px 24px; color: var(--ink-soft); min-height: 320px;
}
.inbox-empty h3 { margin: 0; color: var(--ink); }
.inbox-empty p { margin: 0; max-width: 42ch; }
.inbox { display: grid; grid-template-columns: 320px minmax(0, 1fr) 300px; gap: 16px; min-height: 0; }
.inbox-list { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.inbox-filters { padding: 12px; display: grid; gap: 8px; border-bottom: 1px solid var(--line); }
.inbox-filters .segmented { width: 100%; }
.inbox-filters .segmented button { flex: 1; padding: 7px 6px; font-size: 12px; }
.filter-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.filter-row select:last-child { grid-column: 1 / -1; }
.scroll { overflow-y: auto; flex: 1; }

.conversation-row {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  border-bottom: 1px solid var(--line); padding: 11px 12px; cursor: pointer; font: inherit;
}
.conversation-row:hover { background: var(--canvas); }
.conversation-row.active { background: #f6f7f7; box-shadow: inset 3px 0 0 var(--accent); }
.conversation-row.unread strong { font-weight: 700; }
.row-top { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.row-top .when { font-size: 11px; color: var(--ink-soft); white-space: nowrap; }
.row-preview { font-size: 13px; color: var(--ink-soft); margin: 2px 0 4px; }
.row-preview .you { font-weight: 600; color: var(--ink); }
.row-meta { font-size: 11px; color: var(--ink-soft); display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.row-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.unread-pill { background: var(--brand); color: var(--brand-contrast); border-radius: 999px; padding: 0 6px; font-weight: 700; }

.inbox-thread { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.thread-head { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; padding: 14px 16px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.thread-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.thread-actions select { width: auto; padding: 6px 8px; font-size: 12px; }
.messages { flex: 1; overflow-y: auto; padding: 16px; display: grid; gap: 12px; align-content: start; }
.message { max-width: 78%; }
.message .bubble { padding: 9px 13px; border-radius: 14px; background: var(--canvas); white-space: pre-wrap; overflow-wrap: anywhere; }
.message .message-meta { font-size: 11px; color: var(--ink-soft); margin-top: 3px; }
.message.visitor { justify-self: start; }
.message.agent, .message.assistant { justify-self: end; text-align: right; }
.message.agent .bubble { background: var(--brand); color: #fff; }
.message.assistant .bubble { background: var(--ai-wash); }
.message.proactive .bubble { background: #fdf6e4; color: var(--ink); }
.message.system .bubble { background: none; border: 1px dashed var(--line); }

.composer { border-top: 1px solid var(--line); padding: 12px 16px; display: grid; gap: 8px; }
.composer-tools { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.composer-tools select { width: auto; padding: 5px 8px; font-size: 12px; }
.composer-input { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: end; }

.inbox-context { overflow-y: auto; }
.inbox-context h3 { margin-top: 14px; }
.inbox-context h3:first-child { margin-top: 0; }
.tag-picker { display: grid; gap: 5px; margin-bottom: 12px; }
.tag-option { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.tag-option input { width: auto; }
.tag-option span { border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; }
.note-form { display: grid; gap: 6px; margin-bottom: 10px; }
.notes { display: grid; gap: 8px; }
.note { background: var(--canvas); border-radius: 9px; padding: 8px 10px; }
.note p { margin: 0 0 3px; font-size: 13px; }

/* ----------------------------------------------------------------- Visitors */
.visitor-grid, .site-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.visitor-card header, .site-card header { display: flex; justify-content: space-between; gap: 8px; align-items: flex-start; margin-bottom: 6px; }
.visitor-card p { margin: 2px 0; }
.visitor-card .page { font-size: 12px; color: var(--ink-soft); overflow-wrap: anywhere; margin: 8px 0; }
.visitor-card footer, .site-card footer { display: flex; justify-content: space-between; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
.card-actions { display: flex; gap: 6px; }
.site-stats { display: flex; gap: 14px; font-size: 12px; color: var(--ink-soft); margin: 8px 0; }
.site-stats b { color: var(--ink); font-size: 15px; }

.profile { display: grid; gap: 16px; }
.profile-head { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; align-items: flex-start; }
.profile-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.profile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px; }
.signals { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.signals li { display: flex; justify-content: space-between; border-bottom: 1px solid var(--line); padding-bottom: 5px; font-size: 13px; }
.journey { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; max-height: 420px; overflow-y: auto; }
/* The page title needs a floor, not just a share.
   `1fr` is `minmax(auto, 1fr)`, and the automatic minimum of a string that may
   break anywhere is ONE CHARACTER — so on a phone, where the type takes 130px
   and the timestamp another 127, the title column collapsed to 31px and a page
   name came out one letter per line, 312px tall for a single event. A floor in
   `ch` keeps it readable at every width the row survives at all. */
.journey li { display: grid; grid-template-columns: 130px minmax(14ch, 1fr) auto; gap: 10px; align-items: baseline; border-bottom: 1px solid var(--line); padding-bottom: 6px; font-size: 13px; }
.journey-type { font-weight: 600; text-transform: capitalize; }

/* -------------------------------------------------------------------- Leads */
/* ------------------------------------------------------------ Lead workspace
   Three panes in the order the work happens: what to do next, the person, and
   what you need to know to make the call.

   `data-pane` is the phone's whole layout system. At a width that fits two or
   three columns it is inert -- the grid decides -- and below 900px exactly one
   pane is shown and the attribute says which. That is deliberately not three
   columns squeezed: a 390px screen divided three ways is three unusable
   columns, and an operator on a phone is doing one thing at a time anyway. */
.lead-workspace {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr) 300px;
  gap: var(--space-3);
  min-height: 0;
  height: 100%;
}
/* Each pane owns its own scrolling and takes its height from the grid, which
   takes its height from the shell. Nothing here subtracts a guessed number of
   pixels for the chrome above it -- that guess is wrong the first time a filter
   note wraps onto a second line. */
.lead-queue, .lead-main, .lead-context { min-height: 0; overflow-y: auto; }
.lead-queue { padding: 0; display: flex; flex-direction: column; overflow: hidden; }
.lead-queue-head {
  position: sticky; top: 0; z-index: 1;
  padding: var(--space-3);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  display: grid; gap: 10px;
}
.lead-queue-search { display: flex; gap: 8px; align-items: center; }
.lead-queue-search input { flex: 1; min-width: 0; }
.lead-queue-search .btn { flex: none; }

/* Status as chips rather than a segmented control: there are six of them, they
   wrap, and each carries its own count. */
.lead-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.lead-chip {
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft);
  border-radius: 999px; padding: 5px 11px; min-height: 30px;
  display: inline-flex; align-items: center; gap: 5px;
  transition: background var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out);
}
.lead-chip:hover { border-color: var(--line-strong); }
.lead-chip.is-active { background: var(--brand); border-color: var(--brand); color: var(--brand-contrast); }
.lead-chip-count { font-variant-numeric: tabular-nums; opacity: .75; }

.lead-more-filters summary {
  cursor: pointer; font-size: 12.5px; font-weight: 600; color: var(--ink-soft);
  padding: 4px 0; min-height: 24px;
}
.lead-filter-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; margin-top: 8px; }
.lead-filter-grid .field span { font-size: 11px; }

.lead-queue-list { flex: 1; min-height: 0; padding: var(--space-2) var(--space-3) var(--space-3); }
.lead-queue-count { font-size: 11.5px; color: var(--ink-faint); margin: 4px 0 8px; }
.lead-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }

/* A row, not a card. Four short lines at three weights, so the eye lands on the
   name and then on whatever is wrong -- rather than reading twelve equal
   fields to find the one it wanted. */
.lead-row {
  display: grid; gap: 3px;
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  min-height: 44px;
  transition: background var(--motion-fast) var(--ease-out);
}
.lead-row:hover { background: var(--surface-sunk); }
.lead-row:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.lead-row.is-selected { background: var(--surface-sunk); border-color: var(--line-strong); }
.lead-row.is-selected::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--active-chat-color); border-radius: 3px 0 0 3px;
}
.lead-row { position: relative; }
.lead-row-top { display: flex; align-items: center; gap: 8px; }
.lead-row-name {
  font-weight: 600; font-size: 13.5px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lead-row-contact {
  margin: 0; font-size: 12px; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lead-row-meta, .lead-row-foot {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 11px; color: var(--ink-faint);
}
.lead-row-foot { justify-content: space-between; }
.lead-row-owner, .lead-row-source {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 40%;
}
.lead-row-when { margin-left: auto; flex: none; }

/* Status keeps the product's semantic colours: won is the good green, lost is
   the danger red, and the three in between are neutral because they are stages
   rather than outcomes. */
.lead-status {
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  border-radius: 4px; padding: 2px 6px; background: var(--surface-sunk); color: var(--ink-soft); flex: none;
}
.lead-status-new { background: var(--ai-wash); color: var(--ai); }
.lead-status-qualified { background: var(--accent-wash); color: var(--ink); }
.lead-status-won { background: var(--good-wash); color: var(--good); }
.lead-status-lost { background: var(--danger-wash); color: var(--danger); }

.lead-prio {
  font-size: 10.5px; font-weight: 700; border-radius: 4px; padding: 2px 6px; flex: none; margin-left: auto;
}
.lead-prio-low { background: var(--surface-sunk); color: var(--ink-faint); }
.lead-prio-high { background: var(--warn-wash); color: var(--warn); }
.lead-prio-urgent { background: var(--danger-wash); color: var(--danger); }

/* Two flags and only two, because a queue where everything is flagged is a
   queue where nothing is. */
.lead-flag { font-weight: 700; font-size: 11px; }
.lead-flag-overdue { color: var(--danger); }
.lead-flag-waiting { color: var(--warn); }
.lead-flag-today { color: var(--ink-soft); }
.lead-row.needs-attention .lead-row-name::before {
  content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--warn); margin-right: 6px; vertical-align: middle;
}
.lead-queue-empty { padding: var(--space-4) var(--space-2); text-align: center; display: grid; gap: 8px; justify-items: center; }

/* --- the middle pane --- */
.lead-main { display: flex; flex-direction: column; padding: 0; }
.lead-head {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start;
  padding: var(--space-3); border-bottom: 1px solid var(--line);
}
.lead-head-who { flex: 1; min-width: 0; }
.lead-head-who h2 { margin: 0; font-size: 17px; display: flex; align-items: center; gap: 6px; min-width: 0; }
.lead-head-who p { margin: 2px 0 0; font-size: 12.5px; overflow-wrap: anywhere; }
.lead-head-controls { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.lead-head-controls select { width: auto; min-height: 34px; font-size: 12.5px; }

.lead-actions {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 10px var(--space-3); border-bottom: 1px solid var(--line);
}
.lead-actions .btn { min-height: 32px; display: inline-flex; align-items: center; text-decoration: none; }

.lead-followup {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 9px var(--space-3); font-size: 12.5px;
  border-bottom: 1px solid var(--line); background: var(--surface-sunk);
}
.lead-followup-state { font-weight: 700; }
.lead-followup-overdue { background: var(--danger-wash); }
.lead-followup-overdue .lead-followup-state { color: var(--danger); }
.lead-followup-today { background: var(--warn-wash); }
.lead-followup-today .lead-followup-state { color: var(--warn); }
.lead-followup-note { color: var(--ink-soft); overflow-wrap: anywhere; }
.lead-followup-actions { margin-left: auto; display: flex; gap: 4px; }

.lead-timeline { flex: 1; min-height: 240px; overflow-y: auto; padding: var(--space-3); display: grid; gap: 12px; align-content: start; }
.lead-timeline-note { font-size: 11.5px; color: var(--ink-faint); margin: 0; text-align: center; }
.lead-event { display: grid; gap: 3px; }
.lead-event-meta { margin: 0; font-size: 11px; color: var(--ink-faint); }
.lead-bubble {
  padding: 8px 11px; border-radius: 12px; font-size: 13px; line-height: 1.45;
  max-width: min(78%, 520px); width: fit-content; overflow-wrap: anywhere; white-space: pre-wrap;
  background: var(--surface-sunk);
}
.lead-msg-agent { justify-items: end; }
.lead-msg-agent .lead-bubble { background: var(--brand); color: var(--brand-contrast); }
.lead-msg-agent .lead-event-meta { text-align: right; }
.lead-msg-assistant .lead-bubble { background: var(--ai-wash); }
.lead-note {
  padding: 8px 11px; border-radius: var(--radius-sm); font-size: 13px; line-height: 1.45;
  background: var(--warn-wash); border-left: 3px solid var(--warn); overflow-wrap: anywhere; white-space: pre-wrap;
}
/* A marker is one quiet line. It is context for the messages around it, not an
   event competing with them for attention. */
.lead-event-marker p { margin: 0; font-size: 12px; color: var(--ink-soft); text-align: center; }
.lead-event-marker .lead-event-meta { display: inline; }

.lead-note-form { display: flex; gap: 8px; align-items: flex-end; padding: var(--space-3); border-top: 1px solid var(--line); }
.lead-note-form textarea { flex: 1; min-width: 0; resize: vertical; }

.lead-blank { padding: var(--space-5) var(--space-4); text-align: center; color: var(--ink-soft); }
.lead-blank h3 { margin: 0 0 6px; }

/* --- the right pane --- */
.lead-group { border-bottom: 1px solid var(--line); }
.lead-group:last-of-type { border-bottom: 0; }
.lead-group summary {
  cursor: pointer; font-weight: 600; font-size: 13px; padding: 10px 2px; min-height: 40px;
  display: flex; align-items: center; gap: 6px;
}
/* `display: flex` on a <summary> removes the browser's own disclosure marker,
   so a collapsed group looks like a heading that does nothing. This puts one
   back and turns it, which is the only thing telling an operator the section
   opens at all. */
.lead-group summary::before {
  content: '›'; display: inline-block; color: var(--ink-faint); font-size: 15px;
  transition: transform var(--motion-fast) var(--ease-out);
}
.lead-group[open] summary::before { transform: rotate(90deg); }
.lead-group summary::-webkit-details-marker { display: none; }
.lead-group summary:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
/* Label above value, not beside it. Beside it, the value gets about 190px of a
   300px panel, and an email address of ordinary length then breaks in the
   middle of a word -- "aisha.rahman@example.invali / d" -- which is unreadable
   and impossible to copy by eye. Stacked, it gets the whole column. */
.lead-facts { margin: 0 0 10px; display: grid; gap: 2px; font-size: 12.5px; }
.lead-facts dt { color: var(--ink-faint); font-size: 11px; font-weight: 600; }
.lead-facts dt + dd { margin: 0 0 8px; }
.lead-facts dd { margin: 0 0 8px; overflow-wrap: anywhere; }
.lead-facts dd:last-child { margin-bottom: 0; }
.lead-quote { font-style: italic; color: var(--ink-soft); }
.lead-url { font-size: 11.5px; color: var(--ink-soft); }
.lead-group-link { margin: 0 0 12px; font-size: 12px; }

.lead-picker { display: grid; gap: 4px; max-height: 220px; overflow-y: auto; margin-bottom: 10px; }
.lead-picker-row {
  display: grid; gap: 2px; text-align: left; font: inherit; cursor: pointer;
  padding: 8px 10px; min-height: 44px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface);
}
.lead-picker-row:hover { background: var(--surface-sunk); }
.lead-picker-row.is-chosen { border-color: var(--brand); background: var(--surface-sunk); }

/* The two panes a phone swaps between are hidden by an attribute rather than
   unmounted, so switching back does not reload anything. */
/* Hidden until the width actually needs them. Written at the same specificity
   as the rules that lay them out -- `.lead-actions .btn` is two classes, and a
   one-class `display: none` loses to it, which is how the Details button ended
   up on screen beside the panel it opens. */
.lead-main .lead-back,
.lead-context .lead-context-close,
.lead-actions .lead-context-toggle { display: none; }

/* Two columns once the third will not fit, one once the second will not. The
   thresholds are what the panes need, not the width of somebody's screen:
   the queue at 340, the context at 300, two gaps of 12, and a middle column
   with at least 520 for a message bubble to be a bubble rather than a column
   of words — 1184 in total. Measured with the rail open at 1920, the workspace
   gets 1268, so a threshold set any higher than this hides the third pane on
   the widest screen anybody has. */
@container view (max-width: 1180px) {
  .lead-workspace { grid-template-columns: 300px minmax(0, 1fr); }
  .lead-context { display: none; }
  .lead-actions .lead-context-toggle { display: inline-flex; }
  .lead-workspace[data-pane="context"] .lead-queue,
  .lead-workspace[data-pane="context"] .lead-main { display: none; }
  .lead-workspace[data-pane="context"] { grid-template-columns: minmax(0, 1fr); }
  .lead-workspace[data-pane="context"] .lead-context { display: block; }
  .lead-context .lead-context-close { display: inline-flex; margin-bottom: 8px; }
}

@container view (max-width: 700px) {
  .lead-workspace { grid-template-columns: minmax(0, 1fr); }
  .lead-workspace[data-pane="queue"] .lead-main,
  .lead-workspace[data-pane="queue"] .lead-context { display: none; }
  .lead-workspace[data-pane="lead"] .lead-queue,
  .lead-workspace[data-pane="lead"] .lead-context { display: none; }
  .lead-main .lead-back { display: inline-flex; order: -1; margin-bottom: 4px; }
  /* The back button is the first thing on the pane rather than something
     wedged beside the name, where it was both cramped and easy to miss. */
  .lead-head { flex-direction: column; align-items: stretch; }
  .lead-timeline { max-height: 52vh; }
  /* The Chats tray is fixed to the bottom of the screen on a phone, and it was
     sitting on top of the note composer. */
  .lead-note-form { padding-bottom: calc(var(--space-3) + 52px); }
  /* Every control an operator taps rather than clicks. */
  .lead-row { min-height: 56px; }
  .lead-chip { min-height: 36px; }
  .lead-actions .btn, .lead-head-controls select { min-height: 44px; }
  .lead-picker-row { min-height: 48px; }
}

/* Visible to a screen reader, not to the eye. The selects in the lead header
   are labelled this way rather than left to a title attribute, which is not
   reliably announced. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- Analytics */
.chart { display: grid; gap: 6px; }
.chart svg { width: 100%; height: 180px; background: linear-gradient(180deg, rgba(53, 55, 59, .05), transparent); border-radius: 9px; }
.chart-axis { display: flex; justify-content: space-between; font-size: 11px; color: var(--ink-soft); }
.legend { display: flex; gap: 14px; font-size: 12px; color: var(--ink-soft); flex-wrap: wrap; }
.legend-item { display: inline-flex; align-items: center; gap: 5px; }
.legend-item i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.legend-max { margin-left: auto; }
.bar-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.bar-list li { display: grid; grid-template-columns: minmax(90px, 1fr) 120px 40px; gap: 10px; align-items: center; font-size: 13px; }
.bar { background: var(--canvas); border-radius: 999px; height: 8px; overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--accent); }
.bar-list b { text-align: right; }
/* A row that goes somewhere says so before it is clicked. Background and the
   bar's own tone only — no lift, no inset, nothing that changes the box:
   these rows sit in a fixed three-column grid and a hover that resized one
   would shuffle the numbers in the column beside it.

   The whole row is the target, not the four words of the label. Left as a
   plain inline link the tap area was 34x15 CSS pixels: fine for a mouse, under
   the 24x24 WCAG 2.2 SC 2.5.8 asks of any target, and nowhere near what a
   thumb needs. The ::after below stretches the anchor over the row, so the
   bar and the number are part of the same target — which is also how a person
   reads the row, rather than aiming at the one word that happens to be a
   link. */
.bar-list li.is-linked {
  position: relative;
  min-height: 32px;
  border-radius: var(--radius-sm);
  transition: background var(--motion-fast) linear;
}
.bar-list li.is-linked a::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
/* On anything driven by a finger rather than a cursor, the comfortable target
   both Apple and Material ask for is ~44px. Scoped to coarse pointers so a
   dense desktop table does not grow a third taller for no reason. */
@media (pointer: coarse) {
  .bar-list li.is-linked { min-height: 44px; }
  /* The row actions on Home — Message, Open chat, Details — are the primary
     thing an operator taps on a phone, and were 30px. */
  .visitor-actions .btn.small { min-height: 44px; padding-block: 0; }
}
.bar-list li.is-linked:hover { background: var(--surface-sunk); }
.bar-list li.is-linked:hover .bar i { background: var(--brand); }
.bar-list li.is-linked .bar i { transition: background var(--motion-fast) linear; }
.bar-list li.is-linked a { color: inherit; text-decoration: none; }
.bar-list li.is-linked:hover a,
.bar-list li.is-linked a:focus-visible { text-decoration: underline; }

/* --------------------------------------------------------------- Automation */
.step-card { display: grid; gap: 12px; }
.step-head { display: flex; justify-content: space-between; gap: 12px; align-items: center; flex-wrap: wrap; }
.step-head-actions { display: flex; gap: 10px; align-items: center; }
.variations { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.variation-group { display: grid; gap: 8px; align-content: start; }
.variation { display: grid; grid-template-columns: 1fr auto; gap: 6px; align-items: start; }

/* ---------------------------------------------------------------- Knowledge */
.knowledge-layout { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 16px; align-items: start; }
.doc-list li { border-bottom: 1px solid var(--line); }
.doc-list li.active { background: #f6f7f7; }
.doc-open { display: grid; gap: 2px; width: 100%; text-align: left; background: none; border: 0; padding: 9px 6px; cursor: pointer; font: inherit; }
.doc-open:hover { background: var(--canvas); }
.passage { border: 1px solid var(--line); border-radius: 9px; padding: 10px 12px; margin-top: 10px; }
.passage h4 { text-transform: none; letter-spacing: 0; color: var(--ink); font-size: 13px; }
.passage p { margin: 6px 0 0; font-size: 13px; color: var(--ink-soft); white-space: pre-wrap; }

/* --------------------------------------------------------------------- Team */
.site-permissions { display: grid; gap: 5px; }
.permission { display: flex; align-items: center; gap: 6px; font-size: 12px; flex-wrap: wrap; }
.permission input { width: auto; }
.permission-site { display: inline-flex; align-items: center; gap: 6px; }
.permission .sub { display: inline-flex; align-items: center; gap: 4px; color: var(--ink-soft); }

.permission-note {
  margin: 0; padding: 10px 12px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); background: var(--surface-sunk); color: var(--ink-soft);
}


/* ---------------------------------------------------------- Chat appearance */
.chat-brand-preview {
  --chat-preview-accent: #f5a524;
  position: relative;
  min-height: 330px;
  margin-top: 16px;
  padding: 20px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 18px;
  background:
    radial-gradient(circle at 85% 10%, color-mix(in srgb, var(--chat-preview-accent) 14%, transparent), transparent 34%),
    linear-gradient(145deg, #fafafb, #f2f2f3);
}
.chat-brand-preview__panel {
  width: min(350px, 100%);
  margin-left: auto;
  overflow: hidden;
  border: 1px solid rgba(40, 42, 45, .10);
  border-radius: 20px;
  background: #fff;
  box-shadow: 0 20px 50px rgba(23, 24, 26, .13);
}
.chat-brand-preview__head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
  background: linear-gradient(145deg, #17181a, #0e0f10);
  color: #fff;
}
.chat-brand-preview__avatar,
.chat-brand-preview__mini {
  display: grid;
  place-items: center;
  overflow: hidden;
  background: color-mix(in srgb, var(--chat-preview-accent) 22%, #fff);
  color: #2a2c2f;
}
.chat-brand-preview__avatar {
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  border-radius: 13px;
}
.chat-brand-preview__avatar img,
.chat-brand-preview__mini img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.chat-brand-preview__avatar.is-photo img,
.chat-brand-preview__mini.is-photo img { object-fit: cover; }
.chat-brand-preview__copy { min-width: 0; flex: 1; }
.chat-brand-preview__copy strong,
.chat-brand-preview__copy span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-brand-preview__copy strong { font-size: 13px; }
.chat-brand-preview__copy span {
  margin-top: 2px;
  color: rgba(255,255,255,.64);
  font-size: 10.5px;
}
.chat-brand-preview__online {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--chat-preview-accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--chat-preview-accent) 14%, transparent);
}
.chat-brand-preview__message {
  width: 76%;
  margin: 18px 14px 42px;
  padding: 10px 12px;
  border: 1px solid #e9e9eb;
  border-radius: 7px 15px 15px;
  background: #f8f8f9;
  font-size: 12px;
  line-height: 1.4;
}
.chat-brand-preview__composer {
  margin: 0 12px 12px;
  padding: 9px 10px 9px 12px;
  border: 1px solid #d9dadd;
  border-radius: 14px;
  color: #8b8e95;
  font-size: 11px;
}
.chat-brand-preview__composer b {
  float: right;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  margin-top: -5px;
  border-radius: 8px;
  background: var(--chat-preview-accent);
  color: #1c1d1f;
}
.chat-brand-preview__teaser,
.chat-brand-preview__launcher {
  position: absolute;
  right: 20px;
  display: flex;
  align-items: center;
  box-shadow: 0 14px 34px rgba(23, 24, 26, .15);
}
.chat-brand-preview__teaser {
  bottom: 74px;
  width: min(285px, calc(100% - 40px));
  gap: 9px;
  padding: 9px 34px 9px 9px;
  border: 1px solid rgba(40, 42, 45, .10);
  border-radius: 16px;
  background: #fff;
}
.chat-brand-preview__mini {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  border-radius: 11px;
}
.chat-brand-preview__teaser strong,
.chat-brand-preview__teaser small { display: block; }
.chat-brand-preview__teaser strong { font-size: 11px; }
.chat-brand-preview__teaser small {
  margin-top: 2px;
  color: var(--ink-soft);
  font-size: 9.5px;
  line-height: 1.25;
}
.chat-brand-preview__launcher {
  bottom: 18px;
  gap: 8px;
  min-height: 46px;
  padding: 6px 11px 6px 6px;
  border-radius: 15px;
  background: #131315;
  color: #fff;
  font-size: 11px;
}
.chat-brand-preview__launcher > span {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background: var(--chat-preview-accent);
  color: #1c1d1f;
  font-size: 16px;
}
@media (max-width: 560px) {
  .chat-brand-preview { min-height: 350px; padding: 14px; }
  .chat-brand-preview__panel { width: 100%; }
  .chat-brand-preview__teaser,
  .chat-brand-preview__launcher { right: 14px; }
  .chat-brand-preview__teaser { width: calc(100% - 28px); }
}

/* ------------------------------------------------------------------- Shared */
.code { background: var(--brand-deep); color: #ededef; padding: 12px; border-radius: 9px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; overflow-x: auto; white-space: pre-wrap; overflow-wrap: anywhere; }
.site-detail { display: grid; gap: 16px; }

.modal-backdrop { position: fixed; inset: 0; background: rgba(23, 24, 25, .45); display: grid; place-items: center; padding: 20px; z-index: 40; }
.modal { width: 100%; max-width: 460px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }

#toasts { position: fixed; right: 18px; bottom: 18px; display: grid; gap: 8px; z-index: 60; }
.toast { background: var(--brand-deep); color: #f1f2f3; padding: 10px 14px; border-radius: 9px; box-shadow: var(--shadow); font-size: 13px; max-width: 340px; }
.toast-error { background: var(--danger); }
.toast.leaving { opacity: 0; transition: opacity .4s ease; }

@media (max-width: 1240px) {
  .inbox { grid-template-columns: 280px minmax(0, 1fr); height: auto; }
  .inbox-context { grid-column: 1 / -1; }
  .inbox-list, .inbox-thread { height: 620px; }
}
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { position: static; height: auto; }
  .sidebar nav { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
  .inbox { grid-template-columns: 1fr; }
  .two-column, .variations, .knowledge-layout { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Navigation groups
   ========================================================================== */
.nav-group {
  margin: var(--space-4) 8px 4px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: #95999f;
}
.sidebar nav a:first-child { margin-top: 0; }

/* Setup takes the whole screen: no sidebar, no operator chrome. */
body.setup-mode .sidebar,
body.setup-mode .topbar { display: none; }
/* Setup owns the whole window. The rail and the dock are hidden rather than
   left in the grid, where they fought the setup layout for the columns and
   collapsed the workspace to nothing. */
body.setup-mode .shell,
body.setup-mode.rail-open .shell { grid-template-columns: minmax(0, 1fr); }
body.setup-mode .chats-rail,
body.setup-mode .rail-handle,
body.setup-mode .chat-dock { display: none !important; }
body.setup-mode .view { padding: 0; }

/* ==========================================================================
   Guided setup
   ========================================================================== */
.setup { display: grid; grid-template-columns: 232px minmax(0, 1fr); min-height: 100vh; background: var(--canvas); }

.setup-rail { background: var(--brand-deep); padding: var(--space-6) var(--space-4); }
.setup-rail ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.setup-rail li {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px;
  border-radius: var(--radius-sm); color: #a8abb0; font-size: 13px; font-weight: 500;
}
.setup-rail li .mark {
  width: 16px; height: 16px; border-radius: 50%; flex: none;
  border: 1.5px solid #5a5d63; display: grid; place-items: center;
}
.setup-rail li.done { color: #dedfe1; }
.setup-rail li.done .mark { background: var(--accent-bright); border-color: var(--accent-bright); }
.setup-rail li.done .mark::after { content: '✓'; font-size: 10px; color: var(--accent-ink); font-weight: 700; }
.setup-rail li.current { color: #fff; background: rgba(255, 255, 255, .08); }
.setup-rail li.current .mark { border-color: var(--accent-bright); box-shadow: 0 0 0 3px rgba(212, 214, 217, .18); }

.setup-stage { padding: var(--space-7) var(--space-6); display: flex; justify-content: center; align-items: flex-start; }
.setup-panel { width: 100%; max-width: 560px; display: flex; flex-direction: column; gap: var(--space-4); }
.setup-panel.wide { max-width: 860px; }
.setup-panel h2 { font-size: 27px; line-height: 1.2; margin: 0; letter-spacing: -.015em; }
.setup-panel h3.setup-subhead { font-size: 15px; margin: var(--space-4) 0 0; }
.setup-eyebrow { margin: 0; font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); }
.setup-lead { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--ink-soft); max-width: 58ch; }
.setup-hero { min-height: 60vh; justify-content: center; }
.setup-form { display: flex; flex-direction: column; gap: var(--space-4); }
.setup-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; margin-top: var(--space-2); }
.btn-lg { padding: 11px 22px; font-size: 15px; border-radius: 10px; }
.btn-quiet { background: none; border-color: transparent; color: var(--ink-soft); }
.btn-quiet:hover { background: var(--surface-sunk); border-color: transparent; }
.field-note { margin: 0; font-size: 12.5px; color: var(--ink-faint); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.setup-more { margin-top: var(--space-2); border-top: 1px solid var(--line); padding-top: var(--space-3); }
.setup-more summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ink-soft); }
.setup-more > *:not(summary) { margin-top: var(--space-3); }

/* Learning progress */
.setup-progress { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.setup-progress li {
  display: flex; align-items: center; gap: 10px; padding: 11px 12px;
  border-radius: var(--radius-sm); color: var(--ink-faint); font-size: 14px; background: var(--surface);
  border: 1px solid var(--line);
}
.setup-progress li .tick { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid var(--line-strong); flex: none; }
.setup-progress li em { margin-left: auto; font-style: normal; font-size: 12px; color: var(--ink-faint); }
.setup-progress li.active { color: var(--ink); }
.setup-progress li.active .tick { border-color: var(--accent); border-right-color: transparent; animation: spin 800ms linear infinite; }
.setup-progress li.done { color: var(--ink); }
.setup-progress li.done .tick { background: var(--accent); border-color: var(--accent); display: grid; place-items: center; }
.setup-progress li.done .tick::after { content: '✓'; color: #fff; font-size: 10px; font-weight: 700; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .setup-progress li.active .tick { animation: none; } }

/* Motion is an enhancement, never the message.
 *
 * Someone who has asked their system for less of it gets the same interface
 * with none: the focused window still has its ring, the new window is still
 * where it belongs, and nothing slides, rises or fades to say so. An entrance
 * animation is exactly the kind of thing that triggers vestibular symptoms,
 * and the ring is doing the actual work in both cases. */
@media (prefers-reduced-motion: reduce) {
  .chat-window,
  .chat-window.is-focused { animation: none; transition: none; }
  .chat-row { transition: none; }
}

/* Sources */
.source-list { display: grid; gap: 6px; max-height: 44vh; overflow-y: auto; }
.source-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: var(--space-3); align-items: center;
  padding: 11px 13px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  cursor: pointer;
}
.source-row input { width: auto; }
.source-row.off { opacity: .5; }
.source-body { display: grid; gap: 1px; min-width: 0; }
.source-body strong { font-size: 14px; }
.source-url { font-size: 12px; color: var(--ink-faint); overflow-wrap: anywhere; }
.source-meta { font-size: 12px; color: var(--ink-faint); white-space: nowrap; }

/* Tone */
.tone-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--space-3); }
.tone {
  text-align: left; background: var(--surface); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: var(--space-4); cursor: pointer; font: inherit; display: grid; gap: 3px;
}
.tone strong { font-size: 14px; }
.tone span { font-size: 12.5px; color: var(--ink-soft); line-height: 1.45; }
.tone:hover { border-color: var(--line-strong); }
.tone.selected { border-color: var(--accent); background: var(--accent-wash); }

/* Try it */
.try { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: var(--space-4); align-items: start; }
.try-chat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.try-messages { min-height: 260px; max-height: 380px; overflow-y: auto; padding: var(--space-4); display: flex; flex-direction: column; gap: 10px; }
.try-bubble { max-width: 82%; padding: 9px 13px; border-radius: 14px; font-size: 14px; line-height: 1.5; white-space: pre-wrap; }
.try-bubble.user { align-self: flex-end; background: var(--brand); color: #fff; }
.try-bubble.assistant { align-self: flex-start; background: var(--surface-sunk); }
.try-bubble.thinking { color: var(--ink-faint); font-style: italic; }
.try-notice { background: var(--warn-wash); color: var(--warn); padding: 10px 13px; border-radius: 10px; font-size: 13px; }
.try-composer { display: grid; grid-template-columns: 1fr auto; gap: var(--space-2); padding: var(--space-3); border-top: 1px solid var(--line); }
.try-suggestions { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 var(--space-3) var(--space-3); }
.chip {
  font: inherit; font-size: 12.5px; cursor: pointer; background: var(--surface-sunk);
  border: 1px solid var(--line); border-radius: 999px; padding: 5px 11px; color: var(--ink-soft);
}
.chip:hover { color: var(--ink); border-color: var(--line-strong); }
.try-sources { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-4); }
.try-sources h4 { margin: 0 0 6px; }
.source-used { list-style: none; margin: var(--space-3) 0 0; padding: 0; display: grid; gap: 8px; }
.source-used li { display: grid; gap: 2px; font-size: 13px; }
.source-used span { font-size: 11.5px; color: var(--ink-faint); overflow-wrap: anywhere; }

/* Checkboxes */
.check-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--space-2); }
.check {
  display: flex; align-items: center; gap: 10px; padding: 11px 13px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: 14px;
}
.check input { width: auto; }
.check:hover { border-color: var(--line-strong); }

/* Widget editor */
.widget-editor { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: var(--space-5); align-items: start; }
.widget-preview { position: sticky; top: var(--space-4); }
.preview-frame {
  background: var(--surface-sunk); border: 1px solid var(--line); border-radius: var(--radius);
  height: 320px; position: relative; overflow: hidden; padding: var(--space-4);
}
.preview-page { display: grid; gap: 8px; }
.preview-page span { display: block; height: 8px; background: var(--line); border-radius: 4px; }
.preview-page span:nth-child(1) { width: 55%; } .preview-page span:nth-child(2) { width: 80%; } .preview-page span:nth-child(3) { width: 40%; }
.preview-widget {
  position: absolute; right: 14px; bottom: 60px; width: 200px; background: var(--surface);
  border-radius: 12px; box-shadow: var(--shadow-lift); overflow: hidden; font-size: 11px;
}
.preview-frame.left .preview-widget, .preview-frame.left .preview-launcher { right: auto; left: 14px; }
.preview-head { background: var(--preview-accent); color: #1b1c1e; padding: 9px 11px; font-size: 11.5px; }
.preview-body { padding: 11px; min-height: 74px; }
.preview-bubble { background: var(--surface-sunk); border-radius: 9px; padding: 7px 9px; line-height: 1.45; }
.preview-input { border-top: 1px solid var(--line); padding: 8px 11px; color: var(--ink-faint); }
.preview-launcher {
  position: absolute; right: 14px; bottom: 14px; background: var(--preview-accent); color: #1b1c1e;
  border-radius: 999px; padding: 9px 15px; font-size: 12px; font-weight: 600; box-shadow: var(--shadow);
}

/* Templates */
.template-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-2); }
.template {
  display: flex; gap: 10px; padding: 12px 13px; cursor: pointer; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.template input { width: auto; margin-top: 2px; }
.template span { display: grid; gap: 2px; }
.template strong { font-size: 13.5px; }
.template em { font-style: normal; font-size: 12px; color: var(--ink-soft); line-height: 1.45; }

/* Install */
.install-methods { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--space-3); }
.method {
  font: inherit; text-align: left; cursor: pointer; display: grid; gap: 3px;
  background: var(--surface); border: 1.5px solid var(--line); border-radius: var(--radius); padding: var(--space-4);
}
.method strong { font-size: 14px; }
.method span { font-size: 12.5px; color: var(--ink-soft); }
.method.selected { border-color: var(--accent); background: var(--accent-wash); }
.steps-list { margin: 0; padding-left: 20px; display: grid; gap: 6px; font-size: 14px; }
.verify { margin-top: var(--space-2); display: grid; gap: var(--space-3); }
.verify-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; font-size: 14px; }
.verify-list li { display: flex; align-items: center; gap: 9px; }
.verify-list li::before {
  content: '○'; width: 18px; height: 18px; display: grid; place-items: center; flex: none;
  border-radius: 50%; font-size: 11px;
}
.verify-list li.yes { color: var(--ink); }
.verify-list li.yes::before { content: '✓'; background: var(--good-wash); color: var(--good); }
.verify-list li.no { color: var(--ink-faint); }
.verify-list li.no::before { background: var(--surface-sunk); color: var(--ink-faint); }
.verify-ok { color: var(--good); font-weight: 600; margin: 0; }

/* Invitations */
.invite-rows { display: grid; gap: var(--space-2); }
.invite-row { display: grid; grid-template-columns: 1fr 140px; gap: var(--space-2); }
.role-help { background: var(--surface-sunk); border-radius: var(--radius-sm); padding: var(--space-4); display: grid; gap: 5px; }
.role-help p { margin: 0; font-size: 13px; color: var(--ink-soft); }
.invite-created { background: var(--accent-wash); border-radius: var(--radius-sm); padding: var(--space-4); margin-top: var(--space-3); }
.invite-created p { margin: 0 0 5px; font-size: 13px; }
.invite-failed { background: var(--danger-wash); border-radius: var(--radius-sm); padding: var(--space-3); margin-top: var(--space-3); color: var(--danger); font-size: 13px; }

/* Finish */
.done-mark {
  width: 52px; height: 52px; border-radius: 50%; background: var(--accent-wash); color: var(--accent);
  display: grid; place-items: center; font-size: 24px;
}
.done-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.done-list li { display: flex; align-items: center; gap: 10px; font-size: 14.5px; color: var(--ink-faint); }
.done-list li .tick { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--line-strong); flex: none; }
.done-list li.done { color: var(--ink); }
.done-list li.done .tick { background: var(--accent); border-color: var(--accent); display: grid; place-items: center; }
.done-list li.done .tick::after { content: '✓'; color: #fff; font-size: 10px; font-weight: 700; }
.done-list li em { font-style: normal; font-size: 12px; color: var(--ink-faint); }

/* ==========================================================================
   Home
   ========================================================================== */
.home { display: grid; gap: var(--space-5); }
.home-greeting h2 { font-size: 25px; margin: 0 0 3px; letter-spacing: -.015em; }
.home-greeting p { margin: 0; font-size: 14.5px; }

.stat-link { text-decoration: none; color: inherit; transition: border-color .12s ease; }
.stat-link:hover { border-color: var(--line-strong); }

.setup-card {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-5); align-items: center;
  background: var(--surface); border: 1px solid var(--accent); border-left-width: 3px;
  border-radius: var(--radius); padding: var(--space-5); box-shadow: var(--shadow);
}
.setup-card h3 { margin: 0 0 3px; font-size: 16px; }
.setup-card-body p { margin: 0 0 var(--space-3); }
.setup-card-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 16px; }
.setup-card-list li { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--ink-faint); }
.setup-card-list li .tick { width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--line-strong); flex: none; }
.setup-card-list li.done { color: var(--ink); }
.setup-card-list li.done .tick { background: var(--accent); border-color: var(--accent); }
.setup-card-actions { display: grid; gap: var(--space-2); }

.attention { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-4) var(--space-5); }
.attention h3 { margin: 0 0 var(--space-3); font-size: 15px; }
.attention ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.attention li { display: flex; align-items: center; gap: 10px; font-size: 14px; }
.attention li::before { content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none; }
.attention li.warn::before { background: var(--warn); }
.attention li.danger::before { background: var(--danger); }
.attention li.info::before { background: var(--accent); }
.attention a { color: var(--ink); text-decoration: none; }
.attention a:hover { text-decoration: underline; }

.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.card-head h3 { margin: 0; }
.card-head a { font-size: 12.5px; text-decoration: none; color: var(--accent); }

/* --- the operational overview ------------------------------------------- */

/* Six numbers, one row. They share a width so none of them looks more
   important than the rest by accident; the values do that work. */
.kpi-row { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--space-3); }
.kpi {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 13px var(--space-4); display: grid; gap: 2px; text-decoration: none; color: inherit;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.kpi:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.kpi-label { font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.kpi-value { font-size: 26px; line-height: 1.15; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }

.range-switch { display: inline-flex; background: var(--surface-sunk); border-radius: 999px; padding: 3px; gap: 2px; }
.range-switch button {
  border: 0; background: none; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ink-soft);
  padding: 5px 12px; border-radius: 999px; cursor: pointer;
}
.range-switch button.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }

/* The custom range sits beside the presets rather than replacing them, so the
   operator can see what they are stepping away from. It wraps to its own line
   on a narrow screen instead of squeezing the date fields to nothing. */
.analytics-toolbar { flex-wrap: wrap; row-gap: var(--space-2); }
/* The site picker is one control among several, not a banner: left to grow it
   claimed a whole row to itself beside a range switch that had already fitted. */
.analytics-toolbar > select { flex: 0 1 auto; width: auto; min-width: 160px; max-width: 280px; }
.date-range { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.date-range label { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.date-range input { min-width: 0; }
.date-range[hidden] { display: none; }

/* A series toggle carries the colour of the line it controls, so turning one
   off is visibly the same act as reading it in the legend. */
/* The funnel is a bar list whose label is a link, because a stage nobody can
   open is a number to look at rather than somewhere to go. */
.funnel .funnel-row { display: grid; grid-template-columns: minmax(120px, 1.1fr) minmax(0, 2fr) auto auto; gap: 10px; align-items: center; }
.funnel .funnel-label { font-weight: 600; }
.funnel .funnel-row em { min-width: 38px; text-align: right; }

.series-toggle {
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft);
}
.series-toggle i { width: 9px; height: 9px; border-radius: 3px; opacity: .35; }
.series-toggle.active { border-color: var(--line-strong); color: var(--ink); }
.series-toggle.active i { opacity: 1; }

.chart-card .card-head { align-items: center; }
.chart-switches { display: flex; gap: var(--space-2); flex-wrap: wrap; }
/* The height is chosen in JS from the container's width and the size of the
   numbers, so nothing here may fix it. The minimum is only there to stop the
   card collapsing in the frame before the first draw. */
.chart-host { position: relative; min-height: 132px; }
/* The chart is drawn at a measured pixel width so its labels stay crisp. This
   is the belt to that braces: between a container narrowing and the observer
   redrawing, a stale drawing scales down by a pixel or two instead of pushing
   a horizontal scrollbar across the page. */
.chart-svg { display: block; max-width: 100%; }
.chart-grid { stroke: var(--line); stroke-width: 1; }
.chart-tick, .chart-label { font-size: 11px; fill: var(--ink-faint); font-family: var(--font); }
.chart-hit:hover, .chart-hit:focus-visible { fill: rgba(53, 55, 59, .04); }
/* Focusable, because the figures have to be reachable without a pointer now
   that the SVG <title> — which was also the browser's second, native tooltip —
   is gone. The column highlight above is the visible focus state; the default
   outline would be a rectangle over the plot. */
.chart-hit { outline: none; }
.chart-hit:focus-visible { stroke: var(--brand); stroke-width: 1.5; stroke-dasharray: 3 3; }

/* The trend: a line over a soft area, so the shape of the period reads before
   any single value does. */
.chart-area { opacity: .16; stroke: none; }
.chart-line {
  fill: none; stroke-width: 2.25;
  stroke-linejoin: round; stroke-linecap: round;
}
.chart-point, .chart-marker { stroke: var(--surface); stroke-width: 2; }
.chart-cursor { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 3; }
.chart-cursor[hidden], .chart-marker[hidden] { display: none; }
.chart-empty { margin: 0; padding: 52px 0; text-align: center; color: var(--ink-faint); }

/* Placed beside the hovered column by chart.js, which also flips it to the
   other side near an edge — so `left` and `top` are both set from script and
   there is no transform to undo. Opaque on purpose: a translucent card over a
   chart makes the lines legible and the figures not, which is the wrong way
   round for something whose only job is to be read. */
.chart-tip {
  position: absolute; top: 4px; left: 0;
  background: var(--ink); color: #fff; border-radius: var(--radius-sm);
  padding: 7px 10px; font-size: 12px; line-height: 1.45; pointer-events: none;
  display: grid; gap: 1px; white-space: nowrap; z-index: 2; box-shadow: var(--shadow-lift);
  transition: left var(--motion-fast) var(--ease-out), top var(--motion-fast) var(--ease-out);
}
@media (prefers-reduced-motion: reduce) { .chart-tip { transition: none; } }
/* A class that sets `display` outranks the browser's own [hidden] rule, so
   without this the tooltip is a black rectangle sitting on the chart from the
   moment the page loads. */
.chart-tip[hidden] { display: none; }
.chart-tip strong { font-size: 12.5px; }
/* Each row carries the colour of the shape it describes, so the tooltip and
   the plot cannot be read as two unrelated things. */
.chart-tip .tip-row { display: flex; align-items: center; gap: 6px; }
.chart-tip .tip-row i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.chart-tip .tip-row b { margin-left: auto; padding-left: 12px; }

.legend { margin-top: var(--space-3); }
.legend-item i.swatch-total { background: var(--brand); }
.legend-item i.swatch-new { background: var(--series-2); }
.legend-item i.swatch-returning { background: var(--brand); }
.legend-note { margin-left: auto; font-size: 11.5px; color: var(--ink-faint); }

.overview-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: var(--space-4); align-items: start; }

/* Top pages: the bar is the comparison, so it sits behind the words rather
   than competing with them for space.

   minmax(0, 1fr) is what keeps the row inside the card. A single implicit
   column is sized `auto`, which takes its width from the widest item — and a
   page title is one long nowrap string, so the row grew to 494px inside a
   329px card and carried the view count 127px past the edge, where nothing
   clipped it and nobody could read it. The floor of 0 lets the track shrink,
   which is what lets `.page-name` ellipsise as it was always meant to. */
.page-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); }
.page-list li {
  position: relative; display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); padding: 9px 10px; border-radius: var(--radius-sm); font-size: 13.5px;
}
.page-bar {
  position: absolute; inset: 0 auto 0 0; width: var(--fill); border-radius: var(--radius-sm);
  background: var(--accent-wash);
}
.page-name, .page-views { position: relative; }
.page-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.page-views { flex: none; color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* A visitor row answers who, where, what they are doing and whether they are
   here — in that order, because that is the order the question is asked. */
.visitor-rows { list-style: none; margin: 0; padding: 0; display: grid; }
.visitor-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-3);
  align-items: start; padding: 11px 0; border-bottom: 1px solid var(--line);
}
.visitor-row:last-child { border-bottom: 0; }
.visitor-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); margin-top: 6px; }
.visitor-row.online .visitor-dot { background: var(--good); box-shadow: 0 0 0 3px var(--good-wash); }
.visitor-main { display: grid; gap: 2px; min-width: 0; }
.visitor-name { font-weight: 600; font-size: 14px; display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.visitor-id { font-weight: 500; font-size: 11.5px; color: var(--ink-faint); }
.visitor-facts { font-size: 12.5px; color: var(--ink-soft); }
.visitor-page { font-size: 12.5px; color: var(--ink-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.visitor-side { display: grid; justify-items: end; gap: 5px; flex: none; }
.visitor-when { font-size: 12px; color: var(--ink-soft); }
.visitor-row.online .visitor-when { color: var(--good); font-weight: 600; }
.visitor-actions { display: flex; gap: 6px; }

@media (max-width: 1080px) {
  .try, .widget-editor { grid-template-columns: 1fr; }
  .widget-preview { position: static; }
  /* Six across becomes unreadably narrow before this width; three and three
     keeps every number legible instead of shrinking all of them. */
  .kpi-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .overview-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 760px) {
  /* Below this there is no width to share: what happened and when go on one
     line, and the page it happened on gets the full width underneath. */
  .journey li { grid-template-columns: 1fr auto; row-gap: 2px; }
  .journey-page { grid-column: 1 / -1; }

  .setup { grid-template-columns: 1fr; }
  .setup-rail { display: none; }
  .setup-stage { padding: var(--space-5) var(--space-4); }
  .setup-card { grid-template-columns: 1fr; }
  .field-row, .invite-row { grid-template-columns: 1fr; }

  /* Two columns of full-size tiles, not six shrunken ones. A number nobody
     can read is worse than a number below the fold. */
  .kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
  .kpi { padding: 11px var(--space-3); }
  .kpi-value { font-size: 22px; }

  .chart-card .card-head { flex-wrap: wrap; row-gap: var(--space-2); }
  .legend { flex-direction: column; align-items: flex-start; gap: 4px; }
  .legend-note { margin-left: 0; }

  /* The actions move under the row rather than squeezing the name. */
  .visitor-row { grid-template-columns: auto minmax(0, 1fr); row-gap: var(--space-2); }
  .visitor-side { grid-column: 2; justify-items: start; grid-auto-flow: column; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
}

/* A colour input inherits the text-input box by default and collapses to a
   line; give it a real swatch. */
input[type="color"] {
  padding: 4px; height: 38px; cursor: pointer; background: var(--surface);
}
input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
input[type="color"]::-webkit-color-swatch { border: 1px solid var(--line); border-radius: 5px; }
input[type="color"]::-moz-color-swatch { border: 1px solid var(--line); border-radius: 5px; }

/* Home carries its own greeting, so the generic page title would repeat it. */
body.home-mode .topbar h1,
body.home-mode .topbar p { display: none; }

/* ------------------------------------------------------- Operator workspace */
/*
 * The Chats rail and the chat dock.
 *
 * Every window is the same width, the same header height, the same composer
 * height, and sits on one shared baseline. Nothing is positioned by hand, so
 * nothing can drift off the edge of the screen — which is the single biggest
 * difference between this and the plugin it replaces.
 */

:root {
  --rail-width: 372px;
  --chat-window-width: 320px;
  --chat-window-height: 420px;
  --chat-head-height: 56px;
  --chat-status-height: 34px;
}

/* ---- rail ---- */
.chats-rail {
  grid-column: 3;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  background: var(--surface);
  border-left: 1px solid var(--line);
}
body:not(.rail-open) .chats-rail { display: none; }

.rail-head { padding: var(--space-4); display: grid; gap: var(--space-3); border-bottom: 1px solid var(--line); flex: 0 0 auto; }
.rail-title { display: flex; align-items: center; gap: var(--space-2); }
.rail-title h2 { margin: 0; font-size: 16px; }
.rail-count {
  font-size: 12px; font-weight: 600; color: var(--ink-soft);
  background: var(--surface-sunk); border-radius: 999px; padding: 1px 8px;
}
.rail-count[data-unread] { background: var(--brand); color: #fff; }
.rail-collapse {
  margin-left: auto; border: 0; background: none; cursor: pointer;
  font-size: 18px; line-height: 1; color: var(--ink-faint); padding: 4px 6px; border-radius: var(--radius-sm);
}
.rail-collapse:hover { color: var(--ink); background: var(--surface-sunk); }

.rail-search { width: 100%; font: inherit; padding: 8px 11px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); }
.rail-filters { display: flex; gap: 4px; }
.rail-filters button {
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft);
  border-radius: 999px; padding: 4px 11px;
}
.rail-filters button.active { background: var(--brand); border-color: var(--brand); color: #fff; }

.rail-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.rail-empty { padding: var(--space-6) var(--space-4); color: var(--ink-faint); font-size: 13px; text-align: center; }

/* ---- one conversation in the rail ---- */
/* Identity, what the customer said, then when. Nothing else competes. */
.chat-row {
  display: flex; gap: var(--space-3); width: 100%; text-align: left;
  padding: 11px var(--space-4); border: 0; border-bottom: 1px solid var(--line);
  background: none; cursor: pointer; font: inherit; align-items: flex-start;
  transition: background var(--motion-fast) linear, box-shadow var(--motion-fast) linear;
}
.chat-row:hover { background: var(--surface-sunk); }
.chat-row.open { background: var(--accent-wash); }
/* The rail always shows which conversation is being worked in, including when
   the Inbox owns it and there is no window to look at. Inset shadows only, so
   a row never changes width and the rail never scrolls sideways.

   One 3px marker down the leading edge — the same graphite as the window's
   ring, so the rail and the dock are saying the same thing in the same
   colour. The 45%-alpha outline that used to trace the whole row went with the
   rest of the pile-up. */
.chat-row.is-focused {
  background: var(--surface-sunk);
  box-shadow: inset 3px 0 0 var(--active-chat-color);
}
.chat-row.unread .chat-row-name { font-weight: 700; }
.chat-row.unread .chat-row-preview { color: var(--ink); font-weight: 500; }

.chat-row-avatar {
  position: relative; flex: 0 0 34px; height: 34px; border-radius: 50%;
  background: var(--surface-sunk); display: grid; place-items: center;
  font-size: 15px; color: var(--ink-soft);
}
.chat-row-avatar.online::after {
  content: ''; position: absolute; right: -1px; bottom: -1px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--good); border: 2px solid var(--surface);
}
.chat-row-body { display: grid; gap: 1px; min-width: 0; flex: 1 1 auto; }
.chat-row-top { display: flex; align-items: center; gap: var(--space-2); }
.chat-row-name {
  font-size: 13.5px; color: var(--ink); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1 1 auto;
}
.chat-row-badge {
  flex: 0 0 auto; background: var(--brand); color: #fff; font-size: 11px; font-weight: 700;
  border-radius: 999px; min-width: 18px; height: 18px; padding: 0 5px;
  display: grid; place-items: center;
}
.chat-row-preview {
  font-size: 12.5px; color: var(--ink-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-row-meta { font-size: 11.5px; color: var(--ink-faint); }

/* ---- the tab that brings the rail back ---- */
.rail-handle {
  position: fixed; right: 0; bottom: 96px; z-index: 30;
  display: flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); border-right: 0; background: var(--surface);
  border-radius: var(--radius) 0 0 var(--radius); box-shadow: var(--shadow);
  padding: 9px 13px; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.rail-handle[hidden] { display: none; }
.handle-badge {
  background: var(--brand); color: #fff; border-radius: 999px;
  font-size: 11px; padding: 1px 6px; min-width: 18px; text-align: center;
}

/* ---- the dock ---- */
/*
 * `align-items: flex-end` is what gives every window one baseline however
 * tall its contents are, and the row can never overflow because the number of
 * docked windows is capped and the rest go to the tray.
 */
/* Anchored to the shell, not to the workspace column, and offset past the rail
   so a window can never sit underneath it. */
.chat-dock {
  position: absolute; bottom: 0; z-index: 20;
  right: var(--space-5);
  display: flex; align-items: flex-end; gap: var(--space-3);
  pointer-events: none;
  max-width: calc(100vw - 232px - var(--space-5) * 2);
}
body.rail-open .chat-dock {
  right: calc(var(--rail-width, 372px) + var(--space-5));
  max-width: calc(100vw - 232px - var(--rail-width, 372px) - var(--space-5) * 2);
}
.chat-dock[hidden] { display: none; }
.chat-dock > * { pointer-events: auto; }

/* With windows open the workspace reserves room for them, so the last card on
   a screen can still be scrolled into view instead of sitting under a chat. */
body.chats-docked .view { padding-bottom: calc(var(--chat-window-height) + var(--space-4)); }

.chat-window {
  width: var(--chat-window-width);
  flex: 0 0 var(--chat-window-width);
  height: var(--chat-window-height);
  max-height: min(var(--chat-window-height), calc(100dvh - 140px));
  display: flex; flex-direction: column; min-height: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  box-shadow: var(--shadow-lift);
  overflow: hidden;
}
/* ---- the conversation being worked in ----
   With three windows open, "which one am I typing into" is the question the
   operator asks most often.

   One ring answers it. The version before this stacked seven coloured shadows
   — a ring and a 22px glow on the window, plus an inset ring, an inset bar and
   another 16px glow on the header — because the lime it was drawn in measured
   1.46:1 against the card and could not be seen on its own. Piling translucent
   colour on top of an invisible signal is what made it look cheap; the fix was
   a colour you can actually see, and then one of everything.

   Still box-shadow, never border width, margin or a lift: every window shares
   one baseline so their headers line up and the eye can scan across them. A
   ring that changed the box would shove the two beside it sideways, and a
   focused window sitting 3px higher — which looked right, and which the
   acceptance suite caught across five viewports — breaks the row it is in.
   Colour is never the only signal: the focused window also carries
   aria-current for anyone who cannot see it. */
.chat-window {
  transition:
    box-shadow var(--motion-slow) var(--ease-out),
    border-color var(--motion-fast) linear;
}
.chat-window.is-focused {
  border-color: var(--active-chat-color);
  box-shadow:
    0 0 0 2px var(--active-chat-color),
    0 10px 30px color-mix(in srgb, var(--active-chat-color) 22%, transparent),
    var(--shadow-lift);
}

/* Opening a window is the one place a little motion earns its keep: three
   windows share a baseline, so a new one appearing instantly is easy to miss
   and easy to mistake for one that was already there. It rises the last few
   pixels into place and is done in 220ms. It ends at transform: none, because
   the resting state of every window, focused or not, is the shared baseline. */
@keyframes chat-window-in {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
.chat-window { animation: chat-window-in var(--motion-slow) var(--ease-out) both; }
/* Unread is not focus. A window can be focused with nothing unread in it, and
   a background window can be full of unread messages; they had the same green
   ring, which made both meaningless. Unread now marks the header edge. */
.chat-window.has-unread .chat-window-head::before {
  content: ''; position: absolute; z-index: 1; inset: 0 0 auto; height: 3px;
  background: var(--warn);
}

.chat-window-head {
  position: relative; z-index: 2;
  flex: 0 0 var(--chat-head-height); height: var(--chat-head-height);
  display: flex; align-items: center; gap: var(--space-2);
  padding: 8px var(--space-3); cursor: pointer;
  background: var(--brand); color: var(--brand-contrast);
}
/* The header used to carry an inset ring, an inset bar and a third glow of its
   own. Three more statements of the thing the ring around the window already
   says — and the reason a graphite ring reads cleanly here is that nothing is
   competing with it. Deliberately left with nothing. */
.chat-back { display: none; }
.chat-window-who { min-width: 0; flex: 1 1 auto; display: grid; gap: 1px; }
.chat-window-name { display: flex; align-items: center; gap: 5px; min-width: 0; font-size: 13.5px; font-weight: 600; }
.chat-name-button {
  display: inline-flex; align-items: center; gap: 4px; min-width: 0;
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit; color: inherit;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-name-pencil { opacity: 0; font-size: 11px; }
.chat-window-head:hover .chat-name-pencil { opacity: .75; }
.chat-window-sub { font-size: 11px; opacity: .8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-window-controls { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
.chat-icon {
  border: 0; background: none; color: inherit; cursor: pointer; font: inherit;
  width: 26px; height: 26px; border-radius: var(--radius-sm); line-height: 1;
  display: grid; place-items: center; font-size: 15px;
}
.chat-icon:hover { background: rgba(255, 255, 255, .16); }

.chat-rename { display: flex; align-items: center; gap: 3px; width: 100%; }
.chat-rename input {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 13px;
  padding: 3px 7px; border-radius: var(--radius-sm);
  border: 1px solid rgba(255, 255, 255, .4); background: rgba(255, 255, 255, .12); color: #fff;
}
.chat-rename input::placeholder { color: rgba(255, 255, 255, .6); }

.chat-window-status {
  flex: 0 0 var(--chat-status-height); height: var(--chat-status-height);
  display: flex; align-items: center; gap: var(--space-2);
  padding: 6px var(--space-3); border-bottom: 1px solid var(--line);
  background: var(--surface-sunk); font-size: 11.5px;
}
.chat-presence { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-faint); }
.chat-presence::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--line-strong); }
.chat-presence.online { color: var(--good); }
.chat-presence.online::before { background: var(--good); }
.colour-field { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.colour-field input[type="color"] {
  width: 44px; height: 32px; padding: 2px; cursor: pointer;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface);
}
.colour-field input[type="text"] { width: 9ch; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* ---- who answers this conversation ----
   One control, used in a docked window and in the Inbox header. The chip says
   the current mode without being opened; the menu names both options and what
   each one does before either is chosen. */
/* In a docked window the chip is pushed to the right of the status row; in the
   Inbox header it is one control among several and must not be, or the auto
   margin claims the whole line and pushes assignment, priority and Close onto
   a second row of full-width selects. */
.reply-mode { position: relative; }
.reply-mode-button {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font: inherit; font-size: 11px; font-weight: 700; letter-spacing: .02em;
  border-radius: 999px; padding: 3px 9px; border: 1px solid transparent;
  background: var(--ai-wash); color: var(--ai); border-color: var(--ai-edge);
}
.reply-mode.is-human .reply-mode-button { background: var(--brand); color: #fff; border-color: var(--brand); }
.reply-mode-button:hover { filter: brightness(.97); }
.reply-mode-icon { font-size: 11px; line-height: 1; }
.reply-mode-caret { font-size: 9px; opacity: .7; }
.reply-mode-full .reply-mode-button { font-size: 12.5px; padding: 6px 12px; border-radius: var(--radius-sm); }

/* In a dock, mode is a primary header action beside minimise and close. The
   translucent treatment keeps the label readable on the brand strip without
   turning the whole header into the active highlight colour. */
.chat-window-head .reply-mode-button {
  min-height: 28px; padding: 4px 8px;
  background: rgba(255, 255, 255, .12); color: #fff;
  border-color: rgba(255, 255, 255, .3);
}
.chat-window-head .reply-mode.is-ai .reply-mode-button {
  background: rgba(127, 180, 236, .22);
  border-color: rgba(127, 180, 236, .70);
}
.chat-window-head .reply-mode.is-human .reply-mode-button {
  background: rgba(255, 255, 255, .12); color: #fff;
  border-color: rgba(255, 255, 255, .3);
}

.reply-mode-menu {
  position: absolute; z-index: 60; top: calc(100% + 6px); right: 0;
  /* Anchored to the right edge of a chip that is itself inside the window, and
     capped against the viewport, so it cannot push the page sideways on a
     phone. */
  width: max-content; min-width: 210px; max-width: min(280px, calc(100vw - 32px));
  display: grid; gap: 2px; padding: 5px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lift);
  text-align: left;
}
/* `display: grid` above beats the browser's own [hidden] rule, so the menu was
   permanently open — covering the messages beneath it and swallowing clicks
   meant for them. The same trap the tray list has a rule for. */
.reply-mode-menu[hidden] { display: none; }
.reply-mode-option {
  display: grid; gap: 2px; width: 100%; text-align: left; cursor: pointer;
  font: inherit; background: none; border: 0; padding: 7px 8px; border-radius: var(--radius-sm);
  color: var(--ink);
}
.reply-mode-option:hover, .reply-mode-option:focus-visible { background: var(--surface-sunk); }
.reply-mode-option.is-current { background: var(--accent-wash); }
.reply-mode-option-head {
  display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 650;
}
.reply-mode-option-label { flex: 1 1 auto; }
.reply-mode-tick { color: var(--accent); font-weight: 700; }
.reply-mode-option-note { font-size: 11.5px; color: var(--ink-soft); line-height: 1.35; }
.reply-mode-option-meta { font-size: 11px; color: var(--ink-faint); word-break: break-word; }
.reply-mode-warning {
  margin: 3px 2px 1px; padding: 6px 8px; border-radius: var(--radius-sm);
  background: var(--warn-wash); color: var(--warn); font-size: 11.5px; line-height: 1.35;
}
.chat-expand { margin-left: auto; font-size: 11.5px; color: var(--ink-soft); text-decoration: none; }
.chat-expand:hover { color: var(--brand); text-decoration: underline; }

.chat-window-messages {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: var(--space-3); display: flex; flex-direction: column; gap: 8px;
}
.chat-message { display: grid; gap: 2px; max-width: 88%; }
.chat-message.visitor { justify-self: start; }
.chat-message.agent, .chat-message.assistant { justify-self: end; text-align: right; }
.chat-bubble {
  padding: 7px 11px; border-radius: 13px; font-size: 13px; line-height: 1.45;
  background: var(--surface-sunk); white-space: pre-wrap; overflow-wrap: anywhere;
}
.chat-message.agent .chat-bubble { background: var(--brand); color: #fff; }
.chat-message.assistant .chat-bubble { background: var(--ai-wash); color: var(--ink); }
.chat-message.proactive .chat-bubble { background: var(--warn-wash); color: var(--warn); }
.chat-message-meta { font-size: 10.5px; color: var(--ink-faint); }
.chat-empty { margin: auto; color: var(--ink-faint); font-size: 12.5px; text-align: center; }

.chat-composer {
  flex: 0 0 auto; min-height: 58px; display: flex; align-items: flex-end; gap: var(--space-2);
  padding: var(--space-2) var(--space-3) var(--space-3); border-top: 1px solid var(--line);
}
.chat-composer textarea {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 13px; resize: none;
  padding: 7px 11px; border: 1px solid var(--line-strong); border-radius: 16px;
  min-height: 34px; max-height: 120px; line-height: 1.4;
}
.chat-send {
  flex: 0 0 auto; font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  min-height: 34px; background: var(--brand); color: #fff; border: 0;
  border-radius: 999px; padding: 8px 14px;
}

/* ---- the overflow tray ---- */
/* No cap on how many conversations may be open; a cap on how many are on
   screen. The rest wait here rather than escaping the viewport. */
.chat-tray { position: relative; align-self: flex-end; flex: 0 0 auto; }
.chat-tray-toggle {
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line); border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0; padding: 11px 14px;
  box-shadow: var(--shadow); display: flex; align-items: center; gap: 6px;
  /* The tray is a label, not a paragraph: wrapping it to two lines made it
     look like a squeezed fourth window rather than a control. */
  white-space: nowrap;
}
.chat-tray-list {
  position: absolute; bottom: calc(100% + 6px); right: 0; min-width: 210px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-lift); padding: 5px; display: grid; gap: 2px; max-height: 320px; overflow-y: auto;
}
.chat-tray-list[hidden] { display: none; }
.chat-tray-item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  font: inherit; font-size: 13px; text-align: left; cursor: pointer;
  background: none; border: 0; border-radius: var(--radius-sm); padding: 7px 9px; width: 100%;
}
.chat-tray-item:hover { background: var(--surface-sunk); }
.chat-tray-badge { background: var(--brand); color: #fff; border-radius: 999px; font-size: 11px; padding: 1px 6px; }

/* ---- the focused Inbox route ---- */
.inbox-thread { display: flex; flex-direction: column; padding: 0; min-height: 0; overflow: hidden; }
.focus-head {
  position: relative; z-index: 1;
  flex: 0 0 auto; display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--space-4); padding: var(--space-4); border-bottom: 1px solid var(--line); flex-wrap: wrap;
}
/* The Inbox says the same thing the dock says, in the same colour and with the
   same restraint: one solid 2px rule under the header, no wash behind it. */
.inbox-thread.is-focused .focus-head {
  border-bottom-color: var(--active-chat-color);
  box-shadow: inset 0 -2px 0 var(--active-chat-color);
}
.focus-who { min-width: 0; }
.focus-who h2 { margin: 0 0 2px; font-size: 17px; display: flex; align-items: center; gap: 7px; }
.focus-who p { margin: 0; font-size: 12.5px; }
.icon-button {
  border: 0; background: none; cursor: pointer; color: var(--ink-faint);
  font-size: 13px; padding: 2px 5px; border-radius: var(--radius-sm);
}
.icon-button:hover { color: var(--brand); background: var(--surface-sunk); }
.focus-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
/* Controls default to width:100%, which is right in a form and wrong in a
   toolbar: each select claimed the whole row, so assignment, priority and
   Close stacked into three full-width lines with the mode chip alone above
   them. The same override .thread-actions already uses. */
.focus-actions select { width: auto; min-width: 116px; max-width: 190px; }
.focus-messages {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: var(--space-4); display: grid; gap: var(--space-3); align-content: start;
}
.focus-composer { flex: 0 0 auto; padding: var(--space-3) var(--space-4) var(--space-4); border-top: 1px solid var(--line); display: grid; gap: var(--space-2); }
.focus-composer-row { display: flex; gap: var(--space-2); align-items: flex-end; }
.focus-composer textarea { flex: 1 1 auto; min-width: 0; resize: none; }
.inbox-context { overflow-y: auto; min-height: 0; }

/* ---- responsive ---- */
/*
 * A phone is not a narrow desktop. The three-column shell is abandoned rather
 * than squeezed: navigation becomes a disclosure at the top, the rail becomes
 * a full-screen sheet, and a chat window fills the screen so the composer sits
 * above the keyboard instead of below the fold.
 */
@media (max-width: 1280px) {
  :root { --rail-width: 320px; --chat-window-width: 296px; }
}

@media (max-width: 1080px) {
  /* Two panels at once is one too many at this width: the rail wins, because
     the conversation is the work. */
  body.rail-open .shell { grid-template-columns: 232px 0 minmax(0, 1fr); }
  body.rail-open main { display: none; }
  .inbox-focus { grid-template-columns: minmax(0, 1fr); }
  .inbox-context { max-height: 340px; }
}

@media (max-width: 760px) {
  .shell, body.rail-open .shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }
  .sidebar {
    grid-row: 1; height: auto; overflow: visible;
    flex-direction: row; align-items: center; gap: var(--space-3);
    padding: 10px var(--space-4);
  }
  .sidebar nav { display: none; position: absolute; top: 100%; left: 0; right: 0; z-index: 40; }
  .sidebar nav.open {
    display: block; background: var(--brand-deep);
    padding: var(--space-3); max-height: 60dvh; overflow-y: auto;
  }
  .nav-toggle {
    display: block; margin-left: auto; font: inherit; font-size: 13px; font-weight: 600;
    background: rgba(255, 255, 255, .12); color: #fff; border: 0;
    border-radius: var(--radius-sm); padding: 7px 12px; cursor: pointer;
  }
  .sidebar-foot { display: none; }
  .brand { margin: 0; }

  main { grid-row: 2; }
  body.rail-open main { display: none; }
  .chats-rail { grid-column: 1; grid-row: 2; border-left: 0; }
  .rail-handle { bottom: 16px; }

  /* One conversation, full screen, with the composer reachable. */
  body.chats-docked .view { padding-bottom: var(--space-6); }
  .chat-dock, body.rail-open .chat-dock {
    position: fixed; inset: 0; right: 0; z-index: 60;
    padding: 0; gap: 0; max-width: none;
    flex-direction: column; align-items: stretch;
    background: var(--surface);
  }
  .chat-window {
    width: 100%; flex: 1 1 auto;
    height: auto; max-height: none; min-height: 0;
    border: 0; border-radius: 0;
  }
  .chat-dock .chat-window ~ .chat-window { display: none; }
  /* One conversation fills the screen, so a ring around it would paint outside
     the viewport and give the page a horizontal scrollbar for no information:
     there is nothing to distinguish it from. The inset edge keeps the state
     visible without anything reaching past the edge. */
  .chat-window.is-focused {
    box-shadow: inset 0 0 0 2px var(--active-chat-color);
  }
  /* On a phone the menu is pinned to the header rather than hung off the
     right edge of the chip. Anchoring it to the chip put its left edge seven
     pixels past the side of a 390px screen, because the chip sits well to the
     right and the menu is wider than the space left of it. Pinning both sides
     of the row makes that impossible to reproduce at any width. It still opens
     downwards over the message list and stops well short of the composer. */
  .chat-window-head .reply-mode { position: static; }
  .chat-window-head .reply-mode-menu {
    top: calc(100% + 6px); left: var(--space-3); right: var(--space-3);
    width: auto; min-width: 0; max-width: none;
    max-height: 50dvh; overflow-y: auto;
  }
  /* Going back is the primary action here; minimising has no meaning when
     there is no dock to minimise into. */
  .chat-back {
    display: grid; place-items: center; flex: 0 0 auto;
    width: 34px; height: 34px; margin-left: -6px;
    font: inherit; font-size: 24px; line-height: 1;
    border: 0; background: none; color: inherit; cursor: pointer;
    border-radius: var(--radius-sm);
  }
  .chat-back:hover { background: rgba(255, 255, 255, .16); }
  .chat-window-controls [data-minimise] { display: none; }
  /* The tray sits above the conversation, in the flow, rather than pinned to
     the bottom of the screen — where it covered the reply field, so an
     operator with more than one chat open could not tap the composer at all.
     It is first in the markup, so putting it back in the flow puts it where it
     reads: "there are more conversations", above the one you are in. */
  .chat-tray {
    position: static; align-self: stretch; background: var(--surface);
    border-bottom: 1px solid var(--line);
  }
  .chat-tray-toggle {
    width: 100%; border-radius: 0; justify-content: center;
    border: 0; box-shadow: none;
  }
  .chat-tray-list {
    position: static; min-width: 0; border-radius: 0; border: 0;
    border-top: 1px solid var(--line); box-shadow: none; max-height: 40dvh;
  }
  .focus-actions { width: 100%; }
}

/* A pointer-coarse device gets larger hit targets without changing layout. */
@media (pointer: coarse) {
  .chat-icon { width: 34px; height: 34px; }
  .chat-row { padding: 13px var(--space-4); }
}
