/* ==========================================================================
   Wasl Chat — design system
   --------------------------------------------------------------------------
   app.css grew across ~20 releases and lost its system: 456 distinct hardcoded
   colours in 804 declarations, 23 border-radius values, 115 distinct shadows in
   128 declarations, 267 !important. That is not a style problem, it is the
   absence of a system — which is exactly what reads as "unprofessional".

   This file is that system. It loads last and does three things in order:
     1. defines one scale for colour, type, spacing, radius and elevation
     2. sweeps the accumulated geometry noise onto those scales
     3. restyles the chrome an operator actually looks at all day

   The product is an omnichannel console: agents live in it for a full shift, so
   the direction is calm and dense rather than decorative. Green stays the brand
   but stops being everywhere — it now marks intent (primary action, active
   state, own-channel) and the rest of the interface is a disciplined neutral.
   ========================================================================== */

/* === THEME MATRIX — generated by scripts/build-themes.js. Do not edit by hand. === */
/* Two axes: data-surface (ink|light|warm) x data-accent (green|blue|violet|amber).
   Every value below is derived and contrast-verified by the generator — see the script
   for the thresholds. Change the inputs there and re-run, never edit these literals. */
:root,
[data-surface="ink"][data-accent="green"]{--s-canvas:#0d1117;--s-surface:#141a21;--s-raised:#1a212a;--s-sunken:#10161c;--s-border:#232b34;--s-border-strong:#33404c;--s-ink:#dedfe0;--s-body:#b4b6b8;--s-muted:#828689;--s-faint:#666a6f;--s-brand:#16a37b;--s-brand-ink:#16a37b;--s-brand-tint:#142d2e;--s-brand-edge:#1e554d;--s-on-brand:#0b0f13;--s-danger:#f2778a;--s-danger-tint:#382932;--s-warn:#e0b458;--s-warn-tint:#35332a;--s-info:#7fb2e8;--s-info-tint:#253241;--s-e1:0 1px 2px rgba(0,0,0,.5);--s-e2:0 6px 16px rgba(0,0,0,.55);--s-e3:0 20px 48px rgba(0,0,0,.65)}
[data-surface="ink"][data-accent="blue"]{--s-canvas:#0d1117;--s-surface:#141a21;--s-raised:#1a212a;--s-sunken:#10161c;--s-border:#232b34;--s-border-strong:#33404c;--s-ink:#dedfe0;--s-body:#b4b6b8;--s-muted:#828689;--s-faint:#666a6f;--s-brand:#3b7df0;--s-brand-ink:#538df2;--s-brand-tint:#19283e;--s-brand-edge:#2b4876;--s-on-brand:#0b0f13;--s-danger:#f2778a;--s-danger-tint:#382932;--s-warn:#e0b458;--s-warn-tint:#35332a;--s-info:#7fb2e8;--s-info-tint:#253241;--s-e1:0 1px 2px rgba(0,0,0,.5);--s-e2:0 6px 16px rgba(0,0,0,.55);--s-e3:0 20px 48px rgba(0,0,0,.65)}
[data-surface="ink"][data-accent="violet"]{--s-canvas:#0d1117;--s-surface:#141a21;--s-raised:#1a212a;--s-sunken:#10161c;--s-border:#232b34;--s-border-strong:#33404c;--s-ink:#dedfe0;--s-body:#b4b6b8;--s-muted:#828689;--s-faint:#666a6f;--s-brand:#8257e6;--s-brand-ink:#9b79eb;--s-brand-tint:#23233d;--s-brand-edge:#443a72;--s-on-brand:#ffffff;--s-danger:#f2778a;--s-danger-tint:#382932;--s-warn:#e0b458;--s-warn-tint:#35332a;--s-info:#7fb2e8;--s-info-tint:#253241;--s-e1:0 1px 2px rgba(0,0,0,.5);--s-e2:0 6px 16px rgba(0,0,0,.55);--s-e3:0 20px 48px rgba(0,0,0,.65)}
[data-surface="ink"][data-accent="amber"]{--s-canvas:#0d1117;--s-surface:#141a21;--s-raised:#1a212a;--s-sunken:#10161c;--s-border:#232b34;--s-border-strong:#33404c;--s-ink:#dedfe0;--s-body:#b4b6b8;--s-muted:#828689;--s-faint:#666a6f;--s-brand:#d08700;--s-brand-ink:#d08700;--s-brand-tint:#2e291c;--s-brand-edge:#604b22;--s-on-brand:#0b0f13;--s-danger:#f2778a;--s-danger-tint:#382932;--s-warn:#e0b458;--s-warn-tint:#35332a;--s-info:#7fb2e8;--s-info-tint:#253241;--s-e1:0 1px 2px rgba(0,0,0,.5);--s-e2:0 6px 16px rgba(0,0,0,.55);--s-e3:0 20px 48px rgba(0,0,0,.65)}
[data-surface="light"][data-accent="green"]{--s-canvas:#fbfbfc;--s-surface:#ffffff;--s-raised:#f7f8f9;--s-sunken:#eff1f3;--s-border:#e5e8eb;--s-border-strong:#cfd5da;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#707070;--s-faint:#8c8c8c;--s-brand:#16a37b;--s-brand-ink:#117c5d;--s-brand-tint:#e8f6f2;--s-brand-edge:#a7d3c9;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9eaec;--s-warn:#8a6410;--s-warn-tint:#f3f0e7;--s-info:#1f5f9e;--s-info-tint:#e9eff5;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="light"][data-accent="blue"]{--s-canvas:#fbfbfc;--s-surface:#ffffff;--s-raised:#f7f8f9;--s-sunken:#eff1f3;--s-border:#e5e8eb;--s-border-strong:#cfd5da;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#707070;--s-faint:#8c8c8c;--s-brand:#3b7df0;--s-brand-ink:#3269ca;--s-brand-tint:#ebf2fe;--s-brand-edge:#b2c8ed;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9eaec;--s-warn:#8a6410;--s-warn-tint:#f3f0e7;--s-info:#1f5f9e;--s-info-tint:#e9eff5;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="light"][data-accent="violet"]{--s-canvas:#fbfbfc;--s-surface:#ffffff;--s-raised:#f7f8f9;--s-sunken:#eff1f3;--s-border:#e5e8eb;--s-border-strong:#cfd5da;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#707070;--s-faint:#8c8c8c;--s-brand:#8257e6;--s-brand-ink:#7a52d8;--s-brand-tint:#f3eefd;--s-brand-edge:#c7bdea;--s-on-brand:#ffffff;--s-danger:#c0303f;--s-danger-tint:#f9eaec;--s-warn:#8a6410;--s-warn-tint:#f3f0e7;--s-info:#1f5f9e;--s-info-tint:#e9eff5;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="light"][data-accent="amber"]{--s-canvas:#fbfbfc;--s-surface:#ffffff;--s-raised:#f7f8f9;--s-sunken:#eff1f3;--s-border:#e5e8eb;--s-border-strong:#cfd5da;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#707070;--s-faint:#8c8c8c;--s-brand:#cc8400;--s-brand-ink:#9a6400;--s-brand-tint:#faf3e6;--s-brand-edge:#dfcba5;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9eaec;--s-warn:#8a6410;--s-warn-tint:#f3f0e7;--s-info:#1f5f9e;--s-info-tint:#e9eff5;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="warm"][data-accent="green"]{--s-canvas:#f6f5f3;--s-surface:#fffefc;--s-raised:#faf9f6;--s-sunken:#efece7;--s-border:#e6e3dd;--s-border-strong:#d3cec5;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#6e6d6c;--s-faint:#8a8988;--s-brand:#16a37b;--s-brand-ink:#117c5d;--s-brand-tint:#e8f5ef;--s-brand-edge:#a8d0c0;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9e9e9;--s-warn:#8a6410;--s-warn-tint:#f3efe4;--s-info:#1f5f9e;--s-info-tint:#e9eef3;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="warm"][data-accent="blue"]{--s-canvas:#f6f5f3;--s-surface:#fffefc;--s-raised:#faf9f6;--s-sunken:#efece7;--s-border:#e6e3dd;--s-border-strong:#d3cec5;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#6e6d6c;--s-faint:#8a8988;--s-brand:#3b7df0;--s-brand-ink:#3269ca;--s-brand-tint:#ebf1fb;--s-brand-edge:#b3c4e3;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9e9e9;--s-warn:#8a6410;--s-warn-tint:#f3efe4;--s-info:#1f5f9e;--s-info-tint:#e9eef3;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="warm"][data-accent="violet"]{--s-canvas:#f6f5f3;--s-surface:#fffefc;--s-raised:#faf9f6;--s-sunken:#efece7;--s-border:#e6e3dd;--s-border-strong:#d3cec5;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#6e6d6c;--s-faint:#8a8988;--s-brand:#8257e6;--s-brand-ink:#7a52d8;--s-brand-tint:#f3edfa;--s-brand-edge:#c8b9e0;--s-on-brand:#ffffff;--s-danger:#c0303f;--s-danger-tint:#f9e9e9;--s-warn:#8a6410;--s-warn-tint:#f3efe4;--s-info:#1f5f9e;--s-info-tint:#e9eef3;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="warm"][data-accent="amber"]{--s-canvas:#f6f5f3;--s-surface:#fffefc;--s-raised:#faf9f6;--s-sunken:#efece7;--s-border:#e6e3dd;--s-border-strong:#d3cec5;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#6e6d6c;--s-faint:#8a8988;--s-brand:#cc8400;--s-brand-ink:#966100;--s-brand-tint:#faf2e3;--s-brand-edge:#dfc79b;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9e9e9;--s-warn:#8a6410;--s-warn-tint:#f3efe4;--s-info:#1f5f9e;--s-info-tint:#e9eef3;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="ink"]:not([data-accent]){--s-canvas:#0d1117;--s-surface:#141a21;--s-raised:#1a212a;--s-sunken:#10161c;--s-border:#232b34;--s-border-strong:#33404c;--s-ink:#dedfe0;--s-body:#b4b6b8;--s-muted:#828689;--s-faint:#666a6f;--s-brand:#16a37b;--s-brand-ink:#16a37b;--s-brand-tint:#142d2e;--s-brand-edge:#1e554d;--s-on-brand:#0b0f13;--s-danger:#f2778a;--s-danger-tint:#382932;--s-warn:#e0b458;--s-warn-tint:#35332a;--s-info:#7fb2e8;--s-info-tint:#253241;--s-e1:0 1px 2px rgba(0,0,0,.5);--s-e2:0 6px 16px rgba(0,0,0,.55);--s-e3:0 20px 48px rgba(0,0,0,.65)}
[data-surface="light"]:not([data-accent]){--s-canvas:#fbfbfc;--s-surface:#ffffff;--s-raised:#f7f8f9;--s-sunken:#eff1f3;--s-border:#e5e8eb;--s-border-strong:#cfd5da;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#707070;--s-faint:#8c8c8c;--s-brand:#16a37b;--s-brand-ink:#117c5d;--s-brand-tint:#e8f6f2;--s-brand-edge:#a7d3c9;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9eaec;--s-warn:#8a6410;--s-warn-tint:#f3f0e7;--s-info:#1f5f9e;--s-info-tint:#e9eff5;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
[data-surface="warm"]:not([data-accent]){--s-canvas:#f6f5f3;--s-surface:#fffefc;--s-raised:#faf9f6;--s-sunken:#efece7;--s-border:#e6e3dd;--s-border-strong:#d3cec5;--s-ink:#303030;--s-body:#4c4c4c;--s-muted:#6e6d6c;--s-faint:#8a8988;--s-brand:#16a37b;--s-brand-ink:#117c5d;--s-brand-tint:#e8f5ef;--s-brand-edge:#a8d0c0;--s-on-brand:#0b0f13;--s-danger:#c0303f;--s-danger-tint:#f9e9e9;--s-warn:#8a6410;--s-warn-tint:#f3efe4;--s-info:#1f5f9e;--s-info-tint:#e9eef3;--s-e1:0 1px 2px rgba(13,27,24,.06);--s-e2:0 6px 16px rgba(13,27,24,.09);--s-e3:0 20px 48px rgba(13,27,24,.16)}
/* === END THEME MATRIX === */

:root{
  /* Neutrals carry a slight green cast so the brand feels native rather than
     a sticker on a grey admin panel. */
  --s-ink:#0d1b18;
  --s-body:#31423e;
  --s-muted:#61736f;
  --s-faint:#859591;

  --s-canvas:#f4f7f6;
  --s-surface:#ffffff;
  --s-raised:#fafcfb;
  --s-sunken:#eef3f1;

  --s-border:#e2e9e6;
  --s-border-strong:#cbd8d4;

  /* One brand ramp. --s-brand is the fill; --s-brand-ink is the only green that
     may carry text on white (the old --green was 3.07:1 and failed). */
  --s-brand:#0b7a5c;
  --s-brand-hover:#096b50;
  --s-brand-ink:#0a6b51;
  --s-brand-tint:#e8f5f0;
  --s-brand-edge:#bfe3d6;

  --s-danger:#b3323f;
  --s-danger-tint:#fdecee;
  --s-warn:#8a6410;
  --s-warn-tint:#fdf3de;
  --s-info:#1f5f9e;
  --s-info-tint:#e9f1fa;

  /* Channel identity, used only as small marks — never as surfaces. */
  --s-whatsapp:#128c7e;
  --s-messenger:#0084ff;
  --s-instagram:#c13584;

  /* 4px rhythm. Every gap and pad in this file resolves to one of these. */
  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:20px; --s-6:24px; --s-8:32px;

  /* Four radii replace twenty-three. */
  --s-r-control:7px;
  --s-r-card:11px;
  --s-r-modal:16px;
  --s-r-pill:999px;

  /* Three elevations replace one hundred and fifteen. Borders do most of the
     separation work; shadow is reserved for things that genuinely float. */
  --s-e0:none;
  --s-e1:0 1px 2px rgba(13,27,24,.06);
  --s-e2:0 6px 16px rgba(13,27,24,.09);
  --s-e3:0 20px 48px rgba(13,27,24,.16);

  --s-t-fast:120ms cubic-bezier(.4,0,.2,1);
  --s-t-base:200ms cubic-bezier(.4,0,.2,1);
}

/* Bridge the legacy tokens onto the system so every rule that already reads a
   token moves with it instead of being left behind. */
:root{
  --bg:var(--s-canvas);
  --surface:var(--s-surface);
  --surface-2:var(--s-raised);
  --surface-3:var(--s-sunken);
  --text:var(--s-ink);
  --muted:var(--s-muted);
  --line:var(--s-border);
  --line-strong:var(--s-border-strong);
  --green:var(--s-brand);
  --green-dark:var(--s-brand-ink);
  --green-text:var(--s-brand-ink);
  --green-soft:var(--s-brand-tint);
  --danger:var(--s-danger);
  --warning:var(--s-warn);
  --shadow:var(--s-e2);
  --shadow-sm:var(--s-e1);
  --shadow-lg:var(--s-e3);
  --soft-shadow:var(--s-e1);
  --radius:var(--s-r-card);
  --radius-lg:var(--s-r-modal);
  --card:var(--s-surface);
  --border:var(--s-border);
  --control-radius:var(--s-r-control);
  --chip-radius:var(--s-r-pill);

  /* Arabic type scale. Cairo needs more size than a Latin UI at the same rank. */
  --fs-chip:11px;
  --fs-meta:12px;
  --fs-table:13px;
  --fs-body:14px;
  --fs-name:15px;
}

/* --------------------------------------------------------------------------
   1. Geometry sweep
   The old file assigned radius and shadow per component, so nothing lined up.
   These collapse the spread onto the scale. !important is used deliberately and
   only here: there are already 267 !important declarations to outrank, and the
   alternative is re-specifying ~2500 selectors.
   -------------------------------------------------------------------------- */
.card,.panel,.surface-form,.data-table-wrap,.stat-card,.settings-card,
.conversation-sidebar,.customer-sidebar,.chat-panel,.modal-card,
.preview-table-wrap,.filter-block,.permission-card,.template-card,
.campaign-item,.message-item,.support-ticket-card,.developer-card{
  border-radius:var(--s-r-card) !important;
  box-shadow:var(--s-e1) !important;
  border:1px solid var(--s-border);
  /* Painting the surface here too, not only the geometry: app.css sets a literal #fff on
     these, which is invisible on a light ground but a white slab on the ink one. */
  background:var(--s-surface);
}

/* The remaining surfaces app.css paints white that an operator sees on every session. */
.login-card,.form-panel,.table-toolbar,.conversation-head,.reply-box,.inline-form,
.chat-shell,.preview-header,.preview-footer,.phone-preview,.step{
  background:var(--s-surface);
  border-color:var(--s-border);
  color:var(--s-body)
}
.icon-button,.menu-button{
  background:var(--s-surface);color:var(--s-body);
  border:1px solid var(--s-border-strong);border-radius:var(--s-r-control)
}
.icon-button:hover,.menu-button:hover{background:var(--s-sunken);color:var(--s-ink)}
input,select,textarea,button,.primary-button,.secondary-button,.ghost-button,
.ghost-pale,.danger-outline,.icon-action{border-radius:var(--s-r-control) !important}
.modal-card{border-radius:var(--s-r-modal) !important;box-shadow:var(--s-e3) !important}
/* .conversation-filter and .channel-filter are deliberately NOT in this sweep. They render
   in two different contexts now — square tabs in .inbox-tabs, pills in .inbox-channel-strip —
   and an !important pill here overrode the tab shape, which is what made the filter row
   render as pills with a stray underline. Each context sets its own radius instead. */
.chip,.tag-list span,.customer-status-chip,
.customer-status-filter,.assignment-chip,.conversation-workflow-badge{border-radius:var(--s-r-pill) !important}

/* --------------------------------------------------------------------------
   2. Page canvas and rhythm
   -------------------------------------------------------------------------- */
body{background:var(--s-canvas);color:var(--s-ink);font-size:var(--fs-body);line-height:1.6;-webkit-font-smoothing:antialiased}
h1,h2,h3,h4{color:var(--s-ink);letter-spacing:-.01em;line-height:1.3}
h1{font-size:24px;font-weight:800}
h2{font-size:19px;font-weight:800}
h3{font-size:16px;font-weight:700}
p{color:var(--s-body)}
small,.muted{color:var(--s-muted)}

/* Eyebrows and kickers were shouting at 7px uppercase; make them quiet labels. */
.eyebrow,.section-kicker{
  font-size:var(--fs-chip);font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--s-faint)
}

/* --------------------------------------------------------------------------
   3. Controls
   One button system: solid for the single primary action, quiet for everything
   else. Height and padding come from the rhythm so controls line up in a row.
   -------------------------------------------------------------------------- */
.primary-button,.secondary-button,.ghost-button,.ghost-pale,.danger-outline{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  min-height:36px;padding:0 var(--s-4);
  font-family:inherit;font-size:var(--fs-meta);font-weight:700;
  border:1px solid transparent;cursor:pointer;
  transition:background var(--s-t-fast),border-color var(--s-t-fast),color var(--s-t-fast),box-shadow var(--s-t-fast)
}
.primary-button{background:var(--s-brand);color:#fff;box-shadow:var(--s-e1)}
.primary-button:hover{background:var(--s-brand-ink)}
.primary-button:active{box-shadow:none}
.secondary-button,.ghost-button,.ghost-pale{background:var(--s-surface);color:var(--s-body);border-color:var(--s-border-strong)}
.secondary-button:hover,.ghost-button:hover,.ghost-pale:hover{background:var(--s-sunken);color:var(--s-ink)}
.danger-outline{background:var(--s-surface);color:var(--s-danger);border-color:#e6bcc1}
.danger-outline:hover{background:var(--s-danger-tint)}
button:disabled,.primary-button:disabled{opacity:.5;cursor:not-allowed}

input,select,textarea{
  background:var(--s-surface);color:var(--s-ink);
  border:1px solid var(--s-border-strong);
  padding:var(--s-2) var(--s-3);font-family:inherit;font-size:var(--fs-meta);
  transition:border-color var(--s-t-fast),box-shadow var(--s-t-fast)
}
input:hover,select:hover,textarea:hover{border-color:var(--s-faint)}
input:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--s-brand);box-shadow:0 0 0 3px var(--s-brand-tint)
}
::placeholder{color:var(--s-faint)}
label{color:var(--s-body);font-size:var(--fs-meta);font-weight:600}

/* --------------------------------------------------------------------------
   4. Chips and status
   Tinted rather than saturated, so a screen full of them stays calm.
   -------------------------------------------------------------------------- */
.chip,.tag-list span,.customer-status-chip,.assignment-chip,.conversation-workflow-badge{
  display:inline-flex;align-items:center;gap:var(--s-1);
  padding:3px var(--s-2);font-size:var(--fs-chip);font-weight:700;
  background:var(--s-sunken);color:var(--s-body);border:1px solid var(--s-border)
}
.status-new{background:var(--s-info-tint);color:var(--s-info);border-color:#cfe0f2}
.status-follow_up{background:var(--s-warn-tint);color:var(--s-warn);border-color:#eddcb4}
.status-completed{background:var(--s-brand-tint);color:var(--s-brand-ink);border-color:var(--s-brand-edge)}
.status-blocked{background:var(--s-danger-tint);color:var(--s-danger);border-color:#eec4c9}

/* Filter chips read as a segmented control, with the active state carrying the
   brand and everything else staying quiet. */
.conversation-filter,.customer-status-filter,.channel-filter,.assigned-filter{
  background:transparent;color:var(--s-muted);border:1px solid var(--s-border);
  padding:5px var(--s-3);font-size:var(--fs-chip);font-weight:700;
  transition:all var(--s-t-fast)
}
.conversation-filter:hover,.customer-status-filter:hover,.channel-filter:hover,.assigned-filter:hover{
  background:var(--s-sunken);color:var(--s-ink)
}
.conversation-filter.active,.customer-status-filter.active,.channel-filter.active,.assigned-filter.active{
  background:var(--s-brand);color:#fff;border-color:var(--s-brand)
}
.conversation-filter.active b,.customer-status-filter.active b,.channel-filter.active b{color:#fff}

/* --------------------------------------------------------------------------
   5. Tables
   -------------------------------------------------------------------------- */
.data-table{border-collapse:separate;border-spacing:0;width:100%}
.data-table th{
  background:var(--s-sunken);color:var(--s-muted);
  font-size:var(--fs-chip);font-weight:800;letter-spacing:.04em;text-transform:uppercase;
  padding:var(--s-3);text-align:start;border-bottom:1px solid var(--s-border);white-space:nowrap
}
.data-table td{
  padding:var(--s-3);font-size:var(--fs-table);color:var(--s-body);
  border-bottom:1px solid var(--s-border);line-height:1.65;vertical-align:middle
}
.data-table tbody tr{transition:background var(--s-t-fast)}
.data-table tbody tr:hover{background:var(--s-raised)}
.data-table tbody tr:last-child td{border-bottom:0}

/* --------------------------------------------------------------------------
   6. Inbox — the screen that matters most
   -------------------------------------------------------------------------- */
.crm-chat-shell{gap:var(--s-3);background:transparent}
.conversation-sidebar,.chat-panel,.customer-sidebar{background:var(--s-surface)}

.conversation-item{
  padding:var(--s-3);border-bottom:1px solid var(--s-border);border-radius:0;
  transition:background var(--s-t-fast);cursor:pointer
}
.conversation-item:hover{background:var(--s-raised)}
/* The active thread is marked with a brand edge on the inline-start side rather
   than a full fill, so the list stays readable while still being obvious. */
.conversation-item.active{
  background:var(--s-brand-tint);
  box-shadow:inset 3px 0 0 0 var(--s-brand)
}
.conversation-name{font-size:var(--fs-name);font-weight:700;color:var(--s-ink)}
.conversation-meta{font-size:var(--fs-meta);color:var(--s-muted)}
.conversation-preview{font-size:var(--fs-meta);color:var(--s-body)}

.chat-header{
  background:var(--s-surface);border-bottom:1px solid var(--s-border);
  padding:var(--s-3) var(--s-4);box-shadow:var(--s-e0)
}
.chat-header-identity strong{font-size:var(--fs-name);font-weight:700;color:var(--s-ink)}
.chat-header-identity span{font-size:var(--fs-meta);color:var(--s-muted)}

/* Message thread. Incoming sits on a surface with a border; outgoing carries a
   brand tint. Neither uses a heavy shadow — a long thread of shadowed bubbles
   is what made the old thread feel cluttered. */
.messages,.chat-messages{background:var(--s-canvas);padding:var(--s-4)}
.bubble{
  max-width:min(560px,78%);padding:var(--s-3) var(--s-3);
  border-radius:var(--s-r-card);font-size:var(--fs-body);line-height:1.8;
  box-shadow:var(--s-e1)
}
.bubble-row.incoming .bubble{background:var(--s-surface);border:1px solid var(--s-border);color:var(--s-ink)}
.bubble-row.outgoing .bubble{background:var(--s-brand-tint);border:1px solid var(--s-brand-edge);color:var(--s-ink)}
.bubble small{font-size:var(--fs-chip);color:var(--s-muted)}
.bubble-body{font-size:var(--fs-body);line-height:1.8}

.reply-composer,.chat-composer{
  background:var(--s-surface);border-top:1px solid var(--s-border);padding:var(--s-3) var(--s-4)
}

/* --------------------------------------------------------------------------
   7. Navigation and shell
   -------------------------------------------------------------------------- */
.sidebar,.app-sidebar{background:var(--s-surface);border-inline-end:1px solid var(--s-border)}
.sidebar a,.app-sidebar a{
  display:flex;align-items:center;gap:var(--s-3);
  padding:var(--s-2) var(--s-3);margin:2px var(--s-2);
  border-radius:var(--s-r-control);
  color:var(--s-body);font-size:var(--fs-meta);font-weight:600;text-decoration:none;
  transition:background var(--s-t-fast),color var(--s-t-fast)
}
.sidebar a:hover,.app-sidebar a:hover{background:var(--s-sunken);color:var(--s-ink)}
.sidebar a.active,.app-sidebar a.active{background:var(--s-brand-tint);color:var(--s-brand-ink);font-weight:700}

.topbar,.app-header{background:var(--s-surface);border-bottom:1px solid var(--s-border);box-shadow:var(--s-e0)}

/* --------------------------------------------------------------------------
   8. Cards inside a thread (ad attribution, link previews)
   These are supporting context, so they stay quieter than the message itself.
   -------------------------------------------------------------------------- */
.message-referral-card,.message-link-preview{
  border:1px solid var(--s-border);border-radius:var(--s-r-control);
  background:var(--s-raised);box-shadow:none;overflow:hidden
}
.message-link-preview{border-inline-start:3px solid var(--s-brand)}
.referral-headline,.link-preview-title{font-size:var(--fs-meta);font-weight:700;color:var(--s-ink)}
.referral-description,.link-preview-description{font-size:var(--fs-chip);color:var(--s-muted)}
.referral-open,.link-preview-site{color:var(--s-brand-ink);font-weight:700;font-size:var(--fs-chip)}

/* --------------------------------------------------------------------------
   8b. Channel marks
   A coloured dot cannot say which channel a conversation arrived on — it makes
   the reader learn a legend. The real glyph is recognised instantly, so each
   channel carries its own mark tinted to its own brand colour. The mark is the
   identifier; the written channel name sits beside it for anyone who does not
   recognise a 13px glyph, and collapses on narrow screens where space is tight.
   -------------------------------------------------------------------------- */
.channel-mark{flex:none;vertical-align:-2px}
.channel-mark.whatsapp{color:var(--s-whatsapp)}
.channel-mark.messenger{color:var(--s-messenger)}
.channel-mark.instagram{color:var(--s-instagram)}

.conversation-channel-badge{
  display:inline-flex;align-items:center;gap:5px;
  padding:2px 8px 2px 6px;border-radius:var(--s-r-pill);
  background:var(--s-sunken);border:1px solid var(--s-border);
  font-size:var(--fs-chip);font-weight:700;color:var(--s-muted);
  line-height:1.6
}
.conversation-channel-badge.whatsapp{background:#e7f4f1;border-color:#c3e3dc;color:#0c6b60}
.conversation-channel-badge.messenger{background:var(--s-info-tint);border-color:#cfe0f2;color:#0b5fb0}
.conversation-channel-badge.instagram{background:#fbeaf4;border-color:#f0cae2;color:#a32a6d}

/* In the conversation list the name column is tight, so the mark carries it alone. */
.conversation-item .conversation-channel-badge{background:transparent;border:0;padding:0;gap:0}
.conversation-item .channel-badge-name{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap
}

/* The channels screen shows the mark as an avatar. */
.meta-channel-avatar{
  display:grid;place-items:center;width:44px;height:44px;flex:none;
  border-radius:var(--s-r-card);background:var(--s-sunken);border:1px solid var(--s-border)
}
.meta-channel-avatar.whatsapp{background:#e7f4f1;border-color:#c3e3dc}
.meta-channel-avatar.messenger{background:var(--s-info-tint);border-color:#cfe0f2}
.meta-channel-avatar.instagram{background:#fbeaf4;border-color:#f0cae2}

/* --------------------------------------------------------------------------
   9. Feedback surfaces
   -------------------------------------------------------------------------- */
.alert,.callout{
  padding:var(--s-3) var(--s-4);border-radius:var(--s-r-control);
  border:1px solid var(--s-border);background:var(--s-raised);
  font-size:var(--fs-meta);color:var(--s-body)
}
.alert.error,.alert.danger{background:var(--s-danger-tint);border-color:#eec4c9;color:var(--s-danger)}
.alert.success{background:var(--s-brand-tint);border-color:var(--s-brand-edge);color:var(--s-brand-ink)}
.alert.warning{background:var(--s-warn-tint);border-color:#eddcb4;color:var(--s-warn)}

.empty-state{
  padding:var(--s-8) var(--s-4);text-align:center;
  color:var(--s-muted);font-size:var(--fs-meta)
}

/* --------------------------------------------------------------------------
   11. Panels, forms and the campaigns / templates screens
   These classes carried hardcoded colours (#6a817b, #eefaf6, #eef4f2), a 15px
   radius of their own and a diffuse 35px shadow. They are the shell both these
   screens are built from — and settings, users and logs reuse the same shell —
   so they belong on the system rather than in a per-page override.
   -------------------------------------------------------------------------- */
.panel,.templates-list-panel,.progress-card{
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);padding:var(--s-5);box-shadow:var(--s-e1)
}
.panel-head{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  margin-bottom:var(--s-4);padding-bottom:var(--s-3);border-bottom:1px solid var(--s-border)
}
.panel-head h2,.panel-head h3{margin:0}
.panel-head p{margin:0;font-size:var(--fs-meta);color:var(--s-muted)}

/* Was 1.7px letter-spacing on a hardcoded grey — a label, not a headline. */
.section-label{
  display:block;font-size:var(--fs-chip);font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:var(--s-faint);margin-bottom:var(--s-1)
}
.page-intro,.compact-intro{color:var(--s-body);font-size:var(--fs-meta);margin:0 0 var(--s-4)}
.block-note,.empty-cell{font-size:var(--fs-chip);color:var(--s-muted)}
.empty-cell{padding:var(--s-6) var(--s-3);text-align:center}
.error-note{font-size:var(--fs-chip);color:var(--s-danger)}

/* Informational callout above the campaign and template forms. */
.system-tip{
  display:flex;align-items:flex-start;gap:var(--s-3);
  padding:var(--s-3) var(--s-4);border-radius:var(--s-r-control);
  border:1px solid var(--s-brand-edge);background:var(--s-brand-tint);
  color:var(--s-brand-ink);font-size:var(--fs-meta);line-height:1.7
}

/* Campaign progress. The track is a rail, the fill is the only saturated thing
   in the row, so progress reads at a glance down a column of campaigns. */
.progress-track{
  height:6px;border-radius:var(--s-r-pill);background:var(--s-sunken);
  overflow:hidden;margin-top:var(--s-2);border:1px solid var(--s-border)
}
.progress-track>*{display:block;height:100%;background:var(--s-brand);border-radius:inherit;
  transition:width var(--s-t-base)}

.campaign-actions,.preview-buttons,.button-row,.wrap-actions{
  display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center
}
.small-button{min-height:30px;padding:0 var(--s-3);font-size:var(--fs-chip)}

/* Form rows in the template editor and campaign composer. */
.form-row{display:grid;gap:var(--s-2);margin-bottom:var(--s-3)}
.form-row>label{font-size:var(--fs-meta);font-weight:600;color:var(--s-body)}
.remove-row{
  min-height:30px;padding:0 var(--s-2);font-size:var(--fs-chip);
  background:var(--s-surface);color:var(--s-danger);border:1px solid #e6bcc1;
  border-radius:var(--s-r-control);cursor:pointer
}
.remove-row:hover{background:var(--s-danger-tint)}
.form-section-title{
  font-size:var(--fs-body);font-weight:700;color:var(--s-ink);
  margin:var(--s-5) 0 var(--s-2);padding-bottom:var(--s-2);border-bottom:1px solid var(--s-border)
}

.preview-table-wrap{
  overflow:auto;border:1px solid var(--s-border);
  border-radius:var(--s-r-card);margin-top:var(--s-4);background:var(--s-surface)
}
.pagination-bar{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  padding:var(--s-3) 0;font-size:var(--fs-meta);color:var(--s-muted)
}
.pagination-bar button,.pagination-bar a{
  min-height:32px;padding:0 var(--s-3);border-radius:var(--s-r-control);
  border:1px solid var(--s-border-strong);background:var(--s-surface);
  color:var(--s-body);font-size:var(--fs-meta);font-weight:700;cursor:pointer
}
.pagination-bar button:hover:not(:disabled){background:var(--s-sunken)}
.pagination-bar button:disabled{opacity:.45;cursor:not-allowed}

/* Modals used by both screens for campaign detail and template preview. */
.modal{position:fixed;inset:0;z-index:180;display:grid;place-items:center;
  background:rgba(13,27,24,.55);padding:var(--s-4)}
.modal-card{
  position:relative;background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-modal);box-shadow:var(--s-e3);
  padding:var(--s-6);max-height:90dvh;overflow:auto
}
.modal-close{
  position:absolute;inset-inline-start:var(--s-4);inset-block-start:var(--s-4);
  width:32px;height:32px;display:grid;place-items:center;
  border:1px solid var(--s-border);background:var(--s-sunken);color:var(--s-body);
  border-radius:var(--s-r-control);font-size:18px;line-height:1;cursor:pointer
}
.modal-close:hover{background:var(--s-border);color:var(--s-ink)}

/* --------------------------------------------------------------------------
   12. Settings
   A long form screen: the job is to make a wall of fields scannable, so the
   section head does the separating and the fields themselves stay quiet.
   -------------------------------------------------------------------------- */
.settings-section,.settings-main-panel,.webhook-card,.diagnostic-card{
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);padding:var(--s-5);box-shadow:var(--s-e1)
}
.settings-section+.settings-section{margin-top:var(--s-4)}
.settings-section-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s-3);
  margin-bottom:var(--s-4);padding-bottom:var(--s-3);border-bottom:1px solid var(--s-border)
}
.settings-section-head h2,.settings-section-head h3{margin:0;font-size:var(--fs-name)}
.settings-section-head p{margin:var(--s-1) 0 0;font-size:var(--fs-meta);color:var(--s-muted);max-width:68ch}
.settings-section-head>span{font-size:var(--fs-chip);font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:var(--s-faint)}
.settings-side-stack,.button-stack{display:grid;gap:var(--s-2)}
.optional-hint,.webhook-routing-note{font-size:var(--fs-chip);color:var(--s-muted);line-height:1.7}

/* A secret or endpoint the operator copies — monospace, selectable, with the copy
   control sharing the field's border so they read as one object. */
.copy-field{
  display:flex;align-items:stretch;gap:0;
  border:1px solid var(--s-border-strong);border-radius:var(--s-r-control);
  background:var(--s-raised);overflow:hidden
}
.copy-field input,.copy-field code{
  flex:1;min-width:0;border:0;background:transparent;padding:var(--s-2) var(--s-3);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--fs-meta);
  color:var(--s-ink);direction:ltr;text-align:left;overflow-x:auto;white-space:nowrap
}
.copy-field button{
  flex:none;border:0;border-inline-start:1px solid var(--s-border-strong);
  background:var(--s-sunken);color:var(--s-body);
  padding:0 var(--s-4);font-size:var(--fs-chip);font-weight:700;cursor:pointer;border-radius:0
}
.copy-field button:hover{background:var(--s-border);color:var(--s-ink)}

/* Live health readouts. State is carried by the dot's colour AND the text, never
   colour alone. */
.status-dot-inline{
  display:inline-block;width:8px;height:8px;border-radius:50%;flex:none;
  background:var(--s-faint);margin-inline-end:var(--s-2);vertical-align:1px
}
.status-dot-inline.good,.webhook-health.good .status-dot-inline{background:var(--s-brand)}
.status-dot-inline.warn,.webhook-health.warn .status-dot-inline{background:var(--s-warn)}
.status-dot-inline.bad,.webhook-health.bad .status-dot-inline{background:var(--s-danger)}
.webhook-health,.settings-storage-status{
  display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-2);
  font-size:var(--fs-meta);color:var(--s-body)
}
.diagnostic-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--s-3)}
.diagnostic-grid>*{
  padding:var(--s-3);border:1px solid var(--s-border);border-radius:var(--s-r-control);
  background:var(--s-raised);font-size:var(--fs-meta)
}
.webhook-dedicated-details{
  border:1px solid var(--s-border);border-radius:var(--s-r-control);
  background:var(--s-raised);padding:var(--s-3)
}
.webhook-dedicated-details summary{font-size:var(--fs-meta);font-weight:700;cursor:pointer;color:var(--s-body)}

/* Save bar that follows the operator down a long form. */
.settings-sticky-actions{
  position:sticky;bottom:0;z-index:5;
  display:flex;justify-content:flex-end;gap:var(--s-2);
  padding:var(--s-3) var(--s-4);margin-top:var(--s-4);
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);box-shadow:var(--s-e2)
}
.page-intro-actions{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}

/* --------------------------------------------------------------------------
   13. Theme picker
   Each option previews the palette it selects rather than naming it in the
   abstract, so the choice is made by looking. The chip shows the real ground
   and accent of that combination.
   -------------------------------------------------------------------------- */
.theme-picker{display:grid;gap:var(--s-4)}
.theme-group{display:grid;gap:var(--s-2)}
.theme-group-label{
  font-size:var(--fs-chip);font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:var(--s-faint)
}
.theme-options{display:flex;flex-wrap:wrap;gap:var(--s-2)}
.theme-option{
  display:flex;align-items:center;gap:var(--s-2);
  padding:var(--s-2) var(--s-3);cursor:pointer;
  background:var(--s-surface);color:var(--s-body);
  border:1px solid var(--s-border-strong);border-radius:var(--s-r-control);
  font-family:inherit;font-size:var(--fs-meta);font-weight:600;
  transition:border-color var(--s-t-fast),background var(--s-t-fast)
}
.theme-option:hover{background:var(--s-sunken)}
.theme-option.is-active{border-color:var(--s-brand);background:var(--s-brand-tint);color:var(--s-brand-ink);font-weight:700}
.theme-option-chip{
  width:22px;height:22px;border-radius:6px;flex:none;
  border:1px solid rgba(128,128,128,.35);
  /* The chip is a miniature of the palette: ground on one half, accent on the other. */
  background:linear-gradient(135deg,var(--chip-ground) 0 50%,var(--chip-accent) 50% 100%)
}
/* Grounds — these are literals on purpose: the chip must show what you are switching TO,
   not what is currently applied. */
.theme-option.surface.ink .theme-option-chip{--chip-ground:#0d1117;--chip-accent:#232b34}
.theme-option.surface.light .theme-option-chip{--chip-ground:#ffffff;--chip-accent:#e5e8eb}
.theme-option.surface.warm .theme-option-chip{--chip-ground:#fffefc;--chip-accent:#e6e3dd}
.theme-option.accent.green .theme-option-chip{--chip-ground:#16a37b;--chip-accent:#0f7d5e}
.theme-option.accent.blue .theme-option-chip{--chip-ground:#3b7df0;--chip-accent:#2b5fc0}
.theme-option.accent.violet .theme-option-chip{--chip-ground:#8257e6;--chip-accent:#6540bb}
.theme-option.accent.amber .theme-option-chip{--chip-ground:#d08700;--chip-accent:#a26900}

/* --------------------------------------------------------------------------
   14. Dashboard, logs, users, developer portal
   These four still carried literal #fff surfaces, their own radii (16/17/22px)
   and bespoke shadows. On a light ground that merely looked inconsistent; on
   the ink surface a literal #fff card is a white slab on a dark page, so this
   is a correctness fix for theming as much as a visual one.
   -------------------------------------------------------------------------- */

/* ---- Dashboard ---- */
.stats-grid,.dashboard-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--s-3)}
.stat-card,.quick-action-card,.dashboard-panel{
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);box-shadow:var(--s-e1)
}
.stat-card,.quick-action-card{padding:var(--s-4);display:grid;gap:var(--s-2)}
.stat-top{display:flex;align-items:center;justify-content:space-between;gap:var(--s-2)}
.stat-card strong,.stat-card b{font-size:26px;font-weight:800;color:var(--s-ink);
  line-height:1.15;font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.stat-card span,.stat-card small{font-size:var(--fs-meta);color:var(--s-muted)}
.quick-action-card{text-decoration:none;color:inherit;transition:border-color var(--s-t-fast),background var(--s-t-fast)}
.quick-action-card:hover{border-color:var(--s-brand);background:var(--s-raised)}
.quick-action-icon{
  width:38px;height:38px;display:grid;place-items:center;border-radius:var(--s-r-control);
  background:var(--s-brand-tint);color:var(--s-brand-ink);border:1px solid var(--s-brand-edge)
}
.quick-action-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--s-3)}
.two-column,.dashboard-columns{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:var(--s-4)}
@media(max-width:960px){.two-column,.dashboard-columns{grid-template-columns:1fr}}
.campaign-list,.message-list{display:flex;flex-direction:column;gap:var(--s-2)}
.campaign-item,.message-item{
  background:var(--s-raised);border:1px solid var(--s-border);
  border-radius:var(--s-r-control);padding:var(--s-3)
}
.panel-link{
  border:1px solid var(--s-border-strong);background:var(--s-surface);color:var(--s-body);
  border-radius:var(--s-r-control);padding:var(--s-1) var(--s-3);font-size:var(--fs-chip);
  font-weight:700;text-decoration:none
}
.panel-link:hover{background:var(--s-sunken);color:var(--s-ink)}
/* The loading shimmer was a white-to-pale-green gradient, which flashed white on ink. */
.skeleton,.loading-block{
  border-radius:var(--s-r-card);border:1px solid var(--s-border);
  background:linear-gradient(90deg,var(--s-surface),var(--s-sunken),var(--s-surface));
  background-size:200% 100%;animation:wasl-shimmer 1.4s ease-in-out infinite
}
@keyframes wasl-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}

/* ---- Logs and activity ---- */
.data-page-panel,.filter-drawer,.workspace-drawer{
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);box-shadow:var(--s-e1)
}
.data-page-panel{padding:var(--s-5)}
.filter-drawer>summary,.workspace-drawer>summary{
  padding:var(--s-3) var(--s-4);cursor:pointer;
  font-size:var(--fs-meta);font-weight:700;color:var(--s-body);list-style:none
}
.filter-drawer>summary::-webkit-details-marker,.workspace-drawer>summary::-webkit-details-marker{display:none}
.filter-drawer[open]>summary,.workspace-drawer[open]>summary{border-bottom:1px solid var(--s-border)}
.filter-drawer-body,.drawer-content{padding:var(--s-4)}
.filter-grid,.compact-filter-grid{display:grid;gap:var(--s-2);
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr));align-items:end}
.compact-date-filter{display:flex;align-items:center;gap:var(--s-2);font-size:var(--fs-chip);color:var(--s-muted)}
/* Long free text in a dense table: wrap rather than clip, and keep the column narrow
   enough that the row stays scannable. */
.message-cell{max-width:340px;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--s-body)}
.error-cell{max-width:300px;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--s-danger)}
.audit-details{max-width:380px;white-space:normal;overflow-wrap:anywhere;color:var(--s-muted);font-size:var(--fs-chip)}
.audit-action{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--fs-chip);color:var(--s-brand-ink)}
.tall-table{max-height:640px;overflow:auto}

/* ---- Users and permissions ---- */
.permissions-section{border-top:1px solid var(--s-border);margin-top:var(--s-4);padding-top:var(--s-4)}
.permissions-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:var(--s-2)}
.check-line{
  display:flex;align-items:center;gap:var(--s-2);
  padding:var(--s-2) var(--s-3);border:1px solid var(--s-border);
  border-radius:var(--s-r-control);background:var(--s-raised);
  font-size:var(--fs-meta);color:var(--s-body);cursor:pointer
}
.check-line:hover{background:var(--s-sunken);border-color:var(--s-border-strong)}
.check-line input{accent-color:var(--s-brand);flex:none}
.count-pill{
  display:inline-flex;align-items:center;border-radius:var(--s-r-pill);
  padding:3px var(--s-2);font-size:var(--fs-chip);font-weight:700;
  background:var(--s-sunken);color:var(--s-body);border:1px solid var(--s-border)
}
.user-form-redesign{max-width:1050px;margin-inline:auto}
.row-actions{display:flex;gap:var(--s-1);flex-wrap:wrap}

/* ---- Developer portal ----
   Its own 22px-radius white panels appeared 24 times. Same shell as the tenant
   app, so it uses the same tokens and follows the same theme. */
.developer-panel,.developer-table-wrap,.developer-support-control-card{
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);padding:var(--s-5);box-shadow:var(--s-e1)
}
.developer-panel+.developer-panel{margin-top:var(--s-4)}
.developer-title{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-4);
  margin-bottom:var(--s-4);padding-bottom:var(--s-3);border-bottom:1px solid var(--s-border)
}
.developer-title h1,.developer-title h2,.developer-title h3{margin:0}
.developer-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--s-3)}
.developer-support-stat{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-2);
  padding:var(--s-3);border:1px solid var(--s-border);border-radius:var(--s-r-control);
  background:var(--s-raised);font-size:var(--fs-meta);color:var(--s-body)
}
.developer-support-stat b{font-size:19px;color:var(--s-ink);font-variant-numeric:tabular-nums}
.developer-filter-bar,.developer-form-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--s-3);align-items:end
}
.span-2{grid-column:1/-1}
.developer-table{width:100%;overflow:auto}
.developer-header{background:var(--s-surface);border-bottom:1px solid var(--s-border)}
.developer-header nav a{
  padding:var(--s-2) var(--s-3);border-radius:var(--s-r-control);
  color:var(--s-body);font-size:var(--fs-meta);font-weight:600;text-decoration:none
}
.developer-header nav a:hover{background:var(--s-sunken);color:var(--s-ink)}
.developer-header nav a.active{background:var(--s-brand-tint);color:var(--s-brand-ink);font-weight:700}
.text-button{
  border:0;background:transparent;color:var(--s-brand-ink);
  font-size:var(--fs-chip);font-weight:700;cursor:pointer;padding:var(--s-1) var(--s-2);
  border-radius:var(--s-r-control)
}
.text-button:hover{background:var(--s-brand-tint)}
/* Tenant lifecycle state — colour plus label, never colour alone. */
.tenant-status{
  display:inline-flex;align-items:center;gap:var(--s-1);
  border-radius:var(--s-r-pill);padding:3px var(--s-2);
  font-size:var(--fs-chip);font-weight:700;
  background:var(--s-sunken);color:var(--s-body);border:1px solid var(--s-border)
}
.tenant-status.active,.tenant-status.subscribed{background:var(--s-brand-tint);color:var(--s-brand-ink);border-color:var(--s-brand-edge)}
.tenant-status.expired,.tenant-status.suspended{background:var(--s-danger-tint);color:var(--s-danger)}
.tenant-status.grace,.tenant-status.pending{background:var(--s-warn-tint);color:var(--s-warn)}

/* --------------------------------------------------------------------------
   15. Support centre
   A second conversation surface. It deliberately does NOT copy the customer
   inbox: this is an internal thread between a company and the platform, so it
   reads as a ticket record — avatars, roles and timestamps carry more weight
   than in a chat, and nothing here uses the channel colours.
   -------------------------------------------------------------------------- */
.support-stat-card{
  display:flex;align-items:center;gap:var(--s-3);min-width:0;
  padding:var(--s-3) var(--s-4);background:var(--s-surface);
  border:1px solid var(--s-border);border-radius:var(--s-r-card);box-shadow:var(--s-e1)
}
.support-stat-icon{
  display:grid;place-items:center;width:34px;height:34px;flex:none;
  border-radius:var(--s-r-control);background:var(--s-brand-tint);
  color:var(--s-brand-ink);border:1px solid var(--s-brand-edge)
}
.support-stat-card b{font-size:20px;font-weight:800;color:var(--s-ink);font-variant-numeric:tabular-nums}
.support-stat-card small{font-size:var(--fs-chip);color:var(--s-muted)}

/* Ticket identity and state. Each pill carries a label as well as a colour. */
.support-reference{
  display:inline-flex;align-items:center;border-radius:var(--s-r-pill);
  padding:2px var(--s-2);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:var(--fs-chip);background:var(--s-sunken);color:var(--s-body);
  border:1px solid var(--s-border);direction:ltr
}
.support-status,.support-priority{
  display:inline-flex;align-items:center;white-space:nowrap;
  border-radius:var(--s-r-pill);padding:2px var(--s-2);
  font-size:var(--fs-chip);font-weight:700;
  background:var(--s-sunken);color:var(--s-body);border:1px solid var(--s-border)
}
.support-status.open,.support-status.new{background:var(--s-info-tint);color:var(--s-info)}
.support-status.waiting,.waiting{background:var(--s-warn-tint);color:var(--s-warn)}
.support-status.resolved,.support-status.closed{background:var(--s-brand-tint);color:var(--s-brand-ink);border-color:var(--s-brand-edge)}
.support-priority.high,.support-priority.urgent{background:var(--s-danger-tint);color:var(--s-danger)}
.support-head-badges{display:flex;gap:var(--s-1);flex-wrap:wrap}

.support-conversation{
  flex:1;min-height:300px;max-height:520px;overflow:auto;
  padding:var(--s-5);background:var(--s-canvas);
  border:1px solid var(--s-border);border-radius:var(--s-r-card)
}
.support-chat-message{display:flex;align-items:flex-start;gap:var(--s-2);margin-bottom:var(--s-4)}
.support-message-avatar{
  display:grid;place-items:center;width:30px;height:30px;flex:none;
  border-radius:50%;background:var(--s-sunken);color:var(--s-body);
  border:1px solid var(--s-border);font-size:var(--fs-chip);font-weight:800
}
.support-message-bubble{
  max-width:min(76%,720px);padding:var(--s-3);
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);font-size:var(--fs-body);line-height:1.8;color:var(--s-ink)
}
/* A reply from the platform team is the one thing worth distinguishing. */
.support-chat-message.is-staff .support-message-bubble,
.support-chat-message.internal .support-message-bubble{
  background:var(--s-brand-tint);border-color:var(--s-brand-edge)
}
.support-message-bubble header{
  display:flex;align-items:baseline;gap:var(--s-2);margin-bottom:var(--s-1)
}
.support-message-bubble header strong{font-size:var(--fs-meta);color:var(--s-ink)}
.support-message-bubble header time,.support-message-bubble header small{
  font-size:var(--fs-chip);color:var(--s-muted);font-variant-numeric:tabular-nums
}

.support-attachments,.support-media-attachment{display:flex;flex-direction:column;gap:var(--s-2);margin-top:var(--s-2)}
.support-image-attachment{
  display:block;max-width:320px;overflow:hidden;
  border:1px solid var(--s-border);border-radius:var(--s-r-control)
}
.support-image-attachment img{display:block;width:100%;height:auto}
.support-file-attachment{
  display:flex;align-items:center;gap:var(--s-2);min-width:230px;
  padding:var(--s-2) var(--s-3);background:var(--s-raised);
  border:1px solid var(--s-border);border-radius:var(--s-r-control);
  font-size:var(--fs-meta);color:var(--s-body);text-decoration:none
}
.support-file-attachment:hover{background:var(--s-sunken);border-color:var(--s-border-strong)}
.support-file-icon{
  display:grid;place-items:center;width:30px;height:30px;flex:none;
  border-radius:var(--s-r-control);background:var(--s-sunken);color:var(--s-muted)
}
.support-list-empty{
  display:grid;place-items:center;text-align:center;min-height:260px;
  padding:var(--s-6);color:var(--s-muted);font-size:var(--fs-meta)
}
.support-mobile-back{
  display:none;align-items:center;justify-content:center;width:34px;height:34px;
  border:1px solid var(--s-border-strong);border-radius:var(--s-r-control);
  background:var(--s-surface);color:var(--s-body);cursor:pointer
}
.support-composer-toolbar svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.9}
.progress{
  height:6px;border-radius:var(--s-r-pill);background:var(--s-sunken);
  overflow:hidden;margin-top:var(--s-2);border:1px solid var(--s-border)
}
.progress>*{display:block;height:100%;background:var(--s-brand)}

/* --------------------------------------------------------------------------
   16. Developer portal — leads, plans and destructive actions
   -------------------------------------------------------------------------- */
.lead-admin-grid,.developer-report-grid,.developer-company-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:var(--s-4)
}
.lead-admin-card,.renewal-card,.check-card{
  display:grid;gap:var(--s-3);padding:var(--s-4);
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-card);box-shadow:var(--s-e1)
}
.lead-card-head{display:flex;justify-content:space-between;gap:var(--s-3);align-items:flex-start}
.lead-meta-grid,.two-inputs,.lead-update-form{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--s-2)
}
.lead-created{color:var(--s-muted);font-size:var(--fs-chip)}
.lead-status{
  display:inline-flex;align-items:center;border-radius:var(--s-r-pill);
  padding:2px var(--s-2);font-size:var(--fs-chip);font-weight:700;
  background:var(--s-sunken);color:var(--s-body);border:1px solid var(--s-border)
}
.lead-status.new{background:var(--s-info-tint);color:var(--s-info)}
.lead-status.won,.lead-status.converted{background:var(--s-brand-tint);color:var(--s-brand-ink);border-color:var(--s-brand-edge)}
.lead-status.lost{background:var(--s-danger-tint);color:var(--s-danger)}
.module-checkbox-grid,.module-pills{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--s-2)}
.module-pills{display:flex;gap:var(--s-1);flex-wrap:wrap}
.developer-pagination{max-width:560px;margin:var(--s-3) auto 0}
.activity-feed{display:grid;gap:var(--s-2)}

/* Destructive actions are visually separated so they cannot be hit by momentum. */
.danger-form{
  margin-top:var(--s-3);padding-top:var(--s-3);
  border-top:1px dashed var(--s-danger);
}
.danger-button{
  border:1px solid var(--s-danger);background:var(--s-danger-tint);color:var(--s-danger);
  border-radius:var(--s-r-control);min-height:32px;padding:0 var(--s-3);
  font-size:var(--fs-chip);font-weight:700;cursor:pointer
}
.danger-button:hover{background:var(--s-danger);color:var(--s-surface)}

/* A connection string is code: monospace, LTR, and on the sunken step so it reads as data
   rather than prose. It was a hardcoded near-black block that ignored the theme entirely. */
.database-card{
  display:block;padding:var(--s-3);
  background:var(--s-sunken);color:var(--s-ink);
  border:1px solid var(--s-border);border-radius:var(--s-r-control);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:var(--fs-chip);direction:ltr;text-align:left;overflow-x:auto
}

/* --------------------------------------------------------------------------
   17. Attachment queue
   Several files can be staged at once and go out as consecutive messages, the
   way Meta's own clients do. Each is removable on its own so a mis-picked file
   does not force starting over.
   -------------------------------------------------------------------------- */
.attachment-preview{
  display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center;position:relative;
  padding:var(--s-2) var(--s-8) var(--s-2) var(--s-2);
  background:var(--s-raised);border:1px solid var(--s-border);
  border-radius:var(--s-r-control)
}
.attachment-chip{
  display:flex;align-items:center;gap:var(--s-2);min-width:0;max-width:250px;
  padding:var(--s-1) var(--s-2);background:var(--s-surface);
  border:1px solid var(--s-border);border-radius:var(--s-r-control)
}
.attachment-chip img,.attachment-chip video{
  width:34px;height:34px;flex:none;object-fit:cover;border-radius:5px;background:var(--s-sunken)
}
.attachment-chip>div{min-width:0;display:grid}
.attachment-chip strong{
  font-size:var(--fs-chip);font-weight:600;color:var(--s-ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
.attachment-chip small{font-size:var(--fs-chip);color:var(--s-muted)}
.attachment-chip button{
  flex:none;width:20px;height:20px;display:grid;place-items:center;
  border:0;border-radius:50%;cursor:pointer;
  background:var(--s-sunken);color:var(--s-muted);font-size:14px;line-height:1
}
.attachment-chip button:hover{background:var(--s-danger-tint);color:var(--s-danger)}
.attachment-kind{
  display:grid;place-items:center;width:34px;height:34px;flex:none;
  border-radius:5px;background:var(--s-sunken);font-size:17px
}
.attachment-queue-note{
  flex-basis:100%;font-size:var(--fs-chip);color:var(--s-muted);font-weight:600
}
#removeReplyAttachment{
  position:absolute;inset-inline-end:var(--s-2);inset-block-start:var(--s-2);
  width:24px;height:24px;display:grid;place-items:center;
  border:1px solid var(--s-border);border-radius:var(--s-r-control);
  background:var(--s-surface);color:var(--s-muted);cursor:pointer;font-size:15px;line-height:1
}
#removeReplyAttachment:hover{background:var(--s-danger-tint);color:var(--s-danger)}

/* --------------------------------------------------------------------------
   18. Composer — Meta layout
   Tools, input and send on one row. The old arrangement put the send button on
   a second row next to an attribution line, which cost a row of thread height
   and separated the action from the thing being acted on.
   -------------------------------------------------------------------------- */
.reply-box{
  background:var(--s-surface);border-top:1px solid var(--s-border);
  padding:var(--s-2) var(--s-4) var(--s-2);display:grid;gap:var(--s-1)
}
.reply-compose-area{display:grid;gap:var(--s-2)}

.composer-row{
  display:flex;align-items:flex-end;gap:var(--s-1);
  background:var(--s-sunken);border:1px solid var(--s-border);
  border-radius:22px;padding:var(--s-1);
  transition:border-color var(--s-t-fast),box-shadow var(--s-t-fast)
}
.composer-row:focus-within{border-color:var(--s-brand);box-shadow:0 0 0 3px var(--s-brand-tint)}

/* Order is set here rather than in the markup so the DOM keeps its reading order for
   keyboard and screen-reader users: input, then its tools, then send. Visually the send
   control sits at the start of the row (the right, in RTL) and the attachment, saved-reply
   and voice tools sit at the end (the left). */
.composer-send{order:1}
.reply-box textarea,#replyText{order:2}
.composer-tools{order:3;display:flex;align-items:center;gap:2px;flex:none}
.composer-tool{
  width:34px;height:34px;flex:none;display:grid;place-items:center;
  border:0;border-radius:50%;background:transparent;color:var(--s-muted);cursor:pointer;
  transition:background var(--s-t-fast),color var(--s-t-fast)
}
.composer-tool:hover{background:var(--s-border);color:var(--s-ink)}
.composer-tool svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.composer-tool.is-recording,.voice-record-button.is-recording{background:var(--s-danger-tint);color:var(--s-danger)}

/* Grows with the text instead of reserving two rows up front. */
.reply-box textarea,#replyText{
  flex:1;min-width:0;resize:none;border:0;background:transparent;color:var(--s-ink);
  padding:var(--s-2) var(--s-1);min-height:34px;max-height:150px;
  font-family:inherit;font-size:var(--fs-body);line-height:1.6
}
.reply-box textarea:focus,#replyText:focus{outline:none;box-shadow:none}

.composer-send{
  position:relative;width:36px;height:36px;flex:none;display:grid;place-items:center;
  border:0;border-radius:50%;cursor:pointer;
  background:var(--s-brand);color:var(--s-on-brand);
  transition:background var(--s-t-fast),transform var(--s-t-fast)
}
.composer-send:hover:not(:disabled){background:var(--s-brand-ink)}
.composer-send:active:not(:disabled){transform:scale(.94)}
.composer-send:disabled{background:var(--s-border);color:var(--s-faint);cursor:not-allowed}
/* The button now sits at the right edge of the composer, so the glyph points outward to the
   right — away from the input. It was mirrored while the button sat on the opposite side;
   keeping that mirror here would aim the arrow back into the text field. */
.composer-send svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
.composer-send-count{
  position:absolute;inset-block-start:-6px;inset-inline-start:-6px;
  min-width:20px;height:18px;padding:0 5px;display:grid;place-items:center;
  border-radius:var(--s-r-pill);background:var(--s-ink);color:var(--s-surface);
  font-size:9.5px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1
}
.composer-send-count:empty{display:none}

.composer-footnote{
  display:flex;justify-content:space-between;gap:var(--s-3);flex-wrap:wrap;
  padding:0 var(--s-3);font-size:var(--fs-chip);color:var(--s-faint)
}
.composer-footnote strong{color:var(--s-muted);font-weight:700}

.voice-recorder-bar{
  display:flex;align-items:center;gap:var(--s-2);
  padding:var(--s-2) var(--s-3);border-radius:var(--s-r-pill);
  background:var(--s-danger-tint);color:var(--s-danger);font-size:var(--fs-meta);font-weight:600
}
.voice-recorder-bar strong{font-variant-numeric:tabular-nums}
.voice-recorder-bar button{
  margin-inline-start:auto;border:1px solid currentColor;background:transparent;color:inherit;
  border-radius:var(--s-r-pill);padding:2px var(--s-3);font-size:var(--fs-chip);font-weight:700;cursor:pointer
}
.voice-recorder-bar .stop-recording{margin-inline-start:var(--s-1);background:var(--s-danger);color:var(--s-surface);border-color:var(--s-danger)}
.recording-dot{width:8px;height:8px;border-radius:50%;background:currentColor;animation:wasl-pulse 1.1s ease-in-out infinite}
@keyframes wasl-pulse{0%,100%{opacity:1}50%{opacity:.25}}

@media(max-width:620px){
  .reply-box{padding:var(--s-1) var(--s-2)}
  .composer-footnote{display:none}
  .composer-tool{width:32px;height:32px}
}

/* --------------------------------------------------------------------------
   19. Inbox list header — Meta arrangement
   Status is a permanent tab strip and channel a permanent filter row, because
   those are the two an agent switches constantly. Assignment and CRM stage stay
   behind the filter control. The tab underline marks the active one rather than
   a filled pill, so a row of five tabs does not turn into a row of five blocks.
   -------------------------------------------------------------------------- */
.inbox-tabs{
  display:flex;gap:var(--s-1);overflow-x:auto;scrollbar-width:none;
  border-bottom:1px solid var(--s-border);margin-top:var(--s-2)
}

/* Filters are hidden at EVERY width, not just on phones, and appear only when the filter
   button asks for them. The conversation list is the screen — four rows of filters above it
   pushed the conversations out of view. Previously this was scoped to a narrow breakpoint,
   which still left them forced open on a laptop. */
/* One filter bar. Five identical selects replace the tabs, pills, segmented group and chips
   the screen used to stack — same information, one metaphor, one row that wraps. */
.conversation-head .inbox-filter-bar{display:none}
.conversation-head.filters-open .inbox-filter-bar{
  display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:flex-end;
  margin-top:var(--s-2);padding:var(--s-3);
  background:var(--s-raised);border:1px solid var(--s-border);border-radius:var(--s-r-card)
}
.filter-select{display:grid;gap:2px;min-width:0;flex:1 1 140px}
.filter-select>span{
  font-size:var(--fs-chip);font-weight:700;color:var(--s-faint);
  text-transform:uppercase;letter-spacing:.05em
}
.filter-select>select{
  width:100%;min-width:0;min-height:32px;
  padding:0 var(--s-2);font-size:var(--fs-meta);font-family:inherit;
  color:var(--s-ink);background:var(--s-surface);
  border:1px solid var(--s-border-strong);border-radius:var(--s-r-control)
}
.filter-select>select:hover{border-color:var(--s-faint)}
.filter-clear{
  flex:0 0 auto;min-height:32px;padding:0 var(--s-3);
  border:1px solid var(--s-border-strong);border-radius:var(--s-r-control);
  background:var(--s-surface);color:var(--s-danger);
  font-family:inherit;font-size:var(--fs-chip);font-weight:700;cursor:pointer
}
.filter-clear:hover{background:var(--s-danger-tint);border-color:var(--s-danger)}
.filter-clear.hidden{display:none}

/* Keep the whole filter area from ever pushing the list off screen. */
.conversation-head.filters-open{max-height:70dvh;overflow-y:auto}

/* With the filters closed, this line is the only thing saying why the list looks short. */
.active-filter-summary{display:flex}

/* The summary now reports only what is hidden, and stays quiet when nothing is. */
.active-filter-summary{
  display:flex;align-items:center;gap:var(--s-2);width:100%;
  padding:var(--s-2) var(--s-3);margin-top:var(--s-1);
  background:var(--s-surface);border:1px solid var(--s-border);
  border-radius:var(--s-r-control);color:var(--s-muted);
  font-size:var(--fs-chip);font-weight:600;cursor:pointer;text-align:start
}
.active-filter-summary:hover{background:var(--s-sunken);color:var(--s-ink)}
.active-filter-summary.has-filters{
  background:var(--s-brand-tint);border-color:var(--s-brand-edge);color:var(--s-brand-ink);font-weight:700
}
.active-filter-summary svg{
  width:15px;height:15px;margin-inline-start:auto;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round
}

/* --------------------------------------------------------------------------
   20. Thread header — Meta arrangement
   Identity on one side, icon actions on the other, on a single quiet row. The
   header sits above every conversation an agent opens, so it earns its height
   by identifying the customer and nothing else.
   -------------------------------------------------------------------------- */
.chat-header{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  padding:var(--s-2) var(--s-4);background:var(--s-surface);
  border-bottom:1px solid var(--s-border);box-shadow:none;min-height:56px
}
.chat-header-main{display:flex;align-items:center;gap:var(--s-2);min-width:0;flex:1}
.chat-header-identity{display:flex;align-items:center;gap:var(--s-2);min-width:0}
.chat-header-identity>div{min-width:0;display:grid;gap:1px}
.chat-header-identity .avatar{
  width:38px;height:38px;flex:none;display:grid;place-items:center;border-radius:50%;
  background:var(--s-brand-tint);color:var(--s-brand-ink);border:1px solid var(--s-brand-edge);
  font-size:var(--fs-meta);font-weight:800
}
.chat-header-identity strong{
  font-size:var(--fs-name);font-weight:700;color:var(--s-ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
/* Channel mark, handle and window state read as one quiet line under the name. */
.chat-channel-line{
  display:flex;align-items:center;gap:var(--s-1);min-width:0;
  font-size:var(--fs-chip);color:var(--s-muted)
}
.chat-channel-line>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-header-identity .customer-status-chip{align-self:start}

.chat-header-actions{display:flex;align-items:center;gap:var(--s-1);flex:none}
.chat-action{
  width:34px;height:34px;flex:none;display:grid;place-items:center;
  border:0;border-radius:50%;background:transparent;color:var(--s-muted);cursor:pointer;
  transition:background var(--s-t-fast),color var(--s-t-fast)
}
.chat-action:hover{background:var(--s-sunken);color:var(--s-ink)}
.chat-action:disabled{opacity:.45;cursor:not-allowed}
.chat-action svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.chat-action.danger:hover{background:var(--s-danger-tint);color:var(--s-danger)}
.chat-action[aria-expanded="true"]{background:var(--s-brand-tint);color:var(--s-brand-ink)}

.mobile-chat-back{
  display:none;width:32px;height:32px;flex:none;place-items:center;
  border:0;border-radius:50%;background:transparent;color:var(--s-body);
  font-size:20px;line-height:1;cursor:pointer
}
@media(max-width:980px){.mobile-chat-back{display:grid}}

/* The 24h window is state the agent must know before typing, so it sits with the thread
   rather than shouting as a full-width banner. */
.service-window-banner{
  display:flex;align-items:center;gap:var(--s-2);
  padding:var(--s-2) var(--s-4);font-size:var(--fs-chip);font-weight:600;
  background:var(--s-warn-tint);color:var(--s-warn);
  border-bottom:1px solid var(--s-border)
}
.service-window-banner.closed,.service-window-banner.expired{background:var(--s-danger-tint);color:var(--s-danger)}
.service-window-banner.open{background:var(--s-brand-tint);color:var(--s-brand-ink)}

/* --------------------------------------------------------------------------
   21. Customer panel — the third column
   Meta's contact rail: identity first, then the few fields an agent edits mid
   conversation. It is a working form, not a profile page, so the fields stay
   quiet and the save stays reachable without scrolling back.
   -------------------------------------------------------------------------- */
.customer-sidebar{
  display:flex;flex-direction:column;min-height:0;
  background:var(--s-surface);border-inline-start:1px solid var(--s-border);
  padding:var(--s-4);gap:var(--s-3);overflow-y:auto
}
.customer-profile-head{
  display:flex;align-items:center;gap:var(--s-3);
  padding-bottom:var(--s-3);border-bottom:1px solid var(--s-border)
}
.customer-profile-head .avatar.large{
  width:46px;height:46px;flex:none;display:grid;place-items:center;border-radius:50%;
  background:var(--s-brand-tint);color:var(--s-brand-ink);border:1px solid var(--s-brand-edge);
  font-size:var(--fs-name);font-weight:800
}
.customer-profile-head>div:last-child{min-width:0;display:grid;gap:2px}
.customer-profile-head h3{
  margin:0;font-size:var(--fs-name);font-weight:700;color:var(--s-ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
.customer-profile-head span{font-size:var(--fs-chip);color:var(--s-muted);direction:ltr;text-align:start}

/* Every field is label-above-control on one rhythm; the old panel let each one
   set its own spacing. */
.customer-sidebar label{
  display:grid;gap:var(--s-1);
  font-size:var(--fs-chip);font-weight:700;color:var(--s-muted);
  text-transform:none;letter-spacing:0
}
.customer-sidebar label input,.customer-sidebar label select,.customer-sidebar label textarea{
  width:100%;font-size:var(--fs-meta);color:var(--s-ink)
}
.customer-sidebar label small{font-size:var(--fs-chip);color:var(--s-faint);font-weight:600}
.customer-sidebar textarea{resize:vertical;min-height:96px;line-height:1.7}

/* The stage legend under the select: reference, not controls, so it is quieter
   than the filter chips it resembles. */
.status-help{display:flex;flex-wrap:wrap;gap:var(--s-1)}
.status-help .customer-status-chip{opacity:.75;font-size:var(--fs-chip)}

.customer-stats{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:var(--s-2);
  padding-top:var(--s-3);border-top:1px solid var(--s-border)
}
.customer-stats>div{
  padding:var(--s-2);border:1px solid var(--s-border);border-radius:var(--s-r-control);
  background:var(--s-raised);display:grid;gap:1px
}
.customer-stats strong,.customer-stats b{
  font-size:var(--fs-name);font-weight:800;color:var(--s-ink);font-variant-numeric:tabular-nums
}
.customer-stats span{font-size:var(--fs-chip);color:var(--s-muted)}

/* Save follows the agent down the panel instead of sitting below the notes box. */
#saveCustomerProfile{
  position:sticky;bottom:0;z-index:2;width:100%;
  margin-top:auto;box-shadow:var(--s-e2)
}

.customer-empty{
  display:grid;place-items:center;gap:var(--s-2);text-align:center;
  padding:var(--s-8) var(--s-4);color:var(--s-muted);font-size:var(--fs-meta)
}
.customer-empty strong{color:var(--s-ink);font-size:var(--fs-name)}
.customer-empty .empty-icon{
  width:44px;height:44px;display:grid;place-items:center;border-radius:50%;
  background:var(--s-sunken);color:var(--s-faint);font-size:20px
}

.mobile-customer-close{
  display:none;width:32px;height:32px;place-items:center;align-self:flex-end;
  border:1px solid var(--s-border);border-radius:var(--s-r-control);
  background:var(--s-surface);color:var(--s-body);font-size:17px;line-height:1;cursor:pointer
}
.customer-sidebar-backdrop{
  position:fixed;inset:0;z-index:120;border:0;
  background:rgba(13,27,24,.5);cursor:pointer
}
@media(max-width:1200px){.mobile-customer-close{display:grid}}

/* --------------------------------------------------------------------------
   10. Focus and motion — kept from the accessibility pass, restated on the
   system's own tokens so the ring matches the new brand.
   -------------------------------------------------------------------------- */
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,
select:focus-visible,[tabindex]:focus-visible{
  outline:2px solid var(--s-brand);outline-offset:2px
}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important}
}
