/*
 * Triniteq brand palette, taken from the Style Guide's Web Styles panel.
 *
 * These are the guide's values verbatim -- primary, hover, active and tint for each. They were
 * briefly replaced with colours sampled from the logo artwork, which was wrong: the mark carries
 * a gradient (#e68a48 to #dd5b61) that is deliberately softer than the interface palette, and
 * sampling it desaturated every button and status chip in the product.
 */
:root {
  /* Bright Orange. The primary action colour. */
  --orange: #ff751a;
  --orange-hover: #ff5f07;
  --orange-active: #ff941a;
  --orange-pale: #fae4d3;
  --orange-tint: #f1b892;
  --orange-rgb: 255, 117, 26;

  /* Coral. Anything overdue, breaching or destructive. */
  --coral: #fe3838;
  --coral-hover: #d4202b;
  --coral-active: #fe5b59;
  --coral-pale: #f6d8d9;
  --coral-tint: #e89e9e;
  --coral-rgb: 254, 56, 56;

  /* Green. Met the target, connected, resolved. */
  --green: #21ad7e;
  --green-hover: #219564;
  --green-active: #21c89b;
  --green-pale: #d8ebe4;
  --green-tint: #9fd0bd;

  /* Dark Grey and Zircon: body copy, and the background everything sits on. */
  --grey: #2b2b2b;
  --muted: #656a72;            /* 5.4:1 on white; was #747981 at 4.4:1 */
  --zircon: #f6f9ff;
  --white: #fff;
  --border: #e3e7ee;
  --border-dark: #d3d8e1;
  --sidebar: #2b2b2b;

  /* The guide's gradient, coral to orange, for the few places carrying brand rather than state. */
  --brand-gradient: linear-gradient(135deg, #fe3838 0%, #ff751a 100%);

  --shadow: 0 1px 2px rgba(28, 33, 42, .04), 0 12px 34px rgba(28, 33, 42, .045);

  /*
   * Surfaces, ink and washes. These replaced roughly a hundred one-off literals -- fifteen
   * near-identical greys for secondary text, ten faintly different panel whites -- so the dark
   * theme is one block at the bottom of this section rather than a rewrite of the whole file.
   * The brand palette above is deliberately NOT part of this: orange stays orange in both themes.
   */
  --surface: #fff;            /* panels, cards, rows, modals, popovers */
  --topbar: rgba(255,255,255,.94); /* translucent, so content scrolls under it */
  --surface-sunken: #fbfcff;  /* row hover, filter strip, table footer */
  --surface-head: #fafbfe;    /* table header bands */
  --surface-muted: #edf0f4;   /* neutral chips and icon tiles */
  --hairline: #edf0f4;        /* dividers inside a panel, lighter than --border */
  --border-hover: #b9bfc9;
  --neutral-mark: #aab0b6;    /* priority bars, status dots, toggle tracks */
  --ink: #2b2b2b;             /* surfaces that stay dark in both themes: toasts, card tabs */
  --avatar-bg: #e2e6e4;
  --avatar-ink: #3b4140;
  --avatar-own-bg: #b9ead9;
  --avatar-own-ink: #075940;

  --text-soft: #555a62;       /* form labels and secondary body copy */
  --text-faint: #6b7079;      /* table headings, captions: 5.0:1 on white; was #858a92 at 3.5:1 */
  --text-faintest: #b9bbc1;   /* placeholders, disabled, breadcrumb separators */

  /* Tinted panels, their hairlines, and the dark ink that sits on them. */
  --orange-wash: #fff8f2;
  --orange-wash-strong: #fff0e4;
  --orange-wash-border: #f1d5bd;
  --orange-ink: #8a3f0c;      /* 6.1:1 even on pale-on-wash, the darkest stack it sits on */
  --coral-wash: #fff6f6;
  --coral-wash-border: #efc5c8;
  --coral-ink: #a5252d;
  --green-wash: #f2fbf8;
  --green-wash-border: #cbe6dc;
  --green-ink: #12694d;
  --amber-wash: #fff0c2;
  --amber-ink: #8f5b00;
  --violet-wash: #e6def9;
  --violet-wash-border: #cfc0ee;
  --violet-ink: #5b34b8;
  --indigo-wash: #dcdeef;
  --indigo-wash-border: #c2c6e3;
  --indigo-ink: #3f47a8;

  /*
   * Roles rather than paint. Each names a job in the interface, so the dark theme can answer it
   * differently: an overlay is the same white as a panel here, but lifts above it in the dark.
   */
  --text: var(--grey);                 /* body copy; was used 61 times without ever being defined */
  --text-muted: var(--muted);
  --panel: var(--surface);
  --danger: var(--coral-ink);
  --on-brand: #fff;                    /* text on an orange, coral or green fill */
  --on-orange: #fff;                   /* text on an orange fill: the brand look in light */
  --link: #c2410c;                     /* orange as text -- links, ids, eyebrows: 5.2:1 on white.
                                          The bright brand orange stays for fills; as small text it
                                          measured 2.7-3.1:1. */
  --surface-raised: #fff;              /* a card sitting inside a panel */
  --surface-overlay: #fff;             /* popovers, menus, modals, dropdown results */
  --surface-hover: #f6f9ff;            /* neutral hover on rows, menu items and icon buttons */
  --surface-pressed: #edf0f4;
  --backdrop: rgba(22, 27, 34, .46);   /* behind a modal */
  --selection: rgba(255, 117, 26, .22);
  --toast-bg: #2b2b2b;
  --toast-ink: #fff;
  --blue-ink: #1f5fbf;                 /* "reopened": the one status that is neither brand nor warning */
  --blue-wash: #e1ecfb;
  --blue-wash-border: #b9d0f2;
  --presence: #7c4ddb;                 /* somebody else is on this ticket: not a state of the
                                          ticket, so neither brand nor warning. 4.8:1 on white. */
  --presence-strong: #6b3bd0;
  --lime-ink: #3d6b00;                 /* the NEW tag */
  --lime-wash: #e9f8c9;
  --lime-wash-border: #bfe37a;

  /* One priority palette, matching the chips: the donut, the queue stripe and the attention bars
     used three different sets, so "normal" was green in one place and orange in the next. */
  --priority-urgent: var(--coral);
  --priority-high: var(--orange);
  --priority-normal: var(--green);
  --priority-low: var(--neutral-mark);

  /* Chart marks: sparklines and the like. */
  --chart-green: #21ad7e;
  --chart-coral: #f0484e;
  --chart-orange: #ff750d;
  --chart-indigo: #6f75df;
}

/*
 * Dark theme. Applied only when the attribute is present, which the inline script in _Layout sets
 * before first paint. It is deliberately not driven by a bare `prefers-color-scheme` media query:
 * site.css is also loaded by the login, landing and portal pages, which have their own layouts and
 * no theme script, so a media query would half-darken pages that were never designed for it.
 *
 * Designed as its own theme, not as the light one inverted. The rules it follows, and why:
 *
 *   Depth is lightness. A shadow cannot be seen against a dark page, so each layer that comes
 *   forward is a step lighter: rail #0b0d10, page #101216, panel #171a20, raised #1d2027,
 *   overlay #22262e. Steps are small (Material 3, Atlassian and Primer all keep adjacent layers a
 *   few points of lightness apart); a big jump reads as a hole, not a lift.
 *
 *   Neutrals are cool and barely tinted. Pure black and pure white are avoided: black makes every
 *   edge vibrate, and white text on near-black blooms (halation). Body text is #e6e9ef.
 *
 *   Borders are translucent white, not solid greys, so the same token reads correctly on every
 *   layer it lands on instead of being tuned to one.
 *
 *   Brand colour splits by job. Orange stays #ff751a as a fill -- buttons, the active tab, the
 *   unread dot -- but text, links and small marks use the lighter inks, because a saturated mid
 *   tone that is fine as a block is tiring as a line of copy.
 *
 *   Hover lightens. In the light theme a hover darkens a white row; here it lifts a dark one.
 *
 *   Every text tier is measured (WCAG 2.x, on the panel): primary 14.3:1, soft 9.4:1, muted
 *   6.8:1, faint 5.3:1, faintest 3.2:1 (placeholders and disabled only). Every ink clears 6.4:1
 *   on its own wash.
 */
:root[data-theme="dark"] {
  /* Surfaces, darkest to lightest. */
  --sidebar: #0b0d10;
  --zircon: #101216;                   /* the page */
  --surface: #171a20;                  /* panels */
  --surface-head: #1a1d23;             /* table header bands */
  --surface-sunken: #1c1f26;           /* wells and footers; also a gentle hover on panels */
  --surface-raised: #1d2027;           /* cards inside a panel */
  --surface-hover: #20242b;
  --surface-overlay: #22262e;          /* popovers, menus, modals: the top of the stack */
  --surface-muted: #262a32;            /* neutral chips and icon tiles */
  --surface-pressed: #2a2e37;
  --topbar: rgba(16, 18, 22, .86);     /* the page colour, so the bar is part of it rather than a slab */
  --panel: var(--surface);

  /* Text. */
  --grey: #e6e9ef;
  --text-soft: #b8bfca;
  --muted: #9aa2ae;
  --text-faint: #868e9b;
  --text-faintest: #636a77;
  --white: #fff;
  --on-brand: #fff;
  --on-orange: #1a0f05;                /* near-black on orange: 7.0:1, where white measured 2.7:1 */
  --link: #ff8a3d;                     /* 7.4:1 on a panel */

  /* Lines. */
  --hairline: rgba(210, 220, 240, .075);
  --border: rgba(210, 220, 240, .11);
  --border-dark: rgba(210, 220, 240, .2);    /* controls: inputs, selects, secondary buttons */
  --border-hover: rgba(210, 220, 240, .28);
  --neutral-mark: #6b7380;             /* 3.6:1 on a panel: toggle tracks, status dots, low priority */

  /* Inverse surfaces. A toast is the one thing that must interrupt, so in the dark it turns light
     (Material's inverse surface) instead of being one more dark card on a dark page. */
  --ink: #2c313a;
  --toast-bg: #e6e9ef;
  --toast-ink: #171a20;

  --avatar-bg: #2c3139;
  --avatar-ink: #d3d8df;
  --avatar-own-bg: #13493a;
  --avatar-own-ink: #9de3c6;

  /* Brand, by job. The fills keep the guide's values; what lightens is what is read. */
  --orange-hover: #ff8a3d;             /* lighter, because hover lifts here; 7.4:1 as link text */
  --orange-active: #f06a12;
  --orange-tint: rgba(255, 138, 61, .45);
  --orange-ink: #ffa463;
  --orange-pale: rgba(255, 117, 26, .15);
  --orange-wash: rgba(255, 117, 26, .09);
  --orange-wash-strong: rgba(255, 117, 26, .15);
  --orange-wash-border: rgba(255, 138, 61, .32);

  --coral-hover: #ff6b6b;              /* used as danger text: 6.3:1, where the light value was 3.2:1 */
  --coral-ink: #ff8f8a;
  --coral-pale: rgba(254, 56, 56, .15);
  --coral-wash: rgba(254, 56, 56, .09);
  --coral-wash-border: rgba(255, 107, 107, .32);

  --green-hover: #2fc492;
  --green-ink: #5fd4a8;
  --green-pale: rgba(33, 173, 126, .16);
  --green-wash: rgba(33, 173, 126, .09);
  --green-wash-border: rgba(47, 196, 146, .30);

  --amber-wash: rgba(255, 177, 26, .13);
  --amber-ink: #f2c35a;
  --violet-wash: rgba(167, 139, 250, .15);
  --violet-wash-border: rgba(167, 139, 250, .30);
  --violet-ink: #c4b5fd;
  --indigo-wash: rgba(129, 140, 255, .15);
  --indigo-wash-border: rgba(129, 140, 255, .30);
  --indigo-ink: #a8b4ff;
  --blue-ink: #7ab4ff;
  --blue-wash: rgba(59, 139, 255, .15);
  --blue-wash-border: rgba(122, 180, 255, .32);
  --presence: #b49bf0;                 /* lifted for the dark ground: 6.2:1 on the panel */
  --presence-strong: #c7b4f6;
  --lime-ink: #b9f264;
  --lime-wash: rgba(183, 255, 0, .12);
  --lime-wash-border: rgba(185, 242, 100, .32);

  --danger: var(--coral-ink);
  --backdrop: rgba(4, 5, 8, .66);      /* a dark UI needs a heavier scrim than a light one to read as dimmed */
  --selection: rgba(255, 138, 61, .32);

  --priority-low: #7b8392;

  /* Chart marks, lifted so a thin line still clears 3:1 on the panel. */
  --chart-green: #3fcf9a;
  --chart-coral: #ff6b70;
  --chart-orange: #ff8a3d;
  --chart-indigo: #8f96ff;

  /* Elevation in the dark is mostly the lighter surface; the shadow is a 1px ring that gives the
     edge, plus a soft fall-off that only shows against the page. */
  --shadow: 0 0 0 1px rgba(210, 220, 240, .04), 0 1px 2px rgba(0, 0, 0, .35);
}

* { box-sizing: border-box; }
/* Tells the browser to draw scrollbars, native select popups and date pickers to match. Without
   it a dark workspace still gets a bright scrollbar down its side. */
html { font-size: 15px; color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
/* The browser's own selection blue clashes with an orange product and, in the dark, all but
   disappears into the panel. */
::selection { background: var(--selection); }
/* Thin scrollbars on the page colour. The default dark scrollbar is a light slab down the side of
   every scrolling panel. */
:root[data-theme="dark"] { scrollbar-color: #3a404b transparent; }
:root[data-theme="dark"] * { scrollbar-color: #3a404b transparent; }
body { margin: 0; color: var(--grey); background: var(--zircon); font-family: Inter, "Century Gothic", Arial, sans-serif; -webkit-font-smoothing: antialiased; }
body.no-scroll { overflow: hidden; }
/* Inputs do not inherit colour by default, so in dark mode every field would have rendered black
   text on a dark surface. */
button, input, select, textarea { font: inherit; color: inherit; }
/* A solid ring, with the soft one kept behind it as a halo.

   The soft ring alone was orange at 23% alpha -- 1.26:1 against white, measured -- where WCAG
   asks 3:1 of a focus indicator, and it disappeared entirely on the sunken and muted surfaces.
   The intent was right; a browser-default blue slab would look wrong here. It just needed an
   edge that can be seen.

   --orange-ink rather than --orange, because the brand orange cannot clear 3:1 on a light
   surface: #ff751a measures 2.69:1 on white and 2.55:1 on the app background. --orange-ink is
   already themed for exactly this -- #9a470e in light, #ffab6d in dark -- and measures 6.4:1 and
   8.9:1 on their respective card surfaces. */
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, a:focus-visible,
[tabindex]:focus-visible, summary:focus-visible { outline: 2px solid var(--orange-ink); outline-offset: 2px; box-shadow: 0 0 0 5px rgba(255,117,26,.20); }
/* The sidebar is dark in both themes, so it does not follow --orange-ink: in light mode that
   token is a dark brown and would vanish against it. The brand orange is the one that works
   here -- 5.3:1 on --ink. */
.sidebar :is(button, a, input, select, textarea):focus-visible { outline-color: var(--orange); }
/* The day picker hides its checkbox and styles the label, so focus had nowhere to land at all. */
.day-picker label:has(input:focus-visible) { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
[hidden] { display: none !important; }
/* Off-screen but readable by assistive technology. Used by the one status region that reports
   what changed, in place of the aria-live that used to wrap whole lists. */
.visually-hidden { position:absolute; width:1px; height:1px; margin:-1px; padding:0; border:0; clip-path:inset(50%); overflow:hidden; white-space:nowrap; }
/* Out of the way until it is tabbed to, then the first thing on the page. Uses --ink so it reads
   the same in both themes, like the toasts and the sidebar. */
.skip-link { position:absolute; top:-100px; left:12px; z-index:100; padding:10px 16px; border-radius:0 0 9px 9px; color:#fff; background:var(--ink); font-size:13px; font-weight:600; text-decoration:none; }
/* :focus, not :focus-visible. focus-visible is a heuristic and does not fire reliably for a link
   focused any way but a keypress -- measured: the link stayed off-screen at -100px when focused.
   A skip link that does not appear when it has focus is worse than not having one. */
.skip-link:focus { top:0; }
/* main takes focus when the skip link lands, and should not draw a ring for it. */
.main-content:focus { outline:none; }

.app-shell { min-height: 100vh; min-height: 100dvh; display: flex; }
.sidebar { position: fixed; inset: 0 auto 0 0; z-index: 30; width: 244px; padding: 24px 16px 16px; display: flex; flex-direction: column; color: var(--nav-ink-strong); background: var(--sidebar); }
/* The master artwork is 272x121, so height follows from width rather than being pinned: the old
   fixed 42px was tuned to a differently proportioned file and clipped this one. The product name
   sits in normal flow underneath instead of absolutely positioned, which is what made it collide
   with the wordmark when the logo grew. */
.brand { padding: 2px 11px; display: flex; flex-direction: column; align-items: flex-start; gap: 3px; margin-bottom: 27px; }
.brand img { width: 132px; height: auto; display: block; }
.product-name { color: #a9afad; font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: .3em; }
/* The rail scrolls, which makes it a clipping box -- and its edges sat exactly on the links'
   edges. Anything a link drew outside itself was cut off there: the focus ring (2px offset plus
   its 5px glow) lost its left and right sides, and the 2px hover nudge slid under the edge. The
   padding gives that decoration room inside the clip box; the matching negative margin puts the
   links themselves back where they were, borrowing the space from the sidebar's own padding. */
.main-nav { min-height: 0; flex: 1; overflow-y: auto; padding: 8px; margin: -8px; }
.nav-label { margin: 0 12px 8px; color: var(--nav-label); font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
.nav-space { margin-top: 27px; }
.nav-link { width: 100%; height: 44px; padding: 0 12px; border: 0; border-radius: 9px; display: flex; align-items: center; gap: 11px; color: var(--nav-ink); background: transparent; cursor: pointer; text-align: left; font-size: 13px; font-weight: 500; transition: .15s; }
.nav-link:hover { color: var(--nav-ink-strong); background: rgba(255,255,255,.055); }
.nav-link.active { color: var(--nav-ink-strong); background: rgba(255,117,26,.15); }
.nav-link.active .nav-icon { color: var(--orange); }
.nav-link b { margin-left: auto; min-width: 23px; padding: 2px 6px; border-radius: 999px; color: var(--nav-count); background: rgba(255,255,255,.07); font-size: 9px; text-align: center; }
.nav-link.active b { color: #ffe6d5; background: rgba(255,117,26,.16); }

.workspace-links-dialog { width:min(460px,calc(100vw - 32px)); padding:0; overflow:hidden; border:1px solid var(--border); border-radius:20px; color:var(--text); background:var(--surface); box-shadow:0 32px 90px rgba(15,20,27,.38),0 3px 12px rgba(15,20,27,.12); }
.workspace-links-dialog::backdrop { background:var(--backdrop); backdrop-filter:blur(5px); }
.workspace-links-dialog-head { padding:24px; display:flex; align-items:flex-start; justify-content:space-between; background:linear-gradient(135deg,var(--orange-wash-strong),var(--surface) 72%); }
.workspace-links-heading { display:flex; align-items:center; gap:14px; }
.workspace-links-heading-icon { width:44px; height:44px; border:1px solid var(--orange-wash-border); border-radius:14px; display:grid; place-items:center; flex:none; color: var(--link); background:var(--surface); box-shadow:0 7px 18px rgba(255,117,26,.12); }
.workspace-links-heading-icon svg { width:21px; height:21px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.workspace-links-dialog-head .eyebrow { margin:0 0 3px!important; color: var(--link)!important; font-size:8px!important; letter-spacing:.16em!important; }
.workspace-links-dialog-head h2 { margin:0; font-size:22px; letter-spacing:-.025em; }
.workspace-links-subtitle { margin:4px 0 0; color:var(--muted); font-size:10px; }
.workspace-links-dialog-head > button { width:32px; height:32px; border:0; border-radius:50%; color:var(--muted); background:color-mix(in srgb, var(--surface) 60%, transparent); cursor:pointer; font-size:20px; line-height:1; transition:.16s ease; }
.workspace-links-dialog-head > button:hover { color:var(--text); background:var(--surface); transform:rotate(5deg); }
.workspace-links-launcher { padding:15px 16px 8px; display:grid; gap:9px; }
.workspace-link-launch { min-height:66px; padding:11px 13px; border:1px solid var(--border); border-radius:13px; display:grid; grid-template-columns:38px minmax(0,1fr) 28px; grid-template-rows:auto auto; align-items:center; column-gap:11px; color:var(--text); background:var(--surface); text-decoration:none; box-shadow:0 2px 5px rgba(24,30,39,.025); transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease,background .16s ease; }
.workspace-link-launch:hover { border-color:var(--orange-wash-border); background:var(--orange-wash); box-shadow:0 8px 20px rgba(255,117,26,.1); transform:translateY(-1px); }
.workspace-link-launch-icon { grid-row:1 / span 2; width:38px; height:38px; border-radius:11px; display:grid; place-items:center; color: var(--link); background:var(--orange-wash-strong); font-size:14px; font-weight:900; }
.workspace-link-launch-name { align-self:end; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12px; font-weight:800; }
.workspace-link-launch small { align-self:start; overflow:hidden; color:var(--muted); font-size:9px; text-overflow:ellipsis; white-space:nowrap; }
.workspace-link-launch-arrow { grid-column:3; grid-row:1 / span 2; width:27px; height:27px; border-radius:50%; display:grid; place-items:center; color:var(--text-faint); background:var(--surface-sunken); font-size:14px; transition:.16s ease; }
.workspace-link-launch:hover .workspace-link-launch-arrow { color: var(--on-orange); background:var(--orange); transform:translateX(2px); }
.workspace-links-manage { width:max-content; margin:7px auto 17px; padding:8px 13px; border-radius:999px; display:block; color: var(--link); background:var(--orange-wash); font-size:10px; font-weight:800; text-align:center; text-decoration:none; transition:.16s ease; }
.workspace-links-manage:hover { color: var(--on-orange); background:var(--orange); }
.workspace-links-empty { margin:12px; color:var(--muted); font-size:12px; text-align:center; }
.workspace-links-settings-head { margin-bottom:16px; display:flex; align-items:flex-start; justify-content:space-between; gap:16px; }
.workspace-links-settings-head h3 { margin-bottom:4px; }
.workspace-links-settings-head p { margin:0; }
.workspace-links-settings-list { display:grid; gap:10px; }
.workspace-link-setting-row { padding:12px; border:1px solid var(--border); border-radius:10px; display:grid; grid-template-columns:minmax(130px,.8fr) minmax(220px,1.6fr) auto; align-items:end; gap:10px; background:var(--surface-sunken); }
.workspace-link-setting-row label { margin:0; font-size:10px; font-weight:800; }
.workspace-link-setting-row input { width:100%; height:38px; margin-top:5px; padding:0 10px; border:1px solid var(--border-dark); border-radius:7px; color:var(--text); background:var(--surface); font:inherit; }
.workspace-link-row-actions { display:flex; gap:4px; }
.workspace-link-row-actions button { width:34px; height:38px; border:1px solid var(--border-dark); border-radius:7px; color:var(--text); background:var(--surface); cursor:pointer; font-weight:900; }
.workspace-link-row-actions button:disabled { opacity:.35; cursor:not-allowed; }
@media (max-width:760px) { .workspace-link-setting-row { grid-template-columns:1fr; }.workspace-link-row-actions { justify-content:flex-end; } }
/* Drawn icons rather than typed ones. The rail used whatever geometric characters were nearest to
   hand -- a chess pawn stood in for Contacts, three shaded-block glyphs for Tickets, Venues and
   Reports -- and every font substituted its own idea of them, so no two sat on the same baseline
   or weight. These are the same 24-grid, 1.8-stroke set the overview cards already draw with.
   The glyph is sized in em so the existing font-size steps down the compact breakpoints keep
   scaling the icon exactly as they scaled the character. */
.nav-icon { width: 21px; flex: none; display: grid; place-items: center; color: var(--nav-icon-rest); font-size: 18px; }
.nav-icon svg { width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.view-dot { width: 7px; height: 7px; margin: 0 7px; border-radius: 50%; flex: none; }
.view-dot.green { background: var(--green); }.view-dot.orange { background: var(--orange); }.view-dot.coral { background: var(--coral); }.view-dot.grey { background: var(--neutral-mark); }.view-dot.blue { background: var(--blue-ink); }
.integration-card { margin: 12px 1px 16px; padding: 12px; border: 1px solid rgba(255,255,255,.08); border-radius: 11px; display: flex; align-items: center; gap: 10px; background: rgba(255,255,255,.035); }
.integration-icon { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; flex: none; color: var(--link); background: rgba(255,117,26,.12); }
.integration-icon svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.sidebar-integration-button.connected .integration-icon { color: var(--green); background: rgba(35,190,139,.14); }
.integration-card b, .integration-card span { display: block; }.integration-card b { font-size: 11px; }.integration-card span { margin-top: 3px; color: var(--nav-label); font-size: 9px; }
.avatar { width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; flex: none; color: var(--avatar-ink); background: var(--avatar-bg); font-size: 10px; font-weight: 700; }
.avatar-own { color: var(--avatar-own-ink); background: var(--avatar-own-bg); }

/* The user menu opens upward, because the card it hangs off is the last thing in the sidebar.
   It keeps the sidebar's dark treatment in both themes -- the sidebar is already near-black in
   light mode, so a white panel here would read as a hole punched in it. */
.user-menu { position: relative; }
.user-card { width: 100%; min-height: 56px; padding: 13px 6px 0; border: 0; border-top: 1px solid rgba(255,255,255,.08); display: flex; align-items: center; gap: 9px; color: inherit; background: transparent; cursor: pointer; text-align: left; }
.user-card b, .user-card span { display: block; }.user-card > div:nth-child(2) { min-width: 0; }.user-card b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; }.user-card > div:nth-child(2) span { margin-top: 2px; color: var(--nav-label); font-size: 9px; }
.user-caret { margin-left: auto; padding: 0 4px; color: #7f8482; font-size: 12px; transition: transform .16s, color .16s; }
.user-card:hover .user-caret { color: var(--nav-ink-strong); }
.user-menu.open .user-caret { color: var(--nav-ink-strong); transform: rotate(180deg); }

.user-menu-panel { position: absolute; z-index: 40; left: 0; right: 0; bottom: calc(100% + 10px); padding: 7px; border: 1px solid rgba(255,255,255,.1); border-radius: 12px; background: #383838; box-shadow: 0 18px 44px rgba(0,0,0,.45); }
.user-menu-head { margin-bottom: 4px; padding: 8px 8px 12px; border-bottom: 1px solid rgba(255,255,255,.08); display: flex; align-items: center; gap: 9px; }
.user-menu-head > div:last-child { min-width: 0; }.user-menu-head b, .user-menu-head span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.user-menu-head b { font-size: 11px; }.user-menu-head span { margin-top: 3px; color: var(--nav-label); font-size: 9px; }
.user-menu-label { margin: 8px 0 7px 8px; color: var(--nav-label); font-size: 9px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
.theme-choice { padding: 0 2px; display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 4px; }
.theme-choice button { padding: 9px 2px 8px; border: 1px solid transparent; border-radius: 8px; display: flex; flex-direction: column; align-items: center; gap: 6px; color: var(--nav-ink); background: rgba(255,255,255,.05); cursor: pointer; font-size: 9px; font-weight: 600; transition: .15s; }
.theme-choice button > span { font-size: 14px; line-height: 1; }
.theme-choice button:hover { color: #fff; background: rgba(255,255,255,.1); }
.theme-choice button[aria-checked="true"] { color: #fff; border-color: rgba(255,117,26,.45); background: rgba(255,117,26,.17); }
.theme-choice button[aria-checked="true"] > span { color: var(--link); }
/* The way out to the public site, above the divider that sign out sits under: it is a place to
   go, not a way to end the session, and it reads as the same kind of row. */
.user-menu-link { margin-top: 7px; padding: 9px; border-radius: 8px; display: flex; align-items: center; gap: 9px; color: var(--nav-ink); text-decoration: none; font-size: 10px; font-weight: 600; }
.user-menu-link:hover { color: var(--nav-ink-strong); background: rgba(255,255,255,.08); }
.user-menu-link > span { width: 15px; font-size: 13px; text-align: center; }
.user-menu-signout { margin-top: 7px; padding-top: 6px; border-top: 1px solid rgba(255,255,255,.08); }
.user-menu-signout button { width: 100%; padding: 9px; border: 0; border-radius: 8px; display: flex; align-items: center; gap: 9px; color: var(--nav-ink); background: transparent; cursor: pointer; text-align: left; font-size: 10px; font-weight: 600; }
.user-menu-signout button:hover { color: var(--nav-ink-strong); background: rgba(255,255,255,.08); }
.user-menu-signout button > span { width: 15px; font-size: 13px; text-align: center; }
.user-menu-note { margin: 7px 0 2px; padding: 7px 8px 0; border-top: 1px solid rgba(255,255,255,.08); color: var(--nav-label); font-size: 9px; line-height: 1.45; }

.main-content { min-width: 0; width: calc(100% - 244px); margin-left: 244px; }
.topbar { height: 68px; padding: 0 28px; border-bottom: 1px solid var(--border); display: flex; align-items: center; position: sticky; top: 0; z-index: 20; background: var(--topbar); backdrop-filter: blur(14px); }
.global-search { width: min(430px,46vw); height: 39px; padding: 0 11px; border: 1px solid var(--border); border-radius: 9px; display: flex; align-items: center; gap: 8px; background: var(--zircon); }
.global-search > span { color: var(--text-faint); font-size: 20px; }.global-search input { min-width: 0; width: 100%; border: 0; outline: 0; color: var(--grey); background: transparent; font-size: 12px; }.global-search kbd { padding: 3px 6px; border: 1px solid var(--border); border-radius: 5px; color: var(--text-faint); background: var(--surface); font: 8px Inter; }
.top-actions { margin-left: auto; display: flex; gap: 9px; }
.primary-button, .secondary-button, .danger-button { min-height: 40px; padding: 0 17px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer; font-size: 12px; font-weight: 700; transition: .16s; }
.primary-button { border: 1px solid var(--orange); color: var(--on-orange); background: var(--orange); box-shadow: 0 5px 14px rgba(255,117,26,.18); }.primary-button:hover { border-color: var(--orange-hover); background: var(--orange-hover); transform: translateY(-1px); }.primary-button:active { border-color: var(--orange-active); background: var(--orange-active); }.primary-button.small { min-height: 34px; padding: 0 14px; font-size: 10px; }
.secondary-button { border: 1px solid var(--border-dark); color: var(--grey); background: var(--surface); }.secondary-button:hover { border-color: var(--border-hover); background: var(--surface-sunken); }
.danger-button { border: 1px solid var(--coral); color: #fff; background: var(--coral); }.danger-button:hover { background: var(--coral-hover); }
.notification-button,.icon-button { width: 40px; height: 40px; border: 0; border-radius: 50%; display: grid; place-items: center; position: relative; cursor: pointer; background: transparent; font-size: 20px; }.notification-button:hover,.icon-button:hover { background: var(--surface-hover); }
.notification-button svg { width: 21px; height: 21px; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.notification-button i { position: absolute; right: 0; top: 0; min-width: 17px; height: 17px; padding: 0 4px; border: 2px solid var(--surface); border-radius: 9px; display: grid; place-items: center; color: #fff; background: var(--coral); font-size: 8px; font-style: normal; }
.menu-button { display: none; }
.popover { position: fixed; z-index: 60; top: 60px; right: 27px; width: 335px; overflow: hidden; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); box-shadow: 0 18px 50px rgba(35,40,49,.16); }
.popover-head { height: 49px; padding: 0 15px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; }.popover-head b { font-size: 12px; }.popover-head button { border: 0; color: var(--link); background: transparent; cursor: pointer; font-size: 9px; font-weight: 700; }
.notification-item { width: 100%; padding: 13px 15px; border: 0; border-bottom: 1px solid var(--hairline); display: flex; align-items: center; gap: 10px; text-align: left; background: var(--surface); cursor: pointer; }.notification-item:hover { background: var(--surface-hover); }.notification-item b,.notification-item small { display: block; }.notification-item b { font-size: 11px; }.notification-item small { margin-top: 3px; color: var(--muted); font-size: 9px; }
.notice-icon { width: 29px; height: 29px; border-radius: 50%; display: grid; place-items: center; flex: none; font-size: 10px; font-weight: 800; }.notice-icon.coral { color:var(--coral-ink); background:var(--coral-pale); }.notice-icon.orange { color:var(--orange-ink); background:var(--orange-pale); }
.notification-empty { padding: 28px 18px; color: var(--muted); text-align: center; font-size: 11px; }

.view { display: none; width: 100%; min-height: calc(100vh - 68px); min-height: calc(100dvh - 68px); padding: 28px 30px 32px; }
.view.active { display: flex; flex-direction: column; }
.page-head { min-height: 68px; margin-bottom: 22px; display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex: none; }
.page-head h1 { margin: 0 0 5px; font-size: 29px; line-height: 1.2; letter-spacing: -.035em; }.page-head > div > p:last-child { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; }
/* A back link in a page head is drawn as a button, so it should not also be underlined. */
.page-head .secondary-button { text-decoration: none; }
.eyebrow { margin: 0 0 5px !important; color: var(--orange-ink) !important; font-size: 9px !important; line-height: 1.4 !important; font-weight: 800 !important; letter-spacing: .12em !important; text-transform: uppercase; }
.panel { border: 1px solid var(--border); border-radius: 14px; background: var(--surface); box-shadow: var(--shadow); }
.summary-grid { margin-bottom: 18px; display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 14px; }
.summary-card { min-height: 124px; padding: 20px; border: 1px solid var(--border); border-radius: 14px; display: flex; align-items: center; gap: 15px; position: relative; overflow: hidden; background: var(--surface); box-shadow: var(--shadow); }.summary-card::after { content:""; position:absolute; top:0; right:0; width:44px; height:7px; border-radius:0 0 0 9px; background: var(--ink); }.summary-card.accent-green::after { background:var(--green); }.summary-card.accent-coral::after { background:var(--coral); }.summary-card.accent-orange::after { background:var(--orange); }
.summary-icon { width: 40px; height: 40px; border-radius: 11px; display:grid; place-items:center; flex:none; color: var(--text-soft); background: var(--surface-muted); font-size:17px; }.accent-green .summary-icon { color:var(--green-ink); background:var(--green-pale); }.accent-coral .summary-icon { color:var(--coral-ink); background:var(--coral-pale); }.accent-orange .summary-icon { color:var(--orange-ink); background:var(--orange-pale); }
.summary-card p { margin:0 0 3px; color:var(--muted); font-size:11px; font-weight:600; }.summary-card h2 { margin:0 0 5px; font-size:24px; letter-spacing:-.04em; }.summary-card span { color: var(--text-faint); font-size:9px; }
.panel-head { min-height:76px; padding:18px 21px; display:flex; align-items:center; justify-content:space-between; }.panel-head h2 { margin:0 0 4px; font-size:17px; }.panel-head > div > span { color:var(--muted); font-size:11px; }.quiet-button,.text-button { padding:4px; border:0; color: var(--link); background:transparent; cursor:pointer; font-size:11px; font-weight:700; }.quiet-button:hover,.text-button:hover { text-decoration:underline; }
.empty-icon { width:48px; height:48px; border-radius:15px; display:grid; place-items:center; color:var(--orange-ink); background:var(--orange-pale); font-size:20px; }
.quick-start-panel { overflow:hidden; align-self:start; }.quick-action { width:100%; min-height:76px; padding:13px 19px; border:0; border-top:1px solid var(--hairline); display:flex; align-items:center; gap:11px; text-align:left; background: var(--surface); cursor:pointer; }.quick-action:hover { background: var(--surface-sunken); }.quick-action > span:nth-child(2) { min-width:0; flex:1; }.quick-action b,.quick-action small { display:block; }.quick-action b { font-size:11px; }.quick-action small { margin-top:4px; color:var(--muted); font-size:9px; line-height:1.4; }.quick-action em { color: var(--text-faint); font-style:normal; }.quick-icon { width:34px; height:34px; border-radius:10px; display:grid; place-items:center; flex:none; }.quick-icon.orange { color:var(--orange-ink); background:var(--orange-pale); }.quick-icon.green { color:var(--green-ink); background:var(--green-pale); }.quick-icon.grey { color: var(--text-soft); background: var(--surface-muted); }

.ticket-workspace,.contacts-workspace { min-height:0; flex:1; overflow:hidden; display:flex; flex-direction:column; }
.ticket-toolbar { min-height:64px; padding:0 19px; display:flex; align-items:center; justify-content:space-between; gap:18px; flex:none; }.ticket-tabs { height:64px; display:flex; align-items:stretch; gap:22px; }.ticket-tab { padding:2px 1px 0; border:0; border-bottom:2px solid transparent; color: var(--text-soft); background:transparent; cursor:pointer; font-size:11px; font-weight:600; }.ticket-tab span { margin-left:3px; padding:2px 5px; border-radius:999px; color: var(--text-faint); background: var(--surface-muted); font-size:8px; }.ticket-tab.active { color: var(--link); border-color:var(--orange); }.ticket-tab.active span { color:var(--orange-ink); background:var(--orange-pale); }
.toolbar-actions { display:flex; align-items:center; gap:7px; }.queue-search { width:210px; height:36px; padding:0 10px; border:1px solid var(--border); border-radius:8px; display:flex; align-items:center; gap:6px; background:var(--zircon); }.queue-search span { color: var(--text-faint); font-size:17px; }.queue-search input { min-width:0; width:100%; border:0; outline:0; background:transparent; font-size:10px; }.tool-button,.sort-select { height:36px; border:1px solid var(--border); border-radius:8px; color: var(--text-soft); background: var(--surface); font-size:10px; }.tool-button { padding:0 11px; position:relative; cursor:pointer; font-weight:600; }.tool-button i { position:absolute; right:-3px; top:-3px; width:8px; height:8px; border: 2px solid var(--surface); border-radius:50%; background:var(--orange); }.sort-select { padding:0 28px 0 9px; }
.filter-panel { padding:13px 19px; border-top:1px solid var(--border); display:flex; align-items:flex-end; gap:10px; background: var(--surface-sunken); }.filter-panel label { color: var(--text-soft); font-size:9px; font-weight:700; }.filter-panel select { width:145px; height:34px; margin-top:5px; padding:0 8px; border:1px solid var(--border); border-radius:7px; display:block; background: var(--surface); font-size:10px; }.filter-panel .text-button { margin:0 0 7px 5px; }
.ticket-table-head { min-height:39px; padding:0 20px 0 30px; border-top:1px solid var(--border); border-bottom:1px solid var(--border); display:grid; grid-template-columns:minmax(320px,2.3fr) minmax(210px,1.3fr) 110px minmax(150px,1fr) 115px; gap:16px; align-items:center; color: var(--text-faint); background: var(--surface-head); font-size:8px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; flex:none; }
.ticket-list { min-height:0; flex:1; overflow-y:auto; }.ticket-row { width:100%; min-height:72px; padding:10px 20px; border:0; border-bottom:1px solid var(--hairline); display:grid; grid-template-columns:minmax(320px,2.3fr) minmax(210px,1.3fr) 110px minmax(150px,1fr) 115px; gap:16px; align-items:center; text-align:left; background: var(--surface); cursor:pointer; }.ticket-row:hover { background: var(--surface-sunken); }.ticket-subject { min-width:0; padding-left:10px; position:relative; }.ticket-subject::before { content:""; position:absolute; left:0; top:2px; bottom:2px; width:3px; border-radius:4px; background: var(--neutral-mark); }.ticket-row[data-priority="urgent"] .ticket-subject::before { background:var(--coral); }.ticket-row[data-priority="high"] .ticket-subject::before { background:var(--orange); }.ticket-row[data-priority="normal"] .ticket-subject::before { background:var(--green); }
.ticket-subject b,.ticket-subject span,.ticket-customer b,.ticket-customer span { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }.ticket-subject b { margin-bottom:5px; font-size:12px; }.ticket-subject span,.ticket-customer span { color:var(--muted); font-size:9px; }.ticket-customer { min-width:0; }.ticket-customer b { margin-bottom:4px; font-size:10px; }.ticket-assignee { min-width:0; display:flex; align-items:center; gap:8px; }.ticket-assignee .avatar { width:28px; height:28px; font-size:8px; }.ticket-assignee span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:9px; }
.status-pill,.sla-pill,.priority-chip { width:max-content; padding:5px 9px; border-radius:999px; font-size:8px; font-weight:700; text-transform:capitalize; }.status-pill.open { color:var(--green-ink); background:var(--green-pale); }.status-pill.pending { color: var(--orange-ink); background:var(--orange-pale); }.status-pill.resolved,.status-pill.closed { color: var(--text-soft); background: var(--surface-muted); }.sla-pill { color:var(--amber-ink); background:var(--amber-wash); }.sla-pill.done { color: var(--text-soft); background: var(--surface-muted); }.sla-pill.risk,.sla-pill.warning { color: var(--orange-ink); background:var(--orange-pale); }.sla-pill.overdue { color:var(--coral-ink); background:var(--coral-pale); }
.empty-state { min-height:300px; padding:50px 20px; flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; }.empty-state h3 { margin:14px 0 7px; font-size:15px; }.empty-state p { margin:0 0 17px; color:var(--muted); font-size:11px; }.empty-state .text-button { margin-top:8px; }.table-footer { min-height:50px; padding:0 19px; display:flex; align-items:center; justify-content:space-between; flex:none; color:var(--muted); background: var(--surface-sunken); font-size:9px; }.table-footer div { display:flex; align-items:center; gap:9px; }.table-footer button { width:30px; height:30px; border:1px solid var(--border); border-radius:7px; background: var(--surface); cursor:pointer; }.table-footer button:disabled { opacity:.4; cursor:default; }

.contacts-toolbar { min-height:70px; padding:0 20px; display:flex; align-items:center; justify-content:space-between; flex:none; }.contacts-toolbar h2 { margin:0 0 4px; font-size:15px; }.contacts-toolbar > div span { color:var(--muted); font-size:9px; }.contact-search { width:280px; }.contact-table-head,.contact-row { display:grid; grid-template-columns:minmax(260px,1.5fr) minmax(180px,1fr) minmax(150px,.8fr) 90px 220px; gap:16px; align-items:center; }.contact-table-head { min-height:39px; padding:0 22px; border-top:1px solid var(--border); border-bottom:1px solid var(--border); color: var(--text-faint); background: var(--surface-head); font-size:8px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }.contact-list { min-height:0; overflow-y:auto; }.contact-row { min-height:72px; padding:11px 22px; border-bottom:1px solid var(--hairline); }.contact-person { min-width:0; display:flex; align-items:center; gap:10px; }.contact-person .avatar { width:37px; height:37px; color: var(--orange-ink); background:var(--orange-pale); }.contact-person .contact-open,.contact-person b,.contact-person span:not(.avatar) { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }.contact-person .contact-open,.contact-person b { margin-bottom:4px; font-size:11px; }/* The name is a real button so it can be reached and activated; it should read as the heading it looks like. */.contact-person .contact-open { width:100%; padding:0; border:0; color:inherit; background:none; cursor:pointer; font-weight:700; text-align:left; }.contact-person .contact-open:hover { color: var(--link); text-decoration:underline; }.contact-person span:not(.avatar),.contact-cell { color:var(--muted); font-size:9px; }.contact-ticket-count { font-size:10px; }.contact-actions { display:flex; align-items:center; justify-content:flex-end; gap:6px; }.contact-actions button { min-height:32px; padding:0 11px; border:1px solid var(--border); border-radius:999px; background: var(--surface); cursor:pointer; font-size:9px; font-weight:600; }.contact-actions button:first-child { color: var(--link); border-color:var(--orange-wash-border); }.contact-actions button:hover { background:var(--surface-hover); }.contact-actions .archive-contact { width:32px; padding:0; color:var(--coral-hover); }
/* The venue cell holds two lines -- the venue, then the job title or "+2 more" -- and had no rule
   making them lines, so they ran together as "No venueVenue Manager". The calls list solves the
   same shape this way. */
.contact-cell b,.contact-cell span { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.contact-cell b { margin-bottom:4px; color:var(--grey); font-size:11px; }

.settings-form { min-height:600px; padding:0; overflow:hidden; }.settings-section { display:none; }.settings-section.active { display:block; }.settings-section-head { padding:24px 25px 19px; border-bottom:1px solid var(--border); }.settings-section-head h2 { margin:0 0 5px; font-size:19px; }.settings-section-head p { margin:0; color:var(--muted); font-size:11px; line-height:1.5; }.settings-fields { max-width:720px; padding:22px 25px; display:grid; gap:15px; }.settings-fields.two-column { grid-template-columns:1fr 1fr; }.settings-fields label,.field-label { color: var(--text-soft); font-size:10px; font-weight:700; }.settings-fields input,.settings-fields select { width:100%; height:40px; margin-top:7px; padding:0 11px; border:1px solid var(--border-dark); border-radius:8px; display:block; outline:0; background: var(--surface); font-size:11px; }.settings-fields input:focus,.settings-fields select:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.1); }
.setting-toggles { padding:0 25px 22px; }.setting-toggles.compact { padding-top:20px; padding-bottom:5px; }.toggle-row { min-height:66px; padding:12px 0; border-bottom:1px solid var(--hairline); display:flex; align-items:center; gap:15px; cursor:pointer; }.toggle-row > span { min-width:0; flex:1; }.toggle-row b,.toggle-row small { display:block; }.toggle-row b { font-size:11px; }.toggle-row small { margin-top:4px; color:var(--muted); font-size:9px; line-height:1.45; }/* Clipped to a pixel rather than just transparent: positioned off the flow with no offsets it kept its static position, which on a phone is past the right edge, and the page scrolled sideways. It stays focusable, which display:none would not. */.toggle-row input { position:absolute; width:1px; height:1px; margin:-1px; padding:0; border:0; opacity:0; overflow:hidden; clip-path:inset(50%); pointer-events:none; }.toggle-row i { width:38px; height:22px; padding:3px; border-radius:999px; display:block; flex:none; background: var(--neutral-mark); transition:.18s; }.toggle-row i::after { content:""; width:16px; height:16px; border-radius:50%; display:block; background: var(--surface); box-shadow:0 1px 3px rgba(0,0,0,.18); transition:.18s; }.toggle-row input:checked + i { background:var(--green); }.toggle-row input:checked + i::after { transform:translateX(16px); }.toggle-row input:focus-visible + i { outline:3px solid rgba(255,117,26,.23); outline-offset:2px; }
.field-label { margin:0 25px 9px; font-size:8px; letter-spacing:.09em; }.day-picker { display:flex; flex-wrap:wrap; gap:7px; }.day-picker label { min-width:49px; height:32px; padding:0 10px; border:1px solid var(--border); border-radius:8px; display:flex; align-items:center; justify-content:center; position:relative; color:var(--muted); background: var(--surface); cursor:pointer; font-size:9px; font-weight:600; }.day-picker input { position:absolute; opacity:0; }.day-picker label:has(input:checked) { color: var(--on-orange); border-color:var(--orange); background:var(--orange); }.sla-label { margin-top:18px; }.sla-grid { padding:0 25px 25px; display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }.sla-grid label { padding:13px; border:1px solid var(--border); border-radius:10px; position:relative; background: var(--surface-sunken); }.priority-chip { display:block; margin-bottom:11px; }.priority-chip.urgent { color:var(--coral-ink); background:var(--coral-pale); }.priority-chip.high { color: var(--orange-ink); background:var(--orange-pale); }.priority-chip.normal { color:var(--green-ink); background:var(--green-pale); }.priority-chip.low { color: var(--text-soft); background: var(--surface-muted); }.sla-grid input { width:100%; height:37px; padding:0 43px 0 9px; border:1px solid var(--border-dark); border-radius:7px; font-size:11px; }.sla-grid small { position:absolute; right:20px; bottom:25px; color:var(--muted); font-size:7px; }.notification-label { margin-top:12px; }.integration-settings-card { min-height:84px; margin:18px 25px 0; padding:15px; border:1px solid var(--border); border-radius:11px; display:flex; align-items:center; gap:13px; }.integration-logo { width:40px; height:40px; border-radius:11px; display:grid; place-items:center; flex:none; font-size:17px; }.integration-logo.orange { color:var(--orange-ink); background:var(--orange-pale); }.integration-logo.green { color:var(--green-ink); background:var(--green-pale); }.integration-settings-card > div { flex:1; }.integration-settings-card b { font-size:11px; }.integration-settings-card p { margin:5px 0 0; color:var(--muted); font-size:9px; }.integration-settings-card em { padding:5px 8px; border-radius:999px; color: var(--text-soft); background: var(--surface-muted); font-size:8px; font-style:normal; font-weight:700; }.integration-note { margin:18px 25px 25px; padding:15px; border-radius:10px; color: var(--orange-ink); background:var(--orange-pale); }.integration-note b,.integration-note span { display:block; }.integration-note b { margin-bottom:5px; font-size:10px; }.integration-note span { font-size:9px; line-height:1.5; }
.integration-settings-link { width:calc(100% - 50px); color:inherit; text-align:left; background: var(--surface); cursor:pointer; }.integration-settings-link:hover { border-color:var(--orange-wash-border); background: var(--orange-wash); }.integration-settings-link > span:last-child { color: var(--link); font-size:18px; }.integration-settings-link em.connected { color: var(--green-ink); background:var(--green-pale); }

/* Microsoft 365 email channel */
.email-section-head { min-height:92px; display:flex; align-items:center; justify-content:space-between; gap:20px; }.email-section-head > div { min-width:0; }.connection-status { min-height:29px; padding:0 10px; border-radius:999px; display:inline-flex; align-items:center; gap:7px; flex:none; color: var(--text-soft); background: var(--surface-muted); font-size:9px; font-weight:800; }.connection-status i { width:7px; height:7px; border-radius:50%; background: var(--neutral-mark); }.connection-status.connected { color: var(--green-ink); background:var(--green-pale); }.connection-status.connected i { background:var(--green); box-shadow:0 0 0 3px rgba(33,173,126,.14); }.connection-status.attention { color: var(--orange-ink); background:var(--orange-pale); }.connection-status.attention i { background:var(--orange); }.connection-status.error { color: var(--coral-ink); background:var(--coral-pale); }.connection-status.error i { background:var(--coral); }
.email-action-button { min-height:34px; padding:0 12px; font-size:9px; }
.email-health-item { min-height:61px; padding:11px 12px; border:1px solid var(--border); border-radius:10px; display:flex; align-items:center; gap:9px; background: var(--surface); }.health-dot { width:9px; height:9px; border: 2px solid var(--surface); border-radius:50%; flex:none; background: var(--neutral-mark); box-shadow:0 0 0 1px var(--hairline); }.health-dot.good { background:var(--green); box-shadow:0 0 0 3px rgba(33,173,126,.12); }.health-dot.warning { background:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.12); }.health-dot.bad { background:var(--coral); box-shadow:0 0 0 3px rgba(254,56,56,.1); }.email-health-item b,.email-health-item small { display:block; }.email-health-item b { font-size:10px; }.email-health-item small { margin-top:4px; overflow:hidden; color:var(--muted); font-size:8px; line-height:1.35; text-overflow:ellipsis; white-space:nowrap; }
.connection-callout { margin-top:12px; padding:12px 14px; border:1px solid var(--orange-wash-border); border-radius:10px; display:flex; align-items:flex-start; gap:10px; color: var(--orange-ink); background: var(--orange-wash); }.connection-callout > span { width:21px; height:21px; border-radius:50%; display:grid; place-items:center; flex:none; color: var(--on-orange); background:var(--orange); font:700 10px Georgia,serif; }.connection-callout b,.connection-callout p { display:block; }.connection-callout b { margin-bottom:3px; font-size:10px; }.connection-callout p { margin:0; font-size:9px; line-height:1.5; }.connection-callout.success { border-color:var(--green-wash-border); color: var(--green-ink); background: var(--green-wash); }.connection-callout.success > span { background:var(--green); }.connection-callout.error { border-color:var(--coral-wash-border); color: var(--coral-ink); background: var(--coral-wash); }.connection-callout.error > span { background:var(--coral); }
.email-settings-card,.email-side-card { border:1px solid var(--border); border-radius:12px; background: var(--surface); box-shadow:0 1px 2px rgba(28,33,42,.025); }.email-settings-card { overflow:hidden; }.email-card-head { min-height:74px; padding:15px 17px; border-bottom:1px solid var(--hairline); display:flex; align-items:center; justify-content:space-between; gap:20px; }.email-card-head > div { display:flex; align-items:center; gap:9px; }.email-card-head h3,.email-side-card h3 { margin:0; font-size:12px; }.email-card-head > p { max-width:300px; margin:0; color:var(--muted); font-size:9px; line-height:1.5; text-align:right; }
.email-field-grid { padding:17px; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:15px; }.email-field { min-width:0; color: var(--text-soft); font-size:10px; font-weight:700; }.email-field.full { grid-column:1 / -1; }.email-field input,.email-field textarea,.copy-field input { width:100%; margin-top:7px; padding:0 11px; border:1px solid var(--border-dark); border-radius:8px; display:block; outline:0; color:var(--grey); background: var(--surface); font-size:11px; font-weight:400; }.email-field input,.copy-field input { height:40px; }.email-field textarea { min-height:86px; padding-top:10px; resize:vertical; line-height:1.5; }.email-field input:focus,.email-field textarea:focus,.copy-field input:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.1); }.email-field > small { display:block; margin-top:6px; color:var(--muted); font-size:8px; font-weight:400; line-height:1.45; }.input-label { display:block; }.copy-field { margin-top:7px; display:flex; }.copy-field input { min-width:0; margin:0; border-radius:8px 0 0 8px; color: var(--text-soft); background: var(--surface-muted); }.copy-field button { min-width:58px; padding:0 10px; border:1px solid var(--border-dark); border-left:0; border-radius:0 8px 8px 0; color: var(--link); background: var(--surface); cursor:pointer; font-size:9px; font-weight:700; }.copy-field button:hover { background: var(--orange-wash); }.copy-field button:disabled { color: var(--text-faint); background: var(--surface-muted); cursor:not-allowed; }
.credential-row { min-height:64px; margin:0 17px 17px; padding:11px 12px; border:1px solid var(--hairline); border-radius:9px; display:flex; align-items:center; gap:10px; background: var(--surface-head); }.credential-icon { width:29px; height:29px; border-radius:8px; display:grid; place-items:center; flex:none; color: var(--text-soft); background: var(--surface-muted); font-size:10px; }.credential-row > div { min-width:0; flex:1; }.credential-row b,.credential-row small { display:block; }.credential-row b { font-size:10px; }.credential-row small { margin-top:3px; color:var(--muted); font-size:8px; line-height:1.4; }.credential-badge { padding:4px 7px; border-radius:999px; color: var(--orange-ink); background:var(--orange-pale); font-size:7px; font-weight:800; }.credential-badge.configured { color: var(--green-ink); background:var(--green-pale); }
.credential-row + .credential-row { margin-top:-9px; }
.email-toggle-wrap { padding:0 17px; }.email-toggle { min-height:72px; border-bottom:0; }.email-field-grid[aria-disabled="true"] { opacity:.5; }.email-field-grid[aria-disabled="true"] input,.email-field-grid[aria-disabled="true"] textarea { cursor:not-allowed; }
.email-side-card { padding:17px; }

.ticket-detail-view { padding:0; }.ticket-detail-bar { min-height:80px; padding:12px 24px; border-bottom:1px solid var(--border); display:flex; align-items:center; gap:20px; position:relative; background: var(--surface); flex:none; }.ticket-breadcrumb { min-width:0; flex:1; display:flex; align-items:center; gap:12px; }.ticket-breadcrumb > button { width:36px; height:36px; border:1px solid var(--border); border-radius:9px; flex:none; background: var(--surface); cursor:pointer; }.ticket-breadcrumb > div { min-width:0; }.ticket-breadcrumb span { display:block; margin-bottom:4px; color:var(--muted); font-size:9px; }.ticket-breadcrumb span b { color: var(--link); }.ticket-breadcrumb h1 { margin:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:16px; }.ticket-detail-actions { display:flex; align-items:center; gap:7px; }.ticket-detail-actions .secondary-button { min-height:36px; padding:0 13px; font-size:10px; }.more-button { width:36px; height:36px; border:1px solid var(--border); border-radius:9px; display:grid; place-items:center; cursor:pointer; background: var(--surface); }.drawer-actions-menu { position:absolute; z-index:5; top:62px; right:24px; width:175px; padding:5px; border:1px solid var(--border); border-radius:9px; background: var(--surface); box-shadow:0 12px 35px rgba(30,34,40,.16); }.drawer-actions-menu button { width:100%; padding:10px; border:0; border-radius:6px; text-align:left; background:transparent; cursor:pointer; font-size:9px; }.drawer-actions-menu button:hover { background:var(--surface-hover); }.danger-text { color:var(--coral-hover)!important; }
.ticket-detail-grid { min-height:0; padding:18px 22px 24px; flex:1; display:grid; grid-template-columns:minmax(0,1fr) 330px; gap:18px; align-items:start; }.ticket-thread { min-height:calc(100vh - 128px); min-height:calc(100dvh - 128px); overflow:hidden; }.request-header { padding:22px; border-bottom:1px solid var(--border); display:flex; align-items:flex-start; gap:13px; }.request-icon { width:37px; height:37px; border-radius:10px; display:grid; place-items:center; flex:none; color:var(--orange-ink); background:var(--orange-pale); }.request-header > div:last-child { min-width:0; flex:1; }.request-title-line { display:flex; align-items:center; gap:10px; }.request-title-line h2 { margin:0; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:19px; }.request-header p { margin:7px 0 0; color:var(--muted); font-size:10px; }.request-header p b { color:var(--grey); }.original-request { padding:21px 22px; border-bottom:1px solid var(--border); }.section-label { margin:0 0 10px!important; color: var(--text-faint)!important; font-size:8px!important; font-weight:800!important; letter-spacing:.1em; }.original-request > p:last-child { margin:0; max-width:920px; color: var(--text-soft); font-size:12px; line-height:1.7; white-space:pre-wrap; }
.reply-box { padding:16px 22px 18px; border-bottom:1px solid var(--border); background: var(--surface); }.reply-tabs { display:flex; gap:18px; margin-bottom:9px; }.reply-tabs button { padding:4px 0; border:0; border-bottom:2px solid transparent; color:var(--muted); background:transparent; cursor:pointer; font-size:10px; font-weight:700; }.reply-tabs button.active { color: var(--link); border-color:var(--orange); }.reply-box textarea { width:100%; min-height:112px; padding:12px; border:1px solid var(--border-dark); border-radius:9px; outline:0; resize:vertical; font-size:11px; line-height:1.55; }.reply-box textarea:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.1); }.reply-box textarea.note-mode { border-color:var(--orange-wash-border); background: var(--orange-wash); }.reply-box > div:last-child { margin-top:9px; display:flex; align-items:center; justify-content:space-between; gap:12px; }.reply-box > div:last-child > span { color:var(--muted); font-size:8px; }.reply-box .primary-button { min-height:35px; padding:0 14px; font-size:10px; }
.conversation-head { padding:20px 22px 5px; }.conversation-head > div { display:flex; align-items:center; justify-content:space-between; }.conversation-head .section-label { margin:0!important; }.conversation-head span { color:var(--muted); font-size:9px; }.conversation { padding:5px 22px 28px; }.message { padding:14px; border:1px solid var(--border); border-radius:10px; margin-top:11px; background: var(--surface); }.message.note { border-color:var(--orange-wash-border); background: var(--orange-wash); }.message.activity { background: var(--surface-sunken); }.message-head { margin-bottom:9px; display:flex; align-items:center; gap:8px; }.message-head .avatar { width:28px; height:28px; font-size:8px; }.message-head div { min-width:0; flex:1; }.message-head b,.message-head span:not(.avatar) { display:block; }.message-head b { font-size:10px; }.message-head span:not(.avatar) { margin-top:2px; color:var(--muted); font-size:8px; }.message-type { padding:3px 7px; border-radius:999px; color: var(--orange-ink); background:var(--orange-pale); font-size:7px; font-weight:700; }.message > p { margin:0; color: var(--text-soft); font-size:11px; line-height:1.65; white-space:pre-wrap; }
.conversation-loading { min-height:92px; display:flex; align-items:center; justify-content:center; color:var(--muted); font-size:11px; }
.ticket-side-column { display:flex; flex-direction:column; gap:14px; position:sticky; top:86px; }.property-panel,.contact-summary-panel { overflow:hidden; }.side-panel-head { min-height:54px; padding:0 17px; border-bottom:1px solid var(--border); display:flex; align-items:center; justify-content:space-between; }.side-panel-head h2 { margin:0; font-size:13px; }.side-panel-head span { color:var(--coral-hover); font-size:8px; font-weight:700; }.side-panel-head button { border:0; color: var(--link); background:transparent; cursor:pointer; font-size:9px; font-weight:700; }.drawer-fields { padding:15px 17px 18px; display:grid; gap:11px; }.drawer-fields label { color: var(--text-soft); font-size:9px; font-weight:700; }.drawer-fields select { width:100%; height:37px; margin-top:6px; padding:0 9px; border:1px solid var(--border-dark); border-radius:8px; outline:0; background: var(--surface); font-size:10px; }.customer-summary { padding:17px; display:flex; align-items:center; gap:11px; }.avatar.large { width:44px; height:44px; color: var(--orange-ink); background:var(--orange-pale); font-size:12px; }.customer-summary b,.customer-summary span,.customer-summary a { display:block; }.customer-summary b { margin-bottom:4px; font-size:11px; }.customer-summary span { margin-bottom:3px; color:var(--muted); font-size:9px; }.customer-summary a { margin-bottom:3px; color: var(--link); font-size:9px; text-decoration:none; }

.modal-backdrop,.confirm-backdrop { position:fixed; inset:0; z-index:100; padding:20px; display:none; place-items:center; background:var(--backdrop); backdrop-filter:blur(4px); }.modal-backdrop.open,.confirm-backdrop.open { display:grid; }.modal { width:min(610px,100%); max-height:calc(100vh - 40px); overflow-y:auto; padding:25px; border-radius:16px; background: var(--surface); box-shadow:0 28px 90px rgba(27,30,35,.28); }.contact-modal { width:min(560px,100%); }.modal-head { display:flex; justify-content:space-between; align-items:flex-start; }.modal-head h2 { margin:0 0 5px; font-size:21px; }.modal-head > div > p:last-child { margin:0 0 21px; color:var(--muted); font-size:11px; }.close-button { width:32px; height:32px; border:0; border-radius:50%; display:grid; place-items:center; cursor:pointer; color: var(--text-soft); background: var(--surface-muted); font-size:19px; }.modal form > label,.form-grid label { display:block; margin-bottom:13px; color: var(--text-soft); font-size:10px; font-weight:700; }.modal label > span { color:var(--coral); }.modal input,.modal select,.modal textarea { width:100%; margin-top:6px; padding:0 11px; border:1px solid var(--border-dark); border-radius:8px; outline:0; color:var(--grey); background: var(--surface); font-size:12px; }.modal input,.modal select { height:39px; }.modal textarea { min-height:95px; padding-top:10px; resize:vertical; line-height:1.5; }.modal input:focus,.modal select:focus,.modal textarea:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.1); }.form-grid { display:grid; grid-template-columns:1fr 1fr; gap:11px; }.form-grid-three { grid-template-columns:.8fr 1fr 1fr; }.modal-actions { margin-top:20px; padding-top:18px; border-top:1px solid var(--border); display:flex; justify-content:flex-end; gap:8px; }
.required-alternative { margin-left:5px; color:var(--muted); font-size:8px; font-weight:500; }.contact-identity-error { margin:-2px 0 13px; padding:9px 10px; border:1px solid var(--coral-wash-border); border-radius:8px; color: var(--coral-ink); background: var(--coral-wash); font-size:9px; line-height:1.4; }
.contact-picker-field { min-width:0; margin-bottom:13px; color:var(--text-soft); font-size:10px; font-weight:700; }
.contact-picker-field > label { margin-bottom:0; display:block; }
.contact-picker-field > label span { color:var(--coral); }
.contact-picker { position:relative; }
.contact-picker-results { position:absolute; z-index:20; top:calc(100% + 6px); right:0; left:0; max-height:292px; overflow-y:auto; padding:5px; border:1px solid var(--border-dark); border-radius:11px; background:var(--surface); box-shadow:0 16px 40px rgba(16,20,28,.22); }
.contact-picker-option { width:100%; padding:10px; border:0; border-radius:8px; display:grid; grid-template-columns:34px minmax(0,1fr); gap:9px; align-items:center; text-align:left; color:var(--grey); background:transparent; cursor:pointer; }
.contact-picker-option:hover,.contact-picker-option.is-active { background:var(--surface-muted); }
.contact-picker-option .avatar { grid-row:1 / span 2; width:34px; height:34px; }
.contact-picker-option b,.contact-picker-option small { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.contact-picker-option b { font-size:12px; }
.contact-picker-option small { color:var(--muted); font-size:10px; font-weight:500; }
.contact-picker-empty { padding:13px 11px; color:var(--muted); font-size:10px; font-weight:500; line-height:1.45; }
.contact-picker-hint { display:block; margin-top:5px; color:var(--muted); font-size:9px; font-weight:500; }
/* Venues. The source column is load-bearing rather than decorative: it is the reason half the
   edit form is disabled when a row is opened, so it reads as a badge, not as body copy. */
.page-head-actions { display:flex; align-items:center; gap:8px; flex-wrap:wrap; justify-content:flex-end; }
.venues-toolbar-controls { display:flex; align-items:center; gap:14px; }
.inline-toggle { display:flex; align-items:center; gap:7px; color:var(--text-soft); font-size:10px; font-weight:600; white-space:nowrap; cursor:pointer; }
.inline-toggle input { width:15px; height:15px; margin:0; accent-color:var(--orange); cursor:pointer; }
.attention-button { color:var(--orange-ink); border-color:var(--orange-wash-border); background:var(--orange-wash); }
.attention-button b { margin-left:6px; padding:1px 7px; border-radius:999px; color: var(--on-orange); background:var(--orange); font-size:10px; }

.venue-table-head,.venue-row { display:grid; grid-template-columns:minmax(200px,1.5fr) 120px minmax(180px,2fr) 90px; gap:16px; align-items:center; }
.venue-table-head { padding:11px 18px; color:var(--text-faint); border-bottom:1px solid var(--border); background:var(--surface-head); font-size:9px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }
.venue-list { min-height:0; overflow-y:auto; }
.venue-row { min-height:64px; padding:12px 18px; border-bottom:1px solid var(--hairline); cursor:pointer; }
.venue-row:hover { background:var(--surface-head); }
.venue-row:focus-visible { outline:2px solid var(--orange); outline-offset:-2px; }
.venue-row > span { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--muted); font-size:11px; }
.venue-name { min-width:0; display:flex; align-items:center; gap:8px; }
.venue-name b { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; }
.venue-flag { padding:2px 8px; border-radius:999px; font-size:9px; font-weight:700; white-space:nowrap; }
.venue-flag.archived { color:var(--text-faint); background:var(--surface-muted); }
.venue-flag.inactive { color:var(--coral-ink); background:var(--coral-wash); }
.venue-source { justify-self:start; padding:3px 10px; border-radius:999px; font-size:9px; font-weight:700; white-space:nowrap; }
.venue-source.billing { color:var(--green-ink); background:var(--green-wash); border:1px solid var(--green-wash-border); }
.venue-source.desk { color:var(--orange-ink); background:var(--orange-wash); border:1px solid var(--orange-wash-border); }

/* The venue modal. */
.venue-billing-note { margin:0 0 16px; padding:11px 13px; border:1px solid var(--green-wash-border); border-radius:9px; color:var(--green-ink); background:var(--green-wash); font-size:10.5px; line-height:1.5; }
.modal input:disabled,.modal select:disabled,.modal textarea:disabled { color:var(--text-faintest); background:var(--surface-muted); cursor:not-allowed; }
.venue-section { margin-top:20px; padding-top:17px; border-top:1px solid var(--border); }
.venue-section h3 { margin:0 0 4px; font-size:12px; }
.venue-contact-list { margin-top:11px; display:flex; flex-direction:column; gap:6px; }
.venue-contact-row { padding:9px 12px; border:1px solid var(--border); border-radius:9px; display:flex; align-items:center; justify-content:space-between; gap:12px; }
.venue-contact-row > span { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--muted); font-size:10px; }
.venue-contact-name { display:flex; align-items:baseline; gap:8px; }
.venue-contact-name b { font-size:11.5px; }
.venue-contact-name span { color:var(--muted); font-size:10px; }
.venue-section-head { display:flex; align-items:center; justify-content:space-between; gap:14px; }
.venue-section-head h3 { margin:0; }
.venue-section-head p { margin:4px 0 0; color:var(--muted); font-size:10px; }
.venue-section-actions { display:flex; align-items:center; gap:9px; }
.compact-button { min-height:32px; padding:7px 11px; }
.screenconnect-message { min-height:16px; margin:10px 0 0; color:var(--muted); font-size:10.5px; line-height:1.45; }
.screenconnect-message.error { color:var(--coral-ink); }
.screenconnect-device-list,.screenconnect-search-results { margin-top:8px; display:flex; flex-direction:column; gap:7px; }
.screenconnect-device { padding:11px 0; border-top:1px solid var(--hairline); display:grid; grid-template-columns:minmax(0,1fr) auto; gap:10px 16px; }
.screenconnect-device:first-child { border-top:0; }
.screenconnect-device-main { min-width:0; }
.screenconnect-device-title { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.screenconnect-device-title b { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12px; }
.screenconnect-state { display:inline-flex; align-items:center; gap:5px; color:var(--muted); font-size:9.5px; font-weight:700; }
.screenconnect-state::before { content:""; width:7px; height:7px; border:1px solid currentColor; border-radius:50%; background:transparent; }
.screenconnect-state.online { color:var(--green-ink); }
.screenconnect-state.online::before { background:currentColor; box-shadow:0 0 0 3px var(--green-wash); }
.screenconnect-state.unavailable { color:var(--coral-ink); }
.screenconnect-device-meta { margin-top:5px; display:flex; gap:5px 12px; flex-wrap:wrap; color:var(--muted); font-size:10px; line-height:1.45; }
.screenconnect-device-actions { display:flex; align-items:center; justify-content:flex-end; gap:7px; flex-wrap:wrap; }
.screenconnect-device-actions button { min-height:30px; padding:6px 10px; }
.screenconnect-device-actions .danger-text { padding-inline:4px; }
.screenconnect-picker-backdrop { z-index:120; }
.screenconnect-picker-modal { width:min(690px,100%); }
.screenconnect-search-form { display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:end; gap:10px; }
.screenconnect-search-form label { margin:0!important; }
.screenconnect-search-form .primary-button { min-height:39px; }
.screenconnect-search-result { padding:11px 0; border-top:1px solid var(--hairline); display:flex; align-items:center; justify-content:space-between; gap:14px; }
.screenconnect-search-result:first-child { border-top:0; }
.screenconnect-search-result .screenconnect-device-main { flex:1; }
.venue-merge-row { margin-top:12px; display:flex; align-items:flex-end; gap:9px; }
.venue-merge-target { flex:1; margin-bottom:0!important; }
.modal-actions-spacer { flex:1; }

/* Possible duplicates. Each group leads with the venue to keep, so the choice reads top-down. */
.venue-duplicates { display:flex; flex-direction:column; gap:13px; }
.venue-duplicate-group { padding:13px 15px; border:1px solid var(--border); border-radius:11px; background:var(--surface-sunken); }
.venue-duplicate-group h4 { margin:0 0 9px; color:var(--text-faint); font-size:9px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }
.venue-duplicate-row { padding:8px 0; border-top:1px solid var(--hairline); display:flex; align-items:center; justify-content:space-between; gap:12px; }
.venue-duplicate-row:first-of-type { border-top:0; }
.venue-duplicate-name { min-width:0; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.venue-duplicate-name b { font-size:12px; }
.venue-duplicate-name > span:last-child { color:var(--muted); font-size:10px; }
.venue-duplicate-keep { color:var(--green-ink); font-size:9px; font-weight:700; white-space:nowrap; }
.import-card { max-width:900px; }
.import-file { margin:18px 0 12px; display:block; color:var(--text-soft); font-size:12px; font-weight:700; }
.import-file input { display:block; margin-top:7px; }
.import-preview { margin-top:20px; padding-top:20px; border-top:1px solid var(--border); }
.import-metrics { margin-bottom:22px; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px; }
.import-metrics > div { padding:14px; border:1px solid var(--border); border-radius:10px; background:var(--surface-sunken); }
.import-metrics b,.import-metrics span { display:block; }.import-metrics b { font-size:20px; }.import-metrics span { margin-top:4px; color:var(--muted); font-size:10px; }
.import-preview h4 { margin:0 0 9px; font-size:12px; }
.import-mapping { margin-bottom:18px; border:1px solid var(--border); border-radius:10px; overflow:hidden; }
.import-mapping > div { padding:9px 12px; display:grid; grid-template-columns:1fr 1fr; border-bottom:1px solid var(--border); font-size:11px; }
.import-mapping > div:last-child { border-bottom:0; }.import-mapping span { color:var(--muted); }.import-mapping b { font-weight:600; }
.import-confirm { margin:0 0 14px; display:flex; align-items:center; gap:9px; color:var(--text-soft); font-size:11px; font-weight:600; }
.import-confirm input { width:auto; height:auto; margin:0; }
.spam-name-confirmation { margin:14px 0; display:block; color:var(--text-soft); font-size:11px; font-weight:700; }
.spam-name-confirmation b { color:var(--grey); }
.action-icon { width:18px; display:inline-grid; place-items:center; margin-right:7px; font-size:15px; font-style:normal; }
.spam-action-icon { font-size:17px; }
.ticket-bulk-bar { min-height:52px; padding:7px 18px; border-top:1px solid var(--border); border-bottom:1px solid var(--border); display:flex; align-items:center; gap:10px; background:var(--surface-head); }
.ticket-bulk-bar > label { display:flex; align-items:center; gap:10px; font-size:11px; font-weight:700; }
.ticket-bulk-bar .selected-ticket-count { font-size:11px; font-weight:700; }
.ticket-bulk-bar input,.ticket-select input,.ticket-select-all input { width:16px; height:16px; accent-color:var(--orange); }
.bulk-menu-wrap { position:relative; display:grid; place-items:center; }.bulk-menu-wrap .more-button { display:grid; place-items:center; padding:0; line-height:1; }.bulk-actions-menu { position:absolute; z-index:8; top:42px; left:0; width:170px; padding:5px; border:1px solid var(--border); border-radius:9px; background:var(--surface); box-shadow:var(--shadow); }
.bulk-actions-menu button { width:100%; padding:10px; border:0; border-radius:6px; display:flex; align-items:center; text-align:left; background:transparent; cursor:pointer; font-size:11px; }.bulk-actions-menu button:hover { background:var(--surface-sunken); }.bulk-actions-menu button:disabled { opacity:.4; cursor:not-allowed; }
.ticket-table-head,.ticket-row { grid-template-columns:34px minmax(210px,1.3fr) minmax(320px,2.3fr) 110px minmax(150px,1fr) 115px; }
.ticket-table-head { padding-left:20px; }.ticket-select-all,.ticket-select { display:grid; place-items:center; }.ticket-select-all,.ticket-select { align-self:stretch; cursor:pointer; }
.ticket-row.selected { background:var(--orange-wash); box-shadow:inset 3px 0 0 var(--orange); }
.merged-tag { margin-left:8px; padding:3px 6px; border:1px solid var(--orange-wash-border); border-radius:999px; color:var(--orange-ink); background:var(--orange-wash); font-size:8px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; }
.new-ticket-tag { width:138px;min-height:24px;padding:5px 10px;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;justify-self:center;border:1px solid var(--new-tag-border, #91e600);border-radius:999px;color:var(--new-tag-ink, #000) !important;-webkit-text-fill-color:var(--new-tag-ink, #000);background:var(--new-tag-bg, #b7ff00);box-shadow:0 1px 2px rgba(0,0,0,.08);font-size:10px;font-weight:900;line-height:1;text-align:center;text-transform:uppercase;letter-spacing:.01em;white-space:nowrap; }
.ticket-new-placeholder { display: block; }
.reopened-tag { margin-left:8px; padding:3px 6px; border:1px solid var(--green-wash-border); border-radius:999px; color:var(--green-ink); background:var(--green-wash); font-size:8px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; }
.customer-responded-tag { display:inline-flex;align-items:center;justify-content:center;align-self:center;flex:0 0 auto;margin-left:8px;padding:3px 7px;border:1px solid var(--violet-wash-border);border-radius:999px;color:var(--violet-ink);background:var(--violet-wash);font-size:8px;font-weight:800;line-height:1;text-align:center;text-transform:uppercase;letter-spacing:.04em;white-space:nowrap; }
/* Settings → AI status. Reuses the email channel's badge, health dots and callout; these are the
   three things that panel has no equivalent for. */
/* The email health items carry two-word statuses and clip to one line. These carry a sentence
   saying what to do about it, which is the whole point of the panel. */
.ai-status-section .email-health-item { align-items:flex-start; }
.ai-status-section .email-health-item small { overflow:visible; white-space:normal; text-overflow:clip; }
.ai-stat-grid { padding:0 16px 16px; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:9px; }
.ai-stat { padding:11px 12px; border:1px solid var(--border); border-radius:10px; background:var(--surface); }
.ai-stat b { display:block; font-size:17px; line-height:1.2; }
.ai-stat span { display:block; margin-top:3px; font-size:9px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--text-soft); }
.ai-stat small { display:block; margin-top:4px; color:var(--muted); font-size:8px; line-height:1.4; }
.ai-stat-warn { border-color:var(--orange-wash-border); background:var(--orange-wash); }
.ai-card-note { margin:0 16px 16px; color:var(--muted); font-size:9px; line-height:1.55; }
/* The callout has success and error already; a rate limit is neither. */
.connection-callout.warning { border-color:var(--orange-wash-border); background:var(--orange-wash); }
@media (max-width:520px) { .ai-stat-grid { grid-template-columns:minmax(0,1fr); } }

/* The reply-judgement report. Everything else on this panel reuses the escalation report's own
   classes; these are only what that table has no equivalent for — a column of customer prose,
   and the marking on a row where the customer wrote in again after being told nothing was. */
/* Said in the open, not behind the definitions fold. "Came back anyway" is the one figure here
   somebody could screenshot into a meeting as an error rate, and by then the report has misled
   them. */
.courtesy-caveat { margin:10px 0 22px; padding:10px 13px; border-left:3px solid var(--orange-wash-border); border-radius:0 8px 8px 0; background:var(--orange-wash); color:var(--text-soft); font-size:10px; line-height:1.6; }
.courtesy-sample .courtesy-excerpt { max-width:380px; color:var(--text-soft); font-size:10px; line-height:1.5; }
.courtesy-sample td em { display:block; color:var(--muted); font-size:9px; font-style:normal; }
.courtesy-sample tr.courtesy-cameback { background:var(--orange-wash); }
.courtesy-cameback-tag { display:inline-block; margin-left:6px; padding:2px 6px; border:1px solid var(--orange-wash-border); border-radius:999px; color:var(--orange-ink); background:var(--orange-wash-strong); font-size:8px; font-weight:800; font-style:normal; text-transform:uppercase; letter-spacing:.04em; }

/* The AI summary above the thread. Visibly a reading aid rather than part of the record: inset,
   quieter than a message, and badged, so nobody mistakes it for something a person wrote. */
.ticket-summary { margin:0 0 16px; padding:14px 16px; border:1px solid var(--border); border-left:3px solid rgba(139,92,246,.55); border-radius:11px; background:var(--orange-wash); }
.ticket-summary-head { display:flex; align-items:center; gap:8px; margin-bottom:9px; }
.ticket-summary-head h3 { margin:0; font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--text-soft); }
.ticket-summary-badge { padding:3px 7px; border:1px solid var(--violet-wash-border); border-radius:999px; color:var(--violet-ink); background:var(--violet-wash); font-size:8px; font-weight:800; line-height:1; text-transform:uppercase; letter-spacing:.04em; cursor:help; }
.ticket-summary-age { color:var(--muted); font-size:9px; }
.ticket-summary-toggle { margin-left:auto; padding:3px 9px; border:1px solid var(--border); border-radius:999px; color:var(--muted); background:transparent; font-size:9px; font-weight:700; cursor:pointer; }
.ticket-summary-toggle:hover { color:var(--text-soft); border-color:var(--orange-wash-border); }
.ticket-summary-body p { margin:0 0 7px; font-size:11px; line-height:1.6; }
.ticket-summary-body p:last-child { margin-bottom:0; }
.ticket-summary-body strong { font-weight:800; }
.ticket-summary-list { margin:0; padding-left:18px; }
.ticket-summary-list li { margin-bottom:4px; font-size:11px; line-height:1.55; }
.ticket-summary-list li:last-child { margin-bottom:0; }
.merge-panel-backdrop { position:fixed; z-index:130; inset:0; display:flex; justify-content:flex-end; visibility:hidden; opacity:0; background:var(--backdrop); transition:opacity .18s ease,visibility .18s ease; }
.merge-panel-backdrop.open { visibility:visible; opacity:1; }.merge-panel { width:min(560px,100%); height:100%; display:flex; flex-direction:column; background:var(--surface); box-shadow:-20px 0 60px rgba(0,0,0,.24); transform:translateX(35px); transition:transform .18s ease; }.merge-panel-backdrop.open .merge-panel { transform:translateX(0); }
.merge-panel-head { padding:25px 25px 20px; border-bottom:1px solid var(--border); display:flex; gap:18px; }.merge-panel-head > div { flex:1; }.merge-panel-head h2 { margin:4px 0 8px; font-size:20px; }.merge-panel-head p:last-child { margin:0; color:var(--muted); font-size:11px; line-height:1.55; }
.merge-panel-body { padding:22px 25px; flex:1; overflow:auto; }.merge-panel-body > p { margin:0 0 16px; color:var(--text-soft); font-size:11px; }.merge-ticket-choices { display:grid; gap:10px; }.merge-ticket-choice { padding:16px; border:1px solid var(--border); border-radius:11px; display:grid; grid-template-columns:22px 1fr auto; gap:11px; align-items:center; cursor:pointer; background:var(--surface); }.merge-ticket-choice:has(input:checked) { border-color:var(--orange); background:var(--orange-wash); }.merge-ticket-choice input { width:17px; height:17px; accent-color:var(--orange); }.merge-ticket-choice small,.merge-ticket-choice b,.merge-ticket-choice span { display:block; }.merge-ticket-choice small { margin-bottom:4px; color:var(--muted); font-size:9px; }.merge-ticket-choice b { margin-bottom:5px; font-size:13px; }.merge-ticket-choice span { color:var(--muted); font-size:10px; }.merge-ticket-choice em { visibility:hidden; padding:4px 7px; border-radius:999px; color:var(--orange-ink); background:var(--orange-wash-strong); font-size:8px; font-style:normal; font-weight:800; text-transform:uppercase; }.merge-ticket-choice:has(input:checked) em { visibility:visible; }
.merge-panel-actions { padding:16px 25px; border-top:1px solid var(--border); display:flex; justify-content:flex-end; gap:9px; }
@media (max-width:1100px) { .ticket-table-head,.ticket-row { grid-template-columns:32px minmax(170px,1fr) minmax(270px,2fr) 100px 115px; }.ticket-table-head .column-sort[data-sort-key="assignee"],.ticket-row>.ticket-assignee { display:none; } }
@media (max-width:760px) { .ticket-table-head { display:none; }.ticket-row { grid-template-columns:28px minmax(0,1fr) auto; }.ticket-row>.ticket-select { grid-column:1; grid-row:1 / span 2; }.ticket-row>.ticket-subject { grid-column:2; grid-row:1; }.ticket-row>.ticket-customer { grid-column:2; grid-row:2; }.ticket-row>.status-pill { grid-column:3; grid-row:1; }.ticket-row>.sla-pill { grid-column:3; grid-row:2; }.merge-panel-head,.merge-panel-body,.merge-panel-actions { padding-left:18px; padding-right:18px; } }
.confirm-box { width:min(390px,100%); padding:26px; border-radius:15px; text-align:center; background: var(--surface); box-shadow:0 28px 90px rgba(27,30,35,.28); }.confirm-icon { width:42px; height:42px; margin:0 auto 12px; border-radius:50%; display:grid; place-items:center; color:var(--coral-ink); background:var(--coral-pale); font-size:18px; font-weight:800; }.confirm-box h2 { margin:0 0 8px; font-size:16px; }.confirm-box p { margin:0 auto 20px; max-width:300px; color:var(--muted); font-size:10px; line-height:1.55; }.confirm-box > div:last-child { display:flex; justify-content:center; gap:8px; }
.toast-region { position:fixed; z-index:150; right:22px; bottom:22px; display:flex; flex-direction:column; align-items:flex-end; gap:8px; }.toast { min-width:245px; padding:11px 14px; border-radius:10px; display:flex; align-items:center; gap:9px; color:var(--toast-ink); background: var(--toast-bg); box-shadow:0 13px 40px rgba(25,28,32,.22); font-size:9px; animation:toast-in .2s ease both; }.toast::before { content:"✓"; width:19px; height:19px; border-radius:50%; display:grid; place-items:center; color:#fff; background:var(--green); font-size:9px; }.toast.error::before { content:"!"; background:var(--coral); }.toast.out { animation:toast-out .2s ease both; }
@keyframes toast-in { from { opacity:0; transform:translateY(8px); } } @keyframes toast-out { to { opacity:0; transform:translateY(8px); } }

/* Keep dense support data comfortably readable on full-size workstations. */
.ticket-table-head,.contact-table-head { font-size:9px; }
.ticket-subject b { font-size:13px; }.ticket-subject span,.ticket-customer span { font-size:10px; }.ticket-customer b { font-size:11px; }.ticket-assignee span { font-size:10px; }
.status-pill,.sla-pill,.priority-chip { font-size:9px; }
.contact-person .contact-open,.contact-person b { font-size:12px; }.contact-person span:not(.avatar),.contact-cell { font-size:10px; }.contact-actions button { font-size:10px; }
.settings-section-head p { font-size:12px; }
.settings-fields label,.field-label { font-size:11px; }.settings-fields input,.settings-fields select { font-size:12px; }.toggle-row b { font-size:12px; }.toggle-row small { font-size:10px; }
.ticket-breadcrumb span,.request-header p { font-size:10px; }.drawer-fields label { font-size:10px; }.drawer-fields select { font-size:11px; }.customer-summary b { font-size:12px; }.customer-summary span,.customer-summary a { font-size:10px; }
.message-head b { font-size:11px; }.message-head span:not(.avatar),.message-type { font-size:9px; }.message > p { font-size:12px; }
.toast { font-size:11px; }

.login-body { min-height:100vh; margin:0; overflow:auto; color:var(--grey); background:var(--zircon); }.login-shell { width:min(980px,calc(100% - 40px)); min-height:610px; margin:clamp(20px,6vh,70px) auto; border:1px solid var(--border); border-radius:20px; display:grid; grid-template-columns:minmax(330px,.9fr) minmax(420px,1.1fr); overflow:hidden; background: var(--surface); box-shadow:0 24px 70px rgba(34,38,44,.12); }/* Built from the brand greys with a warm cast in the far corner drawn from the logo's gradient,
   rather than the previous near-black with a brown tint mixed for the old orange. */
.login-brand-panel { padding:44px; display:flex; flex-direction:column; justify-content:space-between; color:#fff; background:linear-gradient(150deg,#282828 0%,#1e1e1e 70%,#3a2518 140%); }.login-brand { display:flex; align-items:flex-end; gap:9px; }/* No filter. This used to force the logo white regardless of source, which is right on the dark
   sign-in panel and wrong everywhere else -- the portal, knowledge base and survey headers are
   #fff, so the mark was white on white and simply not there. Each page now picks the master
   artwork that suits its background, which also keeps the gradient instead of flattening it. */
.login-brand img { width:128px; height:auto; }.login-brand span { margin-bottom:4px; color:var(--orange); font-size:13px; font-weight:800; letter-spacing:.15em; text-transform:uppercase; }.login-brand-panel h1 { margin:10px 0 15px; font-size:35px; line-height:1.12; letter-spacing:-.035em; }.login-brand-panel p:not(.eyebrow) { max-width:340px; margin:0; color:#c6c6c6; font-size:13px; line-height:1.7; }.login-brand-panel > small { color:#8e8e8e; font-size:10px; }.login-form-panel { padding:50px clamp(35px,6vw,72px); display:grid; place-items:center; }.login-card { width:100%; max-width:390px; }.login-card h2 { margin:8px 0 8px; font-size:25px; letter-spacing:-.025em; }.login-intro { margin:0 0 27px; color:var(--muted); font-size:11px; line-height:1.6; }.login-card > label:not(.login-remember) { margin-top:16px; display:block; color: var(--text-soft); font-size:10px; font-weight:700; }.login-card > label input { width:100%; height:44px; margin-top:7px; padding:0 12px; border:1px solid var(--border-dark); border-radius:9px; outline:0; background: var(--surface); }.login-card > label input:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.11); }.login-remember { margin:17px 0; display:flex!important; align-items:center; gap:8px; color:var(--muted)!important; font-weight:500!important; cursor:pointer; }.login-remember input { width:16px!important; height:16px!important; margin:0!important; accent-color:var(--orange); }.login-submit { width:100%; min-height:44px; }.login-error { margin:0 0 12px; padding:11px 12px; border:1px solid var(--coral-wash-border); border-radius:8px; color: var(--coral-ink); background: var(--coral-wash); font-size:10px; line-height:1.5; }.login-help { margin:18px 0 0; color: var(--text-faint); text-align:center; font-size:9px; line-height:1.5; }
.message-attachments { margin-top:10px; display:flex; flex-wrap:wrap; gap:7px; }.message-attachments:empty { display:none; }.attachment-chip { max-width:100%; padding:7px 9px; border:1px solid var(--orange-wash-border); border-radius:8px; overflow:hidden; color: var(--orange-ink); background: var(--orange-wash); text-decoration:none; text-overflow:ellipsis; white-space:nowrap; font-size:9px; font-weight:700; }.attachment-chip:hover { border-color:var(--orange); background:var(--orange-pale); }.attachment-chip.unavailable { color:var(--muted); border-color:var(--border); background: var(--surface-muted); }.message-delivery { margin-left:auto; padding:4px 7px; border-radius:999px; font-size:8px; font-weight:700; }.message-delivery.queued { color: var(--amber-ink); background: var(--amber-wash); }.message-delivery.sent { color: var(--green-ink); background:var(--green-pale); }.message-delivery.failed { color: var(--coral-ink); background:var(--coral-pale); }
.message > p.message-body-empty, .message-body-empty { margin:0; color:var(--text-faint); font-size:11px; font-style:italic; }
/* A voicemail reads as the message it is rather than as a file bolted to one: the recording sits
   on the card with its length beside it, and the mark on the left is a voicemail glyph -- the old
   orange disc looked like a play button, was not one, and sat directly above the control that
   actually plays the audio. */
.voicemail-player { width:min(520px,100%); padding:12px 13px; border:1px solid var(--border); border-radius:12px; display:grid; grid-template-columns:1fr auto; align-items:center; gap:11px 14px; background:var(--surface-sunken); }.voicemail-player-heading { min-width:0; display:flex; align-items:center; gap:10px; }.voicemail-player-icon { width:32px; height:32px; border-radius:10px; display:grid; place-items:center; flex:none; color:var(--orange-ink); background:var(--orange-pale); }.voicemail-player-icon svg { width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; }.voicemail-player-title { min-width:0; display:grid; gap:2px; }.voicemail-player-title b { color:var(--text); font-size:11px; font-weight:750; }.voicemail-player-meta { color:var(--muted); font-size:9px; font-weight:600; font-variant-numeric:tabular-nums; }.voicemail-player audio { width:100%; min-width:220px; grid-column:1 / -1; height:34px; accent-color:var(--orange); }.voicemail-download { padding:6px 9px; border:1px solid var(--border); border-radius:8px; color:var(--text-soft); background:var(--surface); font-size:9px; font-weight:700; text-decoration:none; white-space:nowrap; }.voicemail-download:hover { border-color:var(--orange-wash-border); color:var(--orange-ink); background:var(--orange-wash); }
button.integration-note { width:100%; border:0; text-align:left; cursor:pointer; }button.integration-note:hover { background: var(--orange-wash-strong); }

/* 3CX call workspace and incoming-call experience */
.sidebar-integration-button { width:calc(100% - 2px); color:var(--nav-ink-strong); text-align:left; cursor:pointer; }.sidebar-integration-button > div:last-child { min-width:0; }.sidebar-integration-button:hover { border-color:rgba(255,117,26,.28); background:rgba(255,117,26,.08); }.sidebar-integration-button:focus-visible { outline-color:rgba(255,117,26,.55); }
.call-summary-grid { margin-bottom:18px; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; }.call-summary-card { min-height:104px; padding:17px 18px; border:1px solid var(--border); border-radius:13px; display:flex; align-items:center; gap:13px; position:relative; overflow:hidden; background: var(--surface); box-shadow:var(--shadow); }.call-summary-card::after { content:""; position:absolute; inset:0 0 auto auto; width:42px; height:6px; border-radius:0 0 0 8px; background: var(--neutral-mark); }.call-summary-card.active::after { background:var(--green); }.call-summary-card.missed::after { background:var(--coral); }.call-summary-card.voicemail::after { background:var(--orange); }.call-summary-icon { width:38px; height:38px; border-radius:11px; display:grid; place-items:center; flex:none; color: var(--text-soft); background: var(--surface-muted); font-size:16px; }.call-summary-card.active .call-summary-icon { color:var(--green-ink); background:var(--green-pale); }.call-summary-card.missed .call-summary-icon { color:var(--coral-ink); background:var(--coral-pale); }.call-summary-card.voicemail .call-summary-icon { color:var(--orange-ink); background:var(--orange-pale); }.call-summary-card p,.call-summary-card strong,.call-summary-card small { display:block; }.call-summary-card p { margin:0 0 2px; color:var(--muted); font-size:10px; font-weight:600; }.call-summary-card strong { margin-bottom:3px; font-size:23px; letter-spacing:-.035em; }.call-summary-card small { color: var(--text-faint); font-size:9px; }
.calls-workspace { min-height:420px; flex:1; overflow:hidden; display:flex; flex-direction:column; }.calls-toolbar { min-height:70px; padding:0 20px; display:flex; align-items:center; justify-content:space-between; gap:16px; flex:none; }.calls-toolbar h2 { margin:0 0 4px; font-size:15px; }.calls-toolbar > div:first-child span { color:var(--muted); font-size:9px; }.calls-toolbar-actions { display:flex; align-items:center; gap:8px; }.call-search { width:280px; }.call-table-head,.call-row { display:grid; grid-template-columns:minmax(220px,1.4fr) minmax(155px,.9fr) 100px minmax(125px,.75fr) 90px 175px; gap:14px; align-items:center; }.call-table-head { min-height:39px; padding:0 20px; border-top:1px solid var(--border); border-bottom:1px solid var(--border); color: var(--text-faint); background: var(--surface-head); font-size:9px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }.call-list { min-height:0; overflow-y:auto; }.call-row { min-height:76px; padding:12px 20px; border-bottom:1px solid var(--hairline); background: var(--surface); }.call-row:hover { background: var(--surface-sunken); }.call-caller { min-width:0; display:flex; align-items:center; gap:10px; }.call-caller .avatar { width:36px; height:36px; color: var(--orange-ink); background:var(--orange-pale); }.call-caller > span:last-child,.call-contact,.call-time { min-width:0; }.call-caller b,.call-caller span:not(.avatar),.call-contact b,.call-contact span,.call-time b,.call-time span { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }.call-caller b,.call-contact b,.call-time b { margin-bottom:4px; font-size:11px; }.call-caller span:not(.avatar),.call-contact span,.call-time span { color:var(--muted); font-size:9px; }.call-state-pill { width:max-content; padding:5px 9px; border-radius:999px; color: var(--text-soft); background: var(--surface-muted); font-size:9px; font-weight:700; }.call-state-pill.ringing { color: var(--orange-ink); background:var(--orange-pale); }.call-state-pill.answered { color: var(--green-ink); background:var(--green-pale); }.call-state-pill.missed { color: var(--coral-ink); background:var(--coral-pale); }.call-state-pill.voicemail { color: var(--orange-ink); background: var(--orange-wash-strong); }.call-ticket button,.call-row-actions button { min-height:31px; padding:0 10px; border:1px solid var(--border); border-radius:999px; color: var(--link); background: var(--surface); cursor:pointer; font-size:9px; font-weight:700; }.call-ticket button:hover,.call-row-actions button:hover { border-color:var(--orange-wash-border); background: var(--orange-wash); }.call-ticket > span { color:var(--muted); font-size:9px; }.call-row-actions { display:flex; justify-content:flex-end; gap:6px; }.call-row-actions button:first-child { color: var(--text-soft); }.call-empty { min-height:285px; }
.email-field select { width:100%; height:40px; margin-top:7px; padding:0 10px; border:1px solid var(--border-dark); border-radius:8px; display:block; outline:0; color:var(--grey); background: var(--surface); font-size:11px; font-weight:400; }.email-field select:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.1); }.threecx-simulator-card > p { margin:8px 0 15px; color:var(--muted); font-size:9px; line-height:1.55; }.development-badge { display:inline-block; margin-bottom:9px; padding:4px 7px; border-radius:999px; color: var(--orange-ink); background:var(--orange-pale); font-size:7px; font-weight:800; letter-spacing:.08em; }.threecx-simulator-card > label { display:block; margin-bottom:11px; color: var(--text-soft); font-size:9px; font-weight:700; }.threecx-simulator-card > label input { width:100%; height:39px; margin-top:6px; padding:0 10px; border:1px solid var(--border-dark); border-radius:8px; outline:0; font-size:11px; }.threecx-simulator-card > label input:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.1); }.simulator-call-actions { margin-top:14px; padding-top:13px; border-top:1px solid var(--border); }.simulator-call-actions > p { margin:0 0 9px; color: var(--green-ink); font-size:9px; font-weight:700; }.simulator-call-actions > div { display:flex; flex-wrap:wrap; gap:5px; }.simulator-call-actions .secondary-button { min-height:30px; padding:0 9px; font-size:8px; }.threecx-responsibility-list { margin:13px 0 0; padding:0; list-style:none; }.threecx-responsibility-list li { padding:9px 0 9px 20px; border-top:1px solid var(--hairline); position:relative; color: var(--text-soft); font-size:9px; line-height:1.4; }.threecx-responsibility-list li::before { content:"✓"; position:absolute; left:1px; top:9px; color: var(--green-ink); font-weight:800; }
/* Anchored top right so it is visible alongside the workspace header and follows the requested
   incoming-call position.
 *
 * It overlays rather than displacing the page. Reserving a column for it was tried and was worse:
 * a call lasts seconds, so the whole workspace reflowed and left a tall empty gutter beside a
 * squeezed layout for the duration. A transient thing should float. */
.incoming-call-popup { width:min(360px,calc(100vw - 32px)); max-height:calc(100vh - 100px); max-height:calc(100dvh - 100px); border:1px solid var(--orange-wash-border); border-radius:16px; overflow:auto; position:fixed; z-index:90; top:82px; right:24px; color:var(--grey); background: var(--surface); box-shadow:0 24px 75px rgba(31,34,38,.22); opacity:0; transform:translateY(-10px) scale(.98); transition:opacity .2s ease,transform .2s ease; }.incoming-call-popup.visible { opacity:1; transform:translateY(0) scale(1); }.incoming-call-accent { height:5px; position:sticky; z-index:1; top:0; background:var(--brand-gradient); }.incoming-call-head { min-height:61px; padding:12px 15px; border-bottom:1px solid var(--orange-wash-border); display:flex; align-items:center; gap:10px; background: var(--orange-wash); }.incoming-call-icon { width:34px; height:34px; border-radius:50%; display:grid; place-items:center; flex:none; color: var(--on-orange); background:var(--orange); box-shadow:0 0 0 0 rgba(255,117,26,.3); animation:call-ring-pulse 1.8s ease-out infinite; }.incoming-call-head > div { min-width:0; flex:1; }.incoming-call-head span,.incoming-call-head strong { display:block; }.incoming-call-head > div span { color: var(--orange-ink); font-size:10px; font-weight:800; letter-spacing:.1em; }.incoming-call-head strong { margin-top:2px; font-size:13px; font-weight:600; }.incoming-call-head button { width:30px; height:30px; border:0; border-radius:50%; display:grid; place-items:center; color: var(--text-soft); background: var(--surface-muted); cursor:pointer; font-size:17px; }.incoming-caller { padding:18px; display:flex; align-items:center; gap:12px; }.incoming-caller > div:last-child { min-width:0; }.incoming-caller h2 { margin:0 0 4px; overflow:hidden; font-size:18px; text-overflow:ellipsis; white-space:nowrap; }.incoming-caller p { margin:0 0 5px; overflow:hidden; color:var(--muted); font-size:10px; text-overflow:ellipsis; white-space:nowrap; }.incoming-caller a { color: var(--link); font-size:11px; font-weight:700; text-decoration:none; }.incoming-recent-tickets { margin:0 15px; border:1px solid var(--border); border-radius:10px; overflow:hidden; }.incoming-recent-tickets > div:first-child { min-height:34px; padding:0 10px; border-bottom:1px solid var(--border); display:flex; align-items:center; justify-content:space-between; background: var(--surface-head); }.incoming-recent-tickets > div:first-child span { color: var(--text-faint); font-size:7px; font-weight:800; letter-spacing:.08em; }.incoming-recent-tickets > div:first-child button { border:0; color: var(--link); background:transparent; cursor:pointer; font-size:8px; font-weight:700; }.incoming-ticket-item { width:100%; min-height:48px; padding:9px 10px; border:0; border-bottom:1px solid var(--hairline); display:flex; align-items:center; justify-content:space-between; gap:10px; text-align:left; background: var(--surface); cursor:pointer; }.incoming-ticket-item:last-child { border-bottom:0; }.incoming-ticket-item:hover { background: var(--orange-wash); }.incoming-ticket-item b,.incoming-ticket-item small { display:block; }.incoming-ticket-item b { max-width:300px; overflow:hidden; font-size:9px; text-overflow:ellipsis; white-space:nowrap; }.incoming-ticket-item small { margin-top:3px; color:var(--muted); font-size:8px; }.incoming-ticket-item > span:last-child { color: var(--link); }.incoming-no-tickets { margin:0; padding:14px 10px; color:var(--muted); font-size:9px; }.incoming-call-actions { padding:15px; }/* Still the primary action -- a phone is ringing and answering is the point -- but it was a 43px
   solid slab under a 14px drop shadow, which made it the heaviest thing on screen and left the
   two buttons under it looking like footnotes. Shorter, with the shadow pulled back so it reads
   as the obvious action rather than as an alarm. */
.incoming-answer-button { width:100%; min-height:38px; font-size:13px; font-weight:600; box-shadow:0 2px 6px rgba(255,117,26,.16); }.incoming-call-actions > div { margin-top:8px; display:grid; grid-template-columns:1fr 1fr; gap:7px; }/* 9px was unreadable, and shrinking these was half of why the answer button looked so heavy. */
.incoming-call-actions > div .secondary-button { min-height:34px; padding:0 10px; font-size:11px; }
@keyframes call-ring-pulse { 0% { box-shadow:0 0 0 0 rgba(255,117,26,.3); } 65%,100% { box-shadow:0 0 0 10px rgba(255,117,26,0); } }
/* Everything, not just the call popup. This used to name .incoming-call-icon and
   .incoming-call-popup and nothing else, which left the toast keyframes, the sidebar slide, the
   call-ring pulse and several dozen transitions running for somebody who asked the operating
   system for none of it. portal.css already does this properly in three places; the workspace
   just never got the same pass. Durations rather than `none`, so anything keyed off
   transitionend still fires. */
@media (prefers-reduced-motion:reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
@media (max-width:1200px) {
  .summary-grid { grid-template-columns:1fr 1fr; }
  .ticket-table-head,.ticket-row { grid-template-columns:minmax(270px,2fr) minmax(170px,1fr) 100px 115px; }.ticket-table-head span:nth-child(4),.ticket-row>.ticket-assignee { display:none; }
  .contact-table-head,.contact-row { grid-template-columns:minmax(230px,1.4fr) minmax(150px,1fr) 100px 190px; }.contact-table-head span:nth-child(3),.contact-row>.contact-cell:nth-child(3) { display:none; }
  .sla-grid { grid-template-columns:1fr 1fr; }
  .call-table-head,.call-row { grid-template-columns:minmax(220px,1.4fr) 100px minmax(125px,.8fr) 90px 175px; }.call-table-head span:nth-child(2),.call-row>.call-contact { display:none; }

}
@media (max-width:900px) {
  /* visibility, not just transform: translated off-screen the sidebar was still in the tab order,
     so a phone user tabbing through the page walked fifteen invisible controls before reaching
     anything they could see. visibility is animatable in the sense that matters -- it flips at
     the end of the transition out, and immediately on the way in. */
  .sidebar { visibility:hidden; transform:translateX(-103%); transition:transform .22s ease,visibility .22s; box-shadow:18px 0 55px rgba(26,29,33,.18); }.sidebar.open { visibility:visible; transform:translateX(0); }.main-content { width:100%; margin-left:0; }.menu-button { display:grid; margin-right:8px; }.topbar { padding:0 18px; }.scrim { position:fixed; inset:0; z-index:29; background:rgba(30,32,35,.4); }.quick-start-panel { align-self:auto; }

  .calls-toolbar { padding:13px 16px; align-items:flex-start; flex-direction:column; }.calls-toolbar-actions { width:100%; }.call-search { flex:1; width:auto; }.call-table-head,.call-row { grid-template-columns:minmax(210px,1.4fr) 95px minmax(115px,.8fr) 155px; }.call-table-head span:nth-child(5),.call-row>.call-ticket { display:none; }
  .ticket-detail-grid { grid-template-columns:1fr; }.ticket-side-column { position:static; display:grid; grid-template-columns:1fr 1fr; }.ticket-thread { min-height:auto; }
  .ticket-toolbar { padding:0 14px; align-items:flex-start; flex-direction:column; }.ticket-tabs { height:51px; }.toolbar-actions { width:100%; padding-bottom:12px; }.queue-search { flex:1; width:auto; }
  .ticket-table-head,.ticket-row { grid-template-columns:minmax(240px,1.6fr) minmax(140px,1fr) 90px 105px; }
  /* The address is the first thing to go: the name and where the venue came from are what
     someone is scanning for, and the address is one tap away in the row itself. */
  .venue-table-head,.venue-row { grid-template-columns:minmax(180px,1.6fr) 115px 80px; }
  .venue-table-head span:nth-child(3),.venue-row>span:nth-of-type(2) { display:none; }
}
@media (max-width:650px) {
  .login-shell { width:min(100% - 24px,560px); min-height:auto; grid-template-columns:1fr; }.login-brand-panel { min-height:220px; padding:28px; }.login-brand-panel > div:nth-child(2) { margin-top:50px; }.login-brand-panel h1 { font-size:27px; }.login-form-panel { padding:34px 25px 40px; }
  .global-search { width:auto; flex:1; }.global-search kbd,.desktop-create { display:none; }.top-actions .primary-button { width:40px; padding:0; font-size:0; }.top-actions .primary-button span { font-size:17px; }
  .view { padding:22px 13px 28px; }.ticket-detail-view { padding:0; }.page-head { align-items:flex-start; }.overview-head .secondary-button { display:none; }.page-head h1 { font-size:25px; }.summary-grid { grid-template-columns:1fr 1fr; gap:9px; }.summary-card { min-height:105px; padding:14px; gap:10px; }.summary-icon { width:34px; height:34px; }.summary-card h2 { font-size:20px; }
  .ticket-workspace,.contacts-workspace { border-radius:11px; }.ticket-tabs { width:100%; gap:0; justify-content:space-between; }.ticket-tab span { display:none; }.toolbar-actions { flex-wrap:wrap; }.queue-search { width:100%; flex-basis:100%; }.sort-select { flex:1; }.filter-panel { align-items:stretch; flex-direction:column; }.filter-panel label,.filter-panel select { width:100%; }.filter-panel .text-button { align-self:flex-start; margin:3px 0; }
  .ticket-table-head { display:none; }.ticket-row { min-height:88px; padding:13px; grid-template-columns:minmax(0,1fr) auto; gap:9px; }.ticket-row>.ticket-customer { grid-column:1; grid-row:2; padding-left:10px; }.ticket-row>.status-pill { grid-column:2; grid-row:1; }.ticket-row>.sla-pill { grid-column:2; grid-row:2; justify-self:end; }.ticket-subject { grid-column:1; grid-row:1; }.ticket-customer b { margin:0; }.ticket-customer span,.ticket-row>.ticket-assignee { display:none; }
  .contacts-toolbar { padding:13px; align-items:flex-start; flex-direction:column; gap:12px; }.contact-search { width:100%; }.contact-table-head { display:none; }.contact-row { padding:13px; grid-template-columns:1fr; gap:10px; }.contact-row>.contact-cell { display:block!important; }.contact-actions { justify-content:flex-start; }
  .venues-toolbar-controls { width:100%; align-items:flex-start; flex-direction:column; gap:10px; }
  .venue-table-head { display:none; }
  .venue-row { padding:13px; grid-template-columns:1fr; gap:8px; }
  .venue-row>span:nth-of-type(2) { display:block; }
  .page-head-actions { width:100%; justify-content:flex-start; }
  .venue-merge-row { align-items:stretch; flex-direction:column; }
  .venue-section-head { align-items:stretch; flex-direction:column; }
  .screenconnect-search-form { display:flex; align-items:stretch; flex-direction:column; }
  .screenconnect-device { grid-template-columns:1fr; }
  .screenconnect-device-actions { justify-content:flex-start; }
  .modal-actions-spacer { display:none; }
  .settings-page-head { align-items:center; }.settings-form { min-height:520px; }.settings-fields.two-column,.sla-grid { grid-template-columns:1fr; }.settings-fields,.setting-toggles { padding-left:17px; padding-right:17px; }.integration-settings-card,.integration-note { margin-left:17px; margin-right:17px; }
  .email-section-head { align-items:flex-start; }.email-card-head { align-items:flex-start; flex-direction:column; gap:7px; }.email-card-head > p { max-width:none; text-align:left; }.email-field-grid { grid-template-columns:1fr; }.email-field.full { grid-column:auto; }.integration-settings-link { width:calc(100% - 34px); }
  .call-summary-grid { grid-template-columns:1fr; gap:9px; }.call-summary-card { min-height:86px; }.calls-workspace { border-radius:11px; }.calls-toolbar-actions { flex-wrap:wrap; }.call-search { width:100%; flex-basis:100%; }.calls-toolbar-actions .sort-select { width:100%; }.call-table-head { display:none; }.call-row { padding:13px; grid-template-columns:minmax(0,1fr) auto; gap:10px; }.call-row>.call-caller { grid-column:1; grid-row:1; }.call-row>.call-state-pill { grid-column:2; grid-row:1; }.call-row>.call-time { grid-column:1; grid-row:2; padding-left:46px; }.call-row>.call-row-actions { grid-column:1 / -1; grid-row:3; justify-content:flex-start; }.call-row>.call-contact,.call-row>.call-ticket { display:none; }
  .incoming-call-popup { top:72px; right:12px; bottom:auto; width:calc(100vw - 24px); max-height:calc(100dvh - 84px); }
  .ticket-detail-bar { padding:10px 12px; align-items:flex-start; flex-wrap:wrap; }.ticket-breadcrumb { width:100%; }.ticket-detail-actions { width:100%; padding-left:48px; overflow-x:auto; }.ticket-detail-actions .secondary-button { white-space:nowrap; }.drawer-actions-menu { top:106px; right:12px; }.ticket-detail-grid { padding:12px; }.ticket-side-column { grid-template-columns:1fr; }.request-header,.original-request,.reply-box,.conversation { padding-left:16px; padding-right:16px; }.request-title-line { align-items:flex-start; flex-direction:column; }.request-title-line h2 { white-space:normal; }.reply-box > div:last-child { align-items:flex-end; }.reply-box > div:last-child > span { max-width:180px; }
  .form-grid,.form-grid-three { grid-template-columns:1fr; }.modal { padding:20px; }.toast-region { right:12px; bottom:12px; left:12px; }.toast { width:100%; }
}
@media (max-width:420px) { .summary-grid { grid-template-columns:1fr; }.email-section-head { flex-direction:column; }.connection-status { align-self:flex-start; }.email-field-grid { padding:14px; }.email-card-head { padding:14px; }.credential-row { margin:0 14px 14px; }.incoming-call-actions > div { grid-template-columns:1fr; } }

/* ---- Reports ------------------------------------------------------------------------------- */

.reports-head-actions { display: flex; gap: 10px; align-items: center; }

/* Open breaches sit above the scorecard and are styled to interrupt. Everything below them is
   last month's history; this is the only part of the view that is still actionable. */
.kpi-breaching {
    background: var(--coral-wash);
    border: 1px solid var(--coral);
    border-radius: 12px;
    padding: 16px 18px;
    margin-bottom: 22px;
}

.kpi-breaching-head b { display: block; color: var(--coral-ink); font-size: 15px; }
.kpi-breaching-head span { color: var(--muted); font-size: 13px; }
.kpi-breaching ul { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }

.kpi-breaching li {
    display: grid;
    grid-template-columns: 90px minmax(0, 1fr);
    gap: 4px 12px;
    align-items: baseline;
    font-size: 13px;
}

.kpi-breaching li a { font-weight: 600; color: var(--coral-ink); }
.kpi-breaching-subject { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kpi-breaching-meta { grid-column: 2; color: var(--muted); font-size: 12px; }

.kpi-scope {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    box-shadow: var(--shadow);
    margin-bottom: 22px;
    overflow: hidden;
}

.kpi-scope > h2 {
    font-size: 15px;
    margin: 0;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border);
    background: var(--zircon);
}

.kpi-scope.team > h2 { background: var(--ink); color: var(--white); }

/* Fifteen numeric columns will not fit a laptop. The table scrolls inside its own box so the
   page itself never does, and the metric column stays put while the months move under it. */
.kpi-table-scroll { overflow-x: auto; }

.kpi-table { border-collapse: collapse; width: 100%; font-size: 13px; white-space: nowrap; }
.kpi-table th, .kpi-table td { padding: 7px 10px; text-align: right; border-bottom: 1px solid var(--border); }
.kpi-table thead th { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.kpi-table tbody tr:last-child th, .kpi-table tbody tr:last-child td { border-bottom: 0; }

.kpi-table th[scope="row"], .kpi-metric-col {
    position: sticky;
    left: 0;
    z-index: 1;
    text-align: left;
    background: var(--surface);
    font-weight: 600;
    min-width: 210px;
    border-right: 1px solid var(--border);
}

.kpi-table thead .kpi-metric-col { background: var(--zircon); }
.kpi-scope.team thead .kpi-metric-col { background: var(--ink); }

/* Breakdown rows are the same metric cut a different way, so they read as subordinate rather
   than as four more things to track. */
.kpi-breakdown th[scope="row"] { font-weight: 400; color: var(--muted); padding-left: 22px; }
.kpi-breakdown td { color: var(--muted); }

.kpi-target { color: var(--muted); border-right: 1px solid var(--border); }
/* Every numeric cell, not only .kpi-cell. The Target, Avg, Best and Worst columns sit in the same
   table and were being set in proportional figures, so the digits did not line up with the column
   beside them -- which is the entire point of a right-aligned numeric table. Same for the call
   summary counts. */
.kpi-cell, .kpi-table td, .call-summary-card strong { font-variant-numeric: tabular-nums; }

.kpi-cell.on-target, .kpi-summary.on-target { background:var(--green-pale); color:var(--green-ink); }
.kpi-cell.warning, .kpi-summary.warning { background:var(--orange-pale); color:var(--orange-ink); }
.kpi-cell.off-target, .kpi-summary.off-target { background:var(--coral-pale); color:var(--coral-ink); }

.kpi-summary-col, .kpi-summary { border-left: 1px solid var(--border-dark); font-weight: 600; }

/* Same job in the wide table: a quarterly roll-up standing after the months it covers. */
.kpi-table .kpi-quarter-col { border-left: 1px solid var(--border); border-right: 1px solid var(--border); font-weight: 700; }
.kpi-table thead .kpi-quarter-col { color: var(--link); }
.kpi-best { color: var(--green-ink); }
.kpi-worst { color: var(--coral-ink); }

.kpi-definitions-box {
    background: var(--zircon);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 12px 16px;
    font-size: 13px;
}

.kpi-definitions-box summary { cursor: pointer; font-weight: 600; }
.kpi-definitions-box dl { margin: 12px 0 0; display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: 8px 16px; }
.kpi-definitions-box dt { font-weight: 600; color: var(--muted); }
.kpi-definitions-box dd { margin: 0; }

@media (max-width: 720px) {
    .kpi-table th[scope="row"], .kpi-metric-col { min-width: 150px; white-space: normal; }
    .kpi-definitions-box dl { grid-template-columns: 1fr; gap: 2px; }
    .kpi-definitions-box dd { margin-bottom: 8px; }
}

.field-hint { color: var(--muted); font-size: 12px; margin: -6px 0 10px; }

/* ---- Ticket categories ---------------------------------------------------------------------- */

.category-list { display: grid; gap: 10px; margin: 18px 0 24px; }

.category-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    gap: 16px;
    align-items: center;
    padding: 12px 14px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
}

/* Archived categories stay visible but recede: they exist to explain old tickets, not to be
   picked from. */
.category-row.archived { opacity: .6; background: var(--zircon); }

.category-identity { display: grid; gap: 6px; min-width: 0; }
.category-identity input { width: 100%; }
.category-name { font-weight: 600; }
.category-description { font-size: 13px; }
.category-identity small { color: var(--muted); font-size: 12px; }

.category-toggle { display: flex; gap: 7px; align-items: center; font-size: 13px; white-space: nowrap; }
.category-actions { display: flex; gap: 6px; }

.category-form { border-top: 1px solid var(--border); padding-top: 18px; }
.category-form h3 { font-size: 14px; margin: 0 0 12px; }
.category-empty, .category-error { color: var(--muted); font-size: 13px; }
.category-error { color: var(--coral-hover); }

@media (max-width: 860px) {
    .category-row { grid-template-columns: 1fr; gap: 10px; }
}

/* ---- Sortable columns, agent grouping ------------------------------------------------------- */

/* The header cells are buttons now, so they need resetting back to looking like table headings
   while keeping a real focus ring -- they are the primary sort control and must be reachable
   without a mouse. */
.column-sort {
    padding: 0;
    border: 0;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: inherit;
    background: none;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    text-align: left;
    cursor: pointer;
}

.column-sort:hover { color: var(--grey); }
.column-sort.active { color: var(--link); }

/* The arrow is generated rather than markup so the direction cannot drift out of sync with
   aria-sort -- both are driven off the same data-direction attribute. */
.column-sort::after {
    content: "";
    width: 0;
    height: 0;
    opacity: 0;
    border-left: 3.5px solid transparent;
    border-right: 3.5px solid transparent;
    border-bottom: 4px solid currentColor;
    transition: opacity .12s, transform .12s;
}

.column-sort:hover::after { opacity: .35; }
.column-sort.active::after { opacity: 1; }
.column-sort[data-direction="desc"]::after { transform: rotate(180deg); }

.toolbar-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 10px;
    height: 34px;
    border: 1px solid var(--border-dark);
    border-radius: 9px;
    color: var(--muted);
    background: var(--surface);
    font-size: 12px;
    white-space: nowrap;
    cursor: pointer;
}

.toolbar-toggle:hover { border-color: var(--orange); color: var(--grey); }
.toolbar-toggle:has(input:checked) { border-color: var(--orange); color:var(--orange-ink); background:var(--orange-pale); }
.toolbar-toggle input { margin: 0; accent-color: var(--orange); }

/* Sticky so the agent you are reading stays named while their tickets scroll past. */
.ticket-group-heading {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: 8px 20px 8px 30px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 9px;
    background: var(--zircon);
    width: 100%;
    box-sizing: border-box;
    justify-content: flex-start;
    text-align: left;
}

.ticket-group-heading b { font-size: 13px; }
.ticket-group-heading span { margin-left: auto; color: var(--muted); font-size: 11px; }
.ticket-group-heading .avatar { width: 22px; height: 22px; color: var(--avatar-ink); font-size: 9px; }

.saved-view-controls { display:inline-flex; align-items:center; gap:6px; min-width:0; }
.saved-view-controls select { height:34px; min-width:128px; max-width:190px; padding:0 28px 0 10px; border:1px solid var(--border-dark); border-radius:9px; color:var(--muted); background:var(--surface); }
.saved-view-delete { width:30px; height:30px; padding:0; border:1px solid var(--coral-wash-border); border-radius:8px; color:var(--coral-hover); background:var(--coral-wash); font-size:17px; cursor:pointer; }
.saved-view-delete:hover { border-color:var(--coral); }
.save-ticket-view-modal { width:min(460px,100%); }
.agent-multi-field { min-width:190px; }
.agent-multi-select { position:relative; display:block; margin-top:6px; }
.agent-multi-select > button { width:100%; height:39px; padding:0 34px 0 11px; border:1px solid var(--border-dark); border-radius:8px; overflow:hidden; color:var(--grey); background:var(--surface); font-size:12px; text-align:left; text-overflow:ellipsis; white-space:nowrap; cursor:pointer; }
.agent-multi-select > button::after { content:"⌄"; position:absolute; right:12px; color:var(--muted); }
.agent-multi-menu { position:absolute; z-index:20; top:44px; left:0; width:max(100%,220px); max-height:250px; padding:6px; overflow-y:auto; border:1px solid var(--border-dark); border-radius:10px; background:var(--surface); box-shadow:var(--shadow); }
.agent-multi-option { min-height:34px; margin:0 !important; padding:7px 8px; display:flex !important; align-items:center; gap:9px; border-radius:7px; color:var(--text-soft); cursor:pointer; }
.agent-multi-option:hover { background:var(--surface-sunken); }
.agent-multi-option input { width:15px; height:15px; margin:0; accent-color:var(--orange); }

@media (max-width: 720px) {
    .toolbar-toggle span { display: none; }
    .toolbar-toggle { padding: 0 9px; }
    .saved-view-controls { width:100%; }
    .saved-view-controls select { flex:1; max-width:none; }
}

/* Phone glyphs in the call panel are inline SVG, sized here so they sit on the text baseline
   rather than relying on a font's own metrics. */
/* 16 in a 34px circle. The handset needs a little air around it or it reads as a filled
   shape rather than an object. */
.incoming-call-icon svg { width: 16px; height: 16px; display: block; }

.incoming-answer-button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.incoming-answer-button svg { width: 16px; height: 16px; flex: none; }
.incoming-answer-button.hangup { background: var(--coral); box-shadow: 0 8px 20px rgba(255,62,72,.2); }

/* ---- Category rows: read as a list, not a form ---------------------------------------------- */

/*
 * Every field here was a permanently outlined input, so five categories rendered as twenty boxes
 * and the page read as a form to fill in rather than a list to scan. The inputs are still inputs
 * -- click and type, no edit mode to enter -- they just stop drawing their own chrome until you
 * are actually in one.
 */
.category-row .category-name,
.category-row .category-description {
    border: 1px solid transparent;
    border-radius: 7px;
    background: transparent;
    padding: 4px 7px;
    margin-left: -7px;
    transition: border-color .12s, background-color .12s;
}

.category-row .category-name { font-size: 14px; font-weight: 600; }
.category-row .category-description { color: var(--muted); font-size: 12.5px; }

.category-row .category-name:hover,
.category-row .category-description:hover { border-color: var(--border); }

.category-row .category-name:focus,
.category-row .category-description:focus {
    border-color: var(--orange);
    background: var(--surface);
    outline: none;
}

.category-row .category-description::placeholder { color: var(--text-faintest); font-style: italic; }

.category-row .category-toggle,
.category-row .category-actions { align-self: center; }

.category-row .category-actions button { font-size: 12px; }
.category-row .category-actions .category-archive { color: var(--muted); }
.category-row .category-actions .category-archive:hover { color: var(--coral-hover); }

.field-hint-error { color: var(--coral-hover); font-weight: 600; }

/* ---- Style Guide: button shape and type scale ------------------------------------------------ */

/*
 * The guide specifies "Button Styles: Full Rounded" and "Image Corners: Full Rounded", so buttons
 * are pills rather than the 9-10px radius they had. Applied here at the end so it lands on every
 * button variant without hunting each rule down.
 *
 * Deliberately not applied to inputs, selects or panels: the guide calls out buttons and images,
 * and rounding a text field to a pill makes it read as something to press.
 */
.primary-button,
.secondary-button,
.danger-button,
.quiet-button,
.tool-button,
.toolbar-toggle,
.ghost-button,
.incoming-answer-button,
.status-pill,
.sla-pill { border-radius: 999px; }

/* The guide's web typography scale. Sizes in rem so they follow the 15px root, weights and line
   heights exactly as specified. */
h1 { font-size: 3rem; line-height: 1.2; font-weight: 700; }
h2 { font-size: 2.25rem; line-height: 1.3; font-weight: 700; }
h3 { font-size: 1.875rem; line-height: 1.4; font-weight: 700; }
h4 { font-size: 1.5rem; line-height: 1.4; font-weight: 600; }
h5 { font-size: 1.25rem; line-height: 1.5; font-weight: 600; }
h6 { font-size: 1rem; line-height: 1.6; font-weight: 500; }

/*
 * The scale above is the guide's marketing scale and is far too large inside a dense workspace --
 * a 48px h1 on every panel would leave no room for the tickets. It applies to page headings; the
 * component headings that happen to use the same tags opt out.
 */
.panel-head h2,
.settings-section-head h2,
.modal-head h2,
.kpi-scope h2,
.empty-state h3,
.embedded-empty h3,
.category-form h3,
.kb-article h3 { font-size: inherit; line-height: inherit; font-weight: inherit; }

/* ---- Channel settings: SMS and outbound mail ------------------------------------------------- */

/* A one-line summary of what the channel is actually doing right now, so an admin can tell at a
   glance whether saving had the effect they wanted without reading four fields back. */
.channel-status {
    margin: 0 25px 4px;
    padding: 11px 14px;
    border-radius: 10px;
    font-size: 12px;
    line-height: 1.5;
}

.channel-status:empty { display: none; }
.channel-status.ok { color:var(--green-ink); background:var(--green-pale); }
.channel-status.warn { color: var(--orange-ink); background: var(--orange-pale); }
.channel-status.info { color: var(--text-soft); background: var(--surface-muted); }

/* Separates outbound mail from the Microsoft 365 mailbox above it: same tab, different channel. */
.channel-block {
    margin: 26px 0 0;
    padding-top: 22px;
    border-top: 1px solid var(--border);
}

.settings-block { display: block; margin: 0 25px 6px; }
.settings-block textarea { width: 100%; }

@media (max-width: 860px) {
    .channel-status, .settings-block { margin-left: 17px; margin-right: 17px; }
}

/* ---- Settings: a rail that stays put, and one panel beside it --------------------------------
   This replaced a grid of cards you opened and backed out of. Settings is visited to change one
   thing and check another, and the index charged two clicks for every comparison.

   The rail before that one was abandoned because it took 255px and squeezed the labels down to
   8-11px. This one is 208px of plain text with no icon column, and the type scale below stays at
   the readable sizes -- the panel still clears 900px on the layouts this application is used on. */

.settings-layout { display: grid; grid-template-columns: 208px minmax(0, 1fr); gap: 22px; align-items: start; }

.settings-rail { position: sticky; top: 18px; }
.settings-rail-group { margin: 18px 0 6px; padding: 0 10px; color: var(--text-faint); font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; }
.settings-rail-group:first-child { margin-top: 0; }
.settings-rail button { width: 100%; min-height: 36px; padding: 7px 10px; border: 0; border-radius: 8px; display: block; text-align: left; background: transparent; color: var(--text-soft); cursor: pointer; font-size: 14px; font-weight: 600; }
.settings-rail button:hover { color: var(--grey); background: var(--surface-muted); }
.settings-rail button.active { color: var(--orange-ink); background: var(--orange-pale); }

/* Docked to the panel rather than the page header, where it sat above the fold and out of reach of
   the last field it applies to. Hidden for the groups whose rows save themselves. */
.settings-actions { position: sticky; bottom: 0; margin-top: 14px; padding: 16px 0 10px; display: flex; justify-content: flex-end; background: linear-gradient(to bottom, transparent, var(--zircon) 45%); }
.settings-actions[hidden] { display: none; }

/* ---- Settings type scale ---------------------------------------------------------------------
   Every size here was between 7px and 12px, which is what made these pages hard to read. */

.settings-section-head { padding: 26px 28px 21px; }
.settings-section-head h2 { font-size: 22px; }
.settings-section-head p { font-size: 14px; }

.settings-fields { max-width: 980px; padding: 24px 28px; gap: 18px; }
.settings-fields label, .field-label { font-size: 13px; }
.settings-fields input, .settings-fields select, .email-field select { height: 44px; font-size: 14px; }
.field-label { margin: 0 28px 11px; font-size: 11px; }
.field-hint { font-size: 13px; }

.toggle-row b { font-size: 14.5px; }
.toggle-row small { font-size: 12.5px; line-height: 1.45; }

.day-picker label { min-width: 56px; height: 36px; font-size: 12px; }
.sla-grid { padding: 0 28px 28px; }
.sla-grid input { height: 42px; font-size: 13.5px; }
.sla-grid small { bottom: 27px; font-size: 11px; }

.connection-status { min-height: 32px; padding: 0 12px; font-size: 11.5px; }
.integration-settings-card { margin: 20px 28px 0; }
.integration-settings-card b { font-size: 14px; }
.integration-settings-card p { font-size: 12.5px; line-height: 1.45; }
.integration-settings-card em { font-size: 11px; }
.integration-note { margin: 20px 28px 28px; }
.integration-note b { font-size: 13px; }
.integration-note span { font-size: 12.5px; }
.settings-block { margin: 0 28px 6px; }

.threecx-responsibility-list li { font-size: 12.5px; line-height: 1.5; }

/* The email and 3CX cards were built at 8-11px, small enough that the status line under a health
   light was unreadable at arm's length. Same scale as the rest of settings. */
.email-card-head { min-height: 0; padding: 16px 18px; }
.email-card-head h3, .email-side-card h3 { font-size: 16px; }
.email-card-head > p { max-width: 320px; font-size: 12.5px; }
.email-field-grid { padding: 18px; gap: 16px; }
.email-field { font-size: 13px; }
.email-field input, .email-field textarea, .copy-field input { font-size: 14px; }
.email-field input, .copy-field input { height: 44px; }
.email-field > small { margin-top: 7px; font-size: 12px; }
.copy-field button { min-width: 66px; font-size: 12px; }
.email-health-item { min-height: 0; padding: 13px 14px; }
.email-health-item b { font-size: 13px; }
.email-health-item small { margin-top: 4px; font-size: 12px; }
.connection-callout { padding: 14px 16px; }
.connection-callout > span { width: 24px; height: 24px; font-size: 12px; }
.connection-callout b { margin-bottom: 4px; font-size: 13px; }
.connection-callout p { font-size: 12.5px; }
.credential-row { min-height: 0; margin: 0 18px 18px; padding: 13px 14px; }
.credential-row b { font-size: 13px; }
.credential-row small { font-size: 12px; }
.credential-badge { font-size: 11px; }

/* ---- Channel panel: what is working, then the two things you can change -----------------------
   The mailbox used to open with a hero band repeating the page title, four status tiles, a callout
   and a sidebar of static advice -- roughly a screen and a half before the first editable field.
   Everything that only explained itself is gone; what is left is state, then settings. */

.email-channel-section .settings-body { background: var(--surface-head); }
.email-section-head .channel-head-side { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; flex: none; }
.channel-head-actions { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 7px; }
.channel-head-actions .text-button { padding: 7px; font-size: 12px; }

.channel-health { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 9px; }
.channel-meta { margin: 11px 0 0; display: flex; flex-wrap: wrap; gap: 5px 24px; color: var(--muted); font-size: 12.5px; }
.channel-meta b { color: var(--text-soft); font-weight: 700; }

/* Same 16px as .settings-columns. The two systems sit on adjacent pages, and a three-pixel
   difference in the gutter between them is the sort of thing that reads as untidy without ever
   being identifiable. */
.channel-columns { margin-top: 14px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }

.channel-block-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 22px; }
.channel-block-head h3 { margin: 0; font-size: 17px; }
.channel-block-head p { max-width: 620px; margin: 6px 0 0; color: var(--muted); font-size: 13px; line-height: 1.5; }
.channel-block-head .secondary-button { flex: none; }
.channel-block > .channel-status { margin: 15px 0 0; }

/* ---- Templates: every piece of wording the desk sends, in one list ---------------------------- */

.template-list { margin: 12px 0 26px; border: 1px solid var(--border); border-radius: 13px; background: var(--surface); }
.template-list:last-child { margin-bottom: 0; }
.template-row + .template-row { border-top: 1px solid var(--hairline); }
.template-row-head { min-height: 66px; padding: 15px 18px; display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.template-row-head b, .template-row-head small { display: block; }
.template-row-head b { font-size: 14.5px; }
.template-row-head small { margin-top: 4px; color: var(--muted); font-size: 12.5px; line-height: 1.45; }
.template-row .notification-editor { margin: 0 18px 18px; }
.template-row .notification-editor[aria-disabled="true"] { opacity: .55; }
.notification-editor-actions small { color: var(--muted); font-size: 12px; }

@media (max-width: 1180px) {
    .channel-health { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .channel-columns { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
    .settings-layout { grid-template-columns: minmax(0, 1fr); gap: 14px; }
    .settings-rail { position: static; display: flex; overflow-x: auto; gap: 4px; }
    .settings-rail-group { display: none; }
    .settings-rail button { width: auto; white-space: nowrap; }
    .settings-fields, .settings-section-head { padding-left: 18px; padding-right: 18px; }
    .field-label, .integration-settings-card, .integration-note, .settings-block { margin-left: 18px; margin-right: 18px; }
    .sla-grid { padding-left: 18px; padding-right: 18px; }
}

/* ---- The public landing page ------------------------------------------------------------------
   Shares the sign-in page's split shell so the front door and the door behind it look like the
   same building. Three routes rather than a form, because most arrivals want an answer, not an
   account. */

.landing-card { width: 100%; max-width: 410px; }
.landing-card h2 { margin: 8px 0 24px; font-size: 25px; letter-spacing: -.025em; }

.landing-route { margin-bottom: 12px; padding: 16px; border: 1px solid var(--border-dark); border-radius: 12px; display: flex; align-items: center; gap: 14px; color: inherit; background: var(--surface); text-decoration: none; transition: .16s; }
.landing-route:hover { border-color: var(--orange); transform: translateY(-2px); box-shadow: 0 8px 20px rgba(43,43,43,.09); }
.landing-route.primary { border-color: var(--orange); background: var(--orange-pale); }
.landing-route > span:nth-child(2) { flex: 1; min-width: 0; }
.landing-route b, .landing-route small { display: block; }
.landing-route b { font-size: 14.5px; }
.landing-route small { margin-top: 4px; color: var(--muted); font-size: 12.5px; line-height: 1.45; }

.landing-route-icon { width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; flex: none; color:var(--orange-ink); background:var(--orange-pale); font-size: 17px; font-weight: 700; }
.landing-route.primary .landing-route-icon { color: var(--on-orange); background: var(--orange); }
.landing-route-go { flex: none; color: var(--text-faintest); font-size: 16px; transition: .16s; }
.landing-route:hover .landing-route-go { color: var(--orange); transform: translateX(3px); }

.landing-help { margin: 20px 0 0; color: var(--text-faint); text-align: center; font-size: 11.5px; line-height: 1.5; }

/* The split shell needs 750px for its two columns but only collapsed at 650px, so between those
   widths it ran off the side of the screen. Collapses as soon as the two columns stop fitting. */
@media (max-width: 820px) {
    .login-shell { width: min(100% - 24px, 560px); min-height: auto; grid-template-columns: 1fr; }
    .login-brand-panel { min-height: 220px; padding: 28px; }
    .login-form-panel { padding: 34px 25px 40px; }
    .login-brand-panel > div:nth-child(2) { margin-top: 50px; }
    .login-brand-panel h1 { font-size: 27px; }
    .landing-card { max-width: none; }
}

/* ---- Credentials, and the numbers they unlock --------------------------------------------------
   A configured credential collapses to one status line. The fields underneath can only ever render
   empty -- the server never returns a stored secret -- so leaving them open makes a working channel
   look unconfigured every time the page loads. */

.credential-block { margin: 0 28px; }
.credential-summary { padding: 14px 16px; border: 1px solid var(--border); border-radius: 11px; display: flex; align-items: center; flex-wrap: wrap; gap: 10px; background: var(--surface-sunken); }
.credential-summary > small { flex: 1; min-width: 180px; color: var(--muted); font-size: 12.5px; line-height: 1.45; }
.credential-state { padding: 5px 10px; border-radius: 999px; flex: none; font-size: 11.5px; font-weight: 800; }
.credential-state.ok { color: var(--green-ink); background: var(--green-pale); }
.credential-state.warn { color: var(--orange-ink); background: var(--orange-pale); }
.credential-fields .settings-fields { padding-left: 0; padding-right: 0; }

.link-button { padding: 0; border: 0; background: transparent; color: var(--link); cursor: pointer; font-size: 12.5px; font-weight: 700; }
.link-button:hover { text-decoration: underline; }
.link-button.danger-text { color: var(--muted); }
.link-button.danger-text:hover { color: var(--coral-hover); }

.virtual-numbers { margin: 0 28px 8px; }
.virtual-number-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.virtual-number-list { margin-top: 12px; color: var(--muted); font-size: 12.5px; }
.virtual-number-row { padding: 13px 15px; border: 1px solid var(--border); border-radius: 11px; display: flex; align-items: center; flex-wrap: wrap; gap: 12px; background: var(--surface); }
.virtual-number-row + .virtual-number-row { margin-top: 8px; }
.virtual-number-row.selected { border-color: var(--orange); background: var(--orange-pale); }
.virtual-number-row > div:first-child { flex: 1; min-width: 180px; }
.virtual-number-row b { display: block; color: var(--grey); font-size: 14.5px; }
.virtual-number-row small { display: block; margin-top: 4px; color: var(--muted); font-size: 12px; word-break: break-all; }
.virtual-number-row-actions { display: flex; flex: none; gap: 14px; }

@media (max-width: 900px) {
    .credential-block, .virtual-numbers { margin-left: 18px; margin-right: 18px; }
}

/* ---- Message content editors -------------------------------------------------------------------
   One editor for all six templates, opened from a row in the Templates group. The wording used to
   be split three ways -- agent notifications here, the resolution email there, the acknowledgement
   buried in the mailbox settings -- so changing what a customer reads meant knowing which feature
   happened to own the sentence. */

.notification-editor { margin: 0 0 14px; padding: 16px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-sunken); }
.notification-editor > label { display: block; margin-bottom: 13px; color: var(--text-soft); font-size: 13px; font-weight: 700; }
.notification-editor input, .notification-editor textarea { width: 100%; margin-top: 7px; padding: 10px 11px; border: 1px solid var(--border-dark); border-radius: 8px; display: block; outline: 0; background: var(--surface); color: var(--grey); font: inherit; font-size: 13.5px; font-weight: 400; line-height: 1.5; }
.notification-editor input { height: 42px; padding-top: 0; padding-bottom: 0; }
.notification-editor input:focus, .notification-editor textarea:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.1); }

.notification-tokens { margin: 0 0 10px; display: flex; flex-wrap: wrap; align-items: center; gap: 5px; color: var(--muted); font-size: 12px; }
.token-chip { padding: 4px 8px; border: 1px solid var(--border-dark); border-radius: 999px; background: var(--surface); color: var(--text-soft); cursor: pointer; font-family: inherit; font-size: 11.5px; font-weight: 600; }
.token-chip:hover { border-color: var(--orange); color:var(--orange-ink); background:var(--orange-pale); }

.notification-warning { margin: 0 0 12px; padding: 10px 12px; border-radius: 8px; color: var(--orange-ink); background: var(--orange-pale); font-size: 12.5px; line-height: 1.5; }

.notification-preview { margin-bottom: 14px; padding: 13px 15px; border: 1px dashed var(--border-dark); border-radius: 10px; background: var(--surface); }
.notification-preview b { display: block; margin-bottom: 7px; color: var(--muted); font-size: 11px; letter-spacing: .09em; text-transform: uppercase; }
.notification-preview span { display: block; margin-bottom: 8px; color: var(--grey); font-size: 13.5px; font-weight: 700; }
.notification-preview pre { margin: 0; color: var(--text-soft); font: inherit; font-size: 13px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }

.notification-editor-actions { display: flex; align-items: center; gap: 16px; }

/* ---- Ticket list: contact first ----------------------------------------------------------------
   The team scans this list by who is asking, so the contact leads and the subject follows. The
   priority stripe moves with it -- it marks the row, so it belongs on whichever column is first,
   not on the subject wherever the subject happens to sit. */

.ticket-table-head, .ticket-row { grid-template-columns: minmax(210px, 1.3fr) minmax(320px, 2.3fr) 110px minmax(150px, 1fr) 115px; }

.ticket-subject { padding-left: 0; }
.ticket-subject::before { content: none; }

.ticket-row > .ticket-customer { padding-left: 10px; position: relative; }
.ticket-row > .ticket-customer::before { content: ""; position: absolute; left: 0; top: 2px; bottom: 2px; width: 3px; border-radius: 4px; background: var(--neutral-mark); }
.ticket-row[data-priority="urgent"] .ticket-customer::before { background: var(--coral); }
.ticket-row[data-priority="high"] .ticket-customer::before { background: var(--orange); }
.ticket-row[data-priority="normal"] .ticket-customer::before { background: var(--green); }

@media (max-width: 1200px) {
    .ticket-table-head, .ticket-row { grid-template-columns: minmax(170px, 1fr) minmax(270px, 2fr) 100px 115px; }
}

/* ---- Settings: one measure, and groups that read as groups -------------------------------------
 * Every group in a settings page used to set its own gutter and its own width. The field grid
 * stopped at 980px while the signature box, the status banner, the credential block and the button
 * row ran the full width of a 1600px panel, so the right edge was ragged and a two-line signature
 * was 1500px across. Worse, the groups were separated only by a floating 11px uppercase label, so
 * a page read as one undivided column that had to be scrolled to be understood.
 *
 * One container now owns the gutter and the measure. Inside it the groups are cards, which is what
 * lets two of them sit side by side: the width that was being wasted on the right takes the place
 * of the scroll.
 */

.settings-body { padding: 22px 28px 26px; }
.settings-body > .channel-status,
.settings-body > .integration-note { margin-left: 0; margin-right: 0; }
.settings-body > .channel-status { margin-bottom: 16px; }

/* Two stacks rather than a grid of loose cards: the cards differ in height, and a row-based grid
   would leave the shorter of each pair sitting above a gap the height of the taller one. */
.settings-columns { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.settings-column { display: grid; align-content: start; gap: 16px; }

.settings-card { padding: 20px 22px; border: 1px solid var(--border); border-radius: 13px; background: var(--surface-sunken); }
.settings-card > h3 { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.4; }
.settings-card > h3 + p { margin: 5px 0 0; color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.settings-card > h3 + .settings-fields,
.settings-card > h3 + p + .settings-fields,
.settings-card > h3 + .settings-toggles,
.settings-card > h3 + p + .settings-toggles,
.settings-card > h3 + .settings-block,
.settings-card > h3 + p + .settings-block,
.settings-card > h3 + .credential-block,
.settings-card > h3 + p + .credential-block { margin-top: 16px; }

/* The pieces that used to place themselves against the panel now sit flush inside the card. */
.settings-card .settings-fields { max-width: none; padding: 0; gap: 16px; }
.settings-card .settings-block { margin: 0; }
.settings-card .setting-toggles { padding: 0; }
.settings-card .credential-block,
.settings-card .virtual-numbers { margin: 0; }
.settings-card .sla-grid { padding: 0; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.settings-card .field-label { margin: 18px 0 11px; }
.settings-card .integration-note { margin: 16px 0 0; }
.settings-card .category-list { margin: 16px 0 0; }
.settings-card .category-form { margin: 0; padding-top: 0; border-top: 0; }
.settings-card .field-hint:last-child { margin-bottom: 0; }
.settings-subsection { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--border); }
.settings-subsection > h4 { margin: 0; font-size: 13px; }
.settings-subsection > h4 + p { margin: 5px 0 16px; color: var(--muted); font-size: 11px; line-height: 1.5; }
.settings-subsection > label { margin-top: 15px; display: grid; gap: 7px; color: var(--text-soft); font-size: 11px; font-weight: 650; }
.settings-subsection > label input,
.settings-subsection > label textarea { width: 100%; border: 1px solid var(--border-dark); border-radius: 8px; outline: 0; color: var(--text); background: var(--surface); font: inherit; font-weight: 400; }
.settings-subsection > label input { height: 40px; padding: 0 11px; }
.settings-subsection > label textarea { min-height: 116px; padding: 10px 11px; line-height: 1.5; resize: vertical; }
.settings-subsection > label input:focus,
.settings-subsection > label textarea:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.1); }
.settings-subsection .field-help { margin: 8px 0 0; color: var(--muted); font-size: 10px; line-height: 1.5; }
.settings-subsection :disabled { cursor: not-allowed; opacity: .52; }
.settings-card .settings-block textarea { min-height: 76px; padding: 10px 11px; border: 1px solid var(--border-dark); border-radius: 8px; outline: 0; background: var(--surface); color: var(--grey); font: inherit; font-size: 14px; line-height: 1.5; resize: vertical; }
.settings-card .settings-block textarea:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.1); }

/* Toggles are their own list. Interleaving them with inputs in one grid, which is how Mode ended
   up beside Channel enabled, put two controls of different shape and height in the same row. */
.settings-toggles { display: block; }
.settings-toggles > .toggle-row { min-height: 0; padding: 13px 0; }
.settings-toggles > .toggle-row:first-child { padding-top: 0; }
.settings-toggles > .toggle-row:last-child { padding-bottom: 0; border-bottom: 0; }
.settings-fields + .settings-toggles { margin-top: 18px; padding-top: 4px; border-top: 1px solid var(--border); }

/* One save per page, in the page header where it is always in view. The buttons that used to sit
   at the bottom of a group are gone: on SMS the header button ran the workspace save instead, so
   the prominent button on the page was the one that discarded what had just been typed. */
.settings-body .modal-actions { margin-top: 18px; }

@media (max-width: 1150px) {
    .settings-columns { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
    .settings-body { padding-left: 18px; padding-right: 18px; }
    .settings-card { padding: 17px 16px; }
    .settings-card .sla-grid { grid-template-columns: minmax(0, 1fr); }
}

/* The settings Save button reporting its own outcome. The toast it raises lands in the opposite
   corner of the screen from the button that was just pressed, which reads as nothing happening. */
.primary-button.is-saved { border-color: var(--green); background: var(--green); box-shadow: 0 5px 14px rgba(33,173,126,.2); }
.primary-button.is-saved:hover { border-color: var(--green-hover); background: var(--green-hover); }
.primary-button.is-unsaved { border-color: var(--coral); background: var(--coral); box-shadow: 0 5px 14px rgba(254,56,56,.2); }
.primary-button.is-unsaved:hover { border-color: var(--coral-hover); background: var(--coral-hover); }

/* A confirmation nobody reads is the same as no confirmation. It was 11px, in the far corner. */
.toast { font-size: 13px; }
.toast-region { bottom: 26px; }

/* Three health lights on Calling, four on Email. A flex row rather than a counted grid: auto-fit
   keeps the fourth track alive when only three items are placed in it, which left Calling with a
   257px hole on the right. Wrapping at 210px replaces the media queries that counted for it. */
.channel-health { display: flex; flex-wrap: wrap; }
.channel-health > * { flex: 1 1 210px; min-width: 0; }

/* ---- Venues and history on a contact ----------------------------------------------------------
   A contact is a person; the venues are the sites they look after, and there can be several. The
   free-text venue field they replaced could only ever hold one, and drifted from billing. */

.contact-row { cursor: pointer; }
.contact-row:hover { background: var(--surface-head); }
.contact-row:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }
.contact-cell-empty b { color: var(--muted); font-weight: 500; }

.contact-venues, .contact-archive { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--border); }
.contact-venues h3, .contact-archive h3 { margin: 0 0 4px; font-size: 14px; font-weight: 700; line-height: 1.4; }
.contact-section-hint { margin: 0 0 12px; color: var(--muted); font-size: 12px; line-height: 1.5; }

.contact-venue-list { display: grid; gap: 8px; }
.contact-venue-row { padding: 10px 12px; border: 1px solid var(--border); border-radius: 9px; display: flex; align-items: center; gap: 12px; background: var(--surface); }
.contact-venue-row.primary { border-color: var(--orange-tint); background: var(--orange-wash); }
.contact-venue-name { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; }
.contact-venue-name b { font-size: 13px; }
.contact-venue-tag { padding: 3px 7px; border-radius: 999px; color: var(--orange-ink); background: var(--orange-pale); font-size: 10px; font-weight: 800; }
.contact-venue-empty { margin: 0; padding: 10px 2px; color: var(--muted); font-size: 12.5px; }

.contact-venue-search { position: relative; margin-top: 10px; }
.contact-venue-search input { width: 100%; height: 40px; padding: 0 11px; border: 1px solid var(--border-dark); border-radius: 8px; outline: 0; background: var(--surface); color: var(--grey); font: inherit; font-size: 13px; }
.contact-venue-search input:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.1); }

.contact-venue-results { max-height: 210px; margin-top: 6px; overflow-y: auto; border: 1px solid var(--border); border-radius: 9px; background: var(--surface); }
.contact-venue-results[hidden] { display: none; }
.contact-venue-option { width: 100%; padding: 9px 12px; border: 0; border-bottom: 1px solid var(--hairline); display: block; text-align: left; background: transparent; cursor: pointer; }
.contact-venue-option:last-child { border-bottom: 0; }
.contact-venue-option:hover { background: var(--surface-head); }
.contact-venue-option b { display: block; font-size: 13px; }
.contact-venue-option span { display: block; margin-top: 2px; color: var(--muted); font-size: 11.5px; }

.contact-archive-list { display: grid; gap: 8px; max-height: 260px; overflow-y: auto; }
.contact-archive-row { padding: 10px 12px; border: 1px solid var(--border); border-radius: 9px; display: flex; align-items: center; gap: 12px; background: var(--surface); }
.contact-archive-row > span:first-child { flex: 1; min-width: 0; }
.contact-archive-row b { display: block; overflow: hidden; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }
.contact-archive-row > span:first-child > span { display: block; margin-top: 3px; color: var(--muted); font-size: 11.5px; }
.contact-history-head { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.contact-history-head h2 { margin:0; }
.contact-history-head > span { min-width:25px; padding:4px 8px; border-radius:999px; color:var(--orange-ink); background:var(--orange-wash-strong); font-size:9px; font-weight:800; text-align:center; }
.contact-history .contact-section-hint { margin-top:5px; }
.contact-history .contact-archive-list { max-height:390px; padding-right:3px; }
.contact-history-row { width:100%; color:inherit; font:inherit; text-align:left; }
button.contact-history-row { cursor:pointer; transition:border-color .15s ease,background .15s ease,transform .15s ease; }
button.contact-history-row:hover { border-color:var(--orange-wash-border); background:var(--orange-wash); transform:translateY(-1px); }
button.contact-history-row:focus-visible { outline:2px solid var(--orange); outline-offset:2px; }
div.contact-history-row { opacity:.7; }

/* ---- A received email, as the sender formatted it ---------------------------------------------
   The markup is a stranger's: sanitised server-side, but still written to look right in Outlook
   against a full-width white page, not inside a conversation card. These rules stop it dictating
   the layout around it -- a 900px table or an unbroken URL would otherwise widen the whole thread
   and push the ticket sidebar off screen. */

.message-body-html { min-width: 0; }
.message-html { max-width: 100%; overflow-x: auto; color: var(--grey); font-size: 13.5px; line-height: 1.55; overflow-wrap: anywhere; }
.message-html > *:first-child { margin-top: 0; }
.message-html > *:last-child { margin-bottom: 0; }
.message-html p, .message-html div { margin: 0 0 10px; }
.message-html img { max-width: 100%; height: auto; }

/* An agent's inline images: every one the same small tile in the thread and the composer, the
   whole picture letterboxed inside it, the full size one click away (openImageViewer). */
.message-html img.desk-inline-image,
.app-shell .reply-editor img:not(.desk-agent-signature img) {
  display: inline-block;
  width: 168px !important;
  height: 112px !important;
  max-width: 100%;
  margin: 4px 8px 4px 0;
  padding: 3px;
  object-fit: contain;
  vertical-align: top;
  background: var(--surface-hover);
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  cursor: zoom-in;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.message-html img.desk-inline-image:hover,
.app-shell .reply-editor img:not(.desk-agent-signature img):hover {
  border-color: var(--border-hover);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .12);
}
.app-shell .reply-editor img:not(.desk-agent-signature img) { cursor: default; }

.image-viewer {
  width: min(96vw, 1600px);
  max-width: none;
  height: min(94vh, 1200px);
  max-height: none;
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: #111418;
  color: #e9edf3;
  overflow: hidden;
}
.image-viewer[open] { display: flex; flex-direction: column; }
.image-viewer::backdrop { background: rgba(8, 10, 14, .78); }
.image-viewer-bar { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-bottom: 1px solid rgba(255, 255, 255, .08); font-size: 13px; }
.image-viewer-caption { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.image-viewer-open { color: #9cc3ff; }
.image-viewer-close { border: 0; background: transparent; color: inherit; font-size: 16px; width: 32px; height: 32px; border-radius: 6px; cursor: pointer; }
.image-viewer-close:hover, .image-viewer-step:hover { background: rgba(255, 255, 255, .1); }
.image-viewer-stage { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 12px; }
.image-viewer-stage img { max-width: calc(100% - 96px); max-height: 100%; object-fit: contain; background: #fff; border-radius: 4px; }
.image-viewer-step { flex: none; width: 40px; height: 64px; border: 0; border-radius: 8px; background: rgba(255, 255, 255, .05); color: inherit; font-size: 30px; line-height: 1; cursor: pointer; }
.image-viewer-step[hidden] { display: block; visibility: hidden; }
.message-html table { max-width: 100%; border-collapse: collapse; }
.message-html td, .message-html th { padding: 4px 8px; }
.message-html blockquote { margin: 8px 0; padding: 2px 0 2px 12px; border-left: 3px solid var(--border); color: var(--muted); }
.message-html pre { max-width: 100%; overflow-x: auto; padding: 10px; border-radius: 8px; background: var(--surface-muted); }
.message-html a { color: var(--link); }

/* The original request is a div now, so an email body can render inside it. The old selector
   targeted the last <p> and set pre-wrap, which is right for typed text and wrong for markup. */
.original-request-body { margin: 0; color: var(--text-soft); font-size: 12px; line-height: 1.7; white-space: pre-wrap; }
.contact-venue-prompt { width:min(520px,calc(100vw - 32px)); max-height:85vh; padding:24px; border:1px solid var(--border); border-radius:16px; background:var(--surface); color:var(--text); box-shadow:0 20px 70px #0004; }
.contact-venue-prompt::backdrop { background:var(--backdrop); }
.ticket-contact-modal .contact-picker-results { position:static; max-height: min(350px,45vh); overflow:auto; margin-top:12px; width:100%; }
.support-level-member { display:flex; align-items:center; flex-wrap:wrap; gap:12px; padding:12px 0; border-bottom:1px solid var(--border); }
.support-level-member > div { flex:1 1 180px; }
.support-level-member small { display:block; color:var(--muted); }
.support-level-member label { display:flex; align-items:center; gap:4px; }
.ticket-level-row { padding:12px 17px; border-top:1px solid var(--border); display:flex; align-items:center; gap:10px; }
.ticket-level-caption { color:var(--muted); font-size:11px; font-weight:700; }
.ticket-escalate-button { margin-left:auto; color:var(--muted); font-size:11.5px; }
.ticket-escalate-button:hover { color: var(--link); }
.ticket-escalate-button[hidden] { display:none; }
.support-level-badge { white-space:nowrap; padding:2px 6px; border-radius:6px; color:#fff !important; -webkit-text-fill-color:#fff; background:#263746; font-weight:800; font-size:11px; }
.support-level-badge.level-1 { background:#263746; }
.support-level-badge.level-2 { background:#55306f; }
.support-level-badge.level-3 { background:#762b36; }
/* In the dark the level-1 slate was 1.4:1 against the panel -- the text floated with no badge
   around it. Same three hues, lifted until the shape reads, white text still above 7:1. */
:root[data-theme="dark"] .support-level-badge.level-1 { background:#36506a; }
:root[data-theme="dark"] .support-level-badge.level-2 { background:#6a3d8a; }
:root[data-theme="dark"] .support-level-badge.level-3 { background:#8f3442; }
.support-level-dialog textarea, .support-level-dialog select, .support-level-dialog input[type="text"] { width:100%; margin:8px 0 16px; padding:10px; color:var(--text); background:var(--surface); border:1px solid var(--border); border-radius:8px; }

/* The chosen code's "use when" line, and the running list of what is still missing. Both sit
   directly under the control they describe: an agent should never have to press a disabled button
   to find out why it is disabled. */
.support-level-reason-help { display:block; margin:-10px 0 14px; color:var(--muted); font-size:11.5px; line-height:1.5; }
.support-level-note-help { display:block; margin:-10px 0 14px; color:var(--coral-hover); font-size:11.5px; }
.support-level-note-help.ready { color: var(--green-ink); }
.support-level-fields:not(:empty) { padding:12px 14px; margin:0 0 16px; border:1px solid var(--border); border-radius:9px; background:var(--surface-sunken); }
.support-level-fields label { font-size:11px; font-weight:700; }
.support-level-fields input[type="text"] { margin:6px 0 10px; }
.support-level-fields label:last-of-type + input[type="text"] { margin-bottom:0; }
.contact-venue-prompt h2 { margin:0 0 10px; font-size:19px; }
.contact-venue-prompt p { color:var(--muted); font-size:13px; }
.contact-venue-prompt input { width:100%; padding:10px 12px; border:1px solid var(--border); border-radius:8px; background:var(--surface); color:var(--text); }
.contact-venue-prompt-results { max-height:260px; overflow:auto; margin-top:12px; }
.contact-venue-prompt-results button { width:100%; text-align:left; }
.contact-venue-prompt-results button[aria-pressed="true"] { background:var(--orange-pale); color:var(--orange-ink); }
.contact-venue-prompt-actions { display:flex; justify-content:flex-end; flex-wrap:wrap; gap:8px; margin-top:18px; }
.forward-ticket-dialog { width:min(500px,calc(100vw - 32px)); }
.forward-ticket-heading { display:flex; align-items:center; gap:13px; margin-bottom:18px; }
.forward-ticket-heading h2 { margin:0 0 3px; }
.forward-ticket-heading p { margin:0; font-size:10px; }
.forward-ticket-icon { width:42px; height:42px; border:1px solid var(--orange-wash-border); border-radius:12px; display:grid; place-items:center; flex:none; color: var(--link); background:var(--orange-wash); font-size:18px; font-weight:900; }
.forward-ticket-copy { margin:0 0 18px; padding:12px 14px; border-radius:10px; color:var(--text-soft)!important; background:var(--surface-sunken); font-size:11px!important; line-height:1.55; }
.forward-ticket-label { display:block; color:var(--text-soft); font-size:10px; font-weight:800; }
.forward-ticket-label input { margin-top:7px; }
.forward-ticket-feedback { min-height:18px; margin:8px 0 0; color:var(--coral-hover)!important; font-size:10px!important; }
.original-request-body .message-body-html { white-space: normal; }
.original-request-body .message-html { font-size: 13px; }

/* An email renders on its own paper.
   A message was written against a white background: the sender chose black headings, grey rules
   and a cream warning banner on the assumption of one. Dropped onto a dark workspace surface those
   choices range from muddy to invisible, and the alternative -- overriding the sender's colours --
   throws away the formatting this whole change exists to keep. So the body gets the background it
   was composed for, in both themes, the way an email client shows it. */
.message-html {
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: #fff;
    color: #1f2328;
}

.message-html a { color: #0b57d0; }
.message-html blockquote { border-left-color: #d6dae0; color: #5c636b; }
.message-html pre { background: #f4f6f8; }

/* Every rendered message takes the workspace's own colours, so nothing is a white card in the
   middle of a dark thread. The sender's colours are kept on top of it; fitMessageColours in
   site.js adjusts only the ones that would not read against the theme. The paper above remains
   for anything rendered without that pass. */
.message-html.message-html-themed {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--grey);
}

.message-html.message-html-themed a { color: var(--link); }
.message-html.message-html-themed blockquote { border-left-color: var(--border); color: var(--muted); }
.message-html.message-html-themed pre { background: var(--surface-muted); }

/* ---- Who else is here -------------------------------------------------------------------------
   Two agents answering the same ticket is the thing this prevents, so it has to be visible before
   one of them starts typing -- in the queue, next to the subject, and in the ticket bar. */

.ticket-viewers { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-right: 10px; }
.ticket-viewers[hidden] { display: none; }
.ticket-viewer { display: inline-flex; align-items: center; gap: 7px; padding: 7px 11px; border: 1px solid color-mix(in srgb, var(--presence) 45%, var(--border)); border-radius: 999px; background: color-mix(in srgb, var(--presence) 10%, var(--surface)); color: var(--text); font-size: 11.5px; font-weight: 650; box-shadow: 0 0 18px color-mix(in srgb, var(--presence) 12%, transparent); }
.ticket-viewer-eye { display: grid; width: 18px; height: 18px; place-items: center; color: var(--presence-strong); transform-origin: center; animation: ticket-viewer-blink 3s ease-in-out infinite; }
.ticket-viewer-eye svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.8; }
.ticket-viewer-name { white-space: nowrap; }
.ticket-viewer.typing { border-color: var(--orange-tint); background: var(--orange-wash); color: var(--orange-ink); }
.ticket-viewer-typing { color: var(--link); font-weight: 700; }

@keyframes ticket-viewer-blink {
  0%, 44%, 50%, 100% { transform: scaleY(1); }
  47% { transform: scaleY(.08); }
}

@media (prefers-reduced-motion: reduce) {
  .ticket-viewer-eye,
  .ticket-row-presence svg { animation: none; }
}

.ticket-row-presence {
  width: 26px;
  height: 26px;
  margin-left: 7px;
  border-radius: 50%;
  display: inline-grid;
  place-items: center;
  align-self: center;
  color: var(--presence-strong);
  background: color-mix(in srgb, var(--presence) 12%, transparent);
  cursor: help;
}
.ticket-row-presence svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.9; transform-origin: center; animation: ticket-viewer-blink 3s ease-in-out infinite; }
.ticket-row-presence.typing { color: var(--link); background: var(--orange-wash); }

/* ---- Channel panels: one gutter, one type scale ------------------------------------------------
   The channel cards were built before the settings pages were rescaled and kept their own sizes:
   9px card hints, 10px field labels, 7px badges. Next to a workspace page whose labels are 13px
   they read as a different product, and several of them are simply too small to read. */

.email-card-head { min-height: 0; padding: 16px 18px; }
.email-card-head h3, .email-side-card h3 { font-size: 15px; line-height: 1.4; }
.email-card-head > p { max-width: 340px; font-size: 12.5px; line-height: 1.5; }

.email-field-grid { padding: 18px; gap: 18px; }
.email-field { font-size: 13px; }
.email-field input, .email-field textarea, .copy-field input, .email-field select { font-size: 14px; }
.email-field input, .copy-field input, .email-field select { height: 44px; }
.email-field small { font-size: 12.5px; line-height: 1.45; }

/* The credential block sat at the panel's 28px gutter inside a card whose fields use 18px, so it
   was visibly narrower than everything around it -- the one box that looked a different size. */
.email-settings-card .credential-block { margin: 0; padding: 0 18px; }
/* The grid already carries the gutter when it stands alone; nested in the credential block it
   would add a second one, indenting the credentials past every other field on the panel. */
.credential-block .email-field-grid { padding-left: 0; padding-right: 0; }
.email-settings-card .credential-block + .credential-row { margin-top: 18px; }
.credential-row { min-height: 0; margin: 0 18px 18px; padding: 13px 14px; }
.credential-row b { font-size: 13px; }
.credential-row small { margin-top: 4px; font-size: 12px; line-height: 1.45; }
.credential-badge { padding: 5px 10px; font-size: 11px; }

.email-toggle-wrap { padding: 0 18px 4px; }

/* The rail stuck 18px from the top of the viewport, which is underneath a 68px sticky topbar --
   so its first group heading was permanently cut in half by the bar above it. */
.settings-rail { top: 86px; }

/* Cards in a row match height. Left at start they ended wherever their content did, which put a
   tall Mailbox card beside a short connection card and left a hole under the shorter one. */
.channel-columns { align-items: stretch; }
.channel-columns > * { display: flex; flex-direction: column; }

/* ---- The front door: staff sign-in and the public landing ------------------------------------
   Deliberately the same shell as the billing portal's sign-in — full-bleed hospitality photo, a
   brand wash for contrast, one white card centred on it. Somebody who administers both should
   recognise the second one as the same venue on sight, so the values below are billing's. */

.auth-shell { min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: 24px; position: relative; overflow: hidden; }
.auth-shell::before { content: ""; position: fixed; inset: 0; z-index: 0; background: url('/images/login-bg.jpg') center 35% / cover no-repeat; }
.auth-shell::after { content: ""; position: fixed; inset: 0; z-index: 1; background: linear-gradient(135deg, rgba(20,12,8,.62) 0%, rgba(216,123,56,.45) 55%, rgba(20,12,8,.62) 100%); }

/* The card keeps a light treatment in both themes. It sits on a photograph, not on the workspace
   surface, and a dark card on that wash loses the contrast the wash exists to create. */
.auth-card {
    position: relative; z-index: 2; width: 100%; max-width: 410px;
    padding: 38px 40px 36px; border: 1px solid rgba(255,255,255,.25); border-radius: 18px;
    background: rgba(255,255,255,.98); text-align: center;
    box-shadow: 0 18px 60px rgba(0,0,0,.45), 0 4px 14px rgba(0,0,0,.25);
    color-scheme: light; color: #2b2b2b;
}

.auth-card h1 { margin: 6px 0 8px; font-size: 22px; line-height: 1.3; letter-spacing: -.02em; }
.auth-card p { margin: 0 0 22px; color: #6b7076; font-size: 13.5px; line-height: 1.55; }
.auth-brand { margin-bottom: 14px; }
.auth-brand img { height: 46px; width: auto; display: inline-block; }

.auth-product-label {
    display: inline-block; margin: 0 0 22px; padding: 5px 14px; border-radius: 999px;
    background: var(--orange-pale); color: var(--orange-ink);
    font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
}

.auth-btn { display: flex; width: 100%; margin-top: 10px; text-decoration: none; }
/* The sign-in result. It used to borrow .login-help -- 9px, faintest grey, centred -- which is
   right for a footnote and wrong for the only feedback a customer gets in the entire magic-link
   flow. They type an address, press a button, and everything after that happens in their inbox;
   this line is the whole confirmation that anything worked. */
.login-result { margin: 16px 0 0; padding: 11px 12px; border: 1px solid transparent; border-radius: 8px; color: var(--text-soft); font-size: 13px; line-height: 1.5; }
.login-result:empty { display: none; }
.login-result.is-ok { border-color: var(--green-wash-border, var(--border)); color: var(--green-ink); background: var(--green-pale); }
.login-result.is-error { border-color: var(--coral-wash-border, var(--border)); color: var(--coral-ink); background: var(--coral-pale); }

.auth-note { margin: 20px 0 0; color: #8b9097; font-size: 12px; line-height: 1.5; }
.auth-note a { color: var(--orange-hover); font-weight: 600; }

/* The coming-soon card carries more than the sign-in one, so it is allowed to be wider. */
.auth-card.auth-card-wide { max-width: 520px; }
.auth-soon { display: grid; gap: 12px; margin: 4px 0 4px; text-align: left; }
.auth-soon-item { display: flex; align-items: flex-start; gap: 13px; padding: 15px 16px; border: 1px solid var(--border); border-radius: 12px; background: #fbfcff; }
.auth-soon-icon { width: 38px; height: 38px; border-radius: 11px; display: grid; place-items: center; flex: none; color: var(--orange-ink); background: var(--orange-pale); font-size: 16px; font-weight: 700; }
.auth-soon-item b { display: block; font-size: 14px; }
.auth-soon-item small { display: block; margin-top: 4px; color: #6b7076; font-size: 12.5px; line-height: 1.45; }
.auth-soon-tag { margin-left: auto; align-self: center; flex: none; padding: 4px 9px; border-radius: 999px; background: var(--surface-muted); color: #7d838a; font-size: 10.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.auth-soon-link { color:inherit; text-decoration:none; cursor:pointer; transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease; }
.auth-soon-link:hover { border-color:var(--orange-tint); box-shadow:0 9px 24px rgba(53,35,23,.1); transform:translateY(-1px); }
.auth-soon-arrow { margin-left:auto; align-self:center; color:var(--orange-hover); font-size:20px; font-weight:800; }

@media (max-width: 520px) {
    .auth-card { padding: 30px 24px 28px; }
    .auth-soon-item { padding: 13px; }
}

/* Staff arrive at the public page constantly -- it is where signing out lands them -- so the way
   back in is a button under a labelled rule, not a line of small print at the bottom. */
.auth-divider { display: flex; align-items: center; gap: 12px; margin: 24px 0 14px; color: #9aa0a7; font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.auth-divider::before, .auth-divider::after { content: ""; height: 1px; flex: 1; background: var(--border); }

/* Spacing that reads as deliberate rather than as whatever the elements happened to stack to.
   The label sits closer to the logo than to the heading, so it belongs to the brand; the heading
   and its sentence are one block; the list is separated from both. */
.auth-brand { margin-bottom: 10px; }
.auth-product-label { margin: 0 0 18px; }
.auth-card h1 { margin: 0 0 10px; }
.auth-card > p { margin: 0 0 24px; }
.auth-soon { margin: 0 0 22px; }
.auth-card .auth-btn + .auth-btn { margin-top: 10px; }
.auth-note { margin: 18px 0 0; }
/* Keeps "Go to Triniteq Helpdesk" from breaking across two lines mid-phrase. */
.auth-note a { white-space: nowrap; }

/* ---- The split sign-in shell, on the same photograph as everything else -----------------------
   The portal and staff sign-in pages sat on a flat surface while the front door and the billing
   portal sat on a photograph, so arriving at one from the other looked like leaving the product.
   The panel keeps its size -- it earns it, carrying the brand on one side and the form on the
   other -- and is centred on the same background instead of floating near the top. */

.login-body { display: flex; align-items: center; justify-content: center; padding: 24px; position: relative; background: var(--sidebar); }
.login-body::before { content: ""; position: fixed; inset: 0; z-index: 0; background: url('/images/login-bg.jpg') center 35% / cover no-repeat; }
.login-body::after { content: ""; position: fixed; inset: 0; z-index: 1; background: linear-gradient(135deg, rgba(20,12,8,.62) 0%, rgba(216,123,56,.45) 55%, rgba(20,12,8,.62) 100%); }

.login-shell {
    position: relative; z-index: 2; margin: 0;
    border-color: rgba(255,255,255,.18);
    box-shadow: 0 18px 60px rgba(0,0,0,.45), 0 4px 14px rgba(0,0,0,.25);
}

/* The form half is white in both themes, like the cards on the other sign-in pages: it sits on a
   photograph rather than on the workspace surface. */
.login-form-panel { background: #fff; color: #2b2b2b; }
.login-form-panel .login-card h2 { color: #2b2b2b; }
.login-form-panel .login-intro, .login-form-panel .login-help { color: #6b7076; }
.login-form-panel label { color: #4a5058; }
.login-form-panel input { background: #fff; border-color: #d3d8e1; color: #2b2b2b; }

/* Alignment: the field, its label and the button share one edge and one width, and the button is
   not left sitting tight against the input it follows. */
.login-card label { display: block; margin-bottom: 16px; font-size: 13px; font-weight: 700; }
.login-card label input { width: 100%; height: 46px; margin-top: 7px; padding: 0 13px; border: 1px solid #d3d8e1; border-radius: 9px; outline: 0; font: inherit; font-size: 14px; font-weight: 400; box-sizing: border-box; }
.login-card label input:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.12); }
.login-card .login-submit { width: 100%; margin-top: 4px; }
.login-card .login-intro { margin: 0 0 20px; font-size: 13.5px; line-height: 1.55; }
.login-card h2 { margin: 6px 0 10px; font-size: 24px; letter-spacing: -.02em; }

/* The footer line, which now carries the copyright and the build rather than a bare word. */
.login-brand-panel small { color: #9a9a9a; font-size: 11.5px; line-height: 1.6; }
.login-brand-panel small span { display: block; }

@media (max-width: 820px) {
    .login-body { padding: 16px; }
}

/* ---- Workspace readability and ticket controls ----------------------------------------------
   Support staff spend all day in this shell, so it should not be typeset like a compact admin
   table. These fluid desktop values add roughly one comfortable reading step without relying on
   browser zoom, while the existing responsive breakpoints still decide what fits on small screens. */
.app-shell { font-size: clamp(14px, .16vw + 11.5px, 16px); }
.app-shell .sidebar { width: 260px; }
.app-shell .main-content { width: calc(100% - 260px); margin-left: 260px; }
.app-shell .topbar { height: 74px; padding-inline: clamp(22px, 2vw, 36px); }
.app-shell .view { min-height: calc(100dvh - 74px); padding: clamp(28px, 2vw, 38px) clamp(24px, 2.25vw, 42px) 40px; }
.app-shell .ticket-detail-view { padding: 0; }
.app-shell .nav-link { min-height: 47px; font-size: 14px; }
.app-shell .nav-label { font-size: 11px; }
.app-shell .integration-card b, .app-shell .user-card b { font-size: 12px; }
.app-shell .integration-card span, .app-shell .user-card > div:nth-child(2) span { font-size: 10.5px; }
.app-shell .global-search { height: 42px; }
.app-shell .global-search input { font-size: 13.5px; }
.app-shell .page-head h1 { font-size: clamp(30px, 1.8vw, 36px); }
.app-shell .page-head > div > p:last-child { font-size: 14px; }
.app-shell .eyebrow { font-size: 10px !important; }
.app-shell .primary-button, .app-shell .secondary-button, .app-shell .danger-button { min-height: 42px; font-size: 13px; }
.app-shell .summary-card p { font-size: 12px; }
.app-shell .summary-card span { font-size: 10.5px; }
.app-shell .panel-head h2 { font-size: 18px; }
.app-shell .panel-head > div > span, .app-shell .embedded-empty p, .app-shell .empty-state p { font-size: 12px; }
.app-shell .quick-action b { font-size: 12.5px; }
.app-shell .quick-action small { font-size: 10.5px; }
.app-shell .ticket-tab { font-size: 12.5px; }
.app-shell .ticket-tab span { font-size: 9.5px; }
.app-shell .queue-search input, .app-shell .tool-button, .app-shell .sort-select { font-size: 11.5px; }
.app-shell .toolbar-toggle { font-size: 11.5px; }
.app-shell .ticket-table-head, .app-shell .contact-table-head { font-size: 10px; }
.app-shell .ticket-row { min-height: 80px; }
.app-shell .ticket-subject b { font-size: 14px; }
.app-shell .ticket-subject span, .app-shell .ticket-customer span { font-size: 11px; }
.app-shell .ticket-customer b { font-size: 12.5px; }
.app-shell .ticket-assignee span { font-size: 11px; }
.app-shell .status-pill, .app-shell .sla-pill, .app-shell .priority-chip { font-size: 10px; }
.app-shell .table-footer { font-size: 10.5px; }

/* Ticket actions now live beside the ticket identity. They belong to the thing being acted on,
   and no longer float at the far edge of a wide monitor. */
.app-shell .ticket-detail-bar { min-height: 90px; padding: 14px clamp(18px, 2vw, 32px); }
.app-shell .ticket-breadcrumb { flex: 0 1 auto; max-width: 100%; }
.app-shell .ticket-title-copy { min-width: 170px; max-width: min(34vw, 520px); }
.app-shell .ticket-title-copy h1 { font-size: 19px; }
.app-shell .ticket-detail-actions { position: relative; flex: none; }
.app-shell .ticket-detail-actions .secondary-button { min-height: 39px; padding-inline: 14px; font-size: 11.5px; }
.app-shell .ticket-viewers { margin-left: auto; }
.app-shell .ticket-detail-actions .drawer-actions-menu {
  top: 46px;
  right: 0;
  width: 220px;
  padding: 8px;
  border-radius: 12px;
}
.app-shell .ticket-detail-actions .drawer-actions-menu button {
  min-height: 42px;
  padding: 11px 13px;
  border-radius: 8px;
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: center;
  column-gap: 9px;
  font-size: 11.5px;
  line-height: 1.35;
}
.app-shell .ticket-detail-actions .drawer-actions-menu .action-icon {
  width: 18px;
  margin: 0;
  display: grid;
  place-items: center;
  line-height: 1;
}
.app-shell .ticket-detail-actions .drawer-actions-menu .action-icon + span {
  display: block;
  margin: 0;
}
.app-shell .ticket-detail-grid { grid-template-columns: minmax(0, 1fr) 360px; gap: 22px; padding: 22px clamp(18px, 2vw, 32px) 30px; }
.app-shell .request-title-line h2 { font-size: 21px; }
.app-shell .request-header p { font-size: 11.5px; }
.app-shell .original-request > p:last-child, .app-shell .original-request-body { font-size: 13.5px; }
.app-shell .reply-tabs button { font-size: 11.5px; }
.app-shell .reply-box textarea { font-size: 13px; }
.app-shell .reply-box > div:last-child > span { font-size: 10.5px; }
.app-shell .message > p { font-size: 13px; }
.app-shell .message-head b { font-size: 12px; }
.app-shell .message-head span:not(.avatar), .app-shell .message-type { font-size: 10px; }
.app-shell .side-panel-head h2 { font-size: 14.5px; }
.app-shell .side-panel-head span { font-size: 9.5px; }
.app-shell .drawer-fields label { font-size: 11.5px; }
.app-shell .drawer-fields select { height: 42px; font-size: 12.5px; }
.app-shell .customer-summary b { font-size: 13px; }
.app-shell .customer-summary span, .app-shell .customer-summary a { font-size: 11px; }
.property-actions { padding: 14px 17px 17px; border-top: 1px solid var(--border); display: grid; gap: 10px; }
.property-actions > span { color: var(--muted); font-size: 10.5px; }
.property-actions .primary-button { width: 100%; }
.threecx-responsibilities-card { margin-top: 18px; }

/* ---- Agent extensions (Settings -> Calling) --------------------------------------------------- */

.agent-extension-card { margin-top: 18px; }
.agent-extension-list { padding: 0 18px 18px; display: grid; gap: 10px; }

.agent-extension-summary { margin: 0 0 4px; color: var(--muted); font-size: 12.5px; line-height: 1.5; }

.agent-extension-row {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  background: var(--surface);
}

/* Recedes rather than alarms. An unmapped user is a normal state -- somebody who does not take
   calls -- and not an error to be cleared. */
.agent-extension-row.unmapped { background: var(--surface-sunken); }

.agent-extension-identity { min-width: 0; display: grid; gap: 3px; }
.agent-extension-identity b { font-size: 13.5px; }
.agent-extension-identity small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: 12px;
}

.agent-extension-field { min-width: 0; display: grid; gap: 5px; }
.agent-extension-input {
  width: 100%;
  height: 40px;
  padding: 0 11px;
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  outline: 0;
  color: var(--grey);
  background: var(--surface);
  font-size: 14px;
}
.agent-extension-input:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255, 117, 26, .1); }
.agent-extension-input::placeholder { color: var(--text-faintest); font-style: italic; }

.agent-extension-source { color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.agent-extension-actions { display: flex; gap: 6px; }
.agent-extension-actions button { font-size: 12px; }

.agent-extension-empty, .agent-extension-error { margin: 0; color: var(--muted); font-size: 13px; }
.agent-extension-error { color: var(--coral-hover); }

@media (max-width: 860px) {
  .agent-extension-row { grid-template-columns: 1fr; gap: 10px; }
  .agent-extension-actions button { width: 100%; }
}

@media (max-width: 900px) {
  .app-shell .main-content { width: 100%; margin-left: 0; }
  .app-shell .topbar { height: 70px; }
  .app-shell .view { min-height: calc(100dvh - 70px); }
  .app-shell .ticket-detail-view { padding: 0; }
  .app-shell .ticket-detail-grid { grid-template-columns: 1fr; }
  .app-shell .ticket-side-column { position: static; grid-template-columns: 1fr 1fr; }
  .app-shell .ticket-title-copy { max-width: min(42vw, 420px); }
}

@media (max-width: 650px) {
  .app-shell .view { padding: 24px 14px 30px; }
  .app-shell .ticket-detail-view { padding: 0; }
  .app-shell .ticket-detail-bar { min-height: auto; padding: 12px; }
  .app-shell .ticket-breadcrumb { width: 100%; align-items: flex-start; flex-wrap: wrap; }
  .app-shell .ticket-title-copy { min-width: 0; max-width: calc(100% - 52px); flex: 1; }
  .app-shell .ticket-detail-actions { width: 100%; padding-left: 48px; overflow: visible; }
  .app-shell .ticket-detail-actions .drawer-actions-menu { top: 46px; right: 0; }
  .app-shell .ticket-side-column { grid-template-columns: 1fr; }
  .app-shell .ticket-detail-grid { padding: 14px; }
}

/* Spam quarantine and blocked-sender administration. */
.spam-modal { width: min(560px, 100%); }
.spam-reason-field { display: block; margin: 18px 0 8px; color: var(--text-soft); font-size: 11.5px; font-weight: 700; }
.spam-reason-field > span { color: var(--muted); font-weight: 500; }
.spam-reason-field input { width: 100%; height: 44px; margin-top: 7px; padding: 0 12px; border: 1px solid var(--border-dark); border-radius: 10px; background: var(--surface); }
.spam-block-option { margin-top: 14px; padding: 15px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-sunken); }
.blocked-sender-card { overflow: hidden; }
.blocked-sender-head { padding: 20px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.blocked-sender-head h3 { margin: 0 0 4px; }
.blocked-sender-head p { margin: 0; color: var(--muted); font-size: 12px; }
.blocked-sender-list { display: grid; }
.blocked-sender-row { min-height: 72px; padding: 13px 20px; border-bottom: 1px solid var(--hairline); display: grid; grid-template-columns: minmax(0, 1fr) 100px auto; align-items: center; gap: 18px; }
.blocked-sender-row:last-child { border-bottom: 0; }
.blocked-sender-row > div:first-child b, .blocked-sender-row > div:first-child span { display: block; }
.blocked-sender-row > div:first-child b { font-size: 13.5px; }
.blocked-sender-row > div:first-child span { margin-top: 4px; color: var(--muted); font-size: 11px; }
.blocked-sender-activity { text-align: right; }
.blocked-sender-activity b, .blocked-sender-activity span { display: block; }
.blocked-sender-activity b { font-size: 15px; }
.blocked-sender-activity span { color: var(--muted); font-size: 9.5px; }
.empty-state.compact { min-height: 210px; padding: 30px 20px; }
.domain-warning { margin: 4px 0 0; padding: 12px 14px; border: 1px solid var(--coral-wash-border); border-radius: 10px; color: var(--coral-ink); background: var(--coral-wash); font-size: 12px; line-height: 1.5; }
.ticket-row[data-spam="true"] { background: var(--coral-wash); }
.status-pill.spam { color: var(--coral-ink); background: var(--coral-pale); }

@media (max-width: 650px) {
  .blocked-sender-head { align-items: flex-start; flex-direction: column; }
  .blocked-sender-row { grid-template-columns: minmax(0, 1fr) auto; }
  .blocked-sender-activity { display: none; }
}

/* ---- Reports dashboard ----------------------------------------------------------------------
   The full scorecard is still present, but it is progressive disclosure now: useful answers are
   visible first and the wide accounting table opens only when somebody needs exact history. */
.kpi-scorecard { display: grid; gap: 22px; }
.kpi-team-dashboard,
.kpi-trend-panel,
.kpi-agent-section,
.kpi-detail-disclosure {
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: 0 2px 10px rgba(0,0,0,.04);
}
.kpi-team-dashboard,
.kpi-trend-panel,
.kpi-agent-section { padding: 22px; }
.kpi-dashboard-heading { margin-bottom: 18px; display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
.kpi-dashboard-heading > div > span { display: block; margin-bottom: 5px; color: var(--link); font-size: 10px; font-weight: 800; letter-spacing: .1em; }
.kpi-dashboard-heading h2 { margin: 0; font-size: 20px; }
.kpi-dashboard-heading p { margin: 6px 0 0; color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.kpi-dashboard-heading > b { padding: 7px 10px; border-radius: 999px; color: var(--text-soft); background: var(--surface-muted); font-size: 11px; white-space: nowrap; }
.kpi-dashboard-heading.compact { margin-bottom: 14px; }
.kpi-card-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 13px; }
.kpi-metric-card { min-width: 0; padding: 16px; border: 1px solid var(--border); border-radius: 12px; position: relative; overflow: hidden; background: var(--surface-sunken); }
.kpi-metric-card::before { content: ''; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--neutral-mark); }
.kpi-metric-card.on-target::before { background: var(--green); }
.kpi-metric-card.warning::before { background: var(--orange); }
.kpi-metric-card.off-target::before { background: var(--coral); }
.kpi-metric-card-head { min-height: 34px; display: flex; justify-content: space-between; gap: 10px; color: var(--text-soft); font-size: 12px; font-weight: 700; line-height: 1.4; }
.kpi-metric-card-head i { width: 8px; height: 8px; margin-top: 4px; border-radius: 50%; flex: none; background: var(--neutral-mark); }
.kpi-metric-card.on-target .kpi-metric-card-head i { background: var(--green); }
.kpi-metric-card.warning .kpi-metric-card-head i { background: var(--orange); }
.kpi-metric-card.off-target .kpi-metric-card-head i { background: var(--coral); }
.kpi-metric-card > strong { display: block; margin-top: 5px; font-size: clamp(24px, 1.5vw, 32px); line-height: 1; font-variant-numeric: tabular-nums; }
.kpi-metric-card > p { margin: 8px 0 14px; color: var(--muted); font-size: 11px; }
.kpi-mini-trend { height: 20px; display: grid; grid-template-columns: repeat(12, 1fr); align-items: end; gap: 3px; }
.kpi-mini-trend .kpi-trend-dot { min-width: 0; height: 8px; border-radius: 3px; background: var(--neutral-mark); }
.kpi-mini-trend .kpi-trend-dot.on-target { height: 16px; background: var(--green); }
.kpi-mini-trend .kpi-trend-dot.warning { height: 12px; background: var(--orange); }
.kpi-mini-trend .kpi-trend-dot.off-target { height: 16px; background: var(--coral); }
.kpi-mini-trend .kpi-trend-dot.empty { height: 4px; opacity: .4; }
.kpi-mini-trend small,
.kpi-mini-trend b { display: none; }
.kpi-trend-list { overflow: hidden; border: 1px solid var(--border); border-radius: 11px; }
.kpi-trend-row { min-height: 64px; padding: 10px 14px; border-bottom: 1px solid var(--hairline); display: grid; grid-template-columns: minmax(170px, 1.1fr) minmax(600px, 4fr) 70px; align-items: center; gap: 14px; }
.kpi-trend-row:last-child { border-bottom: 0; }
.kpi-trend-row > div:first-child b,
.kpi-trend-row > div:first-child span { display: block; }
.kpi-trend-row > div:first-child b { font-size: 12.5px; }
.kpi-trend-row > div:first-child span { margin-top: 4px; color: var(--muted); font-size: 10.5px; }

/* The months are named once here instead of on every cell below. Same grid as the rows beneath
   it, so a column heading sits over its own column rather than near it. */
.kpi-trend-head { min-height: 0; padding-top: 12px; padding-bottom: 8px; background: var(--surface-muted); }
.kpi-trend-head > div:first-child b,
.kpi-trend-head > div:first-child span,
.kpi-trend-head > strong,
.kpi-trend-head .kpi-trend-months > span { color: var(--muted); font-size: 9.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.kpi-trend-head > div:first-child span { margin-top: 2px; }
.kpi-trend-head .kpi-trend-months > span { text-align: center; }
.kpi-trend-head .kpi-trend-quarter { color: var(--link); }

/* Three months then the quarter that closes them, four times over. Written out rather than with
   a repeat() inside a repeat(), which is not valid and silently drops the whole declaration --
   leaving the row as one column with sixteen cells stacked down the page. */
.kpi-trend-months {
  display: grid;
  grid-template-columns:
    minmax(30px, 1fr) minmax(30px, 1fr) minmax(30px, 1fr) minmax(40px, 1.15fr)
    minmax(30px, 1fr) minmax(30px, 1fr) minmax(30px, 1fr) minmax(40px, 1.15fr)
    minmax(30px, 1fr) minmax(30px, 1fr) minmax(30px, 1fr) minmax(40px, 1.15fr)
    minmax(30px, 1fr) minmax(30px, 1fr) minmax(30px, 1fr) minmax(40px, 1.15fr);
  gap: 4px;
}
.kpi-trend-months .kpi-trend-dot { min-height: 39px; padding: 5px 3px; border-radius: 6px; display: grid; place-items: center; align-content: center; color: var(--text-soft); background: var(--surface-muted); text-align: center; }
.kpi-trend-months .kpi-trend-dot small { color: var(--muted); font-size: 8px; }
.kpi-trend-months .kpi-trend-dot b { font-size: 11.5px; font-variant-numeric: tabular-nums; }

/* The quarterly roll-up is a summary of the three cells to its left, so it carries the same
   colour against target but reads as a heavier column rather than a thirteenth month. */
.kpi-trend-months .kpi-trend-dot.kpi-trend-quarter { border: 1px solid var(--border-dark); background: var(--surface); }
.kpi-trend-months .kpi-trend-dot.kpi-trend-quarter b { font-weight: 800; }
.kpi-trend-months .kpi-trend-dot.kpi-trend-quarter.empty { border-style: dashed; }
.kpi-trend-months .kpi-trend-dot.on-target { color: var(--green-ink); background: var(--green-pale); }
.kpi-trend-months .kpi-trend-dot.warning { color: var(--orange-ink); background: var(--orange-pale); }
.kpi-trend-months .kpi-trend-dot.off-target { color: var(--coral-ink); background: var(--coral-pale); }
.kpi-trend-months .kpi-trend-dot.empty { opacity: .5; }
.kpi-trend-row > strong { text-align: right; font-size: 13px; font-variant-numeric: tabular-nums; }
.kpi-detail-disclosure { overflow: hidden; }
.kpi-detail-disclosure > summary,
.kpi-agent-card > summary { list-style: none; cursor: pointer; }
.kpi-detail-disclosure > summary::-webkit-details-marker,
.kpi-agent-card > summary::-webkit-details-marker { display: none; }
.kpi-detail-disclosure > summary { min-height: 76px; padding: 16px 20px; display: flex; align-items: center; justify-content: space-between; gap: 15px; }
.kpi-detail-disclosure > summary:hover { background: var(--surface-sunken); }
.kpi-detail-disclosure > summary span b,
.kpi-detail-disclosure > summary span small { display: block; }
.kpi-detail-disclosure > summary span b { font-size: 14px; }
.kpi-detail-disclosure > summary span small { margin-top: 4px; color: var(--muted); font-size: 11px; }
.kpi-detail-disclosure > summary em { color: var(--link); font-size: 11.5px; font-style: normal; font-weight: 700; }
.kpi-detail-disclosure[open] > summary { border-bottom: 1px solid var(--border); }
.kpi-agent-section { margin-top: 0; }
.kpi-agent-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.kpi-agent-card { min-width: 0; border: 1px solid var(--border); border-radius: 11px; background: var(--surface-sunken); overflow: hidden; }
.kpi-agent-card > summary { min-height: 74px; padding: 13px 15px; display: grid; grid-template-columns: 38px minmax(0, 1fr) auto; align-items: center; gap: 11px; }
.kpi-agent-card > summary:hover { background: var(--surface-muted); }
.kpi-agent-avatar { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; color: var(--orange-ink); background: var(--orange-pale); font-size: 11px; font-weight: 800; }
.kpi-agent-card > summary > span:nth-child(2) b,
.kpi-agent-card > summary > span:nth-child(2) small { display: block; }
.kpi-agent-card > summary > span:nth-child(2) b { font-size: 13px; }
.kpi-agent-card > summary > span:nth-child(2) small { margin-top: 4px; color: var(--muted); font-size: 10.5px; }
.kpi-agent-card > summary > em { color: var(--green-ink); font-size: 15px; font-style: normal; font-weight: 800; }
.kpi-agent-card[open] > summary { border-bottom: 1px solid var(--border); background: var(--surface-muted); }
.kpi-agent-highlights { padding: 14px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.kpi-agent-highlights > div { min-width: 0; padding: 10px; border-radius: 8px; background: var(--surface); }
.kpi-agent-highlights span,
.kpi-agent-highlights b,
.kpi-agent-highlights small { display: block; }
.kpi-agent-highlights span { min-height: 30px; color: var(--muted); font-size: 9.5px; line-height: 1.35; }
.kpi-agent-highlights b { margin-top: 5px; font-size: 17px; }
.kpi-agent-highlights small { margin-top: 4px; color: var(--text-faint); font-size: 8.5px; }

/* ---- Drilling into a figure ------------------------------------------------------------------
   Every number on the scorecard is now a control: the card's headline value opens its latest
   month, a month in the year-at-a-glance panel opens that month, and so does any cell in the full
   table. They keep the typography of the number they replaced -- a figure that suddenly looked
   like a button would read as something to press rather than something to understand -- and
   announce themselves on hover and focus instead. */
.kpi-metric-open,
.kpi-cell-open,
button.kpi-trend-dot {
  padding: 0;
  border: 0;
  color: inherit;
  background: none;
  font: inherit;
  cursor: pointer;
}

.kpi-metric-open { border-bottom: 2px solid transparent; }
.kpi-metric-open:hover,
.kpi-metric-open:focus-visible { border-bottom-color: currentColor; }

.kpi-cell-open { width: 100%; text-align: right; text-decoration: underline dotted transparent; text-underline-offset: 3px; }
.kpi-cell-open:hover,
.kpi-cell-open:focus-visible { text-decoration-color: currentColor; }

button.kpi-trend-dot { width: 100%; font: inherit; }
.kpi-trend-months button.kpi-trend-dot:hover,
.kpi-trend-months button.kpi-trend-dot:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }

/* The level picker. Toggles rather than a dropdown, so any combination is one click from any
   other and the current selection is readable without opening anything. */
/* ---- Escalation reasons and per-level targets, in Settings -------------------------------- */

.escalation-reason-list { display: grid; gap: 16px; margin: 4px 0 18px; }
.escalation-reason-group > b { display: block; margin-bottom: 7px; color: var(--muted); font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; }

/* The wording gets the full width of the card and the controls sit under it. This card lives in a
   narrow settings column, and a row that puts the label beside a select and two buttons leaves the
   label clipped halfway through -- which is unusable on the one screen whose job is editing it. */
.escalation-reason-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "identity identity"
    "meta     actions";
  gap: 9px 12px;
  align-items: end;
  padding: 11px 13px;
  margin-bottom: 7px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

/* A retired code recedes but stays legible: it is still the only thing that explains the
   escalations already counted against it. */
.escalation-reason-row.retired { opacity: .55; background: var(--zircon); }

.escalation-reason-identity { grid-area: identity; display: grid; gap: 6px; min-width: 0; }
.escalation-reason-identity code { font-size: 11px; font-weight: 700; color: var(--orange-ink); }
.escalation-reason-identity input { width: 100%; }
.escalation-reason-label { font-weight: 600; }
.escalation-reason-description { font-size: 12px; }
.escalation-reason-meta { grid-area: meta; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-width: 0; }
.escalation-reason-meta select { max-width: 190px; }
.escalation-reason-meta small { color: var(--muted); font-size: 10.5px; }
.escalation-reason-actions { grid-area: actions; display: flex; gap: 6px; }
.escalation-reason-retire { color: var(--coral-ink); }
.escalation-reason-add { padding-top: 16px; border-top: 1px solid var(--border); }
.escalation-reason-add > b { display: block; margin-bottom: 10px; font-size: 13px; }

.kpi-level-targets { display: grid; gap: 14px; margin-top: 4px; }
.kpi-level-target { padding: 14px; border: 1px solid var(--border); border-radius: 11px; background: var(--surface-sunken); }
.kpi-level-target > b { display: block; margin-bottom: 10px; font-size: 13px; }
.kpi-level-target-actions { display: flex; gap: 10px; align-items: center; margin-top: 4px; }
/* A placeholder here must never be mistaken for a value: an empty box means this level follows
   Level 1, and that is the whole point of the screen. */
.kpi-level-target input::placeholder { color: var(--text-faint); opacity: 1; }

@media (max-width: 860px) {
  .escalation-reason-row { grid-template-columns: 1fr; grid-template-areas: "identity" "meta" "actions"; }
}

.kpi-level-picker { display: inline-flex; padding: 2px; border: 1px solid var(--border-dark); border-radius: 9px; background: var(--surface); gap: 2px; }

.kpi-level-button {
  min-width: 42px;
  height: 30px;
  padding: 0 11px;
  border: 0;
  border-radius: 7px;
  color: var(--muted);
  background: none;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.kpi-level-button:hover { color: var(--grey); background: var(--surface-muted); }
.kpi-level-button[aria-pressed="true"] { color: var(--on-orange); background: var(--orange); }
.kpi-level-button[aria-pressed="true"]:hover { background: var(--orange-hover); }
.kpi-level-button:focus-visible { outline: 2px solid var(--orange); outline-offset: 1px; }

.kpi-drilldown-modal { width: min(880px, 100%); }
.kpi-drilldown-modal .modal-head > div > p:last-child { margin-bottom: 0; color: var(--text-soft); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.kpi-drilldown-body { margin-top: 18px; }
.kpi-drilldown-note { margin: 0 0 10px; color: var(--muted); font-size: 11.5px; }
.kpi-drilldown-scroll { max-height: min(60vh, 520px); overflow: auto; border: 1px solid var(--border); border-radius: 10px; }
.kpi-drilldown-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.kpi-drilldown-table thead th { position: sticky; top: 0; z-index: 1; padding: 9px 12px; text-align: left; color: var(--muted); background: var(--surface-muted); font-size: 10px; letter-spacing: .05em; text-transform: uppercase; }
.kpi-drilldown-table td, .kpi-drilldown-table tbody th { padding: 9px 12px; border-top: 1px solid var(--hairline); text-align: left; vertical-align: top; font-weight: 400; }
.kpi-drilldown-table tbody tr:hover { background: var(--surface-sunken); }
.kpi-drilldown-table tbody th a { font-weight: 600; color: var(--link); }
.kpi-drilldown-table tbody th small,
.kpi-drilldown-table tbody th em { display: block; max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kpi-drilldown-table tbody th small { margin-top: 3px; color: var(--text-soft); font-size: 11.5px; }
.kpi-drilldown-table tbody th em { margin-top: 2px; color: var(--text-faint); font-size: 10px; font-style: normal; }
.kpi-drilldown-value { text-align: right !important; font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.kpi-drilldown-unknown { color: var(--text-faint); }
.kpi-drilldown-flag { padding: 2px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 700; }
.kpi-drilldown-flag.yes { color: var(--coral-ink); background: var(--coral-pale); }
.kpi-drilldown-flag.good { color: var(--green-ink); background: var(--green-pale); }
.kpi-drilldown-flag.no { color: var(--text-soft); background: var(--surface-muted); }

@media (max-width: 720px) {
  .kpi-drilldown-table tbody th small,
  .kpi-drilldown-table tbody th em { max-width: 180px; }
}
.kpi-agent-table { margin: 0 14px 14px; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--surface); }
.kpi-agent-table > summary { padding: 11px 13px; cursor: pointer; color: var(--link); font-size: 11px; font-weight: 700; }
.kpi-agent-table[open] > summary { border-bottom: 1px solid var(--border); }

@media (max-width: 1100px) {
  .kpi-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi-trend-row { grid-template-columns: minmax(160px, .8fr) minmax(480px, 3fr) 60px; overflow-x: auto; }
  .kpi-agent-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 700px) {
  .kpi-team-dashboard, .kpi-trend-panel, .kpi-agent-section { padding: 15px; }
  .kpi-card-grid { grid-template-columns: minmax(0, 1fr); }
  .kpi-dashboard-heading { flex-direction: column; }
  .kpi-trend-list { overflow-x: auto; }
  .kpi-trend-row { min-width: 770px; }
  .kpi-agent-highlights { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Ticket rows are the primary working text, so they scale one step above surrounding chrome.
   The fluid ceiling matters on the wide displays used at the support desk, where a fixed 11px
   secondary line becomes visually tiny even though the layout has ample room. */
.app-shell .attention-item {
  min-height: 92px;
  padding: 17px 24px;
  gap: 16px;
}

/* The overview queue is a triage surface, not just a list of subjects. Keep the deadline visually
   dominant while putting the received time, customer, route and owner one glance away. */
.app-shell .attention-item {
  min-height: 66px;
  grid-template-columns: 6px minmax(280px, 1.65fr) minmax(190px, 1fr) minmax(165px, .85fr) minmax(145px, .75fr) minmax(195px, 1fr) 108px;
  gap: 0;
  padding: 6px 14px;
  transition: background-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.app-shell .ticket-table-head { font-size: 11.5px; }
.app-shell .ticket-row { min-height: 90px; padding-top: 15px; padding-bottom: 15px; }
.app-shell .ticket-subject b { font-size: clamp(15px, .16vw + 12px, 17px); line-height: 1.35; }
.app-shell .ticket-customer b { font-size: clamp(13px, .12vw + 10.5px, 14.5px); }
.app-shell .ticket-subject span,
.app-shell .ticket-customer span,
.app-shell .ticket-assignee span { font-size: clamp(12px, .1vw + 10px, 13px); line-height: 1.45; }
.app-shell .status-pill,
.app-shell .sla-pill { font-size: 11.5px; padding: 6px 10px; }

@media (max-width: 650px) {
  .app-shell .ticket-row { min-height: 82px; }
}

.ticket-checkbox-property {
  display: flex !important;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
}
.ticket-checkbox-property span { display: grid; gap: 4px; }
.ticket-checkbox-property b { color: var(--grey); font-size: 13px; }
.ticket-checkbox-property small { color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.ticket-checkbox-property input {
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--orange);
  flex: 0 0 auto;
}

.settings-fields textarea {
  width: 100%;
  min-height: 118px;
  margin-top: 7px;
  padding: 11px 12px;
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  outline: 0;
  color: var(--grey);
  background: var(--surface);
  font: inherit;
  font-size: 14px;
  line-height: 1.5;
  resize: vertical;
}
.settings-fields textarea:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.1); }
.settings-fields label > small { display: block; margin-top: 6px; color: var(--muted); font-size: 11.5px; font-weight: 500; }
.csat-timing-fields { margin-top: 18px; padding: 18px 0 0 !important; border-top: 1px solid var(--border); }
.csat-copy-columns { margin-top: 20px; }
.connection-callout.success { border-color: rgba(28,169,119,.35); background: var(--green-pale); }
.connection-callout.success > span { color: var(--green-ink); background: rgba(28,169,119,.14); }

/* A notification stays in the open popover long enough to be recognisable after hover, while
   its muted treatment and cleared badge make the read state immediate. */
.notification-item.read { opacity: .58; background: var(--surface-sunken); }
.notification-item.read b { font-weight: 600; }

/* Compact ticket workspace: one toolbar, then the subject and requester, then an integrated
   response composer. This keeps the hierarchy of the reference without copying its blue UI. */
.app-shell .ticket-detail-bar {
  min-height: 64px;
  padding-top: 9px;
  padding-bottom: 9px;
}
.app-shell .ticket-breadcrumb { flex: 1 1 auto; }
.app-shell .ticket-title-copy { min-width: 145px; max-width: 240px; }
.app-shell .ticket-title-copy span { margin: 0; font-size: 11.5px; }
.app-shell .ticket-title-copy h1 {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.app-shell .ticket-detail-actions .secondary-button,
.app-shell .ticket-detail-actions .more-button { min-height: 38px; height: 38px; }
.app-shell .ticket-detail-grid { padding-top: 0; gap: 16px; }
.app-shell .ticket-thread {
  border-top: 0;
  border-radius: 0 0 12px 12px;
}
.app-shell .request-header {
  padding: 20px 22px 9px;
  border-bottom: 0;
  align-items: center;
}
.app-shell .request-icon {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  color: var(--text-soft);
  background: var(--surface-muted);
}
.app-shell .request-title-line h2 { font-size: 21px; }
.app-shell .request-header p { margin-top: 7px; font-size: 12.5px; }
.app-shell .original-request {
  padding: 9px 22px 18px 65px;
  border-bottom: 0;
}
.app-shell .original-request .section-label { margin-bottom: 7px !important; }
.app-shell .reply-box {
  margin: 0 22px 18px;
  padding: 10px 12px 11px;
  border: 1px solid var(--border-dark);
  border-radius: 10px;
  background: var(--surface-sunken);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.app-shell .reply-box:focus-within {
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(255,117,26,.1);
}
.app-shell .reply-tabs { gap: 6px; margin-bottom: 5px; }
.app-shell .reply-tabs button {
  padding: 6px 10px;
  border: 0;
  border-radius: 7px;
  font-size: 12px;
}
.app-shell .reply-tabs button.active { color: var(--on-orange); border: 0; background: var(--orange); }
.app-shell .reply-box textarea {
  min-height: 76px;
  padding: 9px 2px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none !important;
  resize: vertical;
}
.app-shell .reply-box textarea.note-mode { background: transparent; border: 0; }
.app-shell .reply-box > div:last-child { margin-top: 4px; }
.app-shell .conversation-head { border-top: 1px solid var(--border); }

/* System activity is folded away by default, so the thread reads as the conversation it is. The
   toggle sits beside the message count and only appears when there is activity to reveal. */
.conversation-head > div { gap: 12px; }
.conversation-head-meta { display: flex; align-items: center; gap: 11px; flex: none; }
.conversation-activity-toggle {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--link);
  cursor: pointer;
  font-size: 9px;
  font-weight: 700;
  white-space: nowrap;
}
.conversation-activity-toggle:hover { text-decoration: underline; }
.app-shell .conversation-activity-toggle { font-size: 10px; }

@media (max-width: 650px) {
  .app-shell .ticket-detail-grid { padding-top: 0; }
  .app-shell .ticket-thread { border-radius: 0 0 10px 10px; }
  .app-shell .request-header { padding: 16px 15px 8px; }
  .app-shell .original-request { padding: 8px 15px 15px; }
  .app-shell .reply-box { margin: 0 14px 15px; }
}

/* ---- Workspace visual system ---------------------------------------------------------------
   A final, shared layer for the working application. It intentionally changes only presentation:
   the existing DOM, IDs, routes and event bindings remain the source of product behaviour. */
:root {
  --radius-sm: 9px;
  --radius-md: 13px;
  --radius-lg: 17px;
  --control-height: 44px;
  --panel-shadow: 0 1px 2px rgba(24, 27, 32, .035), 0 9px 28px rgba(24, 27, 32, .045);
  --floating-shadow: 0 18px 60px rgba(24, 27, 32, .16);
}
/* In the dark a panel's edge is its border and its lighter fill; the shadow only seats it on the
   page. Floating layers get a hairline ring first -- the edge that makes a menu read as above the
   panel it covers -- then a deep, soft fall-off. */
:root[data-theme="dark"] {
  --panel-shadow: 0 1px 2px rgba(0, 0, 0, .28);
  --floating-shadow: 0 0 0 1px rgba(210, 220, 240, .09), 0 4px 10px rgba(0, 0, 0, .32), 0 18px 48px rgba(0, 0, 0, .5);
}

html { font-size: 16px; }
body { line-height: 1.45; }
.app-shell .sidebar {
  width: 256px;
  padding: 25px 17px 17px;
  border-right: 1px solid rgba(255,255,255,.055);
}
.app-shell .main-content { width: calc(100% - 256px); margin-left: 256px; }
.app-shell .brand { margin-bottom: 30px; padding-inline: 12px; }
.app-shell .brand img { width: 138px; }
.app-shell .product-name { margin-top: 2px; font-size: 9.5px; letter-spacing: .32em; }
.app-shell .nav-label { margin-bottom: 9px; font-size: 10.5px; letter-spacing: .13em; }
.app-shell .nav-link {
  min-height: 46px;
  height: auto;
  padding: 0 13px;
  border-radius: 11px;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) max-content;
  column-gap: 12px;
  font-size: 14px;
  transition: color .16s ease, background .16s ease, box-shadow .16s ease;
}
.app-shell .nav-link + .nav-link { margin-top: 2px; }
.app-shell .nav-link:hover { background: rgba(255,255,255,.065); }
.app-shell .nav-link.active { background: linear-gradient(90deg, rgba(255,117,26,.20), rgba(255,117,26,.10)); box-shadow: inset 3px 0 0 var(--orange); }
.app-shell .nav-icon { width: 22px; height: 22px; font-size: 17px; justify-self: center; }
.app-shell .nav-link > span:nth-child(2) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-shell .nav-link b { min-width: 25px; margin-left: 0; padding: 3px 7px; box-sizing: border-box; justify-self: end; font-size: 10px; line-height: 1.35; }
.app-shell .nav-link.saved-view .view-dot { width: 7px; height: 7px; margin: 0; justify-self: center; }
.app-shell .integration-card { min-height: 58px; padding: 12px 13px; border-radius: 13px; }
.app-shell .integration-card b { font-size: 12px; }
.app-shell .integration-card span { font-size: 10px; }
.app-shell .user-card { min-height: 64px; }
.app-shell .user-card b { font-size: 12px; }
.app-shell .user-card span { font-size: 10px; }

.app-shell .topbar {
  height: 72px;
  padding: 0 clamp(20px, 2vw, 36px);
  border-color: var(--hairline);
  box-shadow: 0 1px 0 rgba(20,23,28,.025);
}
.app-shell .global-search { width: min(430px, 42vw); height: 44px; border-radius: 12px; }
.app-shell .global-search input { font-size: 14px; }
.app-shell .global-search kbd { padding: 3px 6px; border-radius: 6px; font-size: 9px; }
.app-shell .notification-button { width: 42px; height: 42px; border-radius: 11px; }
.app-shell .notification-button:hover { background: var(--surface-muted); }
.app-shell .primary-button,
.app-shell .secondary-button,
.app-shell .danger-button {
  min-height: var(--control-height);
  padding-inline: 17px;
  border-radius: 11px;
  font-size: 13px;
  font-weight: 750;
  transition: transform .14s ease, box-shadow .14s ease, background .14s ease, border-color .14s ease;
}
.app-shell .primary-button { box-shadow: 0 8px 18px rgba(var(--orange-rgb), .18); }
.app-shell .primary-button:hover { transform: translateY(-1px); box-shadow: 0 11px 24px rgba(var(--orange-rgb), .25); }
.app-shell .secondary-button:hover { transform: translateY(-1px); border-color: var(--border-hover); background: var(--surface-muted); }

.app-shell .view { min-height: calc(100dvh - 72px); padding: clamp(28px, 2.4vw, 42px) clamp(22px, 2.8vw, 48px) 42px; }
.app-shell .page-head { min-height: 72px; margin-bottom: 26px; align-items: center; }
.app-shell .page-head h1 { margin-bottom: 6px; font-size: clamp(31px, 2.15vw, 40px); line-height: 1.08; letter-spacing: -.045em; }
.app-shell .page-head > div > p:last-child { max-width: 700px; font-size: 14px; }
.app-shell .eyebrow { margin-bottom: 7px !important; font-size: 10.5px !important; letter-spacing: .11em; }
.app-shell .panel,
.app-shell .summary-card,
.app-shell .call-summary-card {
  border-radius: var(--radius-lg);
  border-color: var(--border);
  box-shadow: var(--panel-shadow);
}
.app-shell .panel { overflow: clip; }

.app-shell .summary-grid { margin-bottom: 20px; gap: 16px; }
.app-shell .summary-card { min-height: 138px; padding: 22px; gap: 17px; }
.app-shell .summary-card::after { width: 54px; height: 5px; border-radius: 0 0 0 10px; }
.app-shell .summary-icon { width: 46px; height: 46px; border-radius: 13px; font-size: 19px; }
.app-shell .summary-card p { margin-bottom: 4px; font-size: 13px; }
.app-shell .summary-card h2 { margin-bottom: 6px; font-size: 30px; }
.app-shell .summary-card span { font-size: 11px; }
.app-shell .panel-head { min-height: 84px; padding: 20px 24px; }
.app-shell .panel-head h2 { font-size: 19px; }
.app-shell .panel-head > div > span { font-size: 12px; }

.app-shell .ticket-toolbar,
.app-shell .contacts-toolbar,
.app-shell .calls-toolbar { min-height: 74px; padding-inline: 22px; }
.app-shell .ticket-tabs { height: 74px; gap: 25px; }
.app-shell .ticket-tab { font-size: 13px; }
.app-shell .ticket-tab span { font-size: 10px; }
.app-shell .queue-search { height: 40px; border-radius: 10px; }
.app-shell .queue-search input,
.app-shell .tool-button,
.app-shell .sort-select,
.app-shell .toolbar-toggle { font-size: 12px; }
.app-shell .tool-button,
.app-shell .sort-select { min-height: 40px; border-radius: 10px; }
.app-shell .ticket-table-head,
.app-shell .contact-table-head,
.app-shell .venue-table-head,
.app-shell .call-table-head { min-height: 44px; padding-inline: 22px; font-size: 10.5px; letter-spacing: .075em; }
.app-shell .ticket-row { min-height: 94px; padding-inline: 22px; }
.app-shell .ticket-row:hover,
.app-shell .contact-row:hover,
.app-shell .venue-row:hover,
.app-shell .call-row:hover { background: var(--surface-sunken); }
.app-shell .ticket-subject b { font-size: clamp(15.5px, .18vw + 12px, 17.5px); }
.app-shell .ticket-customer b { font-size: 14px; }
.app-shell .ticket-subject span,
.app-shell .ticket-customer span,
.app-shell .ticket-assignee span { font-size: 12.5px; }
.app-shell .status-pill,
.app-shell .sla-pill,
.app-shell .priority-chip { font-size: 11px; }
.app-shell .table-footer { min-height: 56px; padding-inline: 22px; font-size: 11px; }

.app-shell .contacts-toolbar h2,
.app-shell .calls-toolbar h2 { font-size: 17px; }
.app-shell .contacts-toolbar > div > span,
.app-shell .calls-toolbar > div:first-child span { font-size: 10.5px; }
.app-shell .contact-row,
.app-shell .venue-row,
.app-shell .call-row { min-height: 84px; padding-inline: 22px; }
.app-shell .venue-name b { font-size: 14px; }
.app-shell .venue-row > span { font-size: 12.5px; }
.app-shell .venue-source,
.app-shell .venue-flag { font-size: 10.5px; }
.app-shell .call-caller b,
.app-shell .call-contact b,
.app-shell .call-time b { font-size: 12.5px; }
.app-shell .call-caller span:not(.avatar),
.app-shell .call-contact span,
.app-shell .call-time span { font-size: 10.5px; }

.app-shell .settings-layout { grid-template-columns: 224px minmax(0, 1fr); gap: 26px; }
.app-shell .settings-rail { padding: 8px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); box-shadow: var(--panel-shadow); }
.app-shell .settings-rail-group { padding-inline: 9px; font-size: 10px; }
.app-shell .settings-rail button { min-height: 41px; padding: 9px 11px; border-radius: 9px; font-size: 13px; }
.app-shell .settings-rail button.active { box-shadow: inset 3px 0 0 var(--orange); }
.app-shell .settings-section-head { padding: 27px 29px 22px; }
.app-shell .settings-section-head h2 { font-size: 22px; }
.app-shell .settings-section-head p { font-size: 12.5px; }
.app-shell .settings-body { padding: 24px 28px; }
.app-shell .settings-card { border-radius: 13px; }
.app-shell .settings-card h3 { font-size: 15px; }
.app-shell .settings-card > p { font-size: 12px; }
.app-shell .settings-fields label,
.app-shell .field-label { font-size: 11.5px; }
.app-shell .settings-fields input,
.app-shell .settings-fields select,
.app-shell .settings-fields textarea { font-size: 13.5px; border-radius: 10px; }
.app-shell .settings-fields input,
.app-shell .settings-fields select { height: 44px; }

.app-shell .popover { border-radius: 15px; box-shadow: var(--floating-shadow); }
.app-shell .popover-head { height: 55px; padding-inline: 18px; }
.app-shell .popover-head b { font-size: 13px; }
.app-shell .modal { padding: 28px; border: 1px solid var(--border); border-radius: 19px; box-shadow: var(--floating-shadow); }
.app-shell .modal-head h2 { font-size: 24px; }
.app-shell .modal-head > div > p:last-child { font-size: 12.5px; }
.app-shell .modal form > label,
.app-shell .form-grid label { font-size: 11.5px; }
.app-shell .modal input,
.app-shell .modal select { height: 44px; }
.app-shell .modal input,
.app-shell .modal select,
.app-shell .modal textarea { border-radius: 10px; font-size: 13.5px; }
.app-shell .empty-state h3,
.app-shell .embedded-empty h3 { font-size: 17px; }
.app-shell .empty-state p,
.app-shell .embedded-empty p { font-size: 12.5px; }

.app-shell .ticket-detail-bar { min-height: 72px; padding: 11px clamp(18px, 2.3vw, 38px); background: var(--surface); }
.app-shell .ticket-title-copy span { font-size: 12px; }
.app-shell .ticket-detail-actions .secondary-button,
.app-shell .ticket-detail-actions .more-button { min-height: 40px; height: 40px; font-size: 12.5px; }
.app-shell .ticket-detail-grid { grid-template-columns: minmax(0, 1fr) minmax(330px, 380px); gap: 20px; padding: 0 clamp(18px, 2.3vw, 38px) 38px; }
.app-shell .ticket-thread { border-radius: 0 0 15px 15px; box-shadow: var(--panel-shadow); }
.app-shell .request-header { padding: 25px 26px 11px; }
.app-shell .request-title-line h2 { font-size: 24px; }
.app-shell .request-header p { font-size: 13px; }
.app-shell .original-request { padding: 11px 26px 22px 72px; }
.app-shell .original-request > p:last-child,
.app-shell .original-request-body { font-size: 14.5px; line-height: 1.65; }
.app-shell .reply-box { margin: 0 26px 22px; padding: 12px 14px; border-radius: 12px; }
.app-shell .reply-tabs button { font-size: 12.5px; }
.app-shell .reply-box textarea { min-height: 92px; font-size: 14px; line-height: 1.55; }
.app-shell .message { padding-inline: 26px; }
.app-shell .message > p { font-size: 14px; line-height: 1.65; }
.app-shell .message-head b { font-size: 13px; }
.app-shell .ticket-side-column { gap: 16px; }
.app-shell .side-panel-head { min-height: 60px; padding-inline: 19px; }
.app-shell .side-panel-head h2 { font-size: 15px; }
.app-shell .drawer-fields { padding: 18px 19px 20px; gap: 14px; }
.app-shell .drawer-fields label { font-size: 11.5px; }
.app-shell .drawer-fields select { height: 44px; border-radius: 10px; font-size: 13px; }
.app-shell .customer-summary { padding: 20px; }
.app-shell .customer-summary b { font-size: 14px; }
.app-shell .customer-summary span,
.app-shell .customer-summary a { font-size: 11.5px; }

@media (max-width: 1180px) {
  .app-shell .summary-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .app-shell .toolbar-actions { flex-wrap: wrap; justify-content: flex-end; }
  .app-shell .ticket-toolbar { align-items: flex-start; padding-block: 10px; }
  .app-shell .ticket-tabs { height: 54px; }
}

@media (max-width: 900px) {
  .app-shell .main-content { width: 100%; margin-left: 0; }
  .app-shell .topbar { height: 68px; }
  .app-shell .view { min-height: calc(100dvh - 68px); }
  .app-shell .settings-rail { padding: 6px; border-radius: 12px; }
  .app-shell .ticket-side-column { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

@media (max-width: 650px) {
  html { font-size: 15px; }
  .app-shell .view { padding: 24px 15px 30px; }
  .app-shell .page-head { margin-bottom: 20px; align-items: flex-start; }
  .app-shell .page-head h1 { font-size: 29px; }
  .app-shell .summary-grid { grid-template-columns: 1fr; gap: 11px; }
  .app-shell .summary-card { min-height: 108px; padding: 17px; }
  .app-shell .ticket-toolbar { padding-inline: 14px; }
  .app-shell .ticket-tabs { width: 100%; gap: 18px; padding-inline: 8px; overflow-x: auto; }
  .app-shell .ticket-row,
  .app-shell .contact-row,
  .app-shell .call-row { padding-inline: 15px; }
  .app-shell .ticket-detail-view { padding: 0; }
  .app-shell .ticket-detail-bar { padding: 12px 14px; }
  .app-shell .ticket-detail-grid { padding: 0 14px 24px; }
  .app-shell .request-header { padding: 19px 16px 9px; }
  .app-shell .original-request { padding: 9px 16px 17px; }
  .app-shell .reply-box { margin: 0 15px 17px; }
  .app-shell .ticket-side-column { grid-template-columns: 1fr; }
  .app-shell .modal { padding: 22px 18px; border-radius: 16px; }
}

/* ---- Fluid viewport adaptation --------------------------------------------------------------
   Width breakpoints are based on the room the application actually needs, rather than on a
   phone/desktop binary. This keeps a 1024px laptop, a portrait tablet and a 4K workstation on the
   same visual system without relying on browser zoom or JavaScript measurements. */
/* clip, not hidden: hidden on one axis makes the other a scroll container, so
   the page became a scrollport that never scrolls and anything sticky below it
   -- the composer's send row -- had nothing to stick to. clip does the same job
   for the sideways scroll without that side effect. */
html, body { max-width: 100%; overflow-x: clip; }
.app-shell, .app-shell .main-content, .app-shell .view, .app-shell .panel { min-width: 0; max-width: 100%; }
.app-shell img, .app-shell video, .app-shell iframe { max-width: 100%; }

@media (max-width: 1600px) and (min-width: 1101px) {
  .app-shell .sidebar { width: 224px; padding-inline: 14px; }
  .app-shell .main-content { width: calc(100% - 224px); margin-left: 224px; }
  .app-shell .brand { margin-bottom: 23px; }
  .app-shell .brand img { width: 126px; }
  .app-shell .nav-link { min-height: 42px; font-size: 13px; }
  .app-shell .view { padding: clamp(24px, 2vw, 34px) clamp(18px, 2.15vw, 34px) 34px; }
  .app-shell .summary-card { min-height: 118px; padding: 18px; }
  .app-shell .summary-icon { width: 40px; height: 40px; }
  .app-shell .panel-head { min-height: 74px; padding: 17px 20px; }
  .app-shell .ticket-detail-grid { grid-template-columns: minmax(0, 1fr) minmax(300px, 340px); gap: 16px; }
  .app-shell .settings-layout { grid-template-columns: 200px minmax(0, 1fr); gap: 18px; }
}

/* At this width the permanent rail costs more space than it saves. Use the existing accessible
   slide-out navigation and give every workspace the full viewport instead. */
@media (max-width: 1100px) {
  .app-shell .sidebar {
    visibility: hidden;
    width: min(280px, 86vw);
    transform: translateX(-103%);
    transition: transform .22s ease, visibility .22s;
    box-shadow: 18px 0 55px rgba(26,29,33,.24);
  }
  .app-shell .sidebar.open { visibility: visible; transform: translateX(0); }
  .app-shell .main-content { width: 100%; margin-left: 0; }
  .app-shell .menu-button { display: grid; margin-right: 8px; }
  .app-shell .scrim { position: fixed; inset: 0; z-index: 29; background: var(--backdrop); backdrop-filter: blur(2px); }
  .app-shell .topbar { padding-inline: clamp(14px, 2.5vw, 24px); }
  .app-shell .view { padding-inline: clamp(15px, 2.6vw, 28px); }
  .app-shell .summary-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .app-shell .ticket-detail-grid { grid-template-columns: minmax(0, 1fr); }
  .app-shell .ticket-side-column { position: static; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .app-shell .settings-columns { grid-template-columns: minmax(0, 1fr); }
  .app-shell .channel-columns { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 760px) {
  .app-shell .topbar { height: 64px; gap: 8px; }
  .app-shell .global-search { min-width: 0; width: auto; flex: 1; }
  .app-shell .global-search kbd { display: none; }
  .app-shell .top-actions { gap: 5px; }
  .app-shell .top-actions .primary-button { width: 42px; padding: 0; font-size: 0; }
  .app-shell .top-actions .primary-button span { font-size: 17px; }
  .app-shell .view { min-height: calc(100dvh - 64px); padding: 21px 13px 26px; }
  .app-shell .page-head { min-height: 0; margin-bottom: 18px; align-items: flex-start; }
  .app-shell .page-head h1 { font-size: clamp(27px, 7vw, 32px); }
  .app-shell .overview-head .secondary-button { display: none; }
  .app-shell .summary-grid { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .app-shell .summary-card { min-height: 98px; padding: 15px; }
  .app-shell .ticket-toolbar,
  .app-shell .contacts-toolbar,
  .app-shell .calls-toolbar { padding: 12px 13px; align-items: flex-start; flex-direction: column; }
  .app-shell .ticket-tabs { width: 100%; height: 48px; gap: 18px; padding-inline: 8px; overflow-x: auto; }
  .app-shell .toolbar-actions,
  .app-shell .calls-toolbar-actions { width: 100%; flex-wrap: wrap; }
  .app-shell .queue-search,
  .app-shell .contact-search,
  .app-shell .call-search { width: 100%; flex-basis: 100%; }
  .app-shell .filter-panel { align-items: stretch; flex-direction: column; }
  .app-shell .filter-panel label,
  .app-shell .filter-panel select { width: 100%; }
  .app-shell .ticket-table-head,
  .app-shell .contact-table-head,
  .app-shell .call-table-head { display: none; }
  .app-shell .ticket-row { min-height: 84px; padding: 12px 13px; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
  .app-shell .ticket-row > .ticket-customer { grid-column: 1; grid-row: 2; padding-left: 10px; }
  .app-shell .ticket-row > .status-pill { grid-column: 2; grid-row: 1; }
  .app-shell .ticket-row > .sla-pill { grid-column: 2; grid-row: 2; justify-self: end; }
  .app-shell .ticket-row > .ticket-assignee,
  .app-shell .ticket-customer span { display: none; }
  .app-shell .contact-row { padding: 13px; grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .app-shell .contact-row > .contact-cell { display: block !important; }
  .app-shell .contact-actions { justify-content: flex-start; flex-wrap: wrap; }
  .app-shell .call-row { padding: 13px; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; }
  .app-shell .call-row > .call-caller { grid-column: 1; grid-row: 1; }
  .app-shell .call-row > .call-state-pill { grid-column: 2; grid-row: 1; }
  .app-shell .call-row > .call-time { grid-column: 1; grid-row: 2; padding-left: 46px; }
  .app-shell .call-row > .call-row-actions { grid-column: 1 / -1; grid-row: 3; justify-content: flex-start; }
  .app-shell .call-row > .call-contact,
  .app-shell .call-row > .call-ticket { display: none; }
  .app-shell .ticket-detail-bar { min-height: auto; padding: 11px 12px; }
  .app-shell .ticket-breadcrumb { width: 100%; align-items: flex-start; flex-wrap: wrap; }
  .app-shell .ticket-title-copy { min-width: 0; max-width: calc(100% - 52px); flex: 1; }
  .app-shell .ticket-detail-actions { width: 100%; padding-left: 48px; overflow-x: auto; scrollbar-width: thin; }
  .app-shell .ticket-detail-actions > button { flex: none; }
  .app-shell .ticket-detail-grid { padding: 0 12px 22px; }
  .app-shell .ticket-side-column { grid-template-columns: minmax(0, 1fr); }
  .app-shell .settings-layout { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .app-shell .settings-rail { position: static; display: flex; overflow-x: auto; gap: 4px; scrollbar-width: thin; }
  .app-shell .settings-rail-group { display: none; }
  .app-shell .settings-rail button { width: auto; flex: none; white-space: nowrap; }
  .app-shell .settings-body { padding: 16px; }
  .app-shell .settings-section-head { padding: 20px 18px 16px; }
  .app-shell .channel-health { grid-template-columns: minmax(0, 1fr); }
  .app-shell .form-grid,
  .app-shell .form-grid-three,
  .app-shell .email-field-grid,
  .app-shell .sla-grid { grid-template-columns: minmax(0, 1fr); }
  .app-shell .popover { right: 10px; width: min(335px, calc(100vw - 20px)); }
  .app-shell .incoming-call-popup { top: 72px; right: 10px; width: calc(100vw - 20px); max-height: calc(100dvh - 82px); }
}

/* Short laptop screens need less vertical chrome even when their width is ample. */
@media (max-height: 800px) and (min-width: 761px) {
  .app-shell .topbar { height: 64px; }
  .app-shell .view { min-height: calc(100dvh - 64px); padding-top: 22px; padding-bottom: 26px; }
  .app-shell .page-head { min-height: 58px; margin-bottom: 17px; }
  .app-shell .summary-card { min-height: 98px; padding-block: 14px; }
  .app-shell .summary-icon { width: 38px; height: 38px; }
  .app-shell .panel-head { min-height: 66px; padding-block: 13px; }
  .app-shell .ticket-toolbar,
  .app-shell .contacts-toolbar,
  .app-shell .calls-toolbar { min-height: 64px; }
  .app-shell .ticket-tabs { height: 62px; }
  .app-shell .ticket-row { min-height: 76px; }
  .app-shell .contact-row,
  .app-shell .call-row { min-height: 72px; }
}

/* A monitor's diagonal size does not describe the space available to the page: Windows display
   scaling and the browser chrome can turn a 27-inch display into a viewport only ~900px high.
   Compact the permanent navigation by available height so it retains the same composition as a
   taller screen instead of making the middle of the rail independently scroll. */
@media (max-height: 1050px) and (min-width: 1101px) {
  .app-shell .sidebar { padding-top: clamp(12px, 1.8vh, 18px); padding-bottom: 10px; }
  .app-shell .brand {
    padding-top: 0;
    margin-bottom: clamp(12px, 2vh, 20px);
    gap: 1px;
  }
  .app-shell .brand img { width: clamp(108px, 12vh, 124px); }
  .app-shell .product-name { font-size: 8px; }
  .app-shell .main-nav { overflow-y: hidden; }
  .app-shell .nav-label { margin-bottom: clamp(3px, .7vh, 6px); font-size: 9px; }
  .app-shell .nav-space { margin-top: clamp(9px, 1.6vh, 17px); }
  .app-shell .nav-link {
    height: clamp(34px, 4.1vh, 40px);
    min-height: 34px;
    font-size: 12px;
  }
  .app-shell .nav-icon { font-size: 16px; }
  .app-shell .integration-card {
    min-height: 52px;
    margin-block: clamp(6px, 1.1vh, 11px);
    padding: 9px 10px;
  }
  .app-shell .integration-icon { width: 28px; height: 28px; }
  .app-shell .user-card { min-height: 48px; padding-top: 8px; }
}

/* On especially short desktop windows keep every sidebar destination present, but remove the
   decorative product caption and reduce non-essential gaps one final step. */
@media (max-height: 820px) and (min-width: 1101px) {
  .app-shell .sidebar { padding-top: 9px; }
  .app-shell .brand { margin-bottom: 8px; }
  .app-shell .brand img { width: 102px; }
  .app-shell .product-name { display: none; }
  .app-shell .nav-space { margin-top: 6px; }
  .app-shell .nav-link { height: 32px; min-height: 32px; }
  .app-shell .integration-card { min-height: 45px; margin-block: 5px; padding-block: 7px; }
  .app-shell .user-card { min-height: 43px; padding-top: 5px; }
}

/* ---- Compact, edge-to-edge ticket queue ----------------------------------------------------
   The queue is the tickets workspace, rather than a card inside it. Keep the page heading aligned
   with the rest of the application, then let the working surface use every remaining pixel. */
.app-shell #ticketsView {
  padding-right: 0;
  padding-bottom: 0;
  padding-left: 0;
}
.app-shell #ticketsView .ticket-page-head { margin-inline: clamp(22px, 2.8vw, 48px); }
.app-shell #ticketsView .ticket-workspace {
  border-right: 0;
  border-bottom: 0;
  border-left: 0;
  border-radius: 0;
  box-shadow: none;
}

/* The selection column belongs to ticket rows only. It is checkbox-width: the "Select all" wording
   was a column heading for a control that already reads as one, and it cost the subject ~40px on
   every row. The checkbox keeps its accessible name, and is centred on the compact row hit area. */
.app-shell .ticket-select-heading { display: block; }
.app-shell .ticket-table-head,
.app-shell .ticket-row {
  grid-template-columns: 40px minmax(190px, 1fr) 40px minmax(262px, 2.4fr) repeat(4, minmax(124px, .55fr));
  gap: 14px;
}
.app-shell .ticket-select-all {
  display: grid;
  place-items: center;
  justify-content: center;
  gap: 0;
}
.app-shell .ticket-select {
  align-self: stretch;
  display: grid;
  place-items: center;
  margin: 0;
}
.app-shell .ticket-row { min-height: 52px; padding-block: 5px; }
.app-shell .ticket-subject b { font-size: 14px; }
.app-shell .ticket-customer b { font-size: 12.5px; }
.app-shell .ticket-subject span,
.app-shell .ticket-customer span,
.app-shell .ticket-assignee span { font-size: 10.5px; }
.app-shell .ticket-received {
  overflow: hidden;
  color: var(--text-soft);
  font-size: 10.5px;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell .status-pill,
.app-shell .sla-pill { font-size: 10px; }

/*
 * Hovering a navigation item must not change the rail's scroll geometry.
 *
 * The rail itself is no longer in this: the sidebar is 72px wide when no context panel is open,
 * and clipping it hid every menu that opens beside it -- the user card's menu is 230px, so
 * clicking it showed a 3px sliver and nothing else. The scrolling that rule was protecting lives
 * on .rail-nav and on .nav-panel .main-nav, each of which clips its own content.
 */
.app-shell .main-nav { overflow-x: hidden; }

@media (max-width: 1600px) and (min-width: 1101px) {
  .app-shell #ticketsView .ticket-page-head { margin-inline: clamp(18px, 2.15vw, 34px); }
}

@media (max-width: 1400px) and (min-width: 761px) {
  .app-shell .ticket-table-head,
  .app-shell .ticket-row {
    grid-template-columns: 38px minmax(155px, 1.1fr) 38px minmax(232px, 1.8fr) repeat(3, minmax(100px, .75fr));
    gap: 11px;
  }
  .app-shell .ticket-table-head .column-sort[data-sort-key="assignee"],
  .app-shell .ticket-row > .ticket-assignee { display: none; }
}

@media (max-width: 1100px) {
  .app-shell #ticketsView .ticket-page-head { margin-inline: clamp(15px, 2.6vw, 28px); }
}

@media (max-width: 760px) {
  .app-shell #ticketsView { padding-top: 21px; }
  .app-shell #ticketsView .ticket-page-head { margin-inline: 13px; }
  .app-shell #ticketsView .ticket-row {
    min-height: 86px;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    gap: 5px 9px;
  }
  .app-shell #ticketsView .ticket-row > .ticket-select { grid-column: 1; grid-row: 1 / span 3; }
  .app-shell #ticketsView .ticket-row > .ticket-customer { grid-column: 2; grid-row: 1; }
  .app-shell #ticketsView .ticket-row > .ticket-subject { grid-column: 2; grid-row: 2; }
  .app-shell #ticketsView .ticket-row > .ticket-received { grid-column: 2; grid-row: 3; }
  .app-shell #ticketsView .ticket-row > .ticket-flags { grid-column: 2; grid-row: 4; }
  .app-shell #ticketsView .ticket-row > .ticket-flags:empty { display: none; }
  .app-shell #ticketsView .ticket-row > .status-pill { grid-column: 3; grid-row: 1; }
  .app-shell #ticketsView .ticket-row > .sla-pill { grid-column: 3; grid-row: 2 / span 2; align-self: center; }
}

/* ---- Maximum-density ticket workspaces -------------------------------------------------------
   Tickets are the primary working surface. The page title should identify it without consuming
   a row's worth of viewport, and an opened ticket should meet the real workspace edges rather
   than sitting inside a second padded canvas. */
.app-shell #ticketsView {
  padding: 8px 0 0;
}
.app-shell #ticketsView .ticket-page-head {
  min-height: 44px;
  margin: 0 clamp(16px, 1.6vw, 26px) 8px;
  align-items: center;
}
.app-shell #ticketsView .ticket-page-head .eyebrow {
  margin-bottom: 2px !important;
  font-size: 8px !important;
}
.app-shell #ticketsView .ticket-page-head h1 {
  margin-bottom: 1px;
  font-size: clamp(24px, 1.55vw, 29px);
  line-height: 1;
}
.app-shell #ticketsView .ticket-page-head > div > p:last-child {
  font-size: 11px;
  line-height: 1.3;
}
/* The tab strip is one row and wants an exact height. The toolbar around it is not: it wraps its
   actions onto a second line under 1180px and stacks them under the tabs under 900px, and it needs
   68-140px to do that. Holding it to `height: 58px` did not stop it wrapping -- it just let the
   wrapped controls render outside the box, where the table head and the first rows painted over
   them, so from ~1100px down the queue had no reachable search, filter, sort or toggles at all. */
.app-shell #ticketsView .ticket-tabs {
  min-height: 58px;
  height: 58px;
}
.app-shell #ticketsView .ticket-toolbar {
  min-height: 58px;
  height: auto;
}

.app-shell #ticketView {
  width: 100%;
  padding: 0;
}
.app-shell #ticketView .ticket-detail-bar {
  width: 100%;
  min-height: 58px;
  padding: 8px 14px;
}
.app-shell #ticketView .ticket-detail-grid {
  width: 100%;
  min-height: calc(100dvh - 130px);
  padding: 0;
  gap: 0;
  grid-template-columns: minmax(0, 1fr) minmax(330px, 370px);
  align-items: stretch;
}
.app-shell #ticketView .ticket-thread {
  min-height: 100%;
  border: 0;
  border-right: 1px solid var(--border);
  border-radius: 0;
  box-shadow: none;
}
.app-shell #ticketView .ticket-side-column {
  gap: 0;
  position: static;
  background: var(--surface);
}
.app-shell #ticketView .ticket-side-column > .panel {
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  box-shadow: none;
}

@media (max-width: 1100px) {
  .app-shell #ticketView .ticket-detail-grid { grid-template-columns: minmax(0, 1fr); }
  .app-shell #ticketView .ticket-thread { border-right: 0; border-bottom: 1px solid var(--border); }
  .app-shell #ticketView .ticket-side-column { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .app-shell #ticketView .ticket-side-column > .panel + .panel { border-left: 1px solid var(--border); }
}

@media (max-width: 760px) {
  .app-shell #ticketsView { padding-top: 7px; }
  .app-shell #ticketsView .ticket-page-head { min-height: 40px; margin-inline: 12px; }
  .app-shell #ticketsView .ticket-page-head > div > p:last-child { display: none; }
  .app-shell #ticketView .ticket-side-column { grid-template-columns: minmax(0, 1fr); }
  .app-shell #ticketView .ticket-side-column > .panel + .panel { border-left: 0; }
}

/* Split reply action: the primary half sends immediately; the chevron exposes the familiar
   "send and set as" workflow without making the properties sidebar a second required stop. */
.app-shell .reply-send-actions {
  position: relative;
  display: inline-flex;
  align-items: stretch;
  flex: none;
}
.app-shell .reply-send-actions .primary-button {
  min-height: 38px;
  border-radius: 0;
  box-shadow: none;
}
.app-shell .reply-send-main {
  padding-inline: 15px 13px;
  border-radius: 8px 0 0 8px !important;
}
.app-shell .reply-send-toggle {
  width: 34px;
  padding: 0;
  border-left-color: rgba(255, 255, 255, .42);
  border-radius: 0 8px 8px 0 !important;
  display: grid;
  place-items: center;
}
.app-shell .reply-send-toggle::before {
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  content: "";
  transform: translateY(-2px) rotate(45deg);
}
.app-shell .reply-status-menu {
  position: absolute;
  z-index: 12;
  right: 0;
  top: calc(100% + 6px);
  width: 220px;
  max-height: 280px;
  padding: 8px;
  overflow-y: auto;
  border: 1px solid var(--border-dark);
  border-radius: 9px;
  color: var(--text);
  background: var(--surface);
  box-shadow: var(--floating-shadow);
}
.app-shell .reply-status-menu b {
  display: block;
  padding: 7px 9px 9px;
  font-size: 11px;
  text-transform: uppercase;
}
.app-shell .reply-status-menu button {
  width: 100%;
  padding: 9px;
  border: 0;
  border-radius: 5px;
  color: inherit;
  background: transparent;
  text-align: left;
  cursor: pointer;
  font-size: 12px;
}
.app-shell .reply-status-menu button:hover,
.app-shell .reply-status-menu button:focus-visible {
  outline: 0;
  background: var(--surface-muted);
}

/* Reply files stay visible before sending: paste, picker and drag/drop share the same compact
   preview, and a removal button is always reachable without opening a second dialog. */
.app-shell .reply-attachment-tools {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 31px;
  padding-top: 3px;
}
.app-shell .reply-attachment-tools.disabled { opacity: .62; }
.app-shell .reply-attachment-tools > span {
  color: var(--muted);
  font-size: 10px;
}
.app-shell .reply-attach-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px;
  border: 1px solid var(--border-dark);
  border-radius: 7px;
  color: var(--text-soft);
  background: var(--surface);
  cursor: pointer;
  font-size: 11px;
  font-weight: 700;
}
.app-shell .reply-attach-button:hover:not(:disabled),
.app-shell .reply-attach-button:focus-visible { border-color: var(--orange); color: var(--link); }
.app-shell .reply-attach-button:disabled { cursor: not-allowed; }
.app-shell .reply-attachment-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 5px;
}
.app-shell .reply-attachment-list:empty { display: none; }
.app-shell .reply-attachment-preview {
  position: relative;
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) 24px;
  align-items: center;
  width: min(230px, 100%);
  min-width: 0;
  margin: 0;
  padding: 5px;
  gap: 7px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
}
.app-shell .reply-attachment-preview img {
  width: 46px;
  height: 38px;
  border-radius: 5px;
  object-fit: cover;
  background: var(--surface-muted);
}
.app-shell .reply-attachment-preview .reply-file-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 38px;
  border-radius: 5px;
  color: var(--orange-ink);
  background: var(--orange-wash);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.app-shell .reply-attachment-preview figcaption { min-width: 0; }
.app-shell .reply-attachment-preview figcaption b,
.app-shell .reply-attachment-preview figcaption span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell .reply-attachment-preview figcaption b { font-size: 10px; }
.app-shell .reply-attachment-preview figcaption span { color: var(--muted); font-size: 9px; }
.app-shell .reply-attachment-remove {
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: var(--muted);
  background: transparent;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
}
.app-shell .reply-attachment-remove:hover,
.app-shell .reply-attachment-remove:focus-visible { color: var(--coral-ink); background: var(--coral-pale); }

.app-shell #replyForm.file-drag-active {
  border-color: var(--orange);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--orange) 22%, transparent);
}
.app-shell #replyForm.file-drag-active .reply-editor { position: relative; }
.app-shell #replyForm.file-drag-active .reply-editor::after {
  content: 'Drop files to attach';
  position: absolute;
  inset: 8px;
  display: grid;
  place-items: center;
  border: 1px dashed var(--orange);
  border-radius: 8px;
  color: var(--orange-ink);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  font-size: 12px;
  font-weight: 800;
  pointer-events: none;
}

.app-shell .message-image-attachment-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  max-width: min(320px, 100%);
}
.app-shell .message-image-attachment {
  display: block;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 9px;
  color: var(--text-soft);
  background: var(--surface-muted);
  text-decoration: none;
}
.app-shell .message-image-attachment img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 220px;
  object-fit: contain;
}
.app-shell .message-image-attachment span {
  display: block;
  padding: 6px 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 700;
}

@media (max-width: 560px) {
  .app-shell .reply-attachment-tools { align-items: flex-start; flex-direction: column; gap: 4px; }
}

/* Recent CSAT feedback lives with operational reporting. The table stays compact enough to scan,
   while an administrator's in-place editor expands only the response being corrected. */
.app-shell .sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.app-shell .csat-results-panel {
  margin-top: 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--panel-shadow);
}
.app-shell .csat-results-head {
  padding: 18px 20px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 18px;
  border-bottom: 1px solid var(--border);
}
.app-shell .csat-results-head > div:last-child { display: flex; gap: 8px; }
.app-shell .csat-results-head span {
  color: var(--link);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .12em;
}
.app-shell .csat-results-head h2 { margin: 4px 0 2px; font-size: 20px; }
.app-shell .csat-results-head p { color: var(--muted); font-size: 11px; }
.app-shell .csat-results-summary {
  min-height: 45px;
  padding: 10px 20px;
  display: flex;
  align-items: center;
  gap: 18px;
  border-bottom: 1px solid var(--border);
  color: var(--text-soft);
  font-size: 11px;
}
.app-shell .csat-results-summary b { color: var(--text); }
.app-shell .csat-results-summary strong { color: var(--link); font-size: 17px; }
.app-shell .csat-results-summary em { margin-left: auto; color: var(--muted); font-style: normal; }
.app-shell .csat-results-table-wrap { overflow-x: auto; }
.app-shell .csat-results-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}
.app-shell .csat-results-table th {
  padding: 10px 12px;
  color: var(--muted);
  background: var(--surface-muted);
  text-align: left;
  font-size: 9px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.app-shell .csat-results-table th:nth-child(1) { width: 130px; }
.app-shell .csat-results-table th:nth-child(2) { width: 160px; }
.app-shell .csat-results-table th:nth-child(3) { width: 190px; }
.app-shell .csat-results-table th:nth-child(4) { width: 150px; }
.app-shell .csat-results-table th:nth-child(6) { width: 155px; }
.app-shell .csat-results-table th:nth-child(7) { width: 90px; }
.app-shell .csat-results-table td {
  padding: 12px;
  border-top: 1px solid var(--border);
  vertical-align: top;
  font-size: 11px;
  line-height: 1.45;
}
.app-shell .csat-results-table tbody tr:first-child td { border-top: 0; }
.app-shell .csat-results-table td > small,
.app-shell .csat-results-table td > b + small {
  margin-top: 3px;
  display: block;
  overflow: hidden;
  color: var(--muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell .csat-results-table td > a { color: var(--link); font-weight: 800; }
.app-shell .csat-score { color: var(--amber-ink); letter-spacing: 1px; white-space: nowrap; }
.app-shell .csat-score small { margin-left: 6px; color: var(--muted); letter-spacing: 0; }
.app-shell .csat-comment { overflow-wrap: anywhere; white-space: pre-line; }
.app-shell .csat-comment em { color: var(--muted); }
.app-shell .csat-results-empty { padding: 30px !important; color: var(--muted); text-align: center; }
.app-shell .csat-score-edit,
.app-shell .csat-comment textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid var(--border-dark);
  border-radius: 7px;
  color: var(--text);
  background: var(--surface);
  font: inherit;
}
.app-shell .csat-comment textarea { resize: vertical; }
.app-shell .csat-edit-actions { display: flex; flex-direction: column; align-items: stretch; gap: 6px; }

@media (max-width: 760px) {
  .app-shell .csat-results-head { align-items: stretch; flex-direction: column; }
  .app-shell .csat-results-head > div:last-child { width: 100%; }
  .app-shell .csat-results-head .sort-select { flex: 1; }
  .app-shell .csat-results-summary { align-items: flex-start; flex-direction: column; gap: 4px; }
  .app-shell .csat-results-summary em { margin-left: 0; }
  .app-shell .csat-results-table { min-width: 900px; }
}

/* ---- Ticket list: the subject truncates, its tags do not ---------------------------------------
 * The row heading used to be one nowrap/ellipsis line holding the subject text and the Merged /
 * Reopened tags together, so a long subject consumed the width and the tag it was supposed to be
 * labelled with was clipped away -- the reason .reopened-tag needed !important to hold even its
 * font size. The heading is a flex row now: the subject is the only part allowed to shrink and
 * ellipsise, and every tag after it keeps its intrinsic width at the end of the line. */

.app-shell .ticket-subject b {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  white-space: normal;
  overflow: visible;
}
.app-shell .ticket-subject b > .ticket-subject-title {
  min-width: 0;
  flex: 0 1 auto;
  display: flex;
  align-items: baseline;
  gap: 7px;
  overflow: hidden;
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
  white-space: nowrap;
}
.app-shell .ticket-subject-title > .ticket-subject-id {
  flex: 0 0 auto;
  color: var(--link);
  font-size: inherit;
  font-weight: 800;
  letter-spacing: .005em;
}
.app-shell .ticket-subject-title > .ticket-subject-text {
  min-width: 0;
  flex: 0 1 auto;
  display: block;
  overflow: hidden;
  color: var(--text);
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: inherit;
  font-weight: inherit;
}
.app-shell .ticket-subject b > .merged-tag,
.app-shell .ticket-subject b > .reopened-tag,
.app-shell .ticket-subject b > .ticket-row-presence {
  margin-left: 0;
  flex: 0 0 auto;
  display: inline-grid;
  align-items: center;
  justify-items: center;
  line-height: 1;
  white-space: nowrap;
}
.app-shell .ticket-subject b > .merged-tag,
.app-shell .ticket-subject b > .reopened-tag {
  padding: 3px 7px;
  font-size: 8.5px;
}

/* Narrow rows drop the tag row below the subject rather than squeezing the subject to nothing. */
@media (max-width: 760px) {
  .app-shell .ticket-subject b { flex-wrap: wrap; row-gap: 4px; }
  .app-shell .ticket-subject b > .ticket-subject-title { flex-basis: 100%; }
}

/* ---- "Customer responded" sits under the subject, not across it -------------------------------
 * The tag is a state, not part of the title, and on the title line its fixed width was taken out
 * of the subject: every responded ticket read "Fw: Busine..." beside a badge. It now shares the
 * reference line (id / category / channel), which is short enough to give the width away, and the
 * subject gets the whole line back. Same flex contract as the heading: the text shrinks and
 * ellipsises, the tag keeps its intrinsic width. */
.app-shell .ticket-subject-meta {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  overflow: visible;
  white-space: normal;
}
.app-shell .ticket-subject-meta > .ticket-subject-meta-text {
  min-width: 0;
  flex: 0 1 auto;
  display: block;
  overflow: hidden;
  color: inherit;
  font-size: inherit;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell .ticket-subject-meta > .customer-responded-tag {
  margin-left: 0;
  flex: 0 0 auto;
  padding: 2px 7px;
  font-size: 8.5px;
  line-height: 1;
}

/* The thread header shows "Reopened" in place of the status word. It is the longest label the
 * pill ever carries, and the pill sits in a flex row beside a truncating subject, so pin it
 * rather than letting the subject squeeze it into a wrap. */
.app-shell .request-title-line .status-pill {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* ---- Reply composer: formatting bar and editor -------------------------------------------------
 * The composer is a contenteditable so a public reply can leave as a formatted HTML email. It
 * inherits the textarea's old size and typography deliberately -- the box the agent types in has
 * not moved, it has only gained a toolbar above it and the ability to hold formatting.
 *
 * The toolbar sits with the composer rather than beside Send: it acts on the text, and putting it
 * next to the send actions read as though the buttons did something to the sending. It wraps on a
 * narrow thread pane instead of scrolling sideways, so nothing is reachable only by dragging. */

.app-shell .reply-format-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
  margin-bottom: 6px;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--border);
}
.app-shell .reply-format-group {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-right: 6px;
  border-right: 1px solid var(--border);
}
.app-shell .reply-format-group:last-child { padding-right: 0; border-right: 0; }
.app-shell .reply-attach-group { margin-left: auto; }
.app-shell .reply-canned-control { position: relative; }
.app-shell .reply-canned-button {
  width: auto;
  padding-inline: 8px;
  gap: 5px;
  white-space: nowrap;
}
.app-shell .reply-canned-button > span:first-child { color: var(--link); font-size: 13px; }
.app-shell .reply-canned-button[aria-expanded="true"] {
  border-color: var(--orange-wash-border);
  color: var(--link);
  background: var(--orange-wash);
}
.app-shell .reply-canned-menu {
  position: absolute;
  z-index: 90;
  top: calc(100% + 7px);
  right: -40px;
  width: min(390px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--border-dark);
  border-radius: 12px;
  overflow: hidden;
  color: var(--text);
  background: var(--surface);
  box-shadow: 0 18px 46px rgba(0, 0, 0, .4);
}
.app-shell .reply-canned-menu[hidden] { display: none; }
.app-shell .reply-canned-menu-head {
  padding: 12px 13px 9px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  border-bottom: 1px solid var(--hairline);
}
.app-shell .reply-canned-menu-head > div { display: grid; gap: 2px; }
.app-shell .reply-canned-menu-head b { font-size: 12px; }
.app-shell .reply-canned-menu-head span { color: var(--muted); font-size: 9.5px; }
.app-shell .reply-canned-menu-head button {
  width: 25px;
  height: 25px;
  border: 0;
  border-radius: 6px;
  color: var(--muted);
  background: transparent;
  cursor: pointer;
  font-size: 17px;
}
.app-shell .reply-canned-menu-head button:hover { color: var(--text); background: var(--surface-muted); }
.app-shell .reply-canned-search {
  height: 37px;
  margin: 10px;
  padding: 0 10px;
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  background: var(--surface-sunken);
}
.app-shell .reply-canned-search:focus-within { border-color: var(--orange); box-shadow: 0 0 0 3px var(--orange-wash); }
.app-shell .reply-canned-search input {
  min-width: 0;
  flex: 1;
  border: 0;
  outline: 0;
  color: var(--text);
  background: transparent;
  font: inherit;
  font-size: 11px;
}
.app-shell .reply-canned-list { max-height: min(320px, 43vh); padding: 0 6px 7px; overflow-y: auto; }
.app-shell .reply-canned-option {
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: 8px;
  display: grid;
  gap: 4px;
  color: var(--text);
  background: transparent;
  cursor: pointer;
  text-align: left;
}
.app-shell .reply-canned-option:hover,
.app-shell .reply-canned-option:focus-visible { outline: 0; background: var(--orange-wash); }
.app-shell .reply-canned-option > span { min-width: 0; display: flex; align-items: center; gap: 8px; }
.app-shell .reply-canned-option b { overflow: hidden; font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.app-shell .reply-canned-option code {
  padding: 2px 5px;
  border-radius: 5px;
  color: var(--link);
  background: var(--orange-wash);
  font-size: 8.5px;
}
.app-shell .reply-canned-option small {
  overflow: hidden;
  color: var(--muted);
  font-size: 9.5px;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell .reply-canned-empty { padding: 26px 18px; color: var(--muted); font-size: 10.5px; text-align: center; }
.app-shell .reply-canned-manage {
  width: 100%;
  min-height: 37px;
  padding: 0 13px;
  border: 0;
  border-top: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: var(--text-soft);
  background: var(--surface-muted);
  cursor: pointer;
  font: inherit;
  font-size: 9.5px;
  font-weight: 700;
}
.app-shell .reply-canned-manage:hover { color: var(--link); }
.app-shell .reply-format-bar .reply-attach-button {
  width: 29px;
  min-width: 29px;
  padding: 0;
  border-color: transparent;
  border-radius: 6px;
  font-size: 14px;
}

.app-shell .reply-format-button {
  min-width: 28px;
  height: 27px;
  padding: 0 6px;
  border: 1px solid transparent;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-soft);
  background: transparent;
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
}
.app-shell .reply-format-button:hover:not(:disabled),
.app-shell .reply-format-button:focus-visible {
  border-color: var(--border-dark);
  color: var(--link);
  background: var(--surface);
}
.app-shell .reply-format-button.active {
  border-color: var(--orange);
  color: var(--link);
  background: var(--orange-wash);
}
.app-shell .reply-format-button:disabled { opacity: .45; cursor: not-allowed; }
.app-shell .reply-format-button sub { font-size: 8px; }

.app-shell .reply-format-select select {
  height: 27px;
  max-width: 110px;
  padding: 0 4px;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-soft);
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  font-weight: 700;
}
.app-shell .reply-format-select select:hover,
.app-shell .reply-format-select select:focus-visible {
  border-color: var(--border-dark);
  background: var(--surface);
}

/* The compact toolbar buttons open an Office-style palette instead of the operating system's raw
   colour field. A familiar set of theme shades makes the common choice one click; the native
   picker remains behind More colours for anything outside that set. */
.app-shell .reply-colour-control { position: relative; }
.app-shell .reply-format-colour {
  position: relative;
  width: 28px;
  height: 27px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: transparent;
}
.app-shell .reply-format-colour:hover,
.app-shell .reply-format-colour[aria-expanded="true"] { border-color: var(--border-dark); background: var(--surface); }
.app-shell .reply-format-colour > span {
  color: var(--text-soft);
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  transform: translateY(-2px);
}
.app-shell .reply-format-colour::before {
  content: "";
  position: absolute;
  left: 5px;
  right: 7px;
  bottom: 3px;
  height: 3px;
  border-radius: 2px;
  background: var(--reply-colour, #2b2b2b);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .18);
}
.app-shell .reply-format-colour::after {
  content: "";
  position: absolute;
  right: 2px;
  bottom: 4px;
  border: 3px solid transparent;
  border-top-color: var(--text-faint);
}
.app-shell .reply-format-colour.highlight > span {
  border-radius: 2px;
  padding: 0 2px;
  color: #2b2b2b;
  background: var(--reply-colour, #ffe680);
}
.app-shell .reply-colour-menu {
  position: absolute;
  z-index: 80;
  top: calc(100% + 6px);
  left: 0;
  width: 252px;
  padding: 9px;
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  color: var(--text);
  background: var(--surface);
  box-shadow: 0 16px 38px rgba(0, 0, 0, .38);
}
.app-shell .reply-colour-control.highlight .reply-colour-menu { left: auto; right: 0; }
.app-shell .reply-colour-menu[hidden] { display: none; }
.app-shell .reply-colour-automatic,
.app-shell .reply-colour-more {
  width: 100%;
  min-height: 28px;
  padding: 4px 5px;
  border: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
  background: transparent;
  font: inherit;
  font-size: 11px;
  font-weight: 650;
  text-align: left;
  cursor: pointer;
}
.app-shell .reply-colour-automatic:hover,
.app-shell .reply-colour-more:hover,
.app-shell .reply-colour-automatic:focus-visible,
.app-shell .reply-colour-more:focus-visible { background: var(--surface-muted); outline: 0; }
.app-shell .reply-colour-automatic i {
  width: 15px;
  height: 15px;
  border: 1px solid var(--border-dark);
  background: var(--automatic-colour, #2b2b2b);
}
.app-shell .reply-colour-automatic.no-colour i {
  background: linear-gradient(135deg, transparent 45%, var(--coral-ink) 46%, var(--coral-ink) 54%, transparent 55%);
}
.app-shell .reply-colour-section {
  margin-top: 5px;
  padding-top: 7px;
  border-top: 1px solid var(--border);
}
.app-shell .reply-colour-section > b {
  display: block;
  margin-bottom: 6px;
  color: var(--text-soft);
  font-size: 10px;
  font-weight: 750;
}
.app-shell .reply-theme-colours {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 3px;
}
.app-shell .reply-theme-colour-column { display: grid; gap: 2px; }
.app-shell .reply-standard-colours {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 3px;
}
.app-shell .reply-colour-swatch {
  width: 100%;
  aspect-ratio: 1;
  min-width: 0;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 1px;
  background: var(--swatch);
  cursor: pointer;
}
.app-shell .reply-colour-swatch:hover,
.app-shell .reply-colour-swatch:focus-visible {
  position: relative;
  z-index: 1;
  outline: 2px solid var(--orange);
  outline-offset: 1px;
}
.app-shell .reply-colour-swatch.selected { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--orange); }
.app-shell .reply-colour-more {
  margin-top: 7px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}
.app-shell .reply-colour-more > span { color: var(--link); font-size: 14px; }
.app-shell .reply-custom-colour-panel {
  margin: 2px -9px -9px;
  padding: 10px 11px 11px;
  border-top: 1px solid var(--border-dark);
  border-radius: 0 0 8px 8px;
  background: var(--surface-sunken);
}
.app-shell .reply-custom-colour-panel[hidden] { display: none; }
.app-shell .reply-custom-colour-head {
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.app-shell .reply-custom-colour-head b { font-size: 10px; }
.app-shell .reply-custom-colour-head code { color: var(--text-muted); font-size: 9px; }
.app-shell .reply-custom-colour-field {
  position: relative;
  height: 86px;
  border: 1px solid var(--border-dark);
  border-radius: 5px;
  overflow: hidden;
  cursor: crosshair;
  touch-action: none;
  background:
    linear-gradient(to top, #000, transparent),
    linear-gradient(to right, #fff, transparent),
    var(--custom-hue, #f00);
}
.app-shell .reply-custom-colour-field:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.app-shell .reply-custom-colour-cursor {
  position: absolute;
  left: var(--custom-x, 100%);
  top: var(--custom-y, 0%);
  width: 11px;
  height: 11px;
  border: 2px solid #fff;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 0 1px #000, 0 1px 4px rgba(0, 0, 0, .65);
  pointer-events: none;
}
.app-shell .reply-custom-hue {
  width: 100%;
  height: 17px;
  margin: 7px 0 6px;
  appearance: none;
  border: 1px solid var(--border-dark);
  border-radius: 4px;
  background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
  cursor: pointer;
}
.app-shell .reply-custom-hue::-webkit-slider-thumb {
  width: 8px;
  height: 21px;
  appearance: none;
  border: 2px solid #fff;
  border-radius: 3px;
  background: transparent;
  box-shadow: 0 0 0 1px #111;
}
.app-shell .reply-custom-hue::-moz-range-thumb {
  width: 7px;
  height: 19px;
  border: 2px solid #fff;
  border-radius: 3px;
  background: transparent;
  box-shadow: 0 0 0 1px #111;
}
.app-shell .reply-custom-colour-values {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, .72fr);
  gap: 5px;
}
.app-shell .reply-custom-colour-values label {
  min-width: 0;
  color: var(--text-muted);
  font-size: 8px;
  font-weight: 700;
  text-align: center;
}
.app-shell .reply-custom-colour-values input {
  width: 100%;
  height: 28px;
  margin-top: 3px;
  padding: 0 4px;
  border: 1px solid var(--border-dark);
  border-radius: 4px;
  color: var(--text);
  background: var(--surface);
  font: inherit;
  font-size: 10px;
  text-align: center;
}
.app-shell .reply-custom-colour-actions {
  margin-top: 9px;
  display: flex;
  justify-content: flex-end;
  gap: 6px;
}
.app-shell .reply-custom-colour-actions button {
  min-height: 27px;
  padding: 0 9px;
  border: 1px solid var(--border-dark);
  border-radius: 5px;
  color: var(--text-soft);
  background: var(--surface);
  font: inherit;
  font-size: 9px;
  font-weight: 700;
  cursor: pointer;
}
.app-shell .reply-custom-colour-actions button:last-child { color: var(--on-orange); border-color: var(--orange); background: var(--orange); }
.app-shell .reply-custom-colour-actions button:hover { filter: brightness(1.08); }
@media (max-width: 520px) {
  .app-shell .reply-colour-menu { position: fixed; top: auto; right: 12px; bottom: 12px; left: 12px; width: auto; }
}

.app-shell .reply-editor {
  min-height: 76px;
  max-height: 46vh;
  padding: 9px 2px;
  overflow-y: auto;
  outline: 0;
  color: var(--text);
  font-size: 13px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}
.app-shell .reply-editor.is-empty::before {
  content: attr(data-placeholder);
  color: var(--muted);
  pointer-events: none;
}
.app-shell .reply-editor > *:first-child { margin-top: 0; }
.app-shell .reply-editor > *:last-child { margin-bottom: 0; }
.app-shell .reply-editor p { margin: 0 0 8px; }
.app-shell .reply-editor h2 { margin: 0 0 8px; font-size: 17px; }
.app-shell .reply-editor h3 { margin: 0 0 8px; font-size: 15px; }
.app-shell .reply-editor ul,
.app-shell .reply-editor ol { margin: 0 0 8px; padding-left: 22px; }
.app-shell .reply-editor li { margin-bottom: 3px; }
.app-shell .reply-editor blockquote {
  margin: 0 0 8px;
  padding-left: 11px;
  border-left: 3px solid var(--border-dark);
  color: var(--text-soft);
}
.app-shell .reply-editor pre {
  margin: 0 0 8px;
  padding: 9px 11px;
  border-radius: 7px;
  overflow-x: auto;
  background: var(--surface-muted);
  font-family: ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;
  font-size: 12px;
  white-space: pre-wrap;
}
.app-shell .reply-editor a { color: var(--link); }
.app-shell .reply-editor img { max-width: 100%; }

@media (min-width: 1600px) {
  .app-shell .reply-editor { min-height: 92px; font-size: 14px; }
}
@media (max-width: 650px) {
  .app-shell .reply-format-group { padding-right: 4px; }
  .app-shell .reply-format-select select { max-width: 82px; }
  .app-shell .reply-canned-menu { position: fixed; top: auto; right: 12px; bottom: 12px; left: 12px; width: auto; }
}

/* Internal notes keep the same editor and the same toolbar -- a note renders as formatted markup
   in the ticket too -- with a mark down the side so the mode is legible without reading the tabs. */
.app-shell .reply-editor.note-mode {
  padding-left: 10px;
  border-left: 3px solid var(--orange-wash-border);
}

/* A reopened ticket is still "open" to workflow rules, but visually deserves its own state. */
.app-shell .status-pill.reopened,
.app-shell .attention-badge.status-reopened {
  color: var(--blue-ink);
  background: var(--blue-wash);
  box-shadow: inset 0 0 0 1px var(--blue-wash-border);
}
.app-shell .message-recipients { margin:-2px 0 10px 36px;padding:7px 10px;border-radius:7px;display:flex;gap:8px;color:var(--text-muted);background:var(--surface-sunken);font-size:9.5px;line-height:1.45;overflow-wrap:anywhere; }
.app-shell .message-recipients b { flex:none;color:var(--text-soft);font-size:8.5px;letter-spacing:.06em; }
.app-shell .support-level-dialog select,
.app-shell .support-level-dialog input[type="text"] { width:100%;min-height:42px;margin:6px 0 14px;padding:0 11px;border:1px solid var(--border-dark);border-radius:9px;color:var(--text);background:var(--surface);font:inherit;font-size:12px; }

/* Ticket queue controls: one compact visual family, with clear active and keyboard states. */
.app-shell #ticketsView .toolbar-actions {
  gap: 8px;
  padding: 5px;
  border: 1px solid var(--border);
  border-radius: 13px;
  background: color-mix(in srgb, var(--surface-muted) 62%, transparent);
}

.app-shell #ticketsView .queue-search,
.app-shell #ticketsView .tool-button,
.app-shell #ticketsView .sort-select,
.app-shell #ticketsView .toolbar-toggle {
  height: 38px;
  border: 1px solid var(--border-dark);
  border-radius: 9px;
  color: var(--text-soft);
  background-color: var(--surface);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
  transition: border-color .15s ease, background-color .15s ease, color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.app-shell #ticketsView .queue-search { width: 242px; padding: 0 12px; }
.app-shell #ticketsView .queue-search > span { color: var(--muted); font-size: 18px; }
.app-shell #ticketsView .queue-search:focus-within,
.app-shell #ticketsView .tool-button:focus-visible,
.app-shell #ticketsView .sort-select:focus-visible,
.app-shell #ticketsView .toolbar-toggle:focus-within {
  outline: 0;
  border-color: var(--orange);
  box-shadow: 0 0 0 3px var(--orange-wash);
}

/* The tabs sit in a flex row with `align-items: stretch`, so each one is a 58px-tall box holding
   a 13px word. The global focus ring -- 2px outline at +2px offset plus a 5px glow -- traced that
   whole box, which read as a stray rectangle floating around the label: taller than anything else
   in the strip, overhanging the toolbar edge above and cutting across the active underline below.
   Every other control in this toolbar already swapped the global ring for something that fits its
   own shape; the tab strip was the one that got missed. This rings the label instead of the box,
   and drops the glow. */
.app-shell #ticketsView .ticket-tab { position: relative; }
.app-shell #ticketsView .ticket-tab:focus-visible { outline: 0; box-shadow: none; }
/* A pseudo-element rather than a negative `outline-offset`: the tab is tall and narrow, so any
   inset large enough to clear the strip vertically would have cut straight through the label. */
.app-shell #ticketsView .ticket-tab:focus-visible::after {
  content: "";
  position: absolute;
  inset: 50% -7px auto;
  height: 30px;
  transform: translateY(-50%);
  border: 2px solid var(--orange-ink);
  border-radius: 9px;
  pointer-events: none;
}

.app-shell #ticketsView .tool-button { padding: 0 13px; }
.app-shell #ticketsView .tool-button:hover,
.app-shell #ticketsView .sort-select:hover,
.app-shell #ticketsView .toolbar-toggle:hover {
  border-color: var(--orange-wash-border);
  color: var(--text);
  background-color: var(--surface-sunken);
  transform: translateY(-1px);
}

.app-shell #ticketsView .sort-select { min-width: 150px; padding-left: 12px; font-weight: 600; }
.app-shell #ticketsView .sort-direction-select { min-width: 112px; }
.app-shell #ticketsView .toolbar-toggle { gap: 8px; padding: 0 12px; }
.app-shell #ticketsView .toolbar-toggle input {
  appearance: none;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1px solid var(--border-dark);
  border-radius: 4px;
  display: grid;
  place-items: center;
  background: var(--surface);
}
.app-shell #ticketsView .toolbar-toggle input::after {
  content: "";
  width: 7px;
  height: 4px;
  border: solid #fff;
  border-width: 0 0 2px 2px;
  opacity: 0;
  transform: translateY(-1px) rotate(-45deg);
}
.app-shell #ticketsView .toolbar-toggle input:checked { border-color: var(--orange); background: var(--orange); }
.app-shell #ticketsView .toolbar-toggle input:checked::after { opacity: 1; }
.app-shell #ticketsView .toolbar-toggle:has(input:checked) {
  border-color: var(--orange-wash-border);
  color: var(--orange-ink);
  background: var(--orange-pale);
  box-shadow: inset 0 0 0 1px var(--orange-wash-border);
}

@media (max-width: 1050px) {
  .app-shell #ticketsView .toolbar-actions { width: 100%; }
  .app-shell #ticketsView .queue-search { flex: 1; width: auto; }
}

/* ---- Polished dense ticket rows ---------------------------------------------------------------
   Keep the queue operationally dense, while giving the eye clear anchors and richer interaction. */
.app-shell #ticketsView .ticket-table-head {
  min-height: 38px;
  border-top-color: color-mix(in srgb, var(--border-dark) 68%, transparent);
  border-bottom-color: var(--border-dark);
  color: var(--text-faint);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--surface-head) 92%, var(--surface)) 0%,
    var(--surface-head) 100%);
  letter-spacing: .075em;
}

.app-shell #ticketsView .ticket-list {
  background: color-mix(in srgb, var(--surface) 96%, var(--surface-muted));
}

.app-shell #ticketsView .ticket-row {
  position: relative;
  min-height: 52px;
  border-bottom-color: color-mix(in srgb, var(--hairline) 82%, transparent);
  background: var(--surface);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 2.5%, transparent);
  transition: background-color .14s ease, box-shadow .14s ease, transform .14s ease;
}

.app-shell #ticketsView .ticket-row:nth-child(even) {
  background: color-mix(in srgb, var(--surface) 97%, var(--surface-muted));
}

.app-shell #ticketsView .ticket-row:hover {
  z-index: 1;
  background: color-mix(in srgb, var(--surface-sunken) 88%, var(--orange-wash));
  box-shadow: inset 3px 0 0 var(--orange), inset 0 1px 0 var(--border), 0 5px 16px rgba(0, 0, 0, .09);
}

.app-shell #ticketsView .ticket-row:focus-visible {
  z-index: 2;
  outline: 0;
  background: var(--surface-sunken);
  box-shadow: inset 3px 0 0 var(--orange), inset 0 0 0 2px var(--orange-wash-border);
}

/* One conversation at a time, loaded after a deliberate hover so the queue payload stays small. */
.ticket-hover-preview {
  position: fixed;
  z-index: 120;
  max-height: min(340px, calc(100dvh - 24px));
  border: 1px solid var(--border-dark);
  border-radius: 10px;
  overflow: hidden;
  color: var(--text);
  background: var(--surface);
  box-shadow: 0 18px 48px rgba(0,0,0,.3);
}
.ticket-hover-preview[hidden] { display: none; }
.ticket-hover-preview header { padding: 13px 16px 11px; border-bottom: 1px solid var(--hairline); display: grid; gap: 3px; }
.ticket-hover-preview header b { font-size: 12px; }
.ticket-hover-preview header time { color: var(--muted); font-size: 10.5px; }
.ticket-hover-preview > p { max-height: 190px; margin: 0; padding: 15px 16px; overflow: hidden; font-size: 12.5px; line-height: 1.55; white-space: pre-wrap; }
.ticket-hover-preview footer { min-height: 45px; padding: 6px 10px; border-top: 1px solid var(--border); display: flex; align-items: center; justify-content: flex-end; gap: 5px; background: var(--surface-sunken); }
.ticket-hover-preview footer button { min-height: 32px; padding: 0 10px; border: 0; border-radius: 7px; color: var(--text); background: transparent; cursor: pointer; font: inherit; font-size: 11.5px; }
.ticket-hover-preview footer button:hover,
.ticket-hover-preview footer button:focus-visible { color: var(--link); background: var(--surface); outline: 0; }

.app-shell #ticketsView .ticket-row.selected,
.app-shell #ticketsView .ticket-row.selected:hover {
  background: linear-gradient(90deg, var(--orange-wash) 0%, color-mix(in srgb, var(--orange-wash) 28%, var(--surface)) 54%, var(--surface) 100%);
  box-shadow: inset 3px 0 0 var(--orange), inset 0 1px 0 var(--orange-wash-border);
}

.app-shell #ticketsView .ticket-customer::before {
  width: 3px;
  top: 1px;
  bottom: 1px;
  box-shadow: 0 0 8px color-mix(in srgb, currentColor 25%, transparent);
}

.app-shell #ticketsView .ticket-customer b {
  margin-bottom: 2px;
  color: var(--text);
  font-weight: 750;
  letter-spacing: -.01em;
}

.app-shell #ticketsView .ticket-subject b {
  margin-bottom: 2px;
  color: var(--text);
  font-weight: 700;
  letter-spacing: -.012em;
  transition: color .14s ease;
}

.app-shell #ticketsView .ticket-row:hover .ticket-subject b { color: var(--link); }
.app-shell #ticketsView .ticket-subject > span:last-child,
.app-shell #ticketsView .ticket-customer > span:last-child,
.app-shell #ticketsView .ticket-received {
  color: var(--muted);
  font-weight: 500;
}

.app-shell #ticketsView .ticket-received {
  font-variant-numeric: tabular-nums;
}

.app-shell #ticketsView .ticket-assignee { gap: 9px; }
.app-shell #ticketsView .ticket-assignee .avatar {
  width: 26px;
  height: 26px;
  border: 1px solid color-mix(in srgb, var(--border-dark) 75%, transparent);
  box-shadow: 0 2px 5px rgba(0, 0, 0, .12);
  font-size: 9px;
  font-weight: 800;
}
.app-shell #ticketsView .ticket-assignee > span { color: var(--text-soft); font-weight: 650; }

.app-shell #ticketsView .status-pill,
.app-shell #ticketsView .sla-pill {
  min-height: 24px;
  padding: 5px 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid color-mix(in srgb, currentColor 17%, transparent);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
  font-weight: 750;
  letter-spacing: .01em;
  line-height: 1;
}

.app-shell #ticketsView .ticket-select input,
.app-shell #ticketsView .ticket-select-all input {
  appearance: none;
  width: 17px;
  height: 17px;
  margin: 0;
  border: 1px solid var(--border-dark);
  border-radius: 4px;
  display: grid;
  place-items: center;
  background: var(--surface);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .08);
  cursor: pointer;
  transition: border-color .12s ease, background-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.app-shell #ticketsView .ticket-select input::after,
.app-shell #ticketsView .ticket-select-all input::after {
  content: "";
  width: 8px;
  height: 4px;
  border: solid #fff;
  border-width: 0 0 2px 2px;
  opacity: 0;
  transform: translateY(-1px) rotate(-45deg);
}
.app-shell #ticketsView .ticket-select input:hover,
.app-shell #ticketsView .ticket-select-all input:hover {
  border-color: var(--orange);
  transform: scale(1.06);
}
.app-shell #ticketsView .ticket-select input:checked,
.app-shell #ticketsView .ticket-select-all input:checked,
.app-shell #ticketsView .ticket-select-all input:indeterminate {
  border-color: var(--orange);
  background: linear-gradient(145deg, var(--orange), var(--orange-hover));
  box-shadow: 0 2px 6px var(--orange-wash-border);
}
.app-shell #ticketsView .ticket-select input:checked::after,
.app-shell #ticketsView .ticket-select-all input:checked::after { opacity: 1; }
.app-shell #ticketsView .ticket-select-all input:indeterminate::after {
  width: 8px;
  height: 0;
  border-width: 0 0 2px;
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .app-shell #ticketsView .ticket-row,
  .app-shell #ticketsView .ticket-select input,
  .app-shell #ticketsView .ticket-select-all input { transition: none; }
}

/* ---- Operational overview dashboard ---------------------------------------------------------- */
/* One gap, used everywhere on this page: between the sections down the page, between the four
   tiles across it, and between the panels inside the roster row. The sections used to carry
   their own bottom margins -- 16, 14, 16, then nothing at all between the calendar and the
   performance cards -- and the gaps read as accidental because they were. */
.app-shell #overviewView { --overview-gap: 16px; row-gap: var(--overview-gap); padding: 22px clamp(18px, 1.7vw, 30px) 30px; background: radial-gradient(circle at 42% 0%, color-mix(in srgb, var(--surface-muted) 28%, transparent), transparent 32%); }
.app-shell #overviewView > * { margin-bottom: 0; }
.app-shell #overviewView .overview-head { min-height: 66px; }
.app-shell #overviewView .overview-head h1 { font-size: clamp(28px, 2vw, 36px); }
.overview-head-actions { display: flex; align-items: center; gap: 12px; }
.overview-head-actions .secondary-button,.overview-head-actions .primary-button { min-height: 42px; padding-inline: 18px; }

.app-shell #overviewView .summary-grid { gap: var(--overview-gap); }
.app-shell #overviewView .summary-card {
  min-width: 0;
  min-height: 108px;
  padding: 16px 18px;
  border-color: var(--border-dark);
  align-items: center;
  text-align: left;
  color: inherit;
  background: linear-gradient(145deg, var(--surface), color-mix(in srgb, var(--surface-muted) 45%, var(--surface)));
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0,0,0,.08), inset 0 1px 0 color-mix(in srgb, #fff 4%, transparent);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.app-shell #overviewView .summary-card::after { display: none; }
.app-shell #overviewView .summary-card:hover { border-color: var(--orange-wash-border); transform: translateY(-2px); box-shadow: 0 12px 28px rgba(0,0,0,.12); }
.app-shell #overviewView .summary-card:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.app-shell #overviewView .summary-card > div:nth-child(2) { min-width: 0; }
.app-shell #overviewView .summary-card p { margin-bottom: 3px; color: var(--text-soft); font-size: 10px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; }
.app-shell #overviewView .summary-card h2 { margin: 0 0 3px; font-size: 27px; font-variant-numeric: tabular-nums; }
.app-shell #overviewView .summary-icon { width: 46px; height: 46px; border-radius: 13px; font-size: 21px; }
.app-shell #overviewView .summary-icon svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.accent-blue .summary-icon { color: var(--indigo-ink); background: var(--indigo-wash); }
.metric-spark { height: 42px; margin-left: auto; display: flex !important; align-items: flex-end; gap: 3px; opacity: .9; }
.metric-spark i { width: 4px; min-height: 4px; border-radius: 4px 4px 1px 1px; background: var(--green); }
.accent-coral .metric-spark i { background: var(--coral); }.accent-orange .metric-spark i { background: var(--orange); }.accent-blue .metric-spark i { background: var(--chart-indigo); }
.overview-section-head { min-height: 50px; padding: 11px 18px; }
.overview-section-head h2 { display: flex; align-items: center; gap: 8px; font-size: 13px; letter-spacing: .045em; text-transform: uppercase; }
.overview-section-head > div > span { display: none; }
.section-count { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; display: inline-grid; place-items: center; color: var(--coral-ink); background: var(--coral-pale); font-size: 10px; }
/* Beside the subject, not above it. column-reverse put the ticket id on a line of its own, which
   made every row three lines tall -- id, subject, then who it is from -- to carry six words. */
.app-shell #overviewView .attention-heading { flex-direction: row; align-items: baseline; gap: 8px; }
.overview-kpi-panel,.team-overview-panel { min-width: 0; padding: 14px 16px; border-color: var(--border-dark); }
.overview-section-title { min-height: 28px; display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.overview-section-title h2 { margin: 0; font-size: 13px; letter-spacing: .045em; text-transform: uppercase; }
.my-work-metrics { margin: 9px 0 13px; display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 8px; }
.my-work-metrics button { min-width: 0; min-height: 62px; padding: 9px 10px; border: 1px solid var(--border); border-radius: 9px; display: grid; grid-template-columns: 32px auto; grid-template-rows: auto auto; column-gap: 8px; align-items: center; text-align: left; color: inherit; background: var(--surface-sunken); cursor: pointer; }
.my-work-metrics button:hover { border-color: var(--orange-wash-border); background: var(--orange-wash); }
.work-icon { width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; grid-row: 1 / span 2; }.work-icon.green { color: var(--green-ink); background: var(--green-pale); }.work-icon.orange { color: var(--orange-ink); background: var(--orange-pale); }.work-icon.purple { color: var(--violet-ink); background: var(--violet-wash); }.work-icon.blue { color: var(--indigo-ink); background: var(--indigo-wash); }
.work-icon svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.my-work-metrics strong { align-self: end; font-size: 18px; line-height: 1; }.my-work-metrics small { align-self: start; overflow: hidden; color: var(--muted); font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }
.overview-mini-head { margin-bottom: 5px; color: var(--text-faint); font-size: 9px; font-weight: 800; letter-spacing: .055em; text-transform: uppercase; }
.overview-next-list { border: 1px solid var(--border); border-radius: 9px; overflow: hidden; }
.overview-next-item { width: 100%; min-height: 34px; padding: 5px 10px; border: 0; border-bottom: 1px solid var(--hairline); display: grid; grid-template-columns: 64px minmax(0,1fr) auto auto 18px; gap: 9px; align-items: center; text-align: left; color: inherit; background: transparent; cursor: pointer; }.overview-next-item:last-child { border-bottom: 0; }.overview-next-item:hover { background: var(--surface-sunken); }
.overview-next-item b { overflow: hidden; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }.overview-next-id { color: var(--indigo-ink); font-size: 9px; font-weight: 700; }.overview-next-sla,.overview-next-priority { padding: 4px 7px; border-radius: 6px; color: var(--text-soft); background: var(--surface-muted); font-size: 8px; font-weight: 700; }.overview-next-sla { color:var(--amber-ink); background:var(--amber-wash); }.overview-next-sla.done { color: var(--text-soft); background: var(--surface-muted); }.overview-next-sla.risk,.overview-next-sla.warning,.overview-next-priority.high { color: var(--orange-ink); background: var(--orange-pale); }.overview-next-sla.overdue { color:var(--coral-ink); background:var(--coral-pale); }.overview-next-priority.low { color: var(--indigo-ink); background: var(--indigo-wash); }.overview-next-arrow { color: var(--text-soft); }
.overview-list-empty { margin: 12px 0 2px; color: var(--muted); font-size: 10px; text-align: center; }
@media (max-width: 900px) { .overview-head-actions .secondary-button { display:none; }.my-work-metrics { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (max-width: 650px) { .overview-head-actions { display:none; }.overview-next-item { grid-template-columns:55px minmax(0,1fr) auto; }.overview-next-priority,.overview-next-sla { display:none; } }

/* The Overview used to carry its own navy palette in the dark, so the landing page was a
   different hue from every view it led to. It now uses the shared surfaces; rows sit on the
   panel and lift on hover like every other list. */
:root[data-theme="dark"] .app-shell #overviewView .attention-item,
:root[data-theme="dark"] .app-shell #overviewView .overview-next-item { background: transparent; }
:root[data-theme="dark"] .app-shell #overviewView .attention-item:hover,
:root[data-theme="dark"] .app-shell #overviewView .overview-next-item:hover { background: var(--surface-hover); }

.app-shell #overviewView .summary-card { display: grid; grid-template-columns: 50px minmax(90px,1fr) 126px; }
.app-shell #overviewView .summary-card.accent-green { --trend-colour:var(--chart-green); --trend-ink:var(--green-ink); }.app-shell #overviewView .summary-card.accent-coral { --trend-colour:var(--chart-coral); --trend-ink:var(--coral-ink); }.app-shell #overviewView .summary-card.accent-orange { --trend-colour:var(--chart-orange); --trend-ink:var(--orange-ink); }.app-shell #overviewView .summary-card.accent-blue { --trend-colour:var(--chart-indigo); --trend-ink:var(--indigo-ink); }
.app-shell #overviewView .metric-spark { width:126px; height:65px; margin-left:auto; display:grid!important; grid-template-rows:42px 19px; justify-items:end; align-items:center; color:var(--trend-colour); }
.app-shell #overviewView .metric-spark svg { width:122px; height:42px; overflow:visible; filter:drop-shadow(0 4px 6px color-mix(in srgb,var(--trend-colour) 20%,transparent)); }
.app-shell #overviewView .metric-comparison { min-height:19px; padding:3px 7px; border:1px solid var(--border); border-radius:999px; color:var(--text-soft); background:var(--surface-muted); font-size:8px; font-style:normal; font-weight:650; white-space:nowrap; }
.app-shell #overviewView .metric-comparison { transform: translateY(3px); }
.app-shell #overviewView .metric-comparison.up { color:var(--trend-ink); }
.app-shell #overviewView .accent-blue .metric-comparison.up { color:var(--green-ink); }
.app-shell #overviewView .metric-comparison.down { color:var(--coral-ink); }
.app-shell #overviewView .metric-comparison.flat { color:var(--muted); }
.app-shell #overviewView .accent-green .summary-icon { color:var(--green-ink);background:var(--green-pale); }.app-shell #overviewView .accent-coral .summary-icon { color:var(--coral-ink);background:var(--coral-pale); }.app-shell #overviewView .accent-orange .summary-icon { color:var(--orange-ink);background:var(--orange-pale); }.app-shell #overviewView .accent-blue .summary-icon { color:var(--indigo-ink);background:var(--indigo-wash); }
/* The priority colour is the row's left edge, not a stripe sitting near it. It used to be a 5px
   bar inside the 6px track, which put the row's 14px of left padding between it and the panel --
   an empty margin whose only job was to hold the one thing in the row that is pure signal away
   from the edge. The bar now bleeds back out through that padding (negative margin, stretched to
   its track) so the colour runs edge to edge and full height. Doing it from the bar rather than
   from the grid keeps every column exactly where it was: no track widths change, at any tier. */
.app-shell #overviewView .priority-bar { width:auto;justify-self:stretch;margin-left:calc(var(--attention-gutter, 14px) * -1);height:100%;min-height:42px;border-radius:0; }

@media (max-width:1450px) {
  .app-shell #overviewView .summary-card { grid-template-columns:44px minmax(80px,1fr) 108px; padding-inline:14px; }
  .app-shell #overviewView .metric-spark { width:108px; }.app-shell #overviewView .metric-spark svg { width:106px; }
}
@media (max-width:650px) {
  .app-shell #overviewView .summary-card { grid-template-columns:46px minmax(0,1fr) 112px; }
}

/* Team overview is a fixed two-part instrument panel, including its zero states. */
.app-shell #overviewView .team-overview-panel { padding: 17px 18px 14px; }

/* My Work follows the compact 320px dashboard panel in the reference. Four Next Up slots remain
   visible as structure when there are fewer than four assignments, rather than becoming whitespace. */
.app-shell #overviewView .overview-lower-grid { align-items: stretch; }
.app-shell #overviewView .overview-kpi-panel,
.app-shell #overviewView .team-overview-panel { min-height: 320px; }
.app-shell #overviewView .overview-kpi-panel {
  display: flex;
  flex-direction: column;
  padding: 16px 17px 14px;
}
.app-shell #overviewView .overview-kpi-panel .overview-section-title { min-height: 26px; }
.app-shell #overviewView .overview-kpi-panel .overview-section-title h2 { font-size: 10px; }
.app-shell #overviewView .overview-kpi-panel .quiet-button { font-size: 9px; }
.app-shell #overviewView .my-work-metrics {
  min-height: 68px;
  margin: 8px 0 13px;
  gap: 8px;
}
.app-shell #overviewView .my-work-metrics button {
  min-height: 68px;
  height: 68px;
  padding: 9px 11px;
}
.app-shell #overviewView .my-work-metrics button:first-child {
  border-color: color-mix(in srgb, var(--green) 42%, var(--border));
  background: color-mix(in srgb, var(--green-pale) 30%, var(--surface-sunken));
}
.app-shell #overviewView .my-work-metrics strong { font-size: 20px; }
.app-shell #overviewView .my-work-metrics small { font-size: 9px; }
.app-shell #overviewView .overview-mini-head {
  min-height: 20px;
  margin: 0;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--border-dark);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.app-shell #overviewView .overview-mini-head .quiet-button { flex: none; color: var(--link); font-size: 9px; text-transform: none; letter-spacing: 0; }
.app-shell #overviewView .overview-next-list {
  min-height: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  display: grid;
  grid-template-rows: repeat(4, 1fr);
  flex: 1;
}
.app-shell #overviewView .overview-next-item {
  min-height: 0;
  height: 100%;
  padding: 4px 10px;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
}
.app-shell #overviewView .overview-next-item.empty {
  pointer-events: none;
  opacity: .38;
}
.app-shell #overviewView .overview-next-item.empty b { color: var(--muted); font-weight: 500; }
.app-shell #overviewView .overview-list-empty { display: none; }

/* Team Overview owns its complete half of the lower dashboard. Every internal instrument expands
   with it, instead of leaving fixed 42px rows stranded at the top of a tall column. */
.app-shell #overviewView .team-stats-column {
  grid-template-rows: 24px minmax(168px, 4fr) minmax(61px, 1.35fr);
  gap: 9px;
}

/* The overview is the workspace, not a stack of fixed-height cards floating above unused page
   space. The attention queue takes only the height its rows need; My Work and Team Overview then
   share and fill everything left down to the viewport edge. */
@media (min-width: 1321px) {
  .app-shell #overviewView { min-height: calc(100dvh - 56px); }
  .app-shell #overviewView .overview-grid {
    min-height: 0;
    grid-template-rows: auto minmax(320px, 1fr);
  }
  .app-shell #overviewView .attention-panel { min-height: 0; }
  .app-shell #overviewView .overview-lower-grid { min-height: 320px; height: auto; }
  .app-shell #overviewView .overview-kpi-panel,
  .app-shell #overviewView .team-overview-panel { height: 100%; }
  .app-shell #overviewView .team-stats-column {
    grid-template-rows: 24px minmax(168px, 4fr) minmax(61px, 1.35fr);
  }
  .app-shell #overviewView .team-breakdowns {
    grid-template-rows: 24px minmax(151px, 1.35fr) minmax(89px, .75fr);
  }
}

@media (max-width: 1320px) {
  .app-shell #overviewView .overview-kpi-panel,
  .app-shell #overviewView .team-overview-panel { width: 100%; height: auto; min-height: 360px; }
}

@media (max-width: 760px) {
  .app-shell #overviewView { padding-inline: 14px; }
}

@media (max-width: 480px) {
  .app-shell #overviewView { padding-inline: 10px; }
}
@media (max-width: 650px) {
  .app-shell #overviewView .overview-kpi-panel { height: auto; min-height: 0; }
  .app-shell #overviewView .my-work-metrics { grid-template-columns: repeat(2,minmax(0,1fr)); min-height: 144px; }
  .app-shell #overviewView .overview-next-item { grid-template-columns: 55px minmax(0,1fr) auto; }
}

/* ---- Overview: size by the space the panels actually have -----------------------------------
   Every breakpoint above this point measures the viewport, but the overview never gets the
   viewport: it gets what is left after the 224px navigation rail and the page gutters. A 1440px
   Mac leaves the dashboard ~1150px, so the 1320px and 1150px rules written for exactly that
   amount of room never fired, and the columns they were meant to relax stayed at their widest.
   Three things broke as a result, all of them visible at 1440x900:

     - the attention row's subject ran across the "Assigned to" column,
     - "Tickets by priority" and the channel row were clipped at the panel's right edge,
     - the summary cards overflowed their own borders.

   These rules measure the container instead, so a panel relaxes when it is short of room however
   that came about -- a laptop screen, a narrower window, or a wider rail. They intentionally sit
   last and carry `#overviewView`, so they own these properties outright rather than interleaving
   with the viewport rules above. */

.app-shell #overviewView { container: overview / inline-size; }
.app-shell #overviewView .summary-card { container: card / inline-size; }

/* ---- Overflow that no breakpoint should have to prevent ---- */

/* A column flex line sizes its children to their own content on the cross axis, so the subject --
   one long unbroken string, `white-space: nowrap` -- measured its full 633px inside a 402px cell
   and painted straight over the next column. `overflow: hidden` cannot clip a box that was never
   constrained; capping the cross size is what gives the ellipsis something to do. */
.app-shell #overviewView .attention-heading > * { max-width: 100%; }

/* Second tracks that can reach zero. Their old floors (360px here, 64px per channel, 150px for
   the donut) were larger than the space the panel had at 1440px, and a grid whose tracks do not
   fit does not shrink them -- it overflows and clips whatever sits at the right-hand edge. */
.app-shell #overviewView .team-overview-content {
  grid-template-columns: minmax(190px, .72fr) minmax(0, 1.55fr);
}

/* "Waiting on customer" and "Average response time" are phrases, not tokens. Truncated to
   "Waiting on ..." two of the four My Work tiles read identically, so these wrap onto a second
   line and clip only past that -- the tiles already have the height for it. */
.app-shell #overviewView .my-work-metrics small,
.app-shell #overviewView .team-stat-list small {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  white-space: normal;
  line-height: 1.25;
}

/* ---- Summary cards ---- */

/* The card was `50px minmax(90px,1fr) 126px` with an 18px gutter: 296px of tracks and padding in
   a 277px card. The middle column collapsed to its floor, the subtext broke over three lines and
   the sparkline pushed out past the border. Give the number column the slack instead, and let the
   card decide for itself whether there is room left for a chart. */
.app-shell #overviewView .summary-card {
  grid-template-columns: 44px minmax(0, 1fr) auto;
  gap: 13px;
  padding: 15px 16px;
  min-height: 104px;
}
.app-shell #overviewView .summary-icon { width: 44px; height: 44px; border-radius: 12px; }
.app-shell #overviewView .summary-card h2 { font-size: clamp(23px, 2.1cqi + 15px, 28px); }
.app-shell #overviewView .summary-card p { font-size: 9.5px; }

/* Two lines, then an ellipsis. "0 tickets assigned to you" is a caption, not a paragraph, and a
   third line only ever arrives by pushing the card taller than its neighbours. */
.app-shell #overviewView .summary-card > div:nth-child(2) > span {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-size: 10px;
  line-height: 1.35;
}

.app-shell #overviewView .metric-spark {
  width: 120px;
  height: 62px;
  min-width: 0;
  grid-template-rows: 40px 19px;
}
.app-shell #overviewView .metric-spark svg { width: 100%; height: 40px; }

/* Under ~300px the chart is the first thing to go: the delta pill below it carries the same
   reading in a fifth of the width, so the number and its caption keep the room instead. */
@container card (max-width: 300px) {
  .app-shell #overviewView .metric-spark { width: auto; height: auto; grid-template-rows: auto; }
  .app-shell #overviewView .metric-spark svg { display: none; }
}
@container card (max-width: 196px) {
  .app-shell #overviewView .metric-spark { display: none !important; }
}

@container overview (max-width: 1000px) {
  .app-shell #overviewView .summary-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container overview (max-width: 460px) {
  .app-shell #overviewView .summary-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Attention queue ----
   Seven columns need 946px of track and the panel has ~1120px at 1440x900, so the widest layout
   still holds there. What changes is that each step down now happens when the panel runs out of
   room rather than when the window passes a number chosen for a viewport with no rail in it.

   The status and priority tracks are 8px wider than the room their content needs. Both hold a
   label over a badge, and both were sized when the label was 7px; at the readable size the widest
   of them, "PRIORITY", is 58px of glyphs, which 88px minus 28px of padding did not have. */
/* The header is laid out here rather than in its own style block further down, because the card
   tier below has to be able to take it away. Both rules are `.app-shell #overviewView
   .attention-head-row` -- identical specificity -- so source order decides, and the style block
   sits ~850 lines later: its `display: grid` was overriding the card tier's `display: none` at
   every width. The header stayed on a layout that has no columns for it to name, and its labels
   piled onto each other. Declared above the tiers, the tier that hides it wins. */
.app-shell #overviewView .attention-head-row { display: grid; }

/* Below that the row stops being a table and becomes a card: subject and customer over the full
   width, status beside them, the SLA badge on its own line underneath. */
@container attention (max-width: 519.98px) {
  /* A card has no columns, so it has nothing for a column header to name. */
  .app-shell #overviewView .attention-head-row { display: none; }
  .app-shell #overviewView .attention-item {
    --attention-gutter: 10px;
    min-height: 0;
    grid-template-columns: 5px minmax(0, 1fr) auto;
    padding: 10px;
  }
  .app-shell #overviewView .attention-agent,
  .app-shell #overviewView .attention-priority,
  .app-shell #overviewView .attention-arrow { display: none !important; }
  .app-shell #overviewView .attention-status { grid-column: 3; grid-row: 1; align-self: center; padding: 0; border: 0; }
  .app-shell #overviewView .attention-status small { display: none; }
  .app-shell #overviewView .attention-meta {
    grid-column: 2 / span 2;
    grid-row: 2;
    margin-left: 0;
    padding: 8px 0 0;
    border-left: 0;
    border-top: 1px solid var(--border);
  }
  .app-shell #overviewView .priority-bar { min-height: 100%; grid-row: 1 / span 2; }
  .app-shell #overviewView .attention-content { padding-left: 8px; }
}

/* ---- Team overview ----
   Two columns down to 430px of panel rather than collapsing at a viewport width the panel never
   sees. The instrument panel reads as one thing; stacking it is a last resort, not a 1440px
   default. */
@container team (min-width: 600px) {
  .app-shell #overviewView .team-overview-content { grid-template-columns: minmax(215px, .72fr) minmax(0, 1.55fr); }
  .app-shell #overviewView .priority-breakdown { grid-template-columns: minmax(118px, 150px) minmax(0, 1fr); gap: 18px; }
}

/* ---- Lower grid ----
   My Work and Team Overview sit side by side while the dashboard has ~1000px for them, which a
   1440px Mac does. Below that they stack. */
.app-shell #overviewView .overview-lower-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr); }
@container overview (max-width: 1000px) {
  .app-shell #overviewView .overview-kpi-panel,
  .app-shell #overviewView .team-overview-panel { height: auto; }
}
@container overview (max-width: 560px) {
  .app-shell #overviewView .my-work-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- Team performance cards ----
   The Reports page's KPI cards at half width. The panel is its own size container so the card
   grid follows the room the panel actually gets: three across when it sits beside Team Overview
   on a wide screen or stacks full width, two across in a tighter half, one on a phone. The
   cards stretch to fill the panel's height, so it lines up with Team Overview beside it. */
.app-shell #overviewView .overview-kpi-panel { container: overviewkpi / inline-size; gap: 10px; }
.app-shell #overviewView .overview-kpi-head { display: flex; align-items: flex-start; gap: 10px; }
.app-shell #overviewView .overview-kpi-head > div { min-width: 0; flex: 1; }
.app-shell #overviewView .overview-kpi-head > div > span { display: block; margin-bottom: 3px; color: var(--link); font-size: 9px; font-weight: 800; letter-spacing: .1em; }
.app-shell #overviewView .overview-kpi-head h2 { margin: 0; font-size: 15px; }
.app-shell #overviewView .overview-kpi-head > b { padding: 4px 8px; border-radius: 999px; flex: none; color: var(--text-soft); background: var(--surface-muted); font-size: 10px; white-space: nowrap; }
.app-shell #overviewView .overview-kpi-head .quiet-button { flex: none; color: var(--link); font-size: 10px; text-decoration: none; }
.app-shell #overviewView .overview-kpi-head > div > span,
.app-shell #overviewView .overview-kpi-head h2 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-shell #overviewView .overview-kpi-scope { width: auto; max-width: 170px; min-height: 28px; height: 28px; padding-block: 0; flex: 0 1 auto; font-size: 11px; }
/* The Reports toggles, sized for this much smaller head. */
.app-shell #overviewView .overview-kpi-head > .overview-kpi-levels { padding: 1px; border-radius: 8px; flex: none; }
.app-shell #overviewView .overview-kpi-levels .kpi-level-button { min-width: 30px; height: 26px; padding: 0 7px; border-radius: 6px; font-size: 10px; }
.app-shell #overviewView .overview-kpi-grid { flex: 1; min-height: 0; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 8px; }
.app-shell #overviewView .overview-kpi-grid .kpi-metric-card { padding: 10px 11px 9px 13px; border-radius: 10px; display: flex; flex-direction: column; }
.app-shell #overviewView .overview-kpi-grid .kpi-metric-card::before { width: 3px; }
.app-shell #overviewView .overview-kpi-grid .kpi-metric-card-head { min-height: 0; font-size: 10.5px; line-height: 1.3; }
.app-shell #overviewView .overview-kpi-grid .kpi-metric-card-head span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-shell #overviewView .overview-kpi-grid .kpi-metric-card-head i { width: 7px; height: 7px; margin-top: 3px; }
.app-shell #overviewView .overview-kpi-grid .kpi-metric-card > strong { margin-top: 6px; font-size: clamp(18px, 5cqi, 24px); }
.app-shell #overviewView .overview-kpi-grid .kpi-metric-card > p { margin: 4px 0 8px; font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.app-shell #overviewView .overview-kpi-grid .kpi-mini-trend { height: 14px; margin-top: auto; gap: 2px; }
.app-shell #overviewView .overview-kpi-grid .kpi-mini-trend .kpi-trend-dot { height: 5px; border-radius: 2px; }
.app-shell #overviewView .overview-kpi-grid .kpi-mini-trend .kpi-trend-dot.on-target,
.app-shell #overviewView .overview-kpi-grid .kpi-mini-trend .kpi-trend-dot.off-target { height: 12px; }
.app-shell #overviewView .overview-kpi-grid .kpi-mini-trend .kpi-trend-dot.warning { height: 9px; }
.app-shell #overviewView .overview-kpi-grid .kpi-mini-trend .kpi-trend-dot.empty { height: 3px; }
.app-shell #overviewView .overview-kpi-empty { grid-column: 1 / -1; margin: auto; color: var(--muted); font-size: 11px; text-align: center; }
@container overviewkpi (max-width: 620px) {
  .app-shell #overviewView .overview-kpi-head > b { display: none; }
}
@container overviewkpi (max-width: 480px) {
  .app-shell #overviewView .overview-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container overviewkpi (max-width: 380px) {
  .app-shell #overviewView .overview-kpi-head { flex-wrap: wrap; }
  .app-shell #overviewView .overview-kpi-head h2 { white-space: normal; }
  .app-shell #overviewView .overview-kpi-scope { order: 3; max-width: none; flex: 1 0 100%; }
  /* A line of its own, as a segmented control, rather than squeezing the heading to an
     ellipsis beside it. */
  .app-shell #overviewView .overview-kpi-head > .overview-kpi-levels { order: 2; flex: 1 0 100%; }
  .app-shell #overviewView .overview-kpi-levels .kpi-level-button { flex: 1; min-width: 0; }
}
@container overviewkpi (max-width: 300px) {
  .app-shell #overviewView .overview-kpi-grid { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
}

/* ---- Short screens: fit the dashboard, do not scroll it ------------------------------------
   1440x900 is the common Mac laptop, and after the menu bar, browser chrome and dock it leaves
   roughly 700px of viewport. The overview wanted 877px of it, so Team Overview's channel row --
   the last instrument on the page -- sat below the fold on the screen it was designed for. Every
   value below is the same composition at a smaller step: nothing is dropped, the padding, the
   heading and the row heights just stop being sized for a 27-inch monitor. */
@media (max-height: 940px) and (min-width: 761px) {
  .app-shell #overviewView { --overview-gap: 10px; padding-top: 14px; padding-bottom: 12px; }
  .app-shell #overviewView .overview-head { min-height: 50px; }
  .app-shell #overviewView .overview-head h1 { margin-bottom: 2px; font-size: clamp(22px, 1.5vw, 27px); }
  .app-shell #overviewView .overview-head > div > p:last-child { font-size: 12px; }
  .app-shell #overviewView .eyebrow { margin-bottom: 2px; }
  .app-shell #overviewView .overview-head-actions .secondary-button,
  .app-shell #overviewView .overview-head-actions .primary-button { min-height: 36px; }

  .app-shell #overviewView .summary-grid { gap: var(--overview-gap); }
  .app-shell #overviewView .summary-card { min-height: 86px; padding: 11px 13px; gap: 11px; }
  .app-shell #overviewView .summary-icon { width: 38px; height: 38px; border-radius: 11px; }
  .app-shell #overviewView .summary-icon svg { width: 20px; height: 20px; }
  .app-shell #overviewView .summary-card h2 { font-size: clamp(21px, 1.7cqi + 14px, 25px); }
  .app-shell #overviewView .metric-spark { height: 50px; grid-template-rows: 32px 18px; }
  .app-shell #overviewView .metric-spark svg { height: 32px; }

  .app-shell #overviewView .overview-grid { gap: 11px; }
  .app-shell #overviewView .overview-lower-grid { gap: 11px; }
  .app-shell #overviewView .overview-section-head { min-height: 42px; padding: 8px 16px; }
  .app-shell #overviewView .attention-item { min-height: 40px; }
  .app-shell #overviewView .priority-bar { min-height: 40px; }
  .app-shell #overviewView .attention-head-row { min-height: 24px; }
  .app-shell #overviewView .attention-source-icon { width: 28px; height: 28px; border-radius: 8px; font-size: 12px !important; }
  .app-shell #overviewView .attention-content { gap: 10px; }
  .app-shell #overviewView .attention-agent,
  .app-shell #overviewView .attention-property,
  .app-shell #overviewView .attention-meta { min-height: 28px; }

  /* The lower row was pinned to a 320px floor for a tall window. Let it take the height its
     instruments actually need, so the dashboard ends at the fold instead of 77px past it. */
  .app-shell #overviewView .overview-grid { grid-template-rows: auto minmax(0, 1fr); }
  .app-shell #overviewView .overview-lower-grid { min-height: 0; }
  .app-shell #overviewView .overview-kpi-panel,
  .app-shell #overviewView .team-overview-panel { min-height: 242px; }
  .app-shell #overviewView .overview-kpi-panel { padding: 12px 14px 11px; }
  .app-shell #overviewView .team-overview-panel { padding: 13px 15px 11px; }
  .app-shell #overviewView .my-work-metrics { min-height: 54px; margin: 7px 0 9px; gap: 7px; }
  .app-shell #overviewView .my-work-metrics button { min-height: 54px; height: 54px; padding: 6px 9px; }
  .app-shell #overviewView .my-work-metrics strong { font-size: 17px; }
  .app-shell #overviewView .overview-mini-head { min-height: 17px; padding-bottom: 5px; }
  .app-shell #overviewView .overview-next-item { padding: 3px 9px; }

  /* The instruments still stretch to share the panel; what goes is the floor under each row,
     which was tall enough to hold the lower grid 87px above the height its contents need. */
  .app-shell #overviewView .team-stats-column { grid-template-rows: 20px auto auto; gap: 7px; }
  .app-shell #overviewView .team-stats-column > h2,
  .app-shell #overviewView .breakdown-title { height: 20px; }
  .app-shell #overviewView .team-stat-list { grid-template-rows: repeat(4, minmax(31px, 1fr)); }
  .app-shell #overviewView .team-stat-list > button,
  .app-shell #overviewView .team-stat-list > div { min-height: 33px; padding: 4px 9px; }
  .app-shell #overviewView .team-stat-icon { width: 25px; height: 25px; font-size: 12px; }
  .app-shell #overviewView .team-stat-list strong { font-size: 16px; }
  .app-shell #overviewView .resolution-stat { min-height: 0; padding: 7px 10px; }
  .app-shell #overviewView .team-breakdowns { grid-template-rows: 20px auto auto; }
  .app-shell #overviewView .priority-breakdown { min-height: 0; }
  .app-shell #overviewView .priority-donut { width: clamp(88px, 12vh, 112px); height: clamp(88px, 12vh, 112px); }
  .app-shell #overviewView .priority-donut::after { inset: 11px; }
  .app-shell #overviewView .priority-donut strong { font-size: 19px; }
  .app-shell #overviewView .priority-legend > div { min-height: 0; padding: 4px 2px; }
  .app-shell #overviewView .channel-breakdown { padding-top: 9px; }
  .app-shell #overviewView .channel-breakdown h3 { margin-bottom: 8px; }
  .app-shell #overviewView .channel-icon { width: 32px; height: 32px; font-size: 13px; }
  .app-shell #overviewView .channel-breakdown strong { font-size: 17px; }
}

/* ---- One source of truth for the topbar's height --------------------------------------------
   The overview stretches to fill the window with `calc(100dvh - 56px)`, but the topbar above it
   is 72px, 68px or 64px depending on the breakpoint -- never 56px. The dashboard was therefore
   asked to be 8-16px taller than the space below the bar, which is exactly the scrollbar that
   appeared on a window it otherwise fitted. Track the real height instead, so the fill stays a
   fill rather than becoming an overflow. */
.app-shell { --topbar-height: 72px; }
@media (max-width: 900px) { .app-shell { --topbar-height: 68px; } }
@media (max-width: 760px) { .app-shell { --topbar-height: 64px; } }
@media (max-height: 800px) and (min-width: 761px) { .app-shell { --topbar-height: 64px; } }

.app-shell #overviewView { min-height: calc(100dvh - var(--topbar-height) - var(--ticket-tabs-height)); }

/* ---- Ticket detail: size the composer by the column it sits in ------------------------------
   The reply toolbar's seven groups need 769px on one line. At 1600px of window the thread column
   gives it 822px and it fits; at 1440px the column gives it 746px, so it wrapped -- and because
   the attachment group is pushed right with `margin-left: auto`, the wrap put the paperclip alone
   on a second row against the right edge, which reads as a broken toolbar rather than a second
   line of controls. 23px short, and no viewport breakpoint could see it: the number that decides
   is the width of the thread column, not the width of the window. */
.app-shell #ticketView .ticket-thread { container: thread / inline-size; }
.app-shell #ticketView .reply-box { container: reply / inline-size; }

/* 700-800px of composer: the same toolbar, one row, tightened by the 100-odd px it is short.
   Nothing is dropped -- the selects give up their unused width, the groups their padding. */
@container reply (min-width: 700px) and (max-width: 799.98px) {
  .app-shell #ticketView .reply-format-bar { gap: 4px; }
  .app-shell #ticketView .reply-format-group { gap: 1px; padding-right: 4px; }
  .app-shell #ticketView .reply-format-select select { max-width: 74px; font-size: 10.5px; }
  .app-shell #ticketView .reply-format-button { min-width: 25px; padding: 0 4px; }
  .app-shell #ticketView .reply-format-colour { width: 25px; }
  .app-shell #ticketView .reply-format-bar .reply-attach-button { width: 26px; min-width: 26px; }
}

/* Narrower than that no amount of tightening keeps 20 controls on one line, so let it wrap -- but
   drop the auto margin first, so the groups flow onto the second row together instead of leaving
   one icon stranded at the right. */
@container reply (max-width: 699.98px) {
  .app-shell #ticketView .reply-format-bar { gap: 4px; }
  .app-shell #ticketView .reply-format-group { gap: 1px; padding-right: 5px; }
  .app-shell #ticketView .reply-format-select select { max-width: 78px; font-size: 10.5px; }
  .app-shell #ticketView .reply-format-button { min-width: 26px; padding: 0 4px; }
  .app-shell #ticketView .reply-format-colour { width: 26px; }
  .app-shell #ticketView .reply-attach-group { margin-left: 0; }
}

/* ---- Ticket detail on a short screen --------------------------------------------------------
   Opening a ticket on a 1440x900 Mac put the customer's message 527px down a ~700px viewport:
   the detail bar, a 24px subject, and an empty 251px composer came first, so the agent scrolled
   past a blank reply box to read what the ticket actually said. The composer is still expanded
   and still holds every control -- it is sized for the screen instead of for a 27-inch monitor,
   which brings the first message up above the fold.

   The properties panel is compacted in the same step for a different reason: the side column is
   the taller of the two panes, so it, not the thread, sets how far the page scrolls. */
@media (max-height: 940px) and (min-width: 761px) {
  .app-shell #ticketView .ticket-detail-bar { min-height: 58px; padding-block: 8px; }
  .app-shell #ticketView .ticket-detail-actions .secondary-button,
  .app-shell #ticketView .ticket-detail-actions .more-button { min-height: 34px; height: 34px; }
  .app-shell #ticketView .ticket-breadcrumb > button { width: 32px; height: 32px; }

  .app-shell #ticketView .request-header { padding: 15px 22px 8px; }
  .app-shell #ticketView .request-title-line h2,
  .app-shell #ticketView .subject-edit-input { font-size: 20px; }
  .app-shell #ticketView .request-header p { margin-top: 4px; font-size: 12px; }
  .app-shell #ticketView .request-icon { width: 33px; height: 33px; }

  /* The composer is the foot of the conversation card, so it keeps the card's full
     width here too: the margin this rule used to carry left it floating inside the
     card, narrower than every message above it. */
  .app-shell #ticketView .reply-box { margin: 0; padding: 10px 22px 13px; }
  .app-shell #ticketView .reply-tabs { margin-bottom: 6px; }
  .app-shell #ticketView .reply-format-bar { margin-bottom: 4px; padding-bottom: 5px; }
  .app-shell #ticketView .reply-editor { min-height: 56px; max-height: 34vh; padding-block: 7px; }
  .app-shell #ticketView .reply-send-actions .primary-button { min-height: 34px; }

  .app-shell #ticketView .conversation-head { padding: 12px 22px 4px; }
  .app-shell #ticketView .conversation { padding: 4px 22px 20px; }
  .app-shell #ticketView .ticket-detail-grid { padding-bottom: 0; }

  .app-shell #ticketView .side-panel-head { min-height: 48px; }
  .app-shell #ticketView .drawer-fields { padding: 12px 16px 14px; gap: 10px; }
  .app-shell #ticketView .drawer-fields select { height: 38px; }
  .app-shell #ticketView .ticket-checkbox-property small { font-size: 10px; line-height: 1.4; }
  .app-shell #ticketView .customer-summary { padding: 14px 16px; }
  .app-shell #ticketView .avatar.large { width: 38px; height: 38px; }
}

/* ---- Ticket queue: drop a column when the row runs out of room, not when the window does -----
   The Agent column was hidden below 1400px of window. The row does not get the window, though --
   between 1101px and 1600px it gets the window minus the 224px rail, and below 1101px it gets all
   of it back when the rail collapses. So the threshold was wrong in both directions:

     - at 1400px the row has 1132px and the seven columns need 1084. They fit. Agent went anyway.
     - at 1024px the rail is gone and the row has 980px, which is more than 1400px of window gave
       it -- and Agent was still hidden, because 1024 is under 1400.

   Worse, the six-column fallback needs 818px and nothing switched away from it until 760px of
   window, so between 761px and 860px the rows overflowed their own container and the SLA pill was
   cut off the right-hand edge by up to 67px.

   The row now measures the workspace it is drawn in. Agent survives down to 915px of it, the
   Received column starts wrapping instead of overflowing, and every tier is sized so its declared
   minimums actually fit the width that selects it. Below 761px of window the existing stacked
   card layout still owns the row, so these are held above it. */
.app-shell #ticketsView .ticket-workspace { container: queue / inline-size; }

@media (min-width: 761px) {
  /* 1140px and up the full-size row fits, so restore it -- this is the band, from 1352px to
     1400px of window, where the old rule dropped Agent from a row that had room for it. */
  @container queue (min-width: 1140px) {
    .app-shell #ticketsView .ticket-table-head,
    .app-shell #ticketsView .ticket-row {
      grid-template-columns: 40px minmax(180px, 1fr) 40px minmax(260px, 2.4fr) repeat(4, minmax(124px, .55fr));
      gap: 16px;
    }
    .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="assignee"] { display: block; }
    .app-shell #ticketsView .ticket-row > .ticket-assignee { display: flex; }
  }

  /* 1010-1140px: seven columns, tightened by the ~120px the widest tier is short. */
  @container queue (min-width: 1010px) and (max-width: 1139.98px) {
    .app-shell #ticketsView .ticket-table-head,
    .app-shell #ticketsView .ticket-row {
      grid-template-columns: 38px minmax(165px, 1fr) 38px minmax(238px, 2.2fr) repeat(4, minmax(104px, .6fr));
      gap: 11px;
    }
    .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="assignee"] { display: block; }
    .app-shell #ticketsView .ticket-row > .ticket-assignee { display: flex; }
  }

  /* 915-1010px: seven columns still, at the smallest size they are legible at. */
  @container queue (min-width: 925px) and (max-width: 1009.98px) {
    .app-shell #ticketsView .ticket-table-head,
    .app-shell #ticketsView .ticket-row {
      grid-template-columns: 38px minmax(145px, 1.1fr) 36px minmax(208px, 1.75fr) repeat(4, minmax(94px, .75fr));
      gap: 9px;
    }
    .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="assignee"] { display: block; }
    .app-shell #ticketsView .ticket-row > .ticket-assignee { display: flex; }
    .app-shell #ticketsView .ticket-assignee .avatar { width: 24px; height: 24px; }
  }

  /* 815-915px: Agent goes. It is the column whose value survives being read one row later. */
  @container queue (min-width: 820px) and (max-width: 924.98px) {
    .app-shell #ticketsView .ticket-table-head,
    .app-shell #ticketsView .ticket-row {
      grid-template-columns: 38px minmax(145px, 1.1fr) 34px minmax(215px, 1.8fr) repeat(3, minmax(98px, .75fr));
      gap: 9px;
    }
    .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="assignee"] { display: none; }
    .app-shell #ticketsView .ticket-row > .ticket-assignee { display: none; }
  }

  /* Under 815px: the band that used to overflow. Received wraps to two lines rather than holding
     a 142px track it cannot pay for, which keeps the timestamp instead of dropping the column. */
  @container queue (max-width: 819.98px) {
    .app-shell #ticketsView .ticket-table-head,
    .app-shell #ticketsView .ticket-row {
      grid-template-columns: 36px minmax(135px, 1.1fr) 32px minmax(192px, 1.75fr) repeat(3, minmax(82px, .75fr));
      gap: 8px;
    }
    .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="assignee"] { display: none; }
    .app-shell #ticketsView .ticket-row > .ticket-assignee { display: none; }
    .app-shell #ticketsView .ticket-received {
      white-space: normal;
      line-height: 1.25;
      overflow-wrap: anywhere;
    }
  }
}

/* The toolbar can now grow, so keep it from growing more than it must: the list below it is
   `flex: 1` against a page that already fits the viewport exactly, so every row of toolbar chrome
   costs a row of tickets. Trimming the search and sort fields keeps the controls on one line down
   to ~900px of workspace, and keeps the stacked arrangement below that to two compact rows. */
@media (min-width: 761px) {
  @container queue (min-width: 920px) and (max-width: 1139.98px) {
    .app-shell #ticketsView .ticket-tabs { gap: 16px; }
    .app-shell #ticketsView .toolbar-actions { gap: 6px; }
    .app-shell #ticketsView .queue-search { width: 186px; }
    .app-shell #ticketsView .sort-select { min-width: 124px; }
    .app-shell #ticketsView .tool-button { padding: 0 10px; }
    .app-shell #ticketsView .toolbar-toggle { gap: 6px; padding: 0 9px; }
  }

  @container queue (max-width: 919.98px) {
    .app-shell #ticketsView .ticket-toolbar { padding-block: 8px; gap: 8px; }
    .app-shell #ticketsView .toolbar-actions { gap: 6px; }
    .app-shell #ticketsView .queue-search { min-width: 150px; width: auto; flex: 1; }
    .app-shell #ticketsView .sort-select { min-width: 118px; }
    .app-shell #ticketsView .tool-button { padding: 0 10px; }
    .app-shell #ticketsView .toolbar-toggle { gap: 6px; padding: 0 9px; }
  }
}

/* ---- Contacts and Venues -----------------------------------------------------------------
   Same story as the queue: both lists decide which column to drop from the width of the window,
   and neither row gets the window. With the rail it is 224px less; below 1101px, where the rail
   collapses, it is the lot back again. So each list hid its most useful column at widths where
   the row had ample room for it. */

/* Both panels stop short of the window when the list is short, while the queue's fills it. Match
   the queue, so the three list views frame the same way. (This is presentation only: with a real
   214-contact list all three scroll the page, not the panel.) */
.app-shell #contactsView .contact-list,
.app-shell #venuesView .venue-list { flex: 1; }

/* An empty list must not still claim its half of the panel: the empty state is `flex: 1` too, and
   would otherwise be pushed into the lower half of an apparently blank page. */
.app-shell #contactsView .contact-list:empty,
.app-shell #venuesView .venue-list:empty { flex: none; }

/* A grid track's floor is the larger of its declared minimum and its content's minimum, and an
   email address is one unbreakable token. `.contact-person` sets `min-width: 0`, but the span
   inside it holding the name and the address does not, so a contact like
   b.fitzgerald-smythe@westcoastvenuegroup.com.au widened the first column past its share and
   pushed Create ticket and Archive off the right-hand edge of the row -- by 36px at 768px, and by
   a few pixels at widths as wide as 1280. The ellipsis was already there; it just needed a floor
   low enough to be reached. */
.app-shell .contact-person > span:not(.avatar) { min-width: 0; }

/* Under 900px the search field grows to fill the toolbar, and the toolbar has no column gap --
   `justify-content: space-between` was doing that job, and it has nothing left to do once one
   side flexes. The field ended up touching "All contacts". Column gap only, so the stacked
   arrangement under 650px keeps its own row spacing. */
.app-shell #contactsView .contacts-toolbar,
.app-shell #venuesView .contacts-toolbar { column-gap: 18px; }

.app-shell #contactsView .contacts-workspace { container: contactlist / inline-size; }
.app-shell #venuesView .contacts-workspace { container: venuelist / inline-size; }

@media (min-width: 651px) {
  /* Contacts. Phone was dropped below 1200px of window, so at 1100px -- rail already collapsed,
     1056px of row for a 964px layout -- it was hidden anyway. In a helpdesk contact list the
     phone number is most of the point. It now survives to 840px of workspace. */
  @container contactlist (min-width: 1008px) {
    .app-shell #contactsView .contact-table-head,
    .app-shell #contactsView .contact-row {
      grid-template-columns: minmax(260px, 1.5fr) minmax(180px, 1fr) minmax(150px, .8fr) 90px 220px;
      gap: 16px;
    }
    .app-shell #contactsView .contact-table-head span:nth-child(3),
    .app-shell #contactsView .contact-row > .contact-cell:nth-child(3) { display: block; }
  }
  @container contactlist (min-width: 840px) and (max-width: 1007.98px) {
    .app-shell #contactsView .contact-table-head,
    .app-shell #contactsView .contact-row {
      grid-template-columns: minmax(215px, 1.45fr) minmax(150px, 1fr) minmax(125px, .75fr) 78px 180px;
      gap: 12px;
    }
    .app-shell #contactsView .contact-table-head span:nth-child(3),
    .app-shell #contactsView .contact-row > .contact-cell:nth-child(3) { display: block; }
  }

  /* Under 840px Phone goes, and the row keeps a layout whose minimums fit the width that picks
     it -- the old fallback needed 762px of workspace and nothing replaced it until 650px, so
     between there and 800px the action buttons were cut off the edge. */
  @container contactlist (max-width: 839.98px) {
    .app-shell #contactsView .contact-table-head,
    .app-shell #contactsView .contact-row {
      grid-template-columns: minmax(210px, 1.4fr) minmax(145px, 1fr) 78px 168px;
      gap: 12px;
    }
    .app-shell #contactsView .contact-table-head span:nth-child(3),
    .app-shell #contactsView .contact-row > .contact-cell:nth-child(3) { display: none; }
    .app-shell #contactsView .contact-person .avatar { width: 32px; height: 32px; }
    .app-shell #contactsView .contact-actions button { padding: 0 9px; }
  }

  /* Venues. Address was dropped below 900px of window, where the row has 864px and the four
     columns need 638. It is the column the list exists to show, and it now stays until the row is
     genuinely out of room -- which, above the 650px stacked layout, it never is. */
  @container venuelist (min-width: 674px) {
    .app-shell #venuesView .venue-table-head,
    .app-shell #venuesView .venue-row {
      grid-template-columns: minmax(200px, 1.5fr) 120px minmax(180px, 2fr) 90px;
      gap: 16px;
    }
    .app-shell #venuesView .venue-table-head span:nth-child(3),
    .app-shell #venuesView .venue-row > span:nth-of-type(2) { display: block; }
  }
  @container venuelist (min-width: 572px) and (max-width: 673.98px) {
    .app-shell #venuesView .venue-table-head,
    .app-shell #venuesView .venue-row {
      grid-template-columns: minmax(170px, 1.5fr) 104px minmax(150px, 2fr) 76px;
      gap: 12px;
    }
    .app-shell #venuesView .venue-table-head span:nth-child(3),
    .app-shell #venuesView .venue-row > span:nth-of-type(2) { display: block; }
  }
  @container venuelist (max-width: 571.98px) {
    .app-shell #venuesView .venue-table-head,
    .app-shell #venuesView .venue-row {
      grid-template-columns: minmax(160px, 1.6fr) 100px 72px;
      gap: 10px;
    }
    .app-shell #venuesView .venue-table-head span:nth-child(3),
    .app-shell #venuesView .venue-row > span:nth-of-type(2) { display: none; }
  }
}

/* ---- List workspaces scroll their rows, not the page ----------------------------------------
   Every list view already had the plumbing for this: the panel is `flex: 1` with `overflow:
   hidden`, and the list inside it carries `min-height: 0` and `overflow-y: auto`. What was missing
   was a ceiling. `.view` only ever set `min-height`, which is a floor, so the panel grew to its
   contents and the page scrolled instead -- and the column headings and the search field, which
   sit above the list inside the panel, scrolled away with it. On 214 contacts and 186 venues
   that means losing both the moment you go looking for anything.

   Giving the view the height it already had as a minimum turns the same structure into what it
   was written to be: the panel fills the window, the rows scroll inside it, and the toolbar, the
   headings and the queue's pager stay where they are.

   Held to 761px and up. Below that the table headings are hidden anyway, so the pinning buys
   little, and page scrolling is the better behaviour on a phone -- no nested scroller, and the
   browser's own chrome still collapses on scroll. */

/* The floor was written against a topbar of 68px, 70px, 72px or 74px depending on which rule won,
   and the real one is 72px, 68px or 64px. Track it, so the ceiling below lands exactly on the
   fold rather than 8px past it. */
.app-shell .view { min-height: calc(100dvh - var(--topbar-height) - var(--ticket-tabs-height)); }

@media (min-width: 761px) {
  .app-shell #ticketsView,
  .app-shell #contactsView,
  .app-shell #venuesView,
  .app-shell #callsView {
    height: calc(100dvh - var(--topbar-height) - var(--ticket-tabs-height));
    min-height: 0;
  }

  /* Floors that stop the panel taking the height it is given. The workspace and the list can both
     already shrink; these two could not. */
  .app-shell #callsView .calls-workspace { min-height: 0; }
  .app-shell #ticketsView .empty-state,
  .app-shell #contactsView .empty-state,
  .app-shell #venuesView .empty-state,
  .app-shell #callsView .call-empty { min-height: 0; }

  /* Calls' list needs the same claim on the leftover height the other three lists have. */
  .app-shell #callsView .call-list { flex: 1; }

  /* The summary cards above the calls list are chrome, not content: they keep their height and
     the list takes what is left, rather than both being squeezed. */
  .app-shell #callsView .call-summary-grid { flex: none; }
}

/* ---- Settings: the rail stays, the group scrolls ---------------------------------------------
   Settings is thirteen destinations and one group on screen. The rail is 646px of them, and eight
   of the twelve groups are shorter than that -- General is 425px -- yet the page scrolled ~196px
   on a 1440x900 Mac whatever you opened, because the layout was as tall as its tallest column and
   `.settings-form` carried a 600px floor besides. Scrolling to reach a group you can already see,
   on a page whose content ends above the fold, is the whole cost of that.

   Same shape as the list views: give the view the height it already had as a minimum, and let the
   part that is actually long do the scrolling. The rail keeps all thirteen destinations reachable
   while a 1729px group like Email scrolls beside it, rather than being carried off the top of the
   window by it.

   Held to 761px and up, as the list views are. */
@media (min-width: 761px) {
  .app-shell #settingsView {
    height: calc(100dvh - var(--topbar-height) - var(--ticket-tabs-height));
    min-height: 0;
  }
  .app-shell #settingsView .settings-layout {
    min-height: 0;
    flex: 1;
    align-items: stretch;
  }
  .app-shell #settingsView .settings-detail { min-height: 0; }

  /* The panel is the scroller, not its container, so its border and rounded corners stay put and
     only the fields inside move.

     `position: relative` is load-bearing. The form holds 28 absolutely positioned descendants --
     the screen-reader-only inputs and labels behind the file pickers and toggles -- and on a
     static parent their containing block is the initial one, the viewport. Their static positions
     then sit outside the scroller, and the viewport counted them: the page grew a 1157px scrollbar
     onto blank space below a panel that was itself clipping correctly. Giving them a containing
     block inside the scroller puts them back where they belong. */
  .app-shell #settingsView .settings-form {
    position: relative;
    min-height: 0;
    height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* Two rules disagreed about where the rail stops being a vertical list. An unscoped rule turned it
   into a horizontal scrolling strip under 900px, but the `.app-shell` rule that collapses the
   layout to one column only fires under 760px -- so between 761px and 900px the strip was laid out
   inside a 224px grid column, thirteen nowrap buttons deep. At those widths the sidebar has already
   gone and the pane still has 478-603px beside a 224px rail, which is a perfectly good vertical
   list, so the rail follows the layout down to 760px and the strip starts where one column does.

   It also scrolls on its own account: 646px of destinations does not fit a 636px window, and a rail
   that clipped its last group would be worse than one that scrolls a little. */
@media (min-width: 761px) {
  .app-shell #settingsView .settings-rail {
    position: static;
    display: block;
    min-height: 0;
    height: 100%;
    overflow-x: visible;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .app-shell #settingsView .settings-rail-group { display: block; }
  .app-shell #settingsView .settings-rail button { width: 100%; }
}

/* Better still, mostly avoid the rail needing to scroll: on a short window it gives up the spacing
   it was sized for on a tall one, and every destination stays visible at once. */
@media (max-height: 940px) and (min-width: 761px) {
  .app-shell #settingsView .settings-rail button { min-height: 31px; padding-block: 5px; }
  .app-shell #settingsView .settings-rail-group { margin: 11px 0 4px; }
}

/* The two-column split collapsed below 1200px of window, so at 1024px and 1100px -- where the rail
   has already collapsed and the detail pane has 721px and 794px -- it was a single column with
   half the pane empty. Measure the pane. */
.app-shell #settingsView .settings-detail { container: settingsdetail / inline-size; }

@media (min-width: 761px) {
  @container settingsdetail (min-width: 720px) {
    .app-shell #settingsView .settings-columns { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  }
  @container settingsdetail (max-width: 719.98px) {
    .app-shell #settingsView .settings-columns { grid-template-columns: minmax(0, 1fr); }
  }
}

/* One step further on a laptop window: at 700px of viewport the rail wants 506px and has 486, and
   20px is not worth a scrollbar in front of thirteen destinations. This closes it, so the whole
   rail is visible at once on the screen Settings is most often opened on. */
@media (max-height: 820px) and (min-width: 761px) {
  .app-shell #settingsView .settings-rail button { min-height: 28px; padding-block: 4px; }
  .app-shell #settingsView .settings-rail-group { margin: 9px 0 3px; }
}

/* ---- Call history: the same measurement mistake, twice over -----------------------------------
   Six columns need 935px of track. The row gets that from 1281px of window upward, but the layout
   was chosen at 1201px, so between 1201px and 1280px the two row actions were pushed past the
   right-hand edge -- by 56px at the bottom of that band. And below 1201px the Contact column went
   whatever the row actually had: at 1100px, rail already collapsed, the row has 998px, which is
   more than 1280px of window ever gave it.

   Tiers measured against the workspace, as the other lists are. Ticket survives to the stacked
   layout now rather than going at 900px of window, because at 768px the row still has 682px and
   the five columns need 642. */
.app-shell #callsView .calls-workspace { container: calllist / inline-size; }

@media (min-width: 761px) {
  @container calllist (min-width: 979px) {
    .app-shell #callsView .call-table-head,
    .app-shell #callsView .call-row {
      grid-template-columns: minmax(220px, 1.4fr) minmax(155px, .9fr) 100px minmax(125px, .75fr) 90px 175px;
      gap: 14px;
    }
    .app-shell #callsView .call-table-head span:nth-child(2),
    .app-shell #callsView .call-row > .call-contact { display: block; }
    .app-shell #callsView .call-table-head span:nth-child(5),
    .app-shell #callsView .call-row > .call-ticket { display: block; }
  }

  /* 885-979px: the same six columns at the smallest size they read at. */
  @container calllist (min-width: 885px) and (max-width: 978.98px) {
    .app-shell #callsView .call-table-head,
    .app-shell #callsView .call-row {
      grid-template-columns: minmax(190px, 1.4fr) minmax(135px, .9fr) 92px minmax(112px, .75fr) 84px 160px;
      gap: 11px;
    }
    .app-shell #callsView .call-table-head span:nth-child(2),
    .app-shell #callsView .call-row > .call-contact { display: block; }
    .app-shell #callsView .call-table-head span:nth-child(5),
    .app-shell #callsView .call-row > .call-ticket { display: block; }
  }

  /* Under 885px the matched-contact column goes. It is the one whose content -- a venue name and
     whether the number matched -- the caller column already half answers. */
  @container calllist (max-width: 884.98px) {
    .app-shell #callsView .call-table-head,
    .app-shell #callsView .call-row {
      grid-template-columns: minmax(170px, 1.4fr) 90px minmax(105px, .8fr) 82px 155px;
      gap: 10px;
    }
    .app-shell #callsView .call-table-head span:nth-child(2),
    .app-shell #callsView .call-row > .call-contact { display: none; }
    .app-shell #callsView .call-table-head span:nth-child(5),
    .app-shell #callsView .call-row > .call-ticket { display: block; }
  }
}

/* ---- Reports: let the horizontal scrollers actually scroll ------------------------------------
   Under 700px the trend list is given `overflow-x: auto` and its rows a 770px `min-width`, which is
   the right shape -- the twelve months stay legible and you swipe along them. It never worked. A
   grid item's automatic minimum is its min-content, so `.kpi-trend-panel` inherited that 770px as a
   floor it could not go under, and every panel on the page was pinned to 804px inside a 430px
   phone. The page overflowed sideways by 406px and the scroller never scrolled, because there was
   nothing left for it to scroll. The CSAT table's 900px `min-width` did the same through its own
   wrapper.

   The floors were right; what was missing was permission for the ancestors to be narrower than
   their contents. */
.app-shell #reportsView .kpi-scorecard > *,
.app-shell #reportsView .kpi-team-dashboard,
.app-shell #reportsView .kpi-trend-panel,
.app-shell #reportsView .kpi-agent-section,
.app-shell #reportsView .kpi-detail-disclosure,
.app-shell #reportsView .kpi-trend-list,
.app-shell #reportsView .kpi-table-scroll,
.app-shell #reportsView .kpi-agent-grid,
.app-shell #reportsView .kpi-agent-card,
.app-shell #reportsView .kpi-agent-table,
.app-shell #reportsView .kpi-breaching,
.app-shell #reportsView .csat-results-panel,
.app-shell #reportsView .csat-results-table-wrap { min-width: 0; }

/* The scorecard's own grid, so a wide child cannot widen the column it sits in. */
.app-shell #reportsView .kpi-scorecard { grid-template-columns: minmax(0, 1fr); }

/* Card and agent columns by the space the report has rather than by the window: at 1100px the rail
   has collapsed and the page has 1042px, and it was showing two cards where it had shown three at
   1150px with 926. */
.app-shell #reportsView { container: reports / inline-size; }

@container reports (min-width: 720px) {
  .app-shell #reportsView .kpi-card-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@container reports (min-width: 480px) and (max-width: 719.98px) {
  .app-shell #reportsView .kpi-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container reports (max-width: 479.98px) {
  .app-shell #reportsView .kpi-card-grid { grid-template-columns: minmax(0, 1fr); }
}
@container reports (min-width: 660px) {
  .app-shell #reportsView .kpi-agent-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container reports (max-width: 659.98px) {
  .app-shell #reportsView .kpi-agent-grid { grid-template-columns: minmax(0, 1fr); }
}

/* A visually hidden label sits at its static position, and inside a horizontally scrolling table
   that position can be most of a metre to the right. The CSAT header's "Actions" label is 836px
   along its 900px table, and with its containing block on the body rather than on the scroller it
   dragged the whole document out to 836px: a 430px phone scrolled 406px sideways past the end of
   every panel on the page. Positioning the scrollers contains it -- and anything else absolute
   that lands inside them later. */
.app-shell .csat-results-table-wrap,
.app-shell .kpi-table-scroll,
.app-shell .kpi-trend-list { position: relative; }

/* ---- Dynamic viewport units where the value is a ceiling -------------------------------------
   Most of this stylesheet already writes `100vh` and then `100dvh`, so the newer unit wins where
   it is understood. These three were missed. It matters most for the modals: `vh` is the taller
   measure -- the viewport with the phone browser's address bar collapsed -- so a modal capped at
   `100vh - 40px` can be taller than what is actually on screen while the bar is showing, and its
   action buttons sit below the fold of a dialog that is centred rather than scrolled to. `dvh` is
   never larger than the space really available. */
.app-shell .modal,
.modal { max-height: calc(100dvh - 40px); }
.login-body { min-height: 100dvh; }

/* ---- The contact editor -----------------------------------------------------------------------
   A page, not a dialog. It shares the ticket detail bar so the two detail views back out the same
   way, and lays the form out in two columns: what the agent types on the left, what hangs off a
   saved contact -- venues, ticket history -- on the right. */

.app-shell .contact-detail-view { padding: 0; }
.app-shell .contact-editor-grid {
  min-height: 0;
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 22px;
  padding: 22px clamp(18px, 2vw, 32px) 30px;
  align-items: start;
}
.app-shell .contact-editor-main { min-width: 0; display: grid; gap: 22px; align-content: start; }
.app-shell .contact-editor-side { display: grid; gap: 22px; align-content: start; }
.app-shell .contact-editor-panel { padding: 22px; }
.app-shell .contact-editor-panel h2 { margin: 0 0 4px; font-size: 15px; font-weight: 700; }

/* The fields were written for a modal, where `.modal input` gave them their shape. Outside one
   they get it here, so the two forms stay the same form. */
.app-shell .contact-editor-panel label { display: block; margin-bottom: 14px; color: var(--text-soft); font-size: 11px; font-weight: 700; }
.app-shell .contact-editor-panel label > span { color: var(--coral); }
.app-shell .contact-editor-panel input,
.app-shell .contact-editor-panel select,
.app-shell .contact-editor-panel textarea {
  width: 100%;
  margin-top: 6px;
  padding: 0 11px;
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  outline: 0;
  color: var(--grey);
  background: var(--surface);
  font: inherit;
  font-size: 13px;
}
.app-shell .contact-editor-panel input,
.app-shell .contact-editor-panel select { height: 40px; }
.app-shell .contact-editor-panel textarea { min-height: 110px; padding-top: 10px; resize: vertical; line-height: 1.5; }
.app-shell .contact-editor-panel input:focus,
.app-shell .contact-editor-panel select:focus,
.app-shell .contact-editor-panel textarea:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.1); }
.app-shell .contact-editor-panel .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* Venues and history are panels of their own here, so the rule and top margin that separated them
   inside the modal would draw a line across the top of a box that already has a border. */
.app-shell .contact-editor-panel.contact-venues,
.app-shell .contact-editor-panel.contact-archive { margin-top: 0; padding-top: 22px; border-top: 1px solid var(--border); }

/* ---- One row per number ------------------------------------------------------------------------
   Type, number, which one is primary, and a way to take it off the list. The primary control is a
   radio rather than a button because that is what it is: one of several, exactly one chosen. */

.app-shell .contact-phone-list { display: grid; gap: 10px; }
.app-shell .contact-phone-row {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  display: grid;
  grid-template-columns: 118px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  background: var(--surface);
}
.app-shell .contact-phone-row.primary { border-color: var(--orange-tint); background: var(--orange-wash); }
.app-shell .contact-phone-row label { margin: 0; }
.app-shell .contact-phone-row input[type=tel],
.app-shell .contact-phone-row select { margin-top: 0; }
.app-shell .contact-phone-row input[type=tel] { font-variant-numeric: tabular-nums; }
.app-shell .contact-phone-primary { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 11px; font-weight: 700; white-space: nowrap; }
.app-shell .contact-phone-primary input[type=radio] { width: 15px; height: 15px; margin: 0; accent-color: var(--orange); }
.app-shell .contact-phone-row.primary .contact-phone-primary { color: var(--orange-ink); }
.app-shell .contact-phone-remove { width: 28px; height: 28px; border-radius: 7px; display: grid; place-items: center; font-size: 17px; line-height: 1; }
.app-shell .contact-phone-remove:hover { background: var(--coral-wash); text-decoration: none; }
.app-shell .contact-phone-remove[hidden],
.app-shell .contact-phone-primary[hidden],
.app-shell .contact-phone-add[hidden] { display: none; }
.app-shell .contact-phone-add { margin-top: 12px; }
.app-shell #contactPhoneError { margin: 12px 0 0; }

@media (max-width: 1080px) {
  .app-shell .contact-editor-grid { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .app-shell .contact-editor-grid { padding: 14px; gap: 14px; }
  .app-shell .contact-editor-panel { padding: 16px; }
  .app-shell .contact-editor-panel .form-grid { grid-template-columns: 1fr; }
  /* Four columns will not fit a phone, so the number gets the full width and the controls that
     describe it sit under it rather than being squeezed to nothing beside it. */
  .app-shell .contact-phone-row { grid-template-columns: minmax(0, 1fr) auto; }
  .app-shell .contact-phone-number { grid-column: 1 / -1; order: -1; }
}

/* ---- Overview: type that can actually be read ------------------------------------------------
   The dashboard had drifted into a scale it could not support. The heading was 36px, the metric
   numbers 27px, and then everything carrying the actual information sat between 7px and 10px --
   heavy, uppercase, widely tracked, and in the faintest ink on the palette. At arm's length from
   a desk monitor the attention queue's column labels were shapes rather than words.

   Two separate faults, fixed together because they have the same cause:

     - Size. `--text-faint` is #858a92, which measures 3.6:1 on a white row. WCAG asks 4.5:1 of
       body text and treats nothing below 14px as large, so 7px in that ink fails on both counts
       at once. The labels move to --muted (4.6:1) and to sizes a person reads rather than infers.

     - Rhythm. Letter-spacing above about .06em stops being emphasis and starts being a gap;
       combined with weight 800 at single-digit sizes it is what made the type look, in the
       reporter's words, funny. The microlabels here settle on one treatment -- 10px, 700, .04em
       -- instead of the four slightly different ones they had.

   These sit last and carry `#overviewView` so they win outright over the layers above, which is
   the convention the rest of the overview rules in this file already follow. */

/* The heading. Inter wants negative tracking at display sizes, but -.045em at 36px is -1.6px per
   letter and closes the counters up; -.022em keeps the tightening without the crowding. */
.app-shell #overviewView .overview-head h1 { letter-spacing: -.022em; }

/* Summary card captions. Uppercase is worth keeping -- it separates the label from the number
   below it without a rule or a colour -- but not at 9.5px in the heaviest weight available. */
.app-shell #overviewView .summary-card p {
  color: var(--text-soft);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
}
.app-shell #overviewView .summary-card > div:nth-child(2) > span { font-size: 11px; }
.app-shell #overviewView .metric-comparison { font-size: 9.5px; font-weight: 600; }

/* ---- The attention queue ----
   The row's tracks and heights are not here: they live with the container queries above, because
   a grid rule dropped in after them would out-order every narrowing step and hold the widest
   layout all the way down to a phone. Only type below this point. */

/* "Assigned to", "Status", "Priority" and "SLA status" used to sit on every row, above the value
   they named. Six repetitions of a label is not six times the information, and the stack was most
   of the row's height -- which is what held this list to four tickets out of a queue of forty-six.
   They are said once now, in a header on the same grid, the way the ticket queue names its own
   columns. Only the header carries the treatment; the rows carry values. */
/* `display` is not set here on purpose -- see the note above the container tiers. */
.app-shell #overviewView .attention-head-row {
  min-height: 27px;
  padding: 0 14px;
  border-bottom: 1px solid var(--border);
  align-items: center;
  gap: 0;
  background: var(--surface-muted);
}
/* Each label starts where its column's content starts, so the header reads as the columns rather
   than as a caption strip floating above them. The padding mirrors the row's own cells. */
.app-shell #overviewView .attention-head-cell.is-ticket { padding-left: 16px; }

/* The values under them. These are the words somebody is actually reading -- who the customer is,
   which agent has it -- and they were a point smaller than the labels that introduce them. */
.app-shell #overviewView .attention-detail > span,
.app-shell #overviewView .attention-detail > time,
.app-shell #overviewView .attention-cell-copy > span,
.app-shell #overviewView .attention-cell-copy > time {
  color: var(--text-soft);
  font-size: 12px;
  line-height: 1.4;
}

/* The subject was inheriting --muted. Not by intention: `.attention-item span` paints captions
   muted, `.attention-heading` is a span, and the subject is a `b` inside it, so the one line in
   the row that names the ticket was being drawn in the ink reserved for the notes about it. */
.app-shell #overviewView .attention-subject {
  color: var(--grey);
  font-size: 15.5px;
  line-height: 1.3;
}

/* Was `var(--text)`, which this stylesheet does not define. An unresolvable custom property on an
   inherited property computes to the inherited value, so the arrow happened to land on the right
   colour by falling through to the button. Name the token that exists. */
.app-shell #overviewView .attention-arrow { color: var(--text-soft); }

/* The SLA reading is the reason the row is in this panel at all, so it is the one thing here that
   does not shrink to fit. Uppercase comes off with the size increase: "3D REMAINING" in a coloured
   pill was three competing signals for one fact. */
.app-shell #overviewView .attention-meta strong {
  padding: 6px 10px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
}

/* With the labels gone the identity block is two lines instead of two lines plus a caption, so it
   sets the row's height on its own. These sizes are what let six rows sit where four did: the
   subject stays the largest thing in the row, and the line under it -- customer, route, when it
   arrived -- steps back to being what it is, a footnote to the subject. */
.app-shell #overviewView .attention-heading { margin-bottom: 2px; gap: 8px; }

/* ---- "Customer responded" under the subject, as in the queue ----------------------------------
 * The tag used to sit between the subject and the ticket id, so on a responded row the subject --
 * already the only shrinkable thing on that line -- paid for it and ellipsised early. It moves to
 * the customer line, which is a footnote and can afford the width. That line stops being a single
 * truncating block and becomes the same flex contract used everywhere else in this stylesheet:
 * the text shrinks and ellipsises, the tag keeps its intrinsic width. */
.app-shell #overviewView .attention-customer {
  display: flex;
  align-items: center;
  gap: 7px;
  overflow: visible;
  white-space: normal;
}

/* The stacked card drops the tag to its own line rather than squeezing the customer to nothing. */
@media (max-width: 760px) {
  .app-shell #overviewView .attention-customer { flex-wrap: wrap; row-gap: 4px; }
  .app-shell #overviewView .attention-customer > .attention-customer-text { flex-basis: 100%; }
}

/* ---- The ticket's contact ----
   One section, not two. The picker used to sit among the properties, beside the status and the
   agent, with a summary card underneath it drawn from the details on the ticket -- so a ticket
   appeared to have two contacts, and when the link was missing they disagreed. The link is here
   now, and what is on the card is the person it points at. */
.app-shell #ticketView .side-panel-actions { display: flex; align-items: center; gap: 0; }
.app-shell #ticketView .side-panel-actions button {
  min-height: 28px;
  padding: 0 11px;
  font-size: 11px;
  font-weight: 700;
}
.app-shell #ticketView .side-panel-actions button + button {
  border-left: 1px solid var(--border);
}
.app-shell #ticketView .side-panel-actions button:last-child { padding-right: 0; }
.app-shell #ticketView .side-panel-actions button:hover { color: var(--link); text-decoration: underline; }

/* Contact comes first because it answers who the agent is helping before Properties answers how
   the ticket is classified. The identity is deliberately scannable: name and organisation lead,
   then labelled, actionable contact methods instead of three similarly styled loose lines. */
.app-shell #ticketView .contact-summary-panel {
  overflow: visible;
  border-color: color-mix(in srgb, var(--orange) 24%, var(--border));
  background:
    radial-gradient(circle at 100% 0, rgba(255,117,26,.09), transparent 45%),
    var(--surface);
}
.app-shell #ticketView .ticket-contact-card {
  padding: 18px 17px 16px;
  align-items: flex-start;
  gap: 13px;
}
.app-shell #ticketView .ticket-contact-card .avatar {
  width: 48px;
  height: 48px;
  box-shadow: 0 0 0 4px var(--orange-wash);
}
.app-shell #ticketView .ticket-contact-details { min-width: 0; flex: 1; }
.app-shell #ticketView .ticket-contact-details > b {
  margin: 0;
  overflow: hidden;
  color: var(--text);
  font-size: 14px;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell #ticketView .ticket-contact-company {
  margin: 4px 0 13px;
  overflow: hidden;
  color: var(--muted);
  font-size: 10.5px;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell #ticketView .ticket-contact-methods { margin: 0; display: grid; gap: 8px; }
.app-shell #ticketView .ticket-contact-methods > div {
  min-width: 0;
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr);
  align-items: baseline;
  gap: 8px;
}
.app-shell #ticketView .ticket-contact-methods dt {
  color: var(--text-faint);
  font-size: 8px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.app-shell #ticketView .ticket-contact-methods dd { min-width: 0; margin: 0; }
.app-shell #ticketView .ticket-contact-methods a {
  margin: 0;
  overflow: hidden;
  color: var(--link);
  font-size: 10.5px;
  font-weight: 650;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell #ticketView .ticket-contact-methods a:hover { text-decoration: underline; }
.app-shell #ticketView .ticket-contact-methods > div[hidden] { display: none; }
.app-shell #ticketView .contact-unlinked-note {
  margin: 0;
  padding: 0 17px 14px;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
}
/* Shown only when somebody asks to change the contact, which is the rare correction rather than
   the daily act -- a ticket that arrived under the wrong address, or one the PBX could not put a
   name to. Laid out as the property fields are, because it is one of them. */
.app-shell #ticketView .ticket-contact-change {
  padding: 0 17px 16px;
  display: block;
  color: var(--text-soft);
  font-size: 11px;
  font-weight: 700;
}
.app-shell #ticketView .drawer-contact-picker { margin-top: 6px; position: relative; }
.app-shell #ticketView .drawer-contact-picker > input[type="search"] {
  width: 100%;
  height: 38px;
  padding: 0 11px;
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  outline: 0;
  color: var(--grey);
  background: var(--surface);
  font-size: 12px;
  font-weight: 500;
}
.app-shell #ticketView .drawer-contact-picker > input[type="search"]:focus { border-color: var(--orange); }
/* Above the panels below it, and never taller than the rail it drops inside. */
.app-shell #ticketView .drawer-contact-picker .contact-picker-results {
  z-index: 60;
  max-height: min(320px, 45vh);
}
.app-shell #ticketView .ticket-contact-change > label { display: block; }
.app-shell #ticketView .ticket-contact-change small {
  margin-top: 6px;
  display: block;
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 600;
}

/* ---- The ticket status catalogue ----
   Statuses are a setting, so Settings needs somewhere to show and edit them. A row per status,
   the pill drawn exactly as the queue draws it, so what an admin is arranging is the thing they
   will see on a ticket. */
.ticket-status-settings { display: grid; gap: 8px; margin-top: 14px; }
.ticket-status-setting {
  min-height: 52px;
  padding: 9px 11px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--surface-sunken);
}
.ticket-status-identity { min-width: 0; display: flex; align-items: center; gap: 9px; }
.ticket-status-identity small { color: var(--text-faint); font-size: 9.5px; }
.ticket-status-colour-control {
  min-height: 34px;
  padding: 3px 5px 3px 10px;
  display: flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--hairline);
  border-radius: 9px;
  color: var(--text-muted);
  font-size: 10px;
  cursor: pointer;
}
.ticket-status-colour { width: 28px; height: 26px; padding: 2px; border: 0; background: transparent; cursor: pointer; }
.ticket-status-required { min-width: 48px; color: var(--text-faint); font-size: 9.5px; text-align: right; }
.ticket-status-setting .danger-text { min-width: 48px; padding: 0; text-align: right; }
.ticket-status-create { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--hairline); }
.ticket-status-create > div:first-child { display: flex; flex-direction: column; gap: 2px; }
.ticket-status-create > div:first-child b { font-size: 11px; }
.ticket-status-create > div:first-child small { color: var(--text-muted); font-size: 10px; }
.ticket-status-add { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 9px; margin-top: 10px; align-items: stretch; }
.ticket-status-add input { min-width: 0; }
.status-colour-picker { display: flex; align-items: center; gap: 7px; padding: 0 9px 0 5px; border: 1px solid var(--hairline); border-radius: 8px; color: var(--text-muted); font-size: 10px; cursor: pointer; }
.status-colour-picker input { width: 31px; height: 30px; padding: 3px; border: 0; background: transparent; cursor: pointer; }
.activity-visibility-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.activity-visibility-heading > span { color: var(--green-ink); font-size: 9.5px; font-weight: 700; white-space: nowrap; }
.activity-visibility-heading > span.saving { color: var(--amber-ink); }
.activity-visibility-heading > span.error { color: var(--coral-ink); }
.activity-visibility-grid { display: grid; gap: 7px; margin-top: 13px; }
.activity-visibility-grid label {
  min-height: 48px;
  padding: 8px 10px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--surface-sunken);
  cursor: pointer;
}
.activity-visibility-grid input { width: 15px; height: 15px; accent-color: var(--orange); }
.activity-visibility-grid span { display: flex; flex-direction: column; gap: 2px; }
.activity-visibility-grid b { font-size: 10.5px; }
.activity-visibility-grid small { color: var(--text-muted); font-size: 9.5px; line-height: 1.35; }
@media (min-width: 720px) { .activity-visibility-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) {
  .ticket-status-setting { grid-template-columns: minmax(0, 1fr) auto; }
  .ticket-status-setting > :last-child { grid-column: 2; }
  .ticket-status-add { grid-template-columns: 1fr; }
}

/* The workspace catalogue supplies the colour; this static rule is the pre-settings fallback. */
.status-pill.waiting-on-customer { color: var(--violet-ink); background: var(--violet-wash); }
/* The tint and edge take the admin's hue; the text is that hue moved until it reads on the tint,
   computed per theme in site.js (setStatusColour). The old fixed mix toward white measured
   1.7-2.2:1 for every default status in the light theme. */
.catalogue-status, .workspace-ticket-tab-dot { --status-ink: var(--status-ink-light, var(--status-colour)); }
:root[data-theme="dark"] .catalogue-status,
:root[data-theme="dark"] .workspace-ticket-tab-dot { --status-ink: var(--status-ink-dark, var(--status-colour)); }
.status-pill.catalogue-status,
.attention-badge.catalogue-status {
  color: var(--status-ink);
  background: color-mix(in srgb, var(--status-colour) 14%, transparent);
  border-color: color-mix(in srgb, var(--status-colour) 34%, transparent);
}
:root[data-theme="dark"] .status-pill.catalogue-status,
:root[data-theme="dark"] .attention-badge.catalogue-status { background: color-mix(in srgb, var(--status-colour) 18%, transparent); }
.workspace-ticket-tab-dot { background: var(--status-ink) !important; }

/* Exchange's external-sender warning, after the message rather than in front of it. Sized as
   chrome: it is a standing notice about a category of mail every ticket here belongs to, so it
   should be findable, not loud. */
.external-sender-footer {
  margin-top: 14px;
  padding: 9px 11px;
  border-top: 1px solid var(--hairline);
  display: block;
  color: var(--text-faint);
  font-size: 10.5px;
  line-height: 1.45;
}

/* ---- Selecting contacts ----
   The checkbox rides in the first cell rather than taking a grid track of its own, so the five
   responsive layouts of this table keep their columns and their nth-child rules. */
.app-shell #contactsView .contact-head-person { display: flex; align-items: center; gap: 10px; }
.app-shell #contactsView .contact-select-all,
.app-shell #contactsView .contact-row-select {
  display: flex;
  align-items: center;
  flex: none;
  cursor: pointer;
}
.app-shell #contactsView .contact-select-all input,
.app-shell #contactsView .contact-row-select input {
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--orange);
  cursor: pointer;
}
.app-shell #contactsView .contact-toolbar-actions { display: flex; align-items: center; gap: 12px; }
/* Sized as a toolbar button rather than a form button, and only present while something is
   selected, so the destructive action is never the resting state of the page. */
.app-shell #contactsView .contact-bulk-delete { min-height: 36px; padding: 0 14px; font-size: 11px; }

/* ---- The ten seconds before a reply leaves -------------------------------------------------
   Pressing Send starts a countdown in the send row rather than a request. Nothing has been
   posted while it runs, so Undo puts the agent back in front of the reply they were writing,
   with its files and recipients untouched. It stands in the row the agent is already looking at
   -- the one their hand is on -- and takes the whole row, because for those ten seconds the only
   thing worth offering is the way out. */
.app-shell #replyForm.reply-holding .reply-send-actions,
.app-shell #replyForm.reply-holding #replyHint { display: none; }
.app-shell .reply-send-hold {
  min-height: 38px;
  padding: 0 6px 0 12px;
  border: 1px solid var(--orange-wash-border);
  border-radius: 999px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  background: var(--orange-wash);
}
.app-shell .reply-send-hold[hidden] { display: none; }
.app-shell .reply-send-hold-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
  background: var(--orange);
  animation: reply-send-hold-pulse 1s ease-in-out infinite;
}
.app-shell .reply-send-hold-text {
  flex: 1;
  color: var(--orange-ink);
  font-size: 11px;
  font-weight: 700;
}
.app-shell .reply-send-undo {
  min-height: 30px;
  padding: 0 16px;
  border: 1px solid var(--orange);
  border-radius: 999px;
  flex: none;
  color: var(--orange-ink);
  background: var(--surface);
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  font-weight: 800;
}
.app-shell .reply-send-undo:hover { background: var(--surface-muted); }
.app-shell .reply-send-undo:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
/* The editor keeps its text while the countdown runs; it is only closed to further typing, and
   says so quietly rather than greying out the words about to be sent. */
.app-shell #replyForm.reply-holding .reply-editor { opacity: .75; }
@keyframes reply-send-hold-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .45; transform: scale(.78); }
}
@media (prefers-reduced-motion: reduce) {
  .app-shell .reply-send-hold-dot { animation: none; }
}

.app-shell .reply-send-note { display: none; }
.app-shell #replyForm[data-reply-mode="note"] .reply-send-public { display: none; }
.app-shell #replyForm[data-reply-mode="note"] .reply-send-note { display: inline; }
.app-shell #replyForm[data-reply-mode="note"] .reply-send-main {
  border-radius: 8px !important;
}
.app-shell #replyForm[data-reply-mode="note"] .reply-send-toggle { display: none !important; }

/* ---- Contact workspace: one calm, complete working page --------------------------------------
   The editor used to look like several modal cards placed on a page. A contact is one record, so
   the page now reads as one continuous workspace: a wide identity/phone column and a contextual
   venue/history rail, separated by rhythm and one quiet rule instead of nested boxes. */
.app-shell #contactView {
  background:
    radial-gradient(circle at 78% 0, rgba(255,117,26,.055), transparent 32%),
    var(--surface);
}
.app-shell #contactView .ticket-detail-bar {
  position: sticky;
  top: 0;
  z-index: 4;
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: blur(12px);
}
.app-shell #contactView .contact-editor-grid {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: clamp(18px, 2vw, 30px) clamp(18px, 2.5vw, 42px) 42px;
  grid-template-columns: minmax(0, 1.65fr) minmax(300px, .75fr);
  gap: clamp(24px, 3vw, 52px);
}
.app-shell #contactView .contact-editor-main,
.app-shell #contactView .contact-editor-side { gap: 0; }
.app-shell #contactView .contact-editor-side {
  min-width: 0;
  padding-left: clamp(22px, 2.6vw, 42px);
  border-left: 1px solid var(--border);
}
.app-shell #contactView .contact-editor-panel {
  padding: 0 0 26px;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
}
.app-shell #contactView .contact-editor-panel + .contact-editor-panel {
  padding-top: 26px;
  border-top: 1px solid var(--border);
}
.app-shell #contactView .contact-editor-panel h2 {
  margin-bottom: 7px;
  font-size: 17px;
  letter-spacing: -.015em;
}
.app-shell #contactView .contact-section-hint {
  max-width: 760px;
  margin-bottom: 20px;
  line-height: 1.55;
}
.app-shell #contactView .contact-editor-panel input,
.app-shell #contactView .contact-editor-panel select,
.app-shell #contactView .contact-editor-panel textarea {
  background: var(--surface);
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.app-shell #contactView .contact-editor-panel input:hover,
.app-shell #contactView .contact-editor-panel select:hover,
.app-shell #contactView .contact-editor-panel textarea:hover { border-color: var(--text-faint); }
.app-shell #contactView .contact-phone-row {
  background: var(--surface);
  box-shadow: 0 5px 18px rgba(0,0,0,.035);
}
.app-shell #contactView .contact-venue-row {
  width: 100%;
  min-height: 48px;
  padding: 9px 12px;
  border: 1px solid var(--border);
}
.app-shell #contactView .contact-venue-search { margin-top: 16px; }
.app-shell #contactView .contact-archive { min-height: 130px; }

@media (max-width: 1080px) {
  .app-shell #contactView .contact-editor-grid { grid-template-columns: minmax(0, 1fr); }
  .app-shell #contactView .contact-editor-side {
    padding: 24px 0 0;
    border-top: 1px solid var(--border);
    border-left: 0;
  }
}
@media (max-width: 720px) {
  .app-shell #contactView .ticket-breadcrumb { align-items: flex-start; }
  .app-shell #contactView .ticket-detail-actions { width: 100%; }
  .app-shell #contactView .ticket-detail-actions .primary-button { flex: 1; }
  .app-shell #contactView .contact-editor-grid { padding: 16px 14px 30px; }
}

/* Overview established the compact workspace heading. Keep Contacts, Venues, Calls, Reports and
   the other primary pages on that same rhythm so navigation never causes a title-size jump. */
.app-shell .view > .page-head { min-height: 60px; margin-bottom: 16px; }
.app-shell .view > .page-head h1 { font-size: clamp(28px, 2vw, 36px); }
.app-shell .view > .page-head > div > p:last-child { font-size: 13px; }
@media (max-height: 940px) and (min-width: 761px) {
  .app-shell .view > .page-head { min-height: 50px; margin-bottom: 9px; }
  .app-shell .view > .page-head h1 { margin-bottom: 2px; font-size: clamp(22px, 1.5vw, 27px); }
  .app-shell .view > .page-head > div > p:last-child { font-size: 12px; }
  .app-shell .view > .page-head .eyebrow { margin-bottom: 2px !important; }
}

/* Both controls live in the contact heading, but they are separate labelled groups. Keeping the
   select label on one line prevents it wrapping through or visually colliding with Contact. */
.app-shell #contactsView .contact-head-person { gap: 18px; }
.app-shell #contactsView .contact-select-all { gap: 7px; white-space: nowrap; line-height: 1; }
.app-shell #contactsView .contact-column-label { min-width: 0; }

/* The contact directory is read all day and its original 9–10px type was too small on a normal
   workstation. Keep the established 84px rows, padding and column tracks exactly as they are;
   use that existing room for a clearer name/detail hierarchy instead. */
.app-shell #contactsView .contacts-toolbar h2 { font-size: 19px; letter-spacing: -.015em; }
.app-shell #contactsView .contacts-toolbar > div > span { font-size: 12px; }
.app-shell #contactsView .contact-search input { font-size: 12.5px; }
.app-shell #contactsView .contact-table-head { font-size: 11.5px; letter-spacing: .065em; }
.app-shell #contactsView .contact-person .avatar { font-size: 11px; }
.app-shell #contactsView .contact-person .contact-open {
  margin-bottom: 3px;
  color: var(--grey);
  font-size: 14px;
  line-height: 1.25;
  letter-spacing: -.01em;
}
.app-shell #contactsView .contact-person span:not(.avatar) {
  color: var(--muted);
  font-size: 11.5px;
  line-height: 1.3;
}
.app-shell #contactsView .contact-cell { font-size: 11px; line-height: 1.3; }
.app-shell #contactsView .contact-cell b {
  margin-bottom: 3px;
  color: var(--text-soft);
  font-size: 12.5px;
  line-height: 1.3;
}
.app-shell #contactsView .contact-cell > span { color: var(--muted); font-size: 11px; }
.app-shell #contactsView .contact-cell-empty b { color: var(--muted); }
.app-shell #contactsView .contact-ticket-count {
  width: max-content;
  min-width: 28px;
  min-height: 28px;
  padding: 0 8px;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--text-soft);
  background: var(--surface-muted);
  font-size: 12px;
  font-weight: 750;
}
.app-shell #contactsView .contact-actions button { font-size: 11px; font-weight: 700; }
.app-shell #contactsView .contact-actions .archive-contact { font-size: 14px; }
.app-shell #contactsView .contact-row { transition: background .14s ease, box-shadow .14s ease; }
.app-shell #contactsView .contact-row:hover { box-shadow: inset 3px 0 0 var(--orange); }
.app-shell #contactsView .contact-row:has(.contact-row-select input:checked) {
  background: var(--orange-wash);
  box-shadow: inset 3px 0 0 var(--orange);
}

/* Stable per-contact pastels. Only customer avatars receive the class; agent identity colours and
   status colours keep their existing semantics. Hue is selected from a fixed palette in JS. */
.app-shell .avatar.contact-avatar {
  color: hsl(var(--contact-avatar-hue) 54% 31%);
  background: hsl(var(--contact-avatar-hue) 72% 89%);
  box-shadow: inset 0 0 0 1px hsl(var(--contact-avatar-hue) 48% 54% / .16);
}
:root[data-theme="dark"] .app-shell .avatar.contact-avatar {
  color: hsl(var(--contact-avatar-hue) 76% 78%);
  background: hsl(var(--contact-avatar-hue) 39% 23%);
  box-shadow: inset 0 0 0 1px hsl(var(--contact-avatar-hue) 65% 65% / .18);
}

/* One company design with per-agent fields. This intentionally sits at full email-panel width so
   the real Outlook-sized preview remains readable without making the form cramped. */
.agent-signature-settings { margin-top:18px; overflow:visible; }
.signature-settings-layout { display:grid; grid-template-columns:minmax(0,1.45fr) minmax(320px,.75fr); }
.signature-settings-editor { min-width:0; padding-bottom:18px; border-right:1px solid var(--hairline); }
.signature-master-toggle { margin:0 18px; }
.signature-agent-panel { min-width:0; padding:20px; }
.signature-agent-panel h4 { margin:0 0 5px; font-size:13px; }
.signature-agent-panel > p { margin:0 0 18px; color:var(--muted); font-size:9px; line-height:1.5; }
.signature-agent-panel .email-field { display:block; margin-bottom:14px; }
.signature-agent-panel select,.signature-agent-panel input { width:100%; height:40px; margin-top:7px; padding:0 11px; border:1px solid var(--border-dark); border-radius:8px; color:var(--grey); background:var(--surface); outline:0; }
.signature-agent-panel select:focus,.signature-agent-panel input:focus { border-color:var(--orange); box-shadow:0 0 0 3px rgba(255,117,26,.1); }
.signature-phone-grid { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
.signature-colour-control { height:40px; margin-top:7px; padding:4px 10px 4px 5px; border:1px solid var(--border-dark); border-radius:8px; display:flex; align-items:center; gap:10px; }
.signature-colour-control input { width:48px; height:30px; margin:0; padding:0; border:0; cursor:pointer; }
.signature-colour-control code { color:var(--text-soft); font-size:10px; }
.signature-banner-editor { margin:0 18px 18px; padding:14px; border:1px solid var(--border); border-radius:10px; display:grid; grid-template-columns:1fr auto; gap:12px; align-items:center; }
.signature-banner-editor b,.signature-banner-editor small { display:block; }
.signature-banner-editor small { margin-top:4px; color:var(--muted); font-size:8px; }
.signature-banner-actions { display:flex; align-items:center; gap:8px; }
.signature-banner-editor img { grid-column:1/-1; max-width:100%; max-height:150px; border-radius:5px; object-fit:contain; object-position:left center; }
.signature-settings-editor > .primary-button { margin-left:18px; }
.signature-preview-heading { margin-top:24px !important; padding-top:18px; border-top:1px solid var(--hairline); }
.signature-preview { min-height:190px; margin-top:10px; padding:16px; border:1px solid var(--border); border-radius:10px; overflow:auto; color:#2b2b2b; background:#fff; color-scheme:light; }
/* A preview of what the customer receives, so it stays email paper -- softened, so it is not the
   brightest thing in a dark settings page. */
:root[data-theme="dark"] .signature-preview { background:#f1f3f6; border-color:transparent; box-shadow:0 0 0 1px rgba(210,220,240,.12); }
.signature-preview > span { color:#777; font-size:10px; }
.message-html .desk-agent-signature { max-width:680px; margin-top:20px !important; color:var(--grey) !important; }
.message-html .desk-agent-signature img { max-width:100%; height:auto; }
.reply-editor .desk-agent-signature { max-width:680px; margin-top:24px !important; color:var(--grey) !important; }
.reply-editor .desk-agent-signature img { max-width:100%; height:auto; }
/* Keep the signature's table, spacing, type hierarchy and campaign artwork intact in both the
   editable composer and Activity. Only translate the few dark-on-white template colours to the
   workspace theme; the old blanket inherit rule flattened every carefully formatted element. */
.message-html .desk-agent-signature [style*="#2f2f2f"],
.reply-editor .desk-agent-signature [style*="#2f2f2f"] { color:var(--text) !important; }
.message-html .desk-agent-signature [style*="#727272"],
.message-html .desk-agent-signature [style*="#777"],
.message-html .desk-agent-signature [style*="#8f8f8f"],
.reply-editor .desk-agent-signature [style*="#727272"],
.reply-editor .desk-agent-signature [style*="#777"],
.reply-editor .desk-agent-signature [style*="#8f8f8f"] { color:var(--muted) !important; }
.message-html .desk-agent-signature a,
.reply-editor .desk-agent-signature a { color: var(--link) !important; }
@media (max-width:1000px) { .signature-settings-layout { grid-template-columns:1fr; }.signature-settings-editor { border-right:0; border-bottom:1px solid var(--hairline); } }
@media (max-width:620px) { .signature-phone-grid { grid-template-columns:1fr; gap:0; }.signature-banner-editor { grid-template-columns:1fr; }.signature-banner-actions { flex-wrap:wrap; } }

/* ---- Canned response library -----------------------------------------------------------------
   A compact library beside one focused editor. The selected response owns the right side; there
   are no nested cards competing with the settings panel around it. */
.canned-response-section-head { display:flex; align-items:center; justify-content:space-between; gap:18px; }
.canned-response-settings {
  min-height: 540px;
  padding: 0 !important;
  display: grid;
  grid-template-columns: minmax(280px, .72fr) minmax(420px, 1.28fr);
}
.canned-response-library {
  min-width: 0;
  padding: 20px;
  border-right: 1px solid var(--border);
}
.canned-response-library-head { display:grid; gap:12px; }
.canned-response-library-head > div { display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
.canned-response-library-head h3 { margin:0; font-size:14px; }
.canned-response-library-head > div span { color:var(--muted); font-size:9.5px; }
.canned-response-search {
  height: 39px;
  padding: 0 11px;
  border: 1px solid var(--border-dark);
  border-radius: 9px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  background: var(--surface-sunken);
}
.canned-response-search:focus-within { border-color:var(--orange); box-shadow:0 0 0 3px var(--orange-wash); }
.canned-response-search input { min-width:0; flex:1; border:0; outline:0; color:var(--text); background:transparent; font:inherit; font-size:11px; }
.canned-response-list { margin-top:14px; display:grid; gap:5px; }
.canned-response-row {
  width:100%;
  min-width:0;
  padding:11px 12px;
  border:1px solid transparent;
  border-radius:10px;
  display:grid;
  gap:5px;
  color:var(--text);
  background:transparent;
  cursor:pointer;
  text-align:left;
}
.canned-response-row:hover { background:var(--surface-muted); }
.canned-response-row.active { border-color:var(--orange-wash-border); background:var(--orange-wash); }
.canned-response-row-heading { min-width:0; display:flex; align-items:center; gap:8px; }
.canned-response-row-heading b { overflow:hidden; font-size:11.5px; text-overflow:ellipsis; white-space:nowrap; }
.canned-response-row-heading code { margin-left:auto; color: var(--link); font-size:9px; white-space:nowrap; }
.canned-response-row-preview { overflow:hidden; color:var(--text-muted); font-size:10px; text-overflow:ellipsis; white-space:nowrap; }
.canned-response-row small { color:var(--text-faint); font-size:8.5px; }
.canned-response-list-empty { min-height:180px; padding:44px 20px; display:grid; place-content:center; gap:5px; color:var(--muted); text-align:center; }
.canned-response-list-empty b { color:var(--text-soft); font-size:11px; }
.canned-response-list-empty span { font-size:9.5px; }
.canned-response-editor-panel { min-width:0; padding:24px clamp(22px,3vw,38px); }
.canned-response-editor-empty { min-height:430px; display:grid; place-content:center; justify-items:center; color:var(--muted); text-align:center; }
.canned-response-editor-empty > span { width:42px; height:42px; margin-bottom:12px; border-radius:12px; display:grid; place-items:center; color: var(--link); background:var(--orange-wash); font-size:19px; }
.canned-response-editor-empty h3 { margin:0 0 5px; color:var(--text-soft); font-size:14px; }
.canned-response-editor-empty p { margin:0; font-size:10px; }
.canned-response-editor-fields[hidden],.canned-response-editor-empty[hidden] { display:none; }
.canned-response-editor-head { margin-bottom:20px; display:flex; align-items:flex-start; justify-content:space-between; gap:16px; }
.canned-response-editor-head > div { display:grid; gap:4px; }
.canned-response-editor-head span { color: var(--link); font-size:8px; font-weight:800; letter-spacing:.09em; }
.canned-response-editor-head h3 { margin:0; font-size:17px; }
.canned-response-meta-fields { margin-bottom:17px; }
.canned-response-meta-fields { align-items:start; }
.canned-response-meta-fields > label { display:grid; grid-template-rows:18px 40px; align-items:start; }
.canned-response-field-label { color:var(--text-soft); font-size:10px; font-weight:700; }
.canned-response-field-label > em,.canned-response-body-label > span { color:var(--coral-ink); font-style:normal; }
.canned-response-field-label > small { display:inline; margin-left:4px; color:var(--text-faint); font-size:8px; font-weight:500; }
.canned-response-meta-fields > label > input { margin-top:0; }
.canned-response-shortcut-field { height:40px; margin-top:7px; border:1px solid var(--border-dark); border-radius:8px; display:flex; align-items:center; overflow:hidden; background:var(--surface); }
.canned-response-meta-fields .canned-response-shortcut-field { margin-top:0; }
.canned-response-shortcut-field:focus-within { border-color:var(--orange); box-shadow:0 0 0 3px var(--orange-wash); }
.canned-response-shortcut-field > span { padding-left:11px; color: var(--link); font-size:12px; font-weight:750; }
.canned-response-shortcut-field input { height:38px !important; margin:0 !important; padding-left:3px !important; border:0 !important; box-shadow:none !important; }
.canned-response-body-label { display:block; margin-bottom:7px; color:var(--text-soft); font-size:10px; font-weight:700; }
.canned-response-format-bar { min-height:35px; padding:4px 6px; border:1px solid var(--border-dark); border-bottom:0; border-radius:9px 9px 0 0; display:flex; align-items:center; gap:2px; background:var(--surface-muted); }
.canned-response-format-bar > span { width:1px; height:20px; margin:0 4px; background:var(--border-dark); }
.canned-response-format-bar button { width:29px; height:27px; padding:0; border:0; border-radius:6px; color:var(--text-soft); background:transparent; cursor:pointer; font:inherit; font-size:11px; }
.canned-response-format-bar button:hover,.canned-response-format-bar button:focus-visible { color: var(--link); background:var(--surface); outline:0; }
.canned-response-body { min-height:230px; max-height:48vh; padding:14px; border:1px solid var(--border-dark); border-radius:0 0 9px 9px; overflow:auto; outline:0; color:var(--text); background:var(--surface); font-size:12px; line-height:1.55; }
.canned-response-body:focus { border-color:var(--orange); box-shadow:0 0 0 3px var(--orange-wash); }
.canned-response-body:empty::before { content:attr(data-placeholder); color:var(--muted); pointer-events:none; }
.canned-response-body p { margin:0 0 9px; }
.canned-response-body ul,.canned-response-body ol { padding-left:22px; }
.canned-response-body a { color: var(--link); }
.canned-response-attachments { margin-top:12px; display:flex; align-items:center; justify-content:space-between; gap:12px; }
.canned-response-attachments > div { display:grid; gap:2px; color:var(--text-soft); font-size:10px; }
.canned-response-attachments > div > span { color:var(--muted); font-size:9px; }
.canned-response-attachments .secondary-button { min-height:32px; padding:6px 12px; }
.canned-response-attachment-list { margin-top:9px; display:flex; flex-wrap:wrap; gap:7px; }
.canned-response-attachment-list:empty { display:none; }
.canned-response-attachment { max-width:260px; padding:7px 8px 7px 10px; border:1px solid var(--border); border-radius:8px; display:flex; align-items:center; gap:8px; background:var(--surface-muted); }
.canned-response-attachment > span { min-width:0; display:grid; gap:1px; }
.canned-response-attachment b,.canned-response-attachment small { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.canned-response-attachment b { color:var(--text-soft); font-size:9px; }
.canned-response-attachment small { color:var(--muted); font-size:8px; }
.canned-response-attachment button { width:22px; height:22px; padding:0; border:0; border-radius:6px; color:var(--muted); background:transparent; cursor:pointer; }
.canned-response-attachment button:hover { color:var(--coral-ink); background:var(--coral-pale); }
.canned-response-editor-actions { margin-top:18px; padding-top:14px; border-top:1px solid var(--hairline); display:grid; grid-template-columns:auto 1fr auto auto; align-items:center; gap:9px; }
.canned-response-editor-actions .canned-response-delete-button { min-height:36px; padding:7px 12px; border-color:var(--coral-pale); gap:6px; color:var(--coral-hover)!important; background:var(--surface); }
.canned-response-editor-actions .canned-response-delete-button:hover,.canned-response-editor-actions .canned-response-delete-button:focus-visible { border-color:var(--coral-ink); color:var(--coral-ink)!important; background:var(--coral-pale); }
.canned-response-editor-actions .canned-response-delete-button > span { font-size:15px; line-height:1; }
@media (max-width:1050px) {
  .canned-response-settings { grid-template-columns:1fr; }
  .canned-response-library { border-right:0; border-bottom:1px solid var(--border); }
  .canned-response-list { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:620px) {
  .canned-response-section-head { align-items:flex-start; flex-direction:column; }
  .canned-response-settings { min-height:0; }
  .canned-response-list { grid-template-columns:1fr; }
  .canned-response-editor-panel { padding:20px 15px; }
  .canned-response-editor-actions { grid-template-columns:1fr 1fr; }
  .canned-response-editor-actions > span { display:none; }
  .canned-response-editor-actions .canned-response-delete-button { grid-column:1/-1; width:max-content; }
}

/* ---- Full-page ticket editor ------------------------------------------------------------------
   Ticket creation is substantial work, not a confirmation dialog. The page keeps customer and
   request context wide, routing compact, and the final action visible without trapping the agent
   inside a scrolling modal. */
.app-shell .ticket-create-view {
  min-height: calc(100dvh - 74px);
  padding: 0;
  background:
    radial-gradient(circle at 82% 3%, rgba(255,117,26,.08), transparent 28rem),
    var(--surface-sunken);
}
.app-shell .ticket-create-head {
  min-height: 108px;
  padding: 22px clamp(20px,3vw,46px);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 16px;
  background: var(--surface);
}
.app-shell .ticket-create-back {
  width: 42px;
  height: 42px;
  border: 1px solid var(--border-dark);
  border-radius: 11px;
  display: grid;
  place-items: center;
  flex: none;
  color: var(--text-soft);
  background: var(--surface);
  cursor: pointer;
  font-size: 18px;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.app-shell .ticket-create-back:hover { border-color: var(--orange); color: var(--link); background: var(--orange-wash); }
.app-shell .ticket-create-head .eyebrow { margin: 0 0 5px; color: var(--link); }
.app-shell .ticket-create-head h1 { margin: 0; font-size: clamp(22px,2vw,29px); letter-spacing: -.025em; }
.app-shell .ticket-create-head > div > p:last-child { margin: 5px 0 0; color: var(--muted); font-size: 12.5px; }
.app-shell .ticket-create-form { min-height: 0; flex: 1; display: flex; flex-direction: column; }
.app-shell .ticket-create-layout {
  width: min(1280px,100%);
  margin: 0 auto;
  padding: 28px clamp(20px,3vw,46px) 34px;
  display: grid;
  grid-template-columns: minmax(0,1fr) minmax(300px,360px);
  gap: clamp(34px,4vw,58px);
  align-items: start;
  flex: 1;
}
.app-shell .ticket-create-main { min-width: 0; display: grid; gap: 32px; align-content: start; }
.app-shell .ticket-create-side {
  min-width: 0;
  padding-left: clamp(26px,3vw,42px);
  border-left: 1px solid var(--border);
  display: grid;
  gap: 24px;
  align-content: start;
}
.app-shell .ticket-create-card {
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.app-shell .ticket-create-request-card { padding-top: 32px; border-top: 1px solid var(--border); }
.app-shell .ticket-create-card-head { margin-bottom: 24px; display: flex; align-items: flex-start; gap: 13px; }
.app-shell .ticket-create-card-head > div { min-width: 0; }
.app-shell .ticket-create-card-head h2 { margin: 1px 0 5px; font-size: 17px; letter-spacing: -.015em; }
.app-shell .ticket-create-card-head p { margin: 0; color: var(--muted); font-size: 11.5px; line-height: 1.5; }
.app-shell .ticket-create-step {
  width: 29px;
  height: 29px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  flex: none;
  color: var(--link);
  background: var(--orange-wash);
  box-shadow: inset 0 0 0 1px var(--orange-wash-border);
  font-size: 11px;
  font-weight: 850;
}
.app-shell .ticket-create-card > label,
.app-shell .ticket-create-field-grid > label,
.app-shell .ticket-create-customer > label {
  display: block;
  margin: 0 0 17px;
  color: var(--text-soft);
  font-size: 11.5px;
  font-weight: 750;
}
.app-shell .ticket-create-card label > span { color: var(--coral); }
.app-shell .ticket-create-card input,
.app-shell .ticket-create-card select,
.app-shell .ticket-create-card textarea {
  width: 100%;
  margin-top: 7px;
  border: 1px solid var(--border-dark);
  border-radius: 10px;
  outline: 0;
  color: var(--grey);
  background: var(--surface);
  font: inherit;
  font-size: 13.5px;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.app-shell .ticket-create-card input,
.app-shell .ticket-create-card select { height: 46px; padding: 0 13px; }
.app-shell .ticket-create-card textarea { min-height: 248px; padding: 13px; resize: vertical; line-height: 1.55; }
.app-shell .ticket-create-card input:hover,
.app-shell .ticket-create-card select:hover,
.app-shell .ticket-create-card textarea:hover { border-color: var(--text-faint); }
.app-shell .ticket-create-card input:focus,
.app-shell .ticket-create-card select:focus,
.app-shell .ticket-create-card textarea:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.11); }
.app-shell .ticket-create-field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.app-shell .ticket-create-customer { margin-bottom: 4px; }
.app-shell .ticket-create-customer .contact-picker-hint { margin: 6px 0 18px; display: block; font-size: 10px; line-height: 1.4; }
.app-shell .ticket-create-card .contact-identity-error { margin: 3px 0 0; }
.app-shell .ticket-create-routing-card { position: sticky; top: 88px; }
.app-shell .ticket-create-routing-card > label { margin-bottom: 18px; }
.app-shell .ticket-venue-field { margin-top: 8px; padding-top: 24px; border-top: 1px solid var(--border); }
.app-shell .ticket-venue-field > h2 { margin: 0 0 5px; color: var(--text); font-size: 15px; letter-spacing: -.01em; }
.app-shell .ticket-venue-field > .contact-section-hint { max-width: 700px; margin: 0 0 15px; font-size: 11.5px; }
.app-shell .ticket-venue-field .contact-venue-list { margin-bottom: 14px; }
.app-shell .ticket-venue-field .contact-venue-empty { padding: 5px 2px 10px; }
.app-shell .ticket-venue-field .ticket-venue-row-selected { border-color: var(--orange-tint); background: var(--orange-wash); }
.app-shell .ticket-venue-field .ticket-venue-selected-tag { color: var(--green-ink); background: var(--green-wash); }
.app-shell .ticket-venue-field .ticket-venue-choice .link-button[disabled] { color: var(--muted); cursor: default; opacity: .8; }
.app-shell .ticket-venue-search { margin-top: 0; }
.app-shell .ticket-venue-search input[type="search"] { height: 46px; margin-top: 0; padding: 0 13px; border-radius: 10px; font-size: 13.5px; }
.app-shell .ticket-venue-search .contact-venue-results {
  margin-top: 6px;
  position: absolute;
  z-index: 35;
  top: 100%;
  right: 0;
  left: 0;
  box-shadow: 0 16px 40px rgba(16,20,28,.22);
}
.app-shell .ticket-venue-hint { margin: 6px 0 0; display: block; color: var(--muted); font-size: 10px; line-height: 1.4; }
.app-shell .ticket-venue-create-option b { color: var(--link); }
.app-shell #ticketVenueError { margin-top: 7px; }
.app-shell .ticket-create-guidance {
  margin-top: 6px;
  padding: 15px;
  border: 1px solid var(--green-wash-border);
  border-radius: 11px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--text-soft);
  background: var(--green-wash);
}
.app-shell .ticket-create-guidance > span { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; flex: none; color: var(--green); background: var(--surface); font-size: 11px; font-weight: 900; }
.app-shell .ticket-create-guidance p { margin: 0; font-size: 10.5px; line-height: 1.45; }
.app-shell .ticket-create-guidance b { margin-bottom: 2px; display: block; color: var(--text); font-size: 11px; }
.app-shell .ticket-create-actions {
  min-height: 78px;
  padding: 13px clamp(20px,3vw,46px);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 28px;
  position: sticky;
  z-index: 12;
  bottom: 0;
  background: color-mix(in srgb,var(--surface) 94%,transparent);
  backdrop-filter: blur(14px);
  box-shadow: 0 -12px 32px rgba(20,24,28,.06);
}
.app-shell .ticket-create-actions > p { margin: 0; text-align: right; }
.app-shell .ticket-create-actions > p b,
.app-shell .ticket-create-actions > p span { display: block; }
.app-shell .ticket-create-actions > p b { font-size: 11.5px; }
.app-shell .ticket-create-actions > p span { margin-top: 3px; color: var(--muted); font-size: 10px; }
.app-shell .ticket-create-actions > div { display: flex; align-items: center; gap: 9px; }
.app-shell .ticket-create-actions button { min-height: 43px; padding: 0 20px; }
.app-shell .ticket-create-actions .primary-button { min-width: 132px; }

@media (max-width: 980px) {
  .app-shell .ticket-create-layout { grid-template-columns: 1fr; }
  .app-shell .ticket-create-side { grid-row: 2; padding: 30px 0 0; border-top: 1px solid var(--border); border-left: 0; }
  .app-shell .ticket-create-routing-card { position: static; }
  .app-shell .ticket-create-routing-card { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); column-gap: 14px; }
  .app-shell .ticket-create-routing-card .ticket-create-card-head,
  .app-shell .ticket-create-routing-card .ticket-create-guidance { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .app-shell .ticket-create-head { min-height: 92px; padding: 16px 14px; align-items: flex-start; }
  .app-shell .ticket-create-head h1 { font-size: 21px; }
  .app-shell .ticket-create-layout { padding: 16px 12px 24px; gap: 16px; }
  .app-shell .ticket-create-main,.app-shell .ticket-create-side { gap: 22px; }
  .app-shell .ticket-create-request-card { padding-top: 24px; }
  .app-shell .ticket-create-side { padding-top: 24px; }
  .app-shell .ticket-create-field-grid,
  .app-shell .ticket-create-routing-card { grid-template-columns: 1fr; }
  .app-shell .ticket-create-routing-card .ticket-create-card-head,
  .app-shell .ticket-create-routing-card .ticket-create-guidance { grid-column: auto; }
  .app-shell .ticket-create-card textarea { min-height: 200px; }
  .app-shell .ticket-create-actions { min-height: 72px; padding: 10px 12px; }
  .app-shell .ticket-create-actions > p { display: none; }
  .app-shell .ticket-create-actions > div { width: 100%; }
  .app-shell .ticket-create-actions button { flex: 1; }
}

/* ---- The ticket page fits the window ----
   The page used to scroll as one document, so the properties column -- the thing an agent
   reaches for last, to set a status and save -- was routinely below the fold behind a long
   conversation. On a wide screen the ticket view is now exactly the window: the bar at the top
   stays, the conversation scrolls inside its own panel, and the contact and properties sit in a
   column that fits beside it with the save button pinned at the foot. The column only scrolls
   itself on a window too short to hold it. Below 1100px the columns stack and the document
   scrolls as before. Only the active view: this block sets display, and a plain #ticketView
   selector outranks the .view rule that hides inactive views, which left the last-opened
   ticket painted underneath the queue, the contact page and the ticket editor. */
@media (min-width: 1101px) {
  .app-shell #ticketView.active {
    height: calc(100dvh - var(--topbar-height) - var(--ticket-tabs-height));
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .app-shell #ticketView .ticket-detail-bar { flex: none; }
  .app-shell #ticketView .ticket-detail-grid { flex: 1; min-height: 0; overflow: hidden; }
  .app-shell #ticketView .ticket-thread {
    min-height: 0;
    height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .app-shell #ticketView .ticket-side-column {
    min-height: 0;
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .app-shell #ticketView .contact-summary-panel { flex: none; }
  .app-shell #ticketView .property-panel {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
  .app-shell #ticketView .property-panel .drawer-fields { flex: none; }
  .app-shell #ticketView .property-actions { margin-top: auto; }
  /* Tighter than the document layout so the whole column fits a 900px window. */
  .app-shell #ticketView .ticket-contact-card { padding: 14px 17px 12px; }
  .app-shell #ticketView .ticket-contact-company { margin-bottom: 9px; }
  .app-shell #ticketView .drawer-fields { padding: 12px 17px 10px; gap: 9px; }
  .app-shell #ticketView .drawer-fields select { height: 38px; }
  .app-shell #ticketView .ticket-checkbox-property { padding: 6px 0 2px; }
  .app-shell #ticketView .ticket-level-row { padding: 10px 17px; }
  .app-shell #ticketView .property-actions { padding: 12px 17px 14px; gap: 8px; }
}

/* ---- The queue toolbar keeps its controls whole ----
   Every control in the actions strip was free to shrink, so at ordinary desktop widths the strip
   squeezed them instead of wrapping: "Filters" broke onto two lines under its icon, "Save view"
   did the same, and the direction select was clipped to its minimum with the label cut mid-word.
   A control that no longer fits now moves whole to the next line, and the search box gives up a
   little width so the common case -- a full-width window -- stays on one line. */
.app-shell #ticketsView .toolbar-actions { flex-wrap: wrap; justify-content: flex-end; }
.app-shell #ticketsView .toolbar-actions > :not(.queue-search) { flex: 0 0 auto; }
.app-shell #ticketsView .tool-button,
.app-shell #ticketsView .toolbar-toggle,
.app-shell #ticketsView .toolbar-toggle span { white-space: nowrap; }
.app-shell #ticketsView .sort-select { width: auto; }
.app-shell #ticketsView .queue-search { width: 212px; }
.app-shell #ticketsView .saved-view-controls select { flex: 0 0 auto; }

/* The column headings sit over the text they head. Contact copy in a row is inset 10px behind
   the priority bar; the heading was not, so the whole header read as drifting left. */
.app-shell #ticketsView .ticket-table-head .column-sort { min-width: 0; white-space: nowrap; }
.app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="customer"] { padding-left: 10px; }

/* ---- Global search: tickets, contacts and venues ----
   The box in the top bar used to be a second handle on the queue search. It now answers with
   whatever matches -- tickets, the people on file and the venues -- in a list under the box, and
   only takes the agent to the queue when they ask for it. */
.global-search-wrap { position: relative; width: min(430px, 42vw); }
.global-search-wrap > .global-search { width: 100%; }
.global-search-results {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 70;
  width: min(580px, calc(100vw - 300px));
  max-height: min(72vh, 640px);
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: var(--floating-shadow, 0 18px 50px rgba(35, 40, 49, .16));
}
.global-search-group { padding: 4px 0 6px; }
.global-search-group + .global-search-group { border-top: 1px solid var(--hairline); }
.global-search-group > h3 {
  margin: 0;
  padding: 10px 16px 4px;
  display: flex;
  justify-content: space-between;
  color: var(--text-faint);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .075em;
  text-transform: uppercase;
}
.global-search-group > h3 span { color: var(--muted); font-weight: 600; letter-spacing: 0; text-transform: none; }
.global-search-item {
  width: 100%;
  min-height: 46px;
  padding: 6px 16px;
  border: 0;
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  color: var(--text);
  background: transparent;
  cursor: pointer;
  font: inherit;
  text-align: left;
}
.global-search-item:hover,
.global-search-item[aria-selected="true"] { background: var(--surface-sunken); }
.global-search-item .avatar { width: 30px; height: 30px; font-size: 10px; }
.global-search-item-icon {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  color: var(--orange-ink);
  background: var(--orange-pale);
  font-size: 13px;
  font-weight: 700;
}
.global-search-item-icon.venue { color: var(--green-ink); background: var(--green-pale); }
.global-search-item-text { min-width: 0; }
.global-search-item-text b,
.global-search-item-text span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.global-search-item-text b { font-size: 12.5px; }
.global-search-item-text b em { margin-right: 6px; color: var(--link); font-style: normal; }
.global-search-item-text span { margin-top: 1px; color: var(--muted); font-size: 10.5px; }
.global-search-item .status-pill { justify-self: end; }
.global-search-empty { padding: 20px 16px; color: var(--muted); font-size: 12px; }
.global-search-footer {
  width: 100%;
  min-height: 42px;
  padding: 0 16px;
  border: 0;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  color: var(--link);
  background: var(--surface-sunken);
  cursor: pointer;
  font: inherit;
  font-size: 11.5px;
  font-weight: 700;
  text-align: left;
}
.global-search-footer:hover,
.global-search-footer[aria-selected="true"] { background: var(--orange-wash); }
.global-search-footer kbd { padding: 2px 6px; border: 1px solid var(--border); border-radius: 5px; color: var(--text-faint); background: var(--surface); font: 9px Inter; }
@media (max-width: 760px) {
  .global-search-wrap { min-width: 0; width: auto; flex: 1; }
  .global-search-results { position: fixed; top: 70px; left: 12px; right: 12px; width: auto; max-height: calc(100dvh - 84px); }
  .search-overlay .global-search-results { position: static; left: auto; right: auto; width: 100%; max-height: min(56vh, 520px); }
}

/* ---- Which venue is this ticket for? ----
   A contact who looks after several venues gets a picker in place of the venue line, so the
   ticket can be filed against the site they are actually ringing about. Until it is chosen the
   picker is outlined, because "Unknown" on a ticket for a multi-venue customer is a question. */
.app-shell #ticketView .ticket-contact-venue { margin: 4px 0 13px; display: grid; gap: 5px; }
.app-shell #ticketView .ticket-contact-venue > span {
  color: var(--text-soft);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.app-shell #ticketView .ticket-contact-venue select {
  width: 100%;
  height: 34px;
  padding: 0 28px 0 9px;
  border: 1px solid var(--border-dark);
  border-radius: 8px;
  color: var(--text);
  background: var(--surface);
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
}
.app-shell #ticketView .ticket-contact-venue.needs-choice select { border-color: var(--orange); box-shadow: 0 0 0 3px var(--orange-wash); }
.app-shell #ticketView .ticket-contact-venue small { color: var(--orange-ink); font-size: 10px; line-height: 1.4; }

.venue-confirm-box .confirm-icon { color: var(--orange-ink); background: var(--orange-pale); }

/* Not a warning: the agent is being asked a question about work they have just done, and either
   answer is a normal outcome. The default coral icon would read as something having gone wrong. */
.contacted-confirm-box { width: min(430px, 100%); }
.contacted-confirm-box .confirm-icon { color: var(--orange-ink); background: var(--orange-pale); font-weight: 500; }
.contacted-confirm-box p { max-width: 340px; }
.venue-confirm-field { margin: 0 0 20px; display: grid; gap: 6px; color: var(--text-soft); font-size: 11px; font-weight: 700; text-align: left; }
.venue-confirm-field select {
  width: 100%;
  height: 40px;
  padding: 0 28px 0 11px;
  border: 1px solid var(--border-dark);
  border-radius: 9px;
  color: var(--text);
  background: var(--surface);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
}
.venue-confirm-field select:focus-visible { outline: 0; border-color: var(--orange); box-shadow: 0 0 0 3px var(--orange-wash); }

/* ---- Inline status and agent pickers on the queue ----
   The status pill and the agent cell are controls now: a click opens a menu of the other values
   under the cell, and one choice saves. They read as clickable on hover and take the focus ring. */
.ticket-row .queue-pick { cursor: pointer; }
.ticket-row .ticket-assignee.queue-pick { margin-left: -4px; padding: 3px 9px 3px 4px; border-radius: 999px; }
.ticket-row .ticket-assignee.queue-pick:hover,
.ticket-row .ticket-assignee.queue-pick[aria-expanded="true"] { background: var(--surface-sunken); }
.ticket-row .queue-pick:hover,
.ticket-row .queue-pick[aria-expanded="true"] { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--border-dark); }
.ticket-row .queue-pick:focus-visible { outline: 0; box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--orange); }
.queue-pick-menu {
  position: fixed;
  z-index: 130;
  min-width: 200px;
  max-height: min(60vh, 420px);
  padding: 6px;
  overflow-y: auto;
  border: 1px solid var(--border-dark);
  border-radius: 12px;
  background: var(--surface);
  box-shadow: var(--floating-shadow, 0 18px 50px rgba(35, 40, 49, .16));
}
.queue-pick-option {
  width: 100%;
  min-height: 38px;
  padding: 6px 10px;
  border: 0;
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  text-align: left;
}
.queue-pick-option:hover,
.queue-pick-option:focus-visible { outline: 0; background: var(--surface-sunken); }
.queue-pick-option[aria-checked="true"] { background: var(--orange-wash); }
.queue-pick-option .avatar { width: 26px; height: 26px; font-size: 9px; }
.queue-pick-option .status-pill { font-size: 10.5px; }

/* ---- The gutter between Contact and Subject: presence and NEW ----
   Two things worth seeing before the title -- somebody else has this open, and it is new -- share
   one narrow column of their own, side by side. The eye stands the full height of the row's two
   lines; the tag sits beside it. The title keeps its place whether either is there or not. */
.app-shell .ticket-subject > .ticket-subject-body { min-width: 0; display: block; overflow: hidden; }
.app-shell #ticketsView .ticket-row > .ticket-flags {
  min-width: 0;
  align-self: stretch;
  display: flex;
  align-items: stretch;
  justify-content: center;
}
.app-shell #ticketsView .ticket-flags > .ticket-row-presence {
  width: 100%;
  max-width: 30px;
  height: auto;
  min-height: 34px;
  margin: 0;
  flex: 0 0 auto;
  align-self: stretch;
  border-radius: 8px;
  display: grid;
  place-items: center;
  overflow: visible;
  white-space: normal;
}
.app-shell #ticketsView .ticket-flags > .ticket-row-presence svg { width: 17px; height: 17px; }
.app-shell #ticketsView .ticket-flags > .new-ticket-tag {
  width: 100%;
  max-width: 36px;
  height: auto;
  min-height: 34px;
  padding: 0 3px;
  flex: 0 0 auto;
  align-self: stretch;
  border-radius: 8px;
  display: grid;
  place-items: center;
  font-size: 8.5px;
  letter-spacing: .04em;
}

/* ---- Received, Status, Agent and SLA share one width and sit centred ----
   The four right-hand columns each had a width of their own, so the headings and values drifted
   at different distances from each other. They are one equal track each now, and both heading
   and value sit in the middle of it. The stacked layout below 761px keeps its own placement. */
@media (min-width: 761px) {
  .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="received"],
  .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="status"],
  .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="assignee"],
  .app-shell #ticketsView .ticket-table-head .column-sort[data-sort-key="sla"] { justify-self: center; text-align: center; }
  .app-shell #ticketsView .ticket-row > .ticket-received { text-align: center; }
  .app-shell #ticketsView .ticket-row > .status-pill,
  .app-shell #ticketsView .ticket-row > .sla-pill { justify-self: center; }
  .app-shell #ticketsView .ticket-row > .ticket-assignee { justify-content: center; }
}

/* ---- The header and the rows share a scrollbar gutter ----
   The rows scroll inside the list and lose the scrollbar's width; the header does not scroll and
   kept it, so every centred column below the header drifted left of its label by up to the width
   of the scrollbar. Both reserve the gutter now, whether or not the list needs to scroll. */
.app-shell #ticketsView .ticket-list { scrollbar-gutter: stable; }
.app-shell #ticketsView .ticket-table-head { overflow: hidden; scrollbar-gutter: stable; }

/* Light-mode queue headers use the same dark anchor as the navigation rail. The two formerly
   pale-blue bands are the page heading and each sticky agent heading; dark mode keeps its own
   raised-surface treatment. */
:root[data-theme="light"] .app-shell #ticketsView .ticket-page-head {
  min-height: 62px;
  margin: -8px 0 8px;
  padding: 8px clamp(16px, 1.6vw, 26px);
  color: var(--grey);
  background: color-mix(in srgb, #2b2b2b 8%, #fff);
}
:root[data-theme="light"] .app-shell #ticketsView .ticket-page-head h1 { color: var(--grey); }
:root[data-theme="light"] .app-shell #ticketsView .ticket-page-head > div > p:last-child { color: var(--muted); }
:root[data-theme="light"] .app-shell #ticketsView .ticket-group-heading {
  border-bottom-color: rgba(43, 43, 43, .14);
  color: var(--grey);
  background: color-mix(in srgb, #2b2b2b 8%, #fff);
}
:root[data-theme="light"] .app-shell #ticketsView .ticket-group-heading > span:not(.avatar) { color: var(--muted); }
:root[data-theme="light"] .app-shell #ticketsView .ticket-subject-title > .ticket-subject-text { color: #000; }

/* ---- Received on two lines: weekday and date, then time ---- */
.app-shell #ticketsView .ticket-row > .ticket-received {
  display: grid;
  gap: 2px;
  overflow: visible;
  line-height: 1.2;
  white-space: nowrap;
  text-align: center;
}
.app-shell #ticketsView .ticket-row > .ticket-received > b { color: var(--text-soft); font-weight: 600; }
.app-shell #ticketsView .ticket-row > .ticket-received > span { color: var(--muted); }

/* ---- One width for every status pill ----
   Pills sized to their word lined up ragged, and "Open" beside "Waiting On Customer" read as two
   different kinds of thing. One width, the value centred inside it. */
.app-shell #ticketsView .ticket-row > .status-pill {
  width: 100%;
  max-width: 138px;
  box-sizing: border-box;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Knowledge-base workspace --------------------------------------------------------------- */
.kb-admin-head { align-items:center; }
.kb-admin-actions { display:flex; align-items:center; gap:8px; }
.app-shell .kb-split-button { height:var(--control-height); border:1px solid var(--orange); border-radius:11px; display:inline-flex; position:relative; overflow:visible; background:var(--orange); box-shadow:0 8px 18px rgba(var(--orange-rgb),.18); }
.app-shell .kb-split-button #kbNewArticleButton,
.app-shell .kb-split-button .kb-more-button { min-height:0; height:100%; margin:0; border:0; border-radius:0; box-shadow:none; transform:none; }
.app-shell .kb-split-button #kbNewArticleButton { padding:0 17px; border-radius:10px 0 0 10px; }
.app-shell .kb-split-button .kb-more-button { width:38px; min-width:38px; padding:0; border-left:1px solid rgba(255,255,255,.42); border-radius:0 10px 10px 0; }
.app-shell .kb-split-button #kbNewArticleButton:hover,
.app-shell .kb-split-button .kb-more-button:hover { background:var(--orange-hover); transform:none; }
.kb-admin-search { height:44px; margin:18px 0; border:1px solid var(--border); border-radius:9px; display:flex; align-items:center; background:var(--panel); }
.kb-admin-search span { padding-left:15px; color:var(--muted); font-size:20px; }
.kb-admin-search input { width:100%; height:100%; padding:0 12px; border:0; outline:0; color:var(--text); background:transparent; font:inherit; }
.kb-create-menu { width:180px; padding:7px; border:1px solid var(--border); border-radius:10px; position:absolute; z-index:30; top:calc(100% + 7px); right:0; background:var(--panel); box-shadow:var(--shadow-lg); }
.app-shell .kb-create-menu button { width:100%; min-height:38px; margin:0; padding:9px 11px; border:0 !important; border-radius:7px; display:block; color:var(--text); background:transparent; box-shadow:none; cursor:pointer; font:inherit; text-align:left; }.app-shell .kb-create-menu button + button { margin-top:2px; }.app-shell .kb-create-menu button:hover { border:0; background:var(--surface-hover); box-shadow:none; }
.kb-admin-categories { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:20px; }
.kb-admin-category { min-height:190px; padding:22px; border:1px solid var(--border); border-radius:9px; background:var(--panel); }
.kb-admin-category h2 { margin:0 0 18px; font-size:15px; }.kb-admin-category > div { display:flex; flex-direction:column; }
.kb-admin-category button { padding:12px 8px; border:0; border-bottom:1px solid var(--border); display:flex; justify-content:space-between; color:var(--text); background:transparent; cursor:pointer; text-align:left; }.kb-admin-category button:hover { color: var(--link); }
.kb-admin-category button span { font-weight:800; }.kb-admin-category p,.kb-admin-none { color:var(--muted); font-size:12px; }
.kb-manage { min-height:560px; border:1px solid var(--border); display:grid; grid-template-columns:310px 1fr; background:var(--panel); }
.kb-manage > aside { border-right:1px solid var(--border); }.kb-manage > aside section { border-bottom:1px solid var(--border); }
.kb-tree-category,.kb-tree-folder { width:100%; padding:14px 16px; border:0; color:var(--text); background:transparent; cursor:pointer; font:inherit; font-weight:750; text-align:left; }.kb-tree-category { display:flex; align-items:center; justify-content:space-between; }.kb-tree-category span { color:var(--muted); font-size:9px; font-weight:650; }
.kb-tree-folder { padding-left:38px; display:flex; justify-content:space-between; font-weight:600; }.kb-tree-folder.active { color:var(--orange-ink); background:var(--orange-wash-strong); box-shadow:inset 3px 0 0 var(--orange); }
.kb-article-table-head,.kb-article-row { display:grid; grid-template-columns:minmax(250px,1fr) 90px 90px 105px; align-items:center; }
.kb-selection-bar { min-height:68px; padding:10px 16px; border-bottom:1px solid var(--border); display:flex; align-items:center; justify-content:space-between; gap:12px; background:var(--surface-muted); }.kb-selection-bar[hidden] { display:none; }.kb-selection-bar small,.kb-selection-bar b { display:block; }.kb-selection-bar small { margin-bottom:4px; color:var(--muted); font-size:8px; font-weight:850; }.kb-selection-bar > div:last-child { display:flex; gap:7px; }
.kb-article-table-head { min-height:44px; padding:0 16px; border-bottom:1px solid var(--border); color:var(--muted); font-size:10px; font-weight:850; text-transform:uppercase; }
.kb-article-row { width:100%; min-height:61px; padding:0 16px; border:0; border-bottom:1px solid var(--border); color:var(--text); background:transparent; cursor:pointer; font:inherit; text-align:left; }.kb-article-row:hover { background:var(--surface-hover); }
.kb-article-row b,.kb-article-row small { display:block; }.kb-article-row small { margin:4px 0 0 20px; color:var(--muted); font-size:9px; }
.kb-publish-state { width:max-content; padding:4px 8px; border-radius:999px; color:var(--amber-ink); background:var(--amber-wash); font-size:9px; font-weight:850; }.kb-publish-state.published { color:var(--green-ink); background:var(--green-pale); }
.kb-publish-state.inreview { color:var(--orange-ink); background:var(--orange-wash-strong); }
.kb-admin-search[hidden] { display:none; }

/* The article list. Deliberately the ticket queue's furniture: same row height, same head, same
   hover, so an agent who can read one can read the other. Tokens only, so it themes with
   everything else and needs no second set of colours for dark. */
/* One set of column widths, read by the head and by every row, so a change to the table is a
   change in one place and the two cannot drift apart. */
.kb-queue { --kb-queue-columns:minmax(240px,1fr) 172px 120px 110px 105px; border:1px solid var(--border); border-radius:12px; overflow:hidden; background:var(--panel); }
.kb-queue[hidden] { display:none; }
/* The head and a row are the same two pieces: the five cells, and the review column beside them.
   The inset is on the head and on the row's container, never on the grid itself -- when the row
   carried its own padding and the head carried a different one, every column after the first sat
   16px to the right of the heading above it. */
.kb-queue-head,.kb-queue-item { display:flex; align-items:stretch; padding:0 16px; }
.kb-queue-head { min-height:44px; align-items:center; border-bottom:1px solid var(--border); color:var(--muted); font-size:10px; font-weight:850; text-transform:uppercase; }
.kb-queue-cells,.kb-queue-row { flex:1 1 auto; min-width:0; display:grid; grid-template-columns:var(--kb-queue-columns); align-items:center; gap:12px; }
/* The one bar above the list that clears a whole migration. It sits inside the queue card rather
   than above it so it reads as part of the list it acts on, and it is drawn only in the review
   view, where approving is the whole job. */
.kb-queue-batch { display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap; padding:12px 16px; border-bottom:1px solid var(--border); background:var(--surface-sunken); }
.kb-queue-batch[hidden] { display:none; }
.kb-queue-batch p { margin:0; color:var(--text); font-size:12.5px; font-weight:650; }
.kb-queue-batch .primary-button { padding:8px 18px; font-size:11.5px; }
.kb-queue-item { border-bottom:1px solid var(--border); }
.kb-queue-item:last-child { border-bottom:0; }
.kb-queue-row { min-height:56px; padding:9px 0; border:0; color:var(--text); background:transparent; cursor:pointer; font:inherit; text-align:left; }
.kb-queue-item:hover { background:var(--surface-hover); }
.kb-queue-title { min-width:0; }
.kb-queue-row b,.kb-queue-row small { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* The summary takes a second line rather than losing its end. Two is the limit: a long one would
   otherwise set the height of every row beside it. */
.kb-queue-row small { display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; margin-top:3px; color:var(--muted); font-size:10px; font-weight:500; line-height:1.45; white-space:normal; }
.kb-queue-muted { color:var(--muted); font-size:11px; font-weight:650; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Folder names are whole phrases -- "End of day, X and Z reports" -- and half of one is no use
   for telling two folders apart, so the column wraps to a second line instead of clipping. */
.kb-queue-folder { display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; line-height:1.35; text-overflow:clip; white-space:normal; }
/* Where the draft came from, as one word. The long form -- the Freshdesk id, the link, who sent
   it, anything they said -- is the chip's tooltip: fifty rows of the same sentence told a
   reviewer nothing, and cost the list half its height. */
.kb-source-chip { padding:3px 8px; border-radius:999px; color:var(--text-soft); background:var(--surface-sunken); font-size:9.5px; font-weight:800; letter-spacing:.03em; cursor:help; }
.kb-source-chip.freshdesk { color:var(--violet-ink); background:var(--violet-wash); }
.kb-source-chip.claude { color:var(--orange-ink); background:var(--orange-wash); }
/* An update leaves the article Published while it waits, so the status column cannot say it. */
.kb-queue-flag { margin-left:7px; padding:2px 7px; border-radius:999px; color:var(--coral-ink); background:var(--coral-wash); font-size:9px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; vertical-align:1px; cursor:help; }
/* The decision, in its own column rather than a band of its own under the row. Drawn in the
   review view only: everywhere else there is nothing to decide and the column is not there. */
.kb-queue-head-actions,.kb-queue-decide { flex:0 0 250px; display:flex; align-items:center; justify-content:flex-end; gap:7px; }
.kb-queue:not([data-kb-view="review"]) .kb-queue-head-actions { display:none; }
.kb-queue-action { padding:6px 12px; border:1px solid var(--border-dark); border-radius:999px; color:var(--text); background:var(--surface); cursor:pointer; font:inherit; font-size:10.5px; font-weight:750; white-space:nowrap; }
.kb-queue-action:hover { background:var(--surface-sunken); }
/* The ticket page's Resolve, which is the same kind of button: the affirmative one. Pale rather
   than solid, because forty-six solid green buttons down a review queue is a wall of green. */
.kb-queue-action.approve { border-color:var(--green-pale); color:var(--green-ink); background:var(--green-pale); }
.kb-queue-action.approve:hover { border-color:var(--green); background:var(--green-pale); }
.kb-queue-action:disabled { opacity:.5; cursor:not-allowed; }
.kb-queue-live { color:var(--link); font-size:10.5px; font-weight:700; white-space:nowrap; }
.kb-queue-row .kb-guide-tag { margin:0 0 0 7px; }
.kb-queue-empty { margin:0; padding:34px 16px; }
@media(max-width:1180px){
  .kb-queue { --kb-queue-columns:minmax(200px,1fr) 120px 110px 100px; }
  .kb-queue-cells span:nth-child(2),.kb-queue-row>span:nth-child(2) { display:none; }
}
@media(max-width:900px){
  .kb-queue { --kb-queue-columns:minmax(160px,1fr) 110px 100px; }
  .kb-queue-head,.kb-queue-item { flex-wrap:wrap; }
  .kb-queue-cells span:nth-child(4),.kb-queue-row>span:nth-child(4) { display:none; }
  .kb-queue-head-actions { display:none !important; }
  .kb-queue-decide { flex:1 1 100%; justify-content:flex-start; padding:0 0 12px; }
}
/* The knowledge base's own figures. Tokens only, so the panel themes with everything else. */
.kb-insights { display:grid; gap:20px; }
.kb-insights-head { display:flex; align-items:flex-end; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.kb-insights-head h2 { margin:0; font-size:21px; }
.kb-insights-head label { display:flex; align-items:center; gap:8px; color:var(--muted); font-size:11px; font-weight:750; }
.kb-insights-head select { padding:8px 10px; border:1px solid var(--border-dark); border-radius:7px; color:var(--text); background:var(--panel); font:inherit; font-size:11px; }
.kb-insight-tiles { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:16px; }
.kb-insight-tile { padding:18px; border:1px solid var(--border); border-radius:9px; background:var(--panel); }
.kb-insight-tile small { display:block; color:var(--muted); font-size:9px; font-weight:850; letter-spacing:.04em; text-transform:uppercase; }
.kb-insight-tile b { display:block; margin:8px 0 4px; font-size:28px; font-weight:800; }
.kb-insight-tile span { color:var(--muted); font-size:10px; }
.kb-insight-columns { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:20px; }
.kb-insight-columns > article { padding:20px 0 0; border:1px solid var(--border); border-radius:9px; background:var(--panel); overflow:hidden; }
.kb-insight-columns h3 { margin:0 20px; font-size:14px; }
.kb-insight-columns > article > p { margin:5px 20px 14px; color:var(--muted); font-size:10.5px; }
.kb-insight-row { min-height:56px; padding:10px 20px; border-top:1px solid var(--border); display:grid; grid-template-columns:minmax(0,1fr) auto auto; align-items:center; gap:12px; color:var(--text); text-decoration:none; }
a.kb-insight-row:hover { background:var(--surface-hover); }
.kb-insight-row b, .kb-insight-row small { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.kb-insight-row b { font-size:11.5px; }
.kb-insight-row small { margin-top:3px; color:var(--muted); font-size:9px; }
.kb-insight-figure { color:var(--muted); font-size:10px; font-weight:800; white-space:nowrap; }
.kb-insight-figure.poor { color:var(--coral); }
@media (max-width: 1100px) {
  .kb-insight-tiles { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .kb-insight-columns { grid-template-columns:minmax(0,1fr); }
}
.kb-admin-none { padding:30px; text-align:center; }.kb-editor { max-width:900px; }.kb-editor .modal-head { justify-content:flex-start; gap:12px; }.kb-editor .modal-head .close-button { margin-left:auto; }.kb-modal-title-icon { width:42px; height:42px; border:1px solid var(--border); display:grid; place-items:center; color:var(--muted); font-size:24px; }.kb-editor form label { margin-bottom:14px; display:block; color:var(--text); font-size:11px; font-weight:750; }
.kb-editor input,.kb-editor textarea,.kb-editor select { width:100%; margin-top:6px; padding:10px 12px; border:1px solid var(--border-dark); border-radius:7px; color:var(--text); background:var(--panel); font:inherit; }.kb-editor textarea { resize:vertical; }.kb-editor-error { color:var(--danger); font-size:11px; }
/*
 * Uploading an article file. Drawn from the shell's own tokens, so it follows the theme the
 * agent is working in -- unlike the guide itself, which is deliberately always light because it
 * is a document the customer reads on white.
 */
.kb-import { max-width:620px; }
.kb-import-drop { width:100%; min-height:104px; margin:0 0 14px; padding:18px; border:1px dashed var(--border-dark); border-radius:10px; display:grid; gap:5px; place-content:center; justify-items:center; color:var(--text); background:var(--surface-muted); cursor:pointer; font:inherit; text-align:center; }
.kb-import-drop:hover,.kb-import-drop.is-over { border-color:var(--orange); background:var(--surface); }
.kb-import-drop b { font-size:13px; font-weight:750; }
.kb-import-drop span { color:var(--muted); font-size:11px; }
.kb-import-drop code { padding:1px 5px; border-radius:4px; background:var(--surface-hover); font-size:10.5px; }
.kb-import-report { margin:0 0 12px; padding:14px 16px; border:1px solid var(--border); border-radius:10px; background:var(--surface-muted); font-size:11.5px; }
.kb-import-report dl { margin:0; display:grid; grid-template-columns:118px 1fr; gap:6px 12px; }
.kb-import-report dt { color:var(--muted); font-weight:700; }
.kb-import-report dd { margin:0; color:var(--text); }
.kb-import-checking { margin:0; color:var(--muted); }
/* The two sentences above the buttons in the Freshdesk panel: what it does and how long it takes. */
.kb-import-lead { margin:0 0 10px; color:var(--muted); line-height:1.6; }
.kb-import-lead + .kb-import-lead { margin-bottom:16px; }
.kb-import-problem { margin:0 0 10px; color:var(--coral-ink); font-weight:700; }
.kb-import-warnings { margin:12px 0 0; padding:12px 14px 12px 28px; border:1px solid var(--coral-wash-border); border-radius:8px; color:var(--coral-ink); background:var(--coral-wash); }
.kb-import-warnings li + li { margin-top:6px; }
.kb-inline-action { padding:0; border:0; float:right; color: var(--link); background:transparent; cursor:pointer; font:inherit; font-size:10px; }
.kb-modal-delete { margin-right:auto; }.kb-delete-note { margin:8px 0 0; padding:10px 12px; border:1px solid var(--coral-wash-border); border-radius:7px; color:var(--coral-ink); background:var(--coral-wash); font-size:10px; }
/*
 * The article editor.
 *
 * One document on a sheet of paper, with its properties beside it. The sheet carries the help
 * centre's own --hc- tokens, so `hc-prose` inside it -- the live article's stylesheet, not a
 * second copy of it here -- sets the body in the type, spacing, links, tables and callouts a
 * customer will read. Writing is therefore the preview; the Preview tab adds only the furniture
 * above the body (eyebrow, title, summary, the updated line).
 *
 * None of these selectors is scoped to .app-shell: the editor is appended to the body, outside
 * the shell, which is why the old toolbar rules -- written as `.app-shell .kb-editor-toolbar
 * button` -- never reached it and it was drawn in the browser's own buttons.
 *
 * The sheet stays white in both themes, deliberately and for the same reason the guide wizard's
 * preview does: that is the page being written, and an article shown on a dark sheet here would
 * not be the article. Everything around it -- header, toolbar, properties -- is themed.
 */
.kb-author-workspace { position:fixed; inset:0; z-index:120; color:var(--text); background:var(--surface-sunken); }
.kb-author-workspace > form { height:100%; display:flex; flex-direction:column; }
.kb-author-header { min-height:64px; padding:11px clamp(12px,2vw,20px); border-bottom:1px solid var(--border); display:flex; align-items:center; gap:14px; background:var(--surface); }
.kb-author-id { min-width:0; flex:1 1 220px; display:flex; align-items:center; gap:10px; }
.kb-author-back { width:34px; height:34px; flex:none; padding:0; border:1px solid var(--border-dark); border-radius:50%; display:grid; place-items:center; color:var(--text); background:var(--surface); cursor:pointer; font:inherit; font-size:15px; }
.kb-author-back:hover { border-color:var(--orange); color:var(--link); }
.kb-author-mark { width:34px; height:34px; flex:none; border-radius:10px; display:grid; place-items:center; color:var(--link); background:var(--orange-pale); font-size:18px; }
.kb-author-heading { min-width:0; }
.kb-author-heading b { display:block; font-size:14px; font-weight:800; letter-spacing:-.01em; }
.kb-author-heading small { margin-top:3px; display:flex; align-items:center; gap:8px; min-width:0; color:var(--muted); font-size:11px; }
.kb-author-heading small [data-author-state] { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.kb-author-heading small [data-author-state].is-dirty { color:var(--orange-ink); font-weight:700; }
.kb-author-status { flex:none; padding:2px 9px; border-radius:999px; color:var(--text-soft); background:var(--surface-muted); font-size:9px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; }
.kb-author-status.published { color:var(--green-ink); background:var(--green-pale); }
.kb-author-status.inreview { color:var(--orange-ink); background:var(--orange-pale); }
/* Write and Preview, as one segmented control rather than a button that toggles its own label. */
.kb-author-modes { flex:none; padding:3px; border-radius:999px; display:flex; gap:2px; background:var(--surface-muted); }
.kb-author-modes button { min-height:30px; padding:0 17px; border:0; border-radius:999px; color:var(--muted); background:transparent; cursor:pointer; font:inherit; font-size:12px; font-weight:700; }
.kb-author-modes button[aria-selected="true"] { color:var(--text); background:var(--surface); box-shadow:var(--shadow); }
.kb-author-actions { flex:1 1 auto; display:flex; align-items:center; justify-content:flex-end; gap:8px; }
.kb-author-actions .secondary-button,
.kb-author-actions .primary-button,
.kb-author-actions .danger-button { min-height:38px; padding:0 17px; font-size:12px; }
.kb-author-more { position:relative; flex:none; }
.kb-author-more > button { width:38px; padding:0; font-size:15px; }
.kb-author-menu { position:absolute; z-index:12; top:44px; right:0; width:232px; padding:6px; border:1px solid var(--border); border-radius:12px; background:var(--surface); box-shadow:var(--shadow); }
.kb-author-menu button { width:100%; min-height:34px; padding:0 10px; border:0; border-radius:8px; color:var(--text); background:transparent; cursor:pointer; font:inherit; font-size:12px; font-weight:600; text-align:left; }
.kb-author-menu button:hover { background:var(--surface-hover); }
.kb-author-menu button.is-danger { color:var(--coral-ink); }

.kb-author-layout { min-height:0; flex:1; display:grid; grid-template-columns:minmax(0,1fr) 340px; }
.kb-author-canvas { min-width:0; padding-bottom:50px; overflow:auto; background:var(--surface-sunken); }
/* Sticky, because a long imported article is where the toolbar is wanted and the old one scrolled
   away at the first screenshot. */
.kb-author-toolbar { position:sticky; z-index:6; top:0; padding:9px clamp(14px,4vw,44px); border-bottom:1px solid var(--border); display:flex; flex-wrap:wrap; align-items:center; gap:3px; background:var(--surface); }
.kb-author-block { height:32px; padding:0 9px; margin-right:4px; border:1px solid var(--border-dark); border-radius:8px; color:var(--text); background:var(--surface); font:inherit; font-size:12px; font-weight:600; }
.kb-author-tool { min-width:32px; height:32px; padding:0 9px; border:1px solid transparent; border-radius:8px; display:inline-flex; align-items:center; justify-content:center; gap:6px; color:var(--text); background:transparent; cursor:pointer; font:inherit; font-size:12px; font-weight:600; }
.kb-author-tool:hover { background:var(--surface-muted); }
.kb-author-tool.is-on { color:var(--link); background:var(--orange-pale); }
.kb-author-toolbar-split { width:1px; height:20px; margin:0 6px; flex:none; background:var(--border); }
.kb-author-toolbar-gap { flex:1 1 12px; }

/* The sheet: the article's own palette, so the help centre's rules can be used unchanged. */
.kb-author-paper {
  --hc-ink:#1d2128; --hc-text:#3a414c; --hc-muted:#697180; --hc-line:#e4e8ef;
  --hc-paper:#ffffff; --hc-wash:#f5f7fb; --hc-orange:#ff751a; --hc-orange-deep:#e5590c;
  width:min(880px, 100% - clamp(24px,7vw,88px));
  margin:clamp(18px,3vw,30px) auto 0;
  padding:clamp(26px,4vw,48px) clamp(22px,4vw,54px) clamp(40px,5vw,64px);
  border-radius:16px;
  color-scheme:light;
  color:var(--hc-text);
  background:var(--hc-paper);
  box-shadow:0 2px 4px rgba(0,0,0,.06), 0 18px 46px rgba(0,0,0,.12);
  font-family:Inter,"Segoe UI",Arial,sans-serif;
}
.kb-author-title { display:block; resize:none; overflow:hidden; width:100%; margin:0 0 20px; padding:0 0 15px; border:0; border-bottom:1px solid var(--hc-line); outline:0; color:var(--hc-ink); background:transparent; font-family:inherit; font-size:clamp(27px,3.2vw,40px); font-weight:800; letter-spacing:-.025em; line-height:1.14; }
.kb-author-title::placeholder { color:#b9bec7; }
.kb-author-title:focus { border-bottom-color:var(--hc-orange); }
.kb-author-editor { min-height:52vh; outline:0; }
.kb-author-editor:empty::before { color:#8b929e; content:attr(data-placeholder); pointer-events:none; }
.kb-author-preview .hc-article-head { margin-bottom:26px; }
.kb-author-canvas .kb-editor-hint,
.kb-author-canvas .kb-editor-error { width:min(880px, 100% - clamp(24px,7vw,88px)); margin:14px auto 0; font-size:11px; }
.kb-author-canvas .kb-editor-hint { color:var(--muted); }

.kb-author-properties { padding:18px 16px 60px; border-left:1px solid var(--border); display:flex; flex-direction:column; gap:14px; overflow:auto; background:var(--surface); }
.kb-author-card,
.kb-author-properties .kb-version-history { margin:0; padding:16px 15px; border:1px solid var(--border); border-radius:14px; background:var(--surface); box-shadow:var(--shadow); }
.kb-author-card > .eyebrow,
.kb-author-properties .kb-version-history > .eyebrow { margin:0 0 14px!important; }
.kb-author-properties label { margin-bottom:15px; display:block; color:var(--text); font-size:11px; font-weight:750; }
.kb-author-properties label:last-child { margin-bottom:0; }
.kb-author-properties label > span { color:var(--coral); }
.kb-author-properties label small { margin-top:7px; display:block; color:var(--muted); font-size:10px; font-weight:500; line-height:1.5; }
.kb-author-properties select,
.kb-author-properties input,
.kb-author-properties textarea { width:100%; margin-top:7px; border:1px solid var(--border-dark); border-radius:9px; color:var(--text); background:var(--surface); font:inherit; font-size:12px; }
.kb-author-properties select,
.kb-author-properties input { height:40px; padding:0 11px; }
/* The Summary box had no height of its own, so three rows of placeholder sat on top of its own
   label. It is a textarea: it gets one, and a grip to make it taller. */
.kb-author-properties textarea { min-height:96px; padding:10px 11px; line-height:1.55; resize:vertical; }
.kb-author-properties select:focus,
.kb-author-properties input:focus,
.kb-author-properties textarea:focus { border-color:var(--orange); outline:0; box-shadow:0 0 0 3px rgba(var(--orange-rgb),.12); }

.kb-version-history { margin-top:4px; }
.kb-version-empty { color:var(--muted); font-size:11px; }
.kb-version-list { margin:0; padding:0; list-style:none; }
.kb-version-list li { padding:10px 0; border-bottom:1px solid var(--border); }
.kb-version-list li:first-child { padding-top:0; }
.kb-version-list li:last-child { padding-bottom:0; border-bottom:0; }
.kb-version-list b { display:block; color:var(--text); font-size:11px; font-weight:750; }
.kb-version-list span { display:block; margin-top:3px; color:var(--muted); font-size:10px; }
.kb-version-list em { display:block; margin-top:5px; color:var(--text); font-size:10px; font-style:normal; }
@media(max-width:1180px){ .kb-author-layout { grid-template-columns:minmax(0,1fr) 300px; } }
@media(max-width:900px){
  /* One column that scrolls as a whole: two scrollports on a phone gave the body a third of the
     screen with the properties pinned under it. */
  .kb-author-layout { display:block; overflow:auto; }
  .kb-author-canvas, .kb-author-properties { overflow:visible; }
  .kb-author-toolbar { top:0; }
  .kb-author-properties { border-left:0; border-top:1px solid var(--border); }
  .kb-author-header { flex-wrap:wrap; row-gap:10px; }
  .kb-author-modes { order:3; }
  .kb-author-heading b { font-size:13px; }
  .kb-author-paper { width:calc(100% - 24px); padding:24px 20px 36px; }
}
@media(max-width:1000px){.kb-admin-categories{grid-template-columns:repeat(2,minmax(0,1fr))}.kb-manage{grid-template-columns:240px 1fr}}
@media(max-width:720px){.kb-admin-categories{grid-template-columns:1fr}.kb-manage{grid-template-columns:1fr}.kb-manage>aside{border-right:0}.kb-article-table-head,.kb-article-row{grid-template-columns:minmax(150px,1fr) 55px 70px}.kb-article-table-head span:nth-child(3),.kb-article-row>span:nth-child(3){display:none}}

/* ---- The queue's own header moves into the top bar ----
   The title block above the queue sat on a grey band no other page had, and said what the rail
   already says. The page name now lives beside the search in the top bar, and the queue starts
   with its tab strip and controls, flat on white with a single rule under them. */
.app-shell .topbar-title {
  margin: 0 18px 0 0;
  color: var(--text);
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -.01em;
  white-space: nowrap;
}
.app-shell #ticketsView { padding-top: 0; }
.app-shell #ticketsView .ticket-page-head { display: none; }
.app-shell #ticketsView .ticket-workspace { border-top: 0; }
.app-shell #ticketsView .ticket-toolbar {
  min-height: 56px;
  padding: 6px 18px;
  gap: 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.app-shell #ticketsView .ticket-tabs { height: 44px; min-height: 44px; gap: 18px; }
.app-shell #ticketsView .ticket-tab { font-size: 12.5px; }
.app-shell #ticketsView .toolbar-actions { gap: 6px; padding: 0; border: 0; border-radius: 0; background: transparent; }
.app-shell #ticketsView .queue-search,
.app-shell #ticketsView .tool-button,
.app-shell #ticketsView .sort-select,
.app-shell #ticketsView .toolbar-toggle,
.app-shell #ticketsView .saved-view-controls select {
  height: 34px;
  min-height: 34px;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-soft);
  background-color: var(--surface);
  box-shadow: none;
  font-size: 11.5px;
  font-weight: 500;
}
.app-shell #ticketsView .queue-search { width: 200px; }
.app-shell #ticketsView .tool-button:hover,
.app-shell #ticketsView .sort-select:hover,
.app-shell #ticketsView .toolbar-toggle:hover,
.app-shell #ticketsView .saved-view-controls select:hover {
  border-color: var(--border-dark);
  color: var(--text);
  background-color: var(--surface);
  transform: none;
}
.app-shell #ticketsView .toolbar-toggle:has(input:checked) {
  border-color: var(--orange-wash-border);
  color: var(--orange-ink);
  background: var(--orange-pale);
  box-shadow: none;
}
.app-shell #ticketsView .saved-view-delete { width: 34px; height: 34px; }

/* ---- Group headings stick within their own group ----
   Every heading was a direct child of the list with the same sticky offset, so once two groups
   had scrolled past, both headings sat pinned at the top on top of each other. Each group is its
   own block now, so a heading is released as its last row leaves. */
.app-shell #ticketsView .ticket-group { position: relative; }
.app-shell #ticketsView .ticket-group-heading { position: sticky; top: 0; z-index: 3; }

/* ---- Who a public reply goes to ---------------------------------------------------------------
   To stays visible. Cc and Bcc take no room until asked for, like a mail client rather than a
   settings form; an existing thread Cc opens itself because hiding a real recipient is unsafe. */
.app-shell .reply-recipients {
  margin: 0 0 8px;
  padding: 7px 13px;
  border: 1px solid var(--border);
  border-radius: 10px;
  display: grid;
  gap: 0;
  background: var(--surface-sunken);
  font-size: 11px;
}
.app-shell .reply-recipient-row { min-height:38px; display:grid; grid-template-columns:45px minmax(0,1fr) auto; align-items:center; gap:8px; }
.app-shell .reply-recipient-optional { padding-top:5px; border-top:1px solid var(--hairline); }
.app-shell .reply-recipient-row > b {
  flex: none;
  color: var(--text-faint);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.app-shell .reply-recipient-chips { min-width:0; display:flex; align-items:center; flex-wrap:wrap; gap:5px; color:var(--muted); }
.app-shell .reply-recipient-chip { max-width:100%; padding:5px 9px; border:1px solid var(--border); border-radius:999px; display:inline-flex; align-items:baseline; gap:4px; color:var(--text); background:var(--surface); }
.app-shell .reply-recipient-chip strong { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:10px; }
.app-shell .reply-recipient-chip small { overflow:hidden; color:var(--muted); text-overflow:ellipsis; white-space:nowrap; font-size:9px; }
.app-shell .reply-recipient-actions { display:flex; align-items:center; gap:3px; }
.app-shell .reply-recipient-actions button,
.app-shell .reply-recipient-remove { padding:5px; border:0; border-radius:5px; color: var(--link); background:transparent; cursor:pointer; font-size:10px; font-weight:800; }
.app-shell .reply-recipient-actions button:hover,
.app-shell .reply-recipient-remove:hover { background:var(--orange-wash); }
.app-shell .reply-recipient-entry { min-width:0; display:flex; align-items:center; flex-wrap:wrap; gap:5px; }
.app-shell .reply-recipient-entry input {
  min-width:180px;
  min-height:30px;
  padding: 4px 9px;
  border: 0;
  outline:0;
  flex:1;
  color:var(--text);
  background:transparent;
  font:inherit;
  font-size:10px;
}
.app-shell .reply-recipient-entry input::placeholder { color:var(--text-faintest); }
.app-shell .reply-recipient-entry:focus-within {
  border-radius:7px;
  box-shadow:inset 0 0 0 1px var(--orange),0 0 0 3px var(--orange-wash);
}
.app-shell .reply-recipient-remove {
  width:26px;
  height:26px;
  padding:0;
  color:var(--text-faint);
  font-size:16px;
}
@media (max-width:620px) {
  .app-shell .reply-recipient-row { grid-template-columns:32px minmax(0,1fr) auto; }
  .app-shell .reply-recipient-chip { align-items:flex-start; flex-direction:column; gap:1px; }
  .app-shell .reply-recipient-entry input {
  flex: 1;
  min-width: 0;
  }
}

/* ---- Open-ticket tabs ------------------------------------------------------------------------
   The strip sits under the top bar and stays put while the page scrolls. The views below size
   themselves to the window from --topbar-height; --ticket-tabs-height joins that sum only while
   the strip is showing, so nothing below it gains a scrollbar the moment a ticket is opened. */
.app-shell { --ticket-tabs-height: 0px; }
.app-shell.has-ticket-tabs { --ticket-tabs-height: 52px; }
.app-shell .ticket-tab-strip { height: var(--ticket-tabs-height); padding: 0 clamp(14px, 2vw, 28px); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 6px; position: sticky; top: var(--topbar-height); z-index: 19; background: var(--topbar); backdrop-filter: blur(14px); }
.app-shell .ticket-tab-strip[hidden] { display: none; }
.app-shell .ticket-tab-list { min-width: 0; display: flex; align-items: center; gap: 5px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.app-shell .ticket-tab-list::-webkit-scrollbar { display: none; }
.app-shell .workspace-ticket-tab { width: 210px; min-width: 210px; height: 42px; padding: 0 5px 0 11px; border: 1px solid var(--border); border-radius: 9px; display: flex; align-items: center; color: var(--muted); background: var(--surface); }
.app-shell .workspace-ticket-tab:hover { color: var(--grey); border-color: var(--border-dark); background: var(--surface-sunken); }
.app-shell .workspace-ticket-tab.active { color: var(--grey); border-color: var(--orange-wash-border); background: var(--orange-wash); box-shadow: inset 0 -2px 0 var(--orange); }
.app-shell .workspace-ticket-tab-open { min-width: 0; height: 100%; padding: 0; border: 0; display: flex; align-items: center; gap: 7px; flex: 1; color: inherit; background: transparent; cursor: pointer; font: inherit; }
.app-shell .workspace-ticket-tab-open:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; border-radius: 4px; }
.app-shell .workspace-ticket-tab-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.app-shell .workspace-ticket-tab-text { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; text-align: left; }
.app-shell .workspace-ticket-tab-id { display: block; overflow: hidden; font-size: 12px; font-weight: 800; letter-spacing: -.01em; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
.app-shell .workspace-ticket-tab-subject { display: block; overflow: hidden; color: var(--text-faint); font-size: 10.5px; font-weight: 500; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
.app-shell .workspace-ticket-tab.active .workspace-ticket-tab-subject { color: var(--text-soft); }
.app-shell .workspace-ticket-tab-close { width: 22px; height: 22px; padding: 0; border: 0; border-radius: 5px; display: grid; place-items: center; flex: none; color: var(--text-faint); background: transparent; cursor: pointer; font-size: 16px; line-height: 1; }
.app-shell .workspace-ticket-tab-close:hover { color: var(--coral-hover); background: var(--coral-wash); }
.app-shell .ticket-tab-add { width: 38px; height: 38px; border: 1px solid var(--border); border-radius: 9px; flex: none; color: var(--link); background: var(--surface); cursor: pointer; font-size: 18px; }
.app-shell .ticket-tab-add:hover { border-color: var(--orange); background: var(--orange-wash); }
.app-shell.has-ticket-tabs #ticketView .ticket-detail-grid { min-height: calc(100dvh - 130px - var(--ticket-tabs-height)); }
@media (max-width: 760px) {
  .app-shell .ticket-tab-strip { padding-inline: 10px; }
  .app-shell .workspace-ticket-tab { width: 170px; min-width: 170px; }
}

/* ---- Escalation reports -----------------------------------------------------------------------
   Six panels sharing one filter bar. Tables rather than charts: these are read to find a name, a
   code or a ticket, and a bar chart of twenty-two reason codes answers none of those questions. */

.escalation-reports { margin-top: 26px; padding: 22px 24px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); }
.escalation-reports-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; flex-wrap: wrap; margin-bottom: 16px; }
.escalation-reports-head span { color: var(--muted); font-size: 10.5px; font-weight: 700; letter-spacing: .08em; }
.escalation-reports-head h2 { margin: 5px 0 6px; font-size: 17px; }
.escalation-reports-head p { max-width: 640px; margin: 0; color: var(--muted); font-size: 12.5px; line-height: 1.55; }
.escalation-reports-actions { display: flex; align-items: flex-end; gap: 9px; flex-wrap: wrap; }
.escalation-reports-actions label { display: grid; gap: 4px; color: var(--muted); font-size: 10.5px; font-weight: 600; }
.escalation-reports-actions input { height: 34px; padding: 0 9px; border: 1px solid var(--border-dark); border-radius: 8px; background: var(--surface); font-size: 12px; }

.escalation-report-filters { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; padding: 13px 0 17px; border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); margin-bottom: 18px; }
.escalation-report-filter { display: grid; gap: 4px; color: var(--muted); font-size: 10.5px; font-weight: 600; }
.escalation-report-filter select { max-width: 190px; }
.escalation-report-filters select:disabled { opacity: .5; }

.escalation-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 20px; }
.escalation-summary > div { padding: 13px 15px; border: 1px solid var(--border); border-radius: 11px; background: var(--surface-sunken); }
.escalation-summary b { display: block; font-size: 24px; line-height: 1.2; }
.escalation-summary span { color: var(--muted); font-size: 11px; }

.escalation-panel { padding-top: 20px; border-top: 1px solid var(--hairline); margin-top: 20px; }
.escalation-panel:first-of-type { padding-top: 0; border-top: 0; margin-top: 0; }
.escalation-panel-head h3 { margin: 0 0 5px; font-size: 14px; }
.escalation-panel-head p { max-width: 700px; margin: 0 0 13px; color: var(--muted); font-size: 12px; line-height: 1.55; }

.escalation-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.escalation-table th, .escalation-table td { padding: 8px 10px; border-bottom: 1px solid var(--hairline); text-align: left; vertical-align: middle; }
.escalation-table thead th { color: var(--muted); font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
.escalation-table tbody th { font-weight: 600; }
.escalation-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.escalation-table code { color: var(--orange-ink); font-size: 11px; font-weight: 700; white-space: nowrap; }
.escalation-table a { font-weight: 600; }
.escalation-table tr:last-child td, .escalation-table tr:last-child th { border-bottom: 0; }

/* A share is read as "how much of the whole", which a number alone makes people work out. The bar
   is the figure; the percentage beside it is the precision. */
.escalation-bar { display: inline-block; width: 92px; height: 7px; margin-right: 8px; border-radius: 999px; background: var(--surface-muted); vertical-align: middle; overflow: hidden; }
.escalation-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--orange); }
.escalation-none { color: var(--muted); font-size: 11.5px; font-style: italic; }
.escalation-retired { margin-left: 7px; padding: 2px 6px; border-radius: 999px; color: var(--text-soft); background: var(--surface-muted); font-size: 9.5px; font-style: normal; font-weight: 700; text-transform: uppercase; }

.escalation-transition { margin-bottom: 16px; }
.escalation-transition > b { display: block; margin-bottom: 5px; color: var(--muted); font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; }

.escalation-dependency { margin-bottom: 8px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-sunken); }
.escalation-dependency > summary { padding: 11px 14px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px; cursor: pointer; }
.escalation-dependency > summary span { color: var(--muted); font-size: 11.5px; }
.escalation-dependency[open] > summary { border-bottom: 1px solid var(--hairline); }
.escalation-dependency .escalation-table { padding: 0 6px; }

.escalation-person { margin-bottom: 16px; }
.escalation-person-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 4px; }
.escalation-person-head span { color: var(--muted); font-size: 11.5px; }
/* The flag is the whole point of putting the team's share in the row, so it is marked where the
   eye already is rather than in a legend underneath. */
.escalation-above-team { background: var(--orange-pale); }
.escalation-flag { margin-left: 8px; color: var(--orange-ink); font-size: 10.5px; font-style: normal; font-weight: 700; }
.escalation-more { margin: 9px 0 0; color: var(--muted); font-size: 11.5px; }

@media (max-width: 860px) {
  .escalation-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .escalation-reports { padding: 17px; }
  /* Scroll the panel rather than squash the table: six columns compressed into a phone turn
     every reason label into one word per line, which is less readable than a swipe. */
  .escalation-panel { overflow-x: auto; }
  .escalation-table { min-width: 580px; }
  .escalation-note { max-width: 260px; }
}
.escalation-person-move { margin: 0 0 11px 14px; }
.escalation-person-move > b { display: block; margin-bottom: 3px; color: var(--muted); font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; }
/* The handover note is why the ticket came back, which is the part a manager reads. Clamped so a
   long one does not turn the table into a wall of prose. */
.escalation-note { display: -webkit-box; max-width: 440px; margin-top: 3px; color: var(--muted); font-size: 11.5px; line-height: 1.45; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Sits under the destination picker, explaining a short reason list before somebody reads it as a
   missing one. */

/* ==== Dark theme: component layer ============================================================
   The tokens at the top of this file carry most of the dark theme. What remains here is the
   handful of jobs a token cannot express on its own -- which layer a surface belongs to, where a
   glow stops being a highlight and becomes noise, and how content written for white paper (an
   email, a signature, the composer) is shown on a dark page without being rewritten. Kept in one
   place so the theme can be read as a design rather than found in a hundred patches. */

/* Floating layers sit at the top of the surface stack, with the hairline ring that separates a
   menu from the panel it covers. In the light theme the overlay is the same white as a panel, so
   only the background token is shared; the dark shadow is what changes. */
.app-shell .popover,
.app-shell .modal,
.confirm-box,
.drawer-actions-menu,
.bulk-actions-menu,
.contact-picker-results,
.incoming-call-popup,
.global-search-results,
.kb-create-menu,
.merge-panel,
.workspace-links-dialog,
.app-shell .reply-canned-menu,
.app-shell .reply-colour-menu,
.ticket-hover-preview,
.app-shell .ticket-venue-search .contact-venue-results { background: var(--surface-overlay); }
:root[data-theme="dark"] .app-shell .popover,
:root[data-theme="dark"] .app-shell .modal,
:root[data-theme="dark"] .confirm-box,
:root[data-theme="dark"] .drawer-actions-menu,
:root[data-theme="dark"] .bulk-actions-menu,
:root[data-theme="dark"] .contact-picker-results,
:root[data-theme="dark"] .incoming-call-popup,
:root[data-theme="dark"] .global-search-results,
:root[data-theme="dark"] .kb-create-menu,
:root[data-theme="dark"] .merge-panel,
:root[data-theme="dark"] .workspace-links-dialog,
:root[data-theme="dark"] .app-shell .reply-canned-menu,
:root[data-theme="dark"] .app-shell .reply-colour-menu,
:root[data-theme="dark"] .ticket-hover-preview,
:root[data-theme="dark"] .app-shell .ticket-venue-search .contact-venue-results { border-color: var(--border); box-shadow: var(--floating-shadow); }
/* Rows inside a popover were painted the panel colour, which in the dark is a stripe darker than
   the popover around them. */
.notification-item { background: transparent; }
:root[data-theme="dark"] .toast { box-shadow: 0 0 0 1px rgba(0, 0, 0, .25), 0 14px 36px rgba(0, 0, 0, .55); }

/* Orange buttons glowed: a coloured shadow reads as a soft halo on white, but on a dark page it
   becomes a smear of orange light under every button. The fill is enough. */
:root[data-theme="dark"] .primary-button,
:root[data-theme="dark"] .app-shell .primary-button,
:root[data-theme="dark"] .primary-button.is-saved,
:root[data-theme="dark"] .primary-button.is-unsaved { box-shadow: none; }
:root[data-theme="dark"] .app-shell .primary-button:hover { box-shadow: 0 0 0 3px rgba(var(--orange-rgb), .16); }

/* The rail is the darkest layer; its edge is a hairline rather than a shade. */
:root[data-theme="dark"] .app-shell .sidebar { border-right-color: rgba(210, 220, 240, .07); }
/* The account menu opened as a warm #383838 sheet among cool greys. */
:root[data-theme="dark"] .user-menu-panel { border-color: rgba(210, 220, 240, .12); background: #1d2128; box-shadow: var(--floating-shadow); }

/* The NEW tag keeps its lime, but as a tag rather than a neon block. */
:root[data-theme="dark"] .new-ticket-tag { --new-tag-bg: rgba(183, 255, 0, .13); --new-tag-ink: #c6f56a; --new-tag-border: rgba(185, 242, 100, .38); box-shadow: none; }

/* Tables of figures: the header band and zebra rows step by surface, not by a grey literal. */
:root[data-theme="dark"] .app-shell .table-footer { background: var(--surface-head); }

/* ---- Content written for white paper ----
   Messages are fitted to the theme in site.js (fitMessageColours). These cover what inline
   colours cannot: elements whose colour comes from the browser rather than the sender. */
:root[data-theme="dark"] .message-html mark { color: #1f2328; }
:root[data-theme="dark"] .message-html hr { border-color: var(--border-dark); }
:root[data-theme="dark"] .message-html table[border] td,
:root[data-theme="dark"] .message-html table[border] th { border-color: var(--border-dark); }

/* The Triniteq signature carries the colour logo, whose grey wordmark measured 2.3:1 on a dark
   thread. The white artwork is the same proportions and is what the sidebar already uses. */
:root[data-theme="dark"] .desk-agent-signature img[src$="/images/triniteq-logo.png"] { content: url("/images/triniteq-logo-white.svg"); }

/* The composer holds what the customer will receive on white paper, so it is never recoloured --
   only shown differently. "Automatic" text is written as #2b2b2b, correct in the email and 1.2:1
   in a dark editor; it is drawn in the theme's text colour here, and highlighted text keeps the
   dark ink it will have in the customer's mail client. */
:root[data-theme="dark"] .reply-editor font[color="#2b2b2b"],
:root[data-theme="dark"] .reply-editor [style*="color: rgb(43, 43, 43)"],
:root[data-theme="dark"] .reply-editor [style*="color:#2b2b2b"],
:root[data-theme="dark"] .reply-editor [style*="color: #2b2b2b"] { color: var(--grey) !important; }
:root[data-theme="dark"] .reply-editor [style*="background-color"] { color: #1f2328; }
:root[data-theme="dark"] .app-shell .reply-format-colour::before,
:root[data-theme="dark"] .app-shell .reply-colour-automatic i { box-shadow: 0 0 0 1px rgba(210, 220, 240, .35); }

/* Counts in the queue tabs sat at 4.3:1 on their chip. */
.ticket-tab span { color: var(--muted); }
/* A month with no data was a cell faded to half opacity -- its dash dropped to 3:1. An empty
   month is better drawn as an outline than as a ghost of a full one. */
.kpi-trend-months .kpi-trend-dot.empty { opacity: 1; color: var(--text-faint); background: transparent; box-shadow: inset 0 0 0 1px var(--border); }

/* Internal notes. A translucent orange wash over dark grey mixes to brown, so in the dark the note
   is a raised card with only a breath of orange and an orange rule down its edge: still
   unmistakably "internal", without a muddy slab in the middle of the thread. */
:root[data-theme="dark"] .message.note {
  border-color: rgba(255, 138, 61, .22);
  background: linear-gradient(rgba(255, 138, 61, .05), rgba(255, 138, 61, .05)), var(--surface-raised);
  box-shadow: inset 3px 0 0 var(--orange);
}
/* Orange corner glows were a warm light on white; on a dark panel they read as a stain. */
:root[data-theme="dark"] .app-shell #ticketView .contact-summary-panel {
  border-color: var(--border);
  background: radial-gradient(circle at 100% 0, rgba(255, 117, 26, .045), transparent 45%), var(--surface);
}
:root[data-theme="dark"] .app-shell #contactView { background: radial-gradient(circle at 78% 0, rgba(255, 117, 26, .03), transparent 32%), var(--surface); }
:root[data-theme="dark"] .app-shell .ticket-create-view { background: radial-gradient(circle at 82% 3%, rgba(255, 117, 26, .04), transparent 28rem), var(--zircon); }

/* Open KPI breaches still interrupt, but by edge and accent rather than a saturated slab: a solid
   red border round a red wash read as an error state for the whole page. */
:root[data-theme="dark"] .kpi-breaching {
  border-color: var(--coral-wash-border);
  background: linear-gradient(rgba(254, 56, 56, .07), rgba(254, 56, 56, .07)), var(--surface);
  box-shadow: inset 3px 0 0 var(--coral);
}
:root[data-theme="dark"] .kpi-breaching-head b,
:root[data-theme="dark"] .kpi-breaching li a { color: var(--coral-ink); }

/* Toggle knobs were the panel colour, so in the dark a switch read as a hole with a darker hole
   in it. A light knob is what every dark system UI uses: the thumb is the part you move. */
:root[data-theme="dark"] .toggle-row i::after { background: #e6e9ef; box-shadow: 0 1px 3px rgba(0, 0, 0, .45); }

/* Set by applyTheme for the frame a theme changes in. See site.js. */
.theme-switching *, .theme-switching *::before, .theme-switching *::after { transition: none !important; }
/* The message header greys every span in it, which caught the "Internal note" tag: grey on its
   orange chip measured 4.4:1. The tag keeps its own ink. */
.message-head span.message-type { color: var(--orange-ink); }
/* The unassigned group's "?" avatar was greyed the same way. */
.app-shell .ticket-group-heading span.avatar { color: var(--avatar-ink); }

/* ---- Workspace layout, October 2026 -------------------------------------------------------
   Three changes, all of them about what an agent sees first when a ticket is opened.

   The chrome was three stacked bars -- the search, the open-ticket strip and the ticket's own
   action bar -- which spent roughly 220px before the ticket began. They are one row now: the
   open tickets sit beside the search as pills, and the ticket's actions sit on the ticket's own
   header card rather than on a slab of their own.

   The composer was pinned above the conversation and always open, so opening a ticket showed the
   reply box and pushed what the customer wrote below the fold. It is at the end of the thread
   and closed until it is wanted.

   The side column was one long form ending in Update properties. It is three small panels --
   who the ticket is from, what it is, and the clock -- and the fields save themselves.

   Everything here is written in the theme tokens at the top of this file, so the dark theme
   needs no rules of its own. */

/* The tabs are part of the top bar now, so they add nothing to the height the views size
   themselves against. */
.app-shell.has-ticket-tabs { --ticket-tabs-height: 0px; }
.app-shell .topbar { gap: 12px; }
.app-shell .global-search-wrap { width: min(360px, 32vw); flex: 0 1 auto; }
.app-shell .ticket-tab-strip {
  height: auto;
  min-width: 0;
  padding: 0;
  border: 0;
  position: static;
  flex: 1 1 220px;
  background: transparent;
  backdrop-filter: none;
}
.app-shell .workspace-ticket-tab {
  width: auto;
  min-width: 0;
  max-width: 240px;
  height: 36px;
  padding: 0 4px 0 13px;
  border-radius: 999px;
  gap: 4px;
}
.app-shell .workspace-ticket-tab.active {
  border-color: var(--orange-wash-border);
  background: var(--orange-wash-strong);
  box-shadow: none;
}
/* The id and the subject on one line: two stacked lines inside a 36px pill left nothing of
   either, and the id alone does not tell three tickets from one venue apart. */
.app-shell .workspace-ticket-tab-text { align-items: baseline; flex-direction: row; gap: 7px; }
.app-shell .workspace-ticket-tab-id { flex: none; font-size: 11.5px; }
.app-shell .workspace-ticket-tab-subject { min-width: 0; font-size: 11.5px; }
.app-shell .ticket-tab-add {
  width: 32px;
  height: 32px;
  border-style: dashed;
  border-radius: 999px;
  font-size: 16px;
}

/* The breadcrumb row is part of the ticket's card, not a slab above it: back, the ticket
   number, and what you can do with it. Sticky inside the card, so Reply and Resolve stay put
   while the conversation scrolls under them. The subject is on the header below, so the
   heading here is for screen readers only -- clipped rather than display:none, which would
   leave the section with no accessible name. */
.app-shell .ticket-detail-bar {
  min-height: 0;
  padding: 14px 26px;
  border-bottom: 1px solid var(--hairline);
  border-radius: 15px 15px 0 0;
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--surface);
}
.app-shell .ticket-detail-bar h1 {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.app-shell .ticket-breadcrumb > button,
.app-shell .more-button { border-radius: 999px; }

/* The ticket's header card: subject, where it came from, and its state as chips. */
.app-shell .request-header { display: block; padding: 22px 26px 18px; border-bottom: 1px solid var(--hairline); }
.app-shell .request-title-line h2 { font-size: 21px; white-space: normal; }
.app-shell .request-header > p { margin: 7px 0 0; font-size: 12.5px; }
.app-shell .ticket-chip-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 15px;
  padding-top: 14px;
  border-top: 1px solid var(--hairline);
}
.app-shell .ticket-chip {
  padding: 4px 11px;
  border-radius: 999px;
  color: var(--text-soft);
  background: var(--surface-muted);
  font-size: 11.5px;
  font-weight: 600;
}
/* Priority and the clock carry the same colours as the queue, so a ticket reads the same in
   both places. Urgent and high differ in lightness as well as hue, for anyone who cannot tell
   the coral from the orange. */
.app-shell .ticket-chip-priority.priority-urgent { color: var(--coral-ink); background: var(--coral-wash); }
.app-shell .ticket-chip-priority.priority-high { color: var(--orange-ink); background: var(--orange-wash-strong); }
.app-shell .ticket-chip-sla { margin-left: auto; font-weight: 700; }
.app-shell .ticket-chip-sla.overdue { color: var(--coral-ink); background: var(--coral-wash); }
.app-shell .ticket-chip-sla.risk,
.app-shell .ticket-chip-sla.warning { color: var(--orange-ink); background: var(--orange-wash-strong); }

/* The summary sits between the header and the conversation, where a handover note is read:
   before the thread, not after it. */
.app-shell .ticket-summary {
  margin: 16px 26px 0;
  padding: 15px 17px;
  border: 1px solid var(--orange-wash-border);
  border-left-width: 1px;
  border-radius: 13px;
  background: var(--orange-wash);
}

/* The composer, docked at the end of the thread. Closed it is one line; open it is everything
   it always was. */
.app-shell .reply-box {
  margin: 0;
  /* 22px, the inset the conversation below it carries, so the composer's own box
     lines up with the message cards rather than sitting a few pixels inside them. */
  padding: 14px 22px 16px;
  border: 1px solid var(--hairline);
  border-radius: 15px;
  background: var(--surface);
}
.app-shell .reply-box.reply-collapsed > *:not(.reply-open-button) { display: none; }
.app-shell .reply-box:not(.reply-collapsed) .reply-open-button { display: none; }
.app-shell .reply-open-button {
  width: 100%;
  padding: 8px 8px 8px 12px;
  border: 1px solid var(--border-dark);
  border-radius: 999px;
  display: flex;
  align-items: center;
  gap: 11px;
  color: var(--text-faint);
  background: var(--surface-sunken);
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  text-align: left;
}
.app-shell .reply-open-button:hover { border-color: var(--orange); background: var(--orange-wash); }
.app-shell .reply-open-button .avatar { width: 30px; height: 30px; flex: none; font-size: 11px; }
.app-shell .reply-open-placeholder {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell .reply-open-affordance {
  padding: 7px 15px;
  border-radius: 999px;
  flex: none;
  color: var(--on-orange);
  background: var(--orange);
  font-size: 11.5px;
  font-weight: 700;
}

/* The side column: three panels rather than one form. */
.app-shell .ticket-side-column { gap: 14px; }
.app-shell .drawer-fields { padding: 14px 17px 16px; gap: 9px; }
/* Label beside the control rather than above it: five stacked pairs made the panel taller than
   the conversation it sits next to. The label is a bare text node, which both grid and flex wrap
   in an anonymous item -- grid places it in the first column, which is what sizes it. */
.app-shell .drawer-fields label {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  color: var(--text-soft);
  font-size: 12.5px;
  font-weight: 500;
  text-transform: none;
}
.app-shell .drawer-fields select { margin-top: 0; height: 36px; border-radius: 10px; }
.app-shell .property-save-state {
  color: var(--text-faint);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0;
}
.app-shell .property-actions { padding: 0 17px 15px; display: flex; justify-content: flex-end; border-top: 0; }
.app-shell .property-actions .secondary-button { min-height: 34px; font-size: 11.5px; }

.app-shell .ticket-service-panel .sla-remaining {
  color: var(--text-soft);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0;
}
.app-shell .ticket-service-panel .sla-remaining.overdue { color: var(--coral-ink); }
.app-shell .ticket-service-panel .sla-remaining.risk,
.app-shell .ticket-service-panel .sla-remaining.warning { color: var(--orange-ink); }
.app-shell .ticket-service-panel .sla-remaining.done { color: var(--green-ink); }
.app-shell .ticket-service-body { padding: 15px 17px 17px; display: grid; gap: 13px; }
/* How much of the window between the ticket arriving and its target has gone. "15h remaining"
   means something different on a four-hour target and a four-day one. */
.app-shell .sla-meter { height: 7px; border-radius: 999px; background: var(--surface-muted); overflow: hidden; }
.app-shell .sla-meter > span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--green);
  transition: width .3s ease;
}
.app-shell .sla-meter > span.warning,
.app-shell .sla-meter > span.risk { background: var(--orange); }
.app-shell .sla-meter > span.overdue { background: var(--coral); }
.app-shell .sla-due { margin: 0; color: var(--text-faint); font-size: 11.5px; }
.app-shell .ticket-service-body .ticket-level-row { margin: 0; padding: 0; border: 0; }
.app-shell .ticket-service-body .ticket-checkbox-property { padding-top: 13px; border-top: 1px solid var(--hairline); }

@media (min-width: 1101px) {
  /* The fields are what they are; the clock below them takes the space left over, so the two
     panels do not stretch into one tall form with a gap in the middle of it. */
  .app-shell #ticketView .property-panel { flex: none; }
  .app-shell #ticketView .ticket-service-panel { flex: 1; min-height: 0; }
  .app-shell #ticketView .property-actions { margin-top: 0; }
}

/* ---- Cards, not panes ----
   The ticket used to be two full-bleed columns divided by hairlines, which read as one dense
   sheet: the contact, the fields and the clock ran together, and the conversation had no edge
   of its own. Each part is a card on the page again -- the thread, the contact, the properties
   and the service target -- with the page colour showing between them, which is what makes the
   three groups legible as three groups. The columns still scroll independently above 1100px;
   the card is simply the scroll container now. */
.app-shell #ticketView .ticket-detail-grid {
  padding: 0 clamp(18px, 2.3vw, 38px) clamp(18px, 1.8vw, 26px);
  gap: clamp(14px, 1.4vw, 18px);
  align-items: start;
}
.app-shell #ticketView .ticket-thread {
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--shadow);
}
.app-shell #ticketView .ticket-side-column { gap: clamp(12px, 1.2vw, 14px); background: transparent; }
.app-shell #ticketView .ticket-side-column > .panel {
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--shadow);
}
/* A card has its own edges, so the dividers that stood in for them go. */
.app-shell #ticketView .ticket-side-column > .panel + .panel { border-left: 1px solid var(--border); }
.app-shell #ticketView .property-actions:empty { display: none; }

@media (min-width: 1101px) {
  /* The columns are as tall as the window; the cards sit inside that, each scrolling itself. */
  .app-shell #ticketView .ticket-thread { height: auto; max-height: 100%; }
  .app-shell #ticketView .ticket-side-column { height: 100%; overflow: visible; }
  .app-shell #ticketView .ticket-side-column > .panel { flex: none; }
  /* The clock takes what is left so the column ends flush with the thread beside it. */
  .app-shell #ticketView .ticket-service-panel { flex: 0 1 auto; }
}

@media (max-width: 1100px) {
  /* The tabs take the row under the search once both cannot share one. The views size
     themselves against --topbar-height, so the bar says how tall it has become. */
  .app-shell .topbar { flex-wrap: wrap; height: auto; padding-block: 10px; }
  .app-shell .ticket-tab-strip { order: 3; flex-basis: 100%; overflow: hidden; }
  .app-shell.has-ticket-tabs { --topbar-height: 116px; }
}
@media (max-width: 760px) {
  .app-shell .ticket-detail-bar { padding: 12px 12px 0; }
  .app-shell .request-header { padding: 18px 16px 14px; }
  .app-shell .reply-box { padding: 12px 22px 16px; }
  .app-shell .ticket-summary { margin-inline: 16px; }
  .app-shell .ticket-chip-sla { margin-left: 0; }
}

/* ---- The shell and the contact card, as drawn ----
   The navigation and the contact's details are the two places where the workspace still read as
   a form: square rows down the side, and a definition list of labels and values in the panel.
   Both become the shape everything else here is -- the Style Guide's fully rounded control. */
.app-shell .nav-link { border-radius: 999px; padding-inline: 14px; }
.app-shell .nav-link b { min-width: 22px; }
/* Email and phone as chips you can hit, rather than a label column and a value column. */
.app-shell #ticketView .ticket-contact-methods {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 12px 0 0;
}
.app-shell #ticketView .ticket-contact-methods > div {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  max-width: 100%;
  padding: 7px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-sunken);
}
.app-shell #ticketView .ticket-contact-methods dt {
  color: var(--text-faint);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.app-shell #ticketView .ticket-contact-methods dd {
  min-width: 0;
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-shell #ticketView .ticket-contact-methods dd a { font-size: 12px; font-weight: 600; text-decoration: none; }

/* ------------------------------------------------------------------ Support roster
 *
 * Every colour here is a token, so the panel follows the workspace into dark mode without a
 * second set of rules. The exception is a roster member's own colour, which is data rather than
 * theme: it arrives on the element as an inline style and is used as a dot, a left edge or a
 * low-alpha wash, never as a solid fill behind text, so the same three colours stay legible on
 * the light surface and the dark one.
 */
.roster-head { align-items: flex-start; }

/* The shift panel's head carries the date and the zone switch that used to sit on a "Support
   today" row above the whole roster. The date describes these shifts, and the switch changes the
   times in them, so both belong on the panel rather than over it. */
.roster-shift-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.roster-shift-head #rosterDateLine { margin: 3px 0 0; color: var(--text-soft); font-size: .9375rem; }
.roster-shift-head .secondary-button { text-decoration: none; }

.roster-zone-switch { display: inline-flex; gap: 2px; padding: 3px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface-sunken); }
.roster-zone-switch button { padding: 6px 14px; border: 0; border-radius: 999px; background: transparent; color: var(--text-soft); font: inherit; font-size: .875rem; font-weight: 500; cursor: pointer; }
.roster-zone-switch button:hover { color: var(--grey); }
.roster-zone-switch button.active { background: var(--surface); color: var(--grey); box-shadow: var(--shadow); }
.roster-zone-switch button:focus-visible { outline: 2px solid var(--orange); outline-offset: 1px; }

.roster-holiday-line { margin: 0 0 16px; padding: 10px 14px; border: 1px solid var(--coral-wash-border); border-radius: 10px; background: var(--coral-wash); color: var(--coral-ink); font-size: .9375rem; }

/* The name column every row in the shift list shares, and the gap beside it. Named rather than
   repeated so the hours line under a bar cannot drift out of step with the bar above it. */
.roster-shift-panel { --roster-name-column: 160px; --roster-row-gap: 16px; }

/* The two columns end on the same line. They are side by side and the same kind of thing, so
   one finishing 40px short of the other read as a mistake rather than as two panels. The shorter
   column takes up the slack: on the left the shift panel's notes stretch, on the right the
   stints list does. */
.roster-today-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: stretch; gap: var(--overview-gap, 16px); }
.roster-today-grid > .panel { height: 100%; }

/* Tonight's phone, who takes it next and the reader's own nights are one subject, so the column
   holding them is a stack rather than three panels scattered down the page. The on-call card is
   sized by its content and the stints panel takes whatever height is left. */
.roster-today-side { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: var(--overview-gap, 16px); }

/* Every panel body on this page is inset by the same amount as the head above it. They were
   not: the heads carry the panel's own 21px and the lists were drawn from the panel's edge, so
   a name sat 21px to the left of the heading it belonged under, on every panel. */
.roster-shift-rows,
.roster-stints,
.roster-oncall,
.roster-calendar,
.roster-tally { padding: 0 21px 18px; }

.roster-empty { margin: 0; padding: 4px 0 14px; color: var(--text-faint); font-size: .9375rem; }

/* A shift row is two lines: who, the bar and the pill across the top, then the hours under the
   bar. One line with the hours wedged between the bar and the pill put three things of three
   different widths on one baseline, and no two rows lined up.

   The three columns are declared once on the list and every row borrows them with subgrid, so
   the bars all start and end in the same place whatever the row says. Rows used to carry their
   own grid, which gave the pill column a width per row: "On break until 11:30am" is half as wide
   again as "On now", so that row's track was shorter, and the same percentage along a shorter
   track is a different place on the page. The now-lines fanned out across the rows and a shift
   that ends at 5pm looked like it ended earlier than somebody else's 5pm.

   The hours sit in the bar's column, so they start where the bar does. */
.roster-shift-rows { display: grid; grid-template-columns: var(--roster-name-column) minmax(0, 1fr) auto; column-gap: var(--roster-row-gap); }
.roster-shift-rows > * { grid-column: 1 / -1; }

.roster-shift-row { display: grid; grid-template-columns: subgrid; align-items: center; padding: 12px 0; border-top: 1px solid var(--hairline); }
.roster-shift-row:first-child { border-top: 0; }
/* The negative margin and the matching inset cancel out, so the highlight sits wider than the
   row without moving the columns off the ones the list declared. */
.roster-shift-row.is-you { background: var(--orange-wash); margin: 0 -10px; padding-inline: 10px; border-radius: 8px; }

/* The top line has no box of its own: its three children are the row's own grid items, which is
   what lets them sit on the list's columns. */
.roster-shift-top { display: contents; }

.roster-shift-who { display: flex; align-items: center; gap: 10px; min-width: 0; }
.roster-shift-who b { color: var(--grey); font-size: 1.0625rem; font-weight: 600; }
.roster-you { color: var(--text-faint); font-size: .8125rem; }
.roster-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; }

.roster-bar { position: relative; height: 10px; border-radius: 999px; background: var(--surface-muted); overflow: hidden; }
.roster-bar-fill { position: absolute; top: 0; bottom: 0; border-radius: 999px; }
.roster-bar-break { position: absolute; top: 0; bottom: 0; background: var(--surface); opacity: .85; }
.roster-bar-now { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--coral); }

.roster-shift-hours { grid-column: 2 / -1; margin: 6px 0 0; color: var(--text-soft); font-size: .875rem; font-variant-numeric: tabular-nums; }

.roster-pill { padding: 4px 10px; border-radius: 999px; font-size: .8125rem; font-weight: 600; white-space: nowrap; }
.roster-pill-on { background: var(--green-wash); color: var(--green-ink); border: 1px solid var(--green-wash-border); }
.roster-pill-break { background: var(--amber-wash); color: var(--amber-ink); }
.roster-pill-soon { background: var(--orange-wash-strong); color: var(--orange-ink); }
.roster-pill-leave { background: var(--coral-wash); color: var(--coral-ink); border: 1px solid var(--coral-wash-border); }
/* --text-faint on the muted surface lands at 4.35:1, just under. The pill is small text. */
.roster-pill-off { background: var(--surface-muted); color: var(--text-soft); }

/* Who is away, between the shift rows and the day's notes. On the same 21px inset as the rows
   above it, and with the name in the same column as theirs, so the two lists read as one. */
.roster-leave { padding: 12px 21px 14px; border-top: 1px solid var(--hairline); }
.roster-leave-title { margin: 0 0 8px; color: var(--text-faint); font-size: .75rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.roster-leave-row { display: flex; align-items: baseline; gap: 10px; padding: 3px 0; font-size: .9375rem; }
.roster-leave-row .roster-dot { align-self: center; }
.roster-leave-row b { color: var(--grey); font-weight: 600; }
.roster-leave-kind { color: var(--text-soft); }
.roster-leave-group + .roster-leave-group { margin-top: 10px; }
.roster-leave-label { margin: 0 0 2px; color: var(--text-soft); font-size: .8125rem; font-weight: 600; }
.roster-leave-when { margin-left: auto; color: var(--text-soft); font-variant-numeric: tabular-nums; }
.roster-leave-none { margin: 0; color: var(--text-soft); font-size: .9375rem; }
/* On a phone the dates get a line of their own, lined up under the name rather than broken
   across two lines beside it. */
@media (max-width: 760px) {
  .roster-leave-row { flex-wrap: wrap; }
  .roster-leave-when { margin: 0 0 0 22px; flex: 1 1 100%; }
}

.roster-day-notes { padding: 12px 21px 16px; border-top: 1px solid var(--hairline); }
.roster-day-notes:empty { display: none; }
.roster-day-notes p { margin: 0 0 6px; color: var(--text-soft); font-size: .875rem; }
.roster-day-notes p:last-child { margin-bottom: 0; }
.roster-day-notes b { margin-right: 6px; color: var(--text-faint); font-weight: 600; }

/* Left-aligned on the same edge as everything else in the card, and sized to be read from
   across a desk, which is what this card is for. The colour is the member's own, adjusted by
   roster.js until it is readable on whichever theme is showing. */
.roster-oncall-name { margin: 0 0 4px; font-size: 2.25rem; font-weight: 800; line-height: 1.05; letter-spacing: -.03em; }
.roster-oncall-through { margin: 0; color: var(--text-soft); font-size: .9375rem; line-height: 1.5; }
.roster-oncall-aside { color: var(--text-faint); font-weight: 500; }

/* Who takes the phone next, as a name and a date rather than the tail of a sentence: it is the
   second thing anybody looks for on this card, and a clause does not answer it at a glance. */
.roster-oncall-next { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hairline); }
.roster-oncall-next-label { margin: 0; color: var(--text-faint); font-size: .75rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.roster-oncall-next-name { margin: 2px 0 0; font-size: 1.5rem; font-weight: 700; line-height: 1.15; letter-spacing: -.02em; }
.roster-oncall-next-from { margin: 1px 0 0; color: var(--text-soft); font-size: .9375rem; }

/* The way to the month grid, on the card the month grid is about. Full width because it is the
   only thing to do on this card, and on the panel's own inset so it lines up with the name. */
.roster-oncall-panel .roster-oncall { padding-bottom: 14px; }
.roster-oncall-foot { padding: 0 21px 18px; }
.roster-oncall-foot .secondary-button { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; text-decoration: none; }

.roster-calendar-head, .roster-tally-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.roster-calendar-head h2 { font-size: 1.25rem; letter-spacing: -.01em; }

.roster-legend { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 18px; padding: 0 21px 14px; }
.roster-legend-item { display: inline-flex; align-items: center; gap: 8px; color: var(--text-soft); font-size: .8125rem; }

/* The workspace's panel head is sized for a page with one or two panels on it. The roster has
   six, so its heads carry the same type on two thirds of the height. */
.roster-today-grid .panel-head,
.roster-calendar-panel .panel-head,
.roster-stints-panel .panel-head { min-height: 0; padding: 14px 21px 10px; }
.roster-month-nav, .roster-tally-actions { display: flex; align-items: center; gap: 6px; }

/* Seven columns, six rows, every cell the same height whatever is in it. A holiday name long
   enough to wrap must not make its row taller than the others, so the overflow is clipped and
   the full text is on the day panel instead. */
.roster-calendar { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.roster-cal-head { padding: 0 4px 8px 10px; color: var(--text-faint); font-size: .8125rem; font-weight: 500; }
.roster-cal-cell { position: relative; height: 68px; padding: 5px 8px 5px 9px; border: 1px solid var(--hairline); border-left: 3px solid var(--cell-edge, transparent); border-radius: 6px; background: var(--cell-tint, transparent); overflow: hidden; }
.roster-cal-cell.is-outside { opacity: .45; }
/* Drawn inside the cell so today's ring cannot change its size and shunt the grid. */
.roster-cal-cell.is-today::after { content: ''; position: absolute; inset: 2px; border: 2px solid var(--orange); border-radius: 4px; pointer-events: none; }

.roster-cal-date { display: flex; align-items: center; gap: 5px; font-size: .8125rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.roster-cal-holiday-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--coral); }
.roster-cal-name { margin-top: 1px; font-size: .8125rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roster-cal-line { color: var(--text-soft); font-size: .6875rem; line-height: 1.3; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1; overflow: hidden; }
.roster-cal-note { font-style: italic; }

/* In the side column there is no room for a fixed date column beside the count, so the dates
   take the line and the number of nights sits under them. */
.roster-stint { padding: 7px 0; border-top: 1px solid var(--hairline); font-size: .875rem; }
.roster-stint:first-child { border-top: 0; }
.roster-stint b { display: block; font-weight: 600; }
.roster-stint span { display: block; margin-top: 1px; color: var(--text-faint); font-size: .75rem; }

.roster-tally-table { width: 100%; border-collapse: collapse; font-size: .9375rem; }
.roster-tally-table th, .roster-tally-table td { padding: 8px 10px; text-align: right; }
.roster-tally-table thead th { color: var(--text-faint); font-size: .75rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.roster-tally-table thead tr:first-child th { border-bottom: 1px solid var(--hairline); }
/* The two group headings span a pair of columns each, so they are centred over the pair
   rather than right-aligned against its last column, where they read as a label for one. */
.roster-tally-table thead tr:first-child th[colspan] { text-align: center; }
.roster-tally-subhead th { font-size: .6875rem; }
.roster-tally-table tbody th { display: flex; align-items: center; gap: 8px; font-weight: 600; text-align: left; }
.roster-tally-table tbody td { font-variant-numeric: tabular-nums; }
.roster-tally-table tbody tr { border-top: 1px solid var(--hairline); }

/* Below a tablet the two columns stack, the bar goes (it is comparative, and there is nothing
   left to compare it against in a single column) and the calendar keeps only its headline. */
@media (max-width: 1100px) {
  .roster-today-grid { grid-template-columns: minmax(0, 1fr); }
}

/* A calendar cell opens the night, so it has to look and behave like something you can press:
   the same hover and focus ring the rest of the shell uses, and a pointer on it. */
.roster-cal-cell { cursor: pointer; transition: box-shadow .12s ease; }
.roster-cal-cell:hover { box-shadow: var(--shadow); }
.roster-cal-cell:focus-visible { outline: 2px solid var(--orange); outline-offset: 1px; }

/* One night, opened from the grid. Narrower than the default modal: it is a handful of lines
   about a single date, and the full width reads as a form that forgot its fields. */
.roster-day-modal { width: min(460px, 100%); }
.roster-day-body p { margin: 0 0 8px; color: var(--text-soft); font-size: .9375rem; }
.roster-day-body p:last-child { margin-bottom: 0; }

@media (max-width: 760px) {
  .roster-shift-panel { --roster-name-column: minmax(0, 1fr); --roster-row-gap: 10px; }
  /* No bar at this width, so the row is who and the pill, and the hours run the full width. */
  .roster-shift-rows { grid-template-columns: minmax(0, 1fr) auto; }
  .roster-bar { display: none; }
  .roster-shift-hours { grid-column: 1 / -1; }
  .roster-oncall-name { font-size: 2rem; }
  /* The three month buttons take the width rather than running off the side of it. */
  .roster-calendar-head { flex-wrap: wrap; }
  .roster-month-nav { width: 100%; }
  .roster-month-nav .secondary-button { flex: 1; min-width: 0; padding-inline: 10px; }

  .roster-cal-cell { height: 72px; padding: 4px 3px 4px 5px; border-left-width: 3px; }
  /* The secondary lines go, as the brief asks, but the name stays: a column of "Br..." tells
     nobody who is on call, which is the one thing the grid exists to say. The first names on
     this roster are short, so they fit once the padding and the type come down. */
  .roster-cal-line { display: none; }
  .roster-cal-date { font-size: .6875rem; }
  .roster-cal-name { font-size: .6875rem; letter-spacing: -.01em; }
  .roster-calendar { gap: 3px; }
}

/* ------------------------------------------------------------------ Manage roster
 *
 * The admin side of the same page, on the same tokens. Two forms side by side at the top because
 * they are alternatives to each other -- extend the rotation, or hand one stretch of nights over
 * -- then the three lists, each full width because each is a table.
 */
.roster-head-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

.roster-admin-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-bottom: 16px; align-items: start; }
.roster-admin-panel { display: flex; flex-direction: column; }
.roster-admin-form { padding: 0 21px 18px; }
.roster-admin-form label { display: block; margin-bottom: 13px; color: var(--text-soft); font-size: 10px; font-weight: 700; }
.roster-admin-form input, .roster-admin-form select { width: 100%; height: 39px; margin-top: 6px; padding: 0 11px; border: 1px solid var(--border-dark); border-radius: 8px; outline: 0; color: var(--grey); background: var(--surface); font-size: 12px; }
.roster-admin-form input:focus, .roster-admin-form select:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,117,26,.1); }
.roster-admin-order { margin-bottom: 13px; }
.roster-admin-order-label { display: block; margin-bottom: 6px; color: var(--text-soft); font-size: 10px; font-weight: 700; }
.roster-order-chip { display: inline-flex; align-items: center; gap: 6px; margin: 0 6px 6px 0; padding: 4px 6px 4px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface-sunken); font-size: .8125rem; font-weight: 600; }
.roster-order-chip b { color: var(--text-faint); font-size: .6875rem; }
.roster-order-chip button { width: 22px; height: 22px; border: 0; border-radius: 50%; display: grid; place-items: center; color: var(--text-soft); background: var(--surface-muted); font-size: 11px; cursor: pointer; }
.roster-order-chip button:hover:not(:disabled) { color: var(--orange-ink); background: var(--orange-wash); }
.roster-order-chip button:disabled { opacity: .35; cursor: default; }
/* The shared toggle hides its checkbox with position:absolute and no offsets, so the box keeps
   its static position inside whatever is positioned above it. On a phone that lands it off the
   right of the screen and scrolls the whole page sideways, invisibly. Anchored to the row and
   shrunk to a point, which is what an input nobody can see should measure. */
.roster-admin-toggle { position: relative; margin-bottom: 14px; }
.roster-admin-toggle input { top: 0; left: 0; width: 1px; height: 1px; }
.roster-admin-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* What the rotation would do, in a sentence. Three counts do not read as a warning, and the
   count that matters -- nights taken off somebody who has them -- is the one nobody expects. */
.roster-admin-summary:not(:empty) { margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--orange-wash-border); border-radius: 10px; background: var(--orange-wash); color: var(--text-soft); font-size: .875rem; line-height: 1.5; }

/* Four time inputs and a day name need about 520px before the columns start overlapping each
   other, so that is the width a member's week is allowed to shrink to; below it they stack. */
.roster-hours { display: grid; grid-template-columns: repeat(auto-fit, minmax(520px, 1fr)); gap: 24px 32px; padding: 4px 21px 18px; }
.roster-hours-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; font-size: .9375rem; }
.roster-hours-head span:last-child { color: var(--text-faint); font-size: .75rem; }
.roster-hours-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
/* The day name takes what it needs; the four time columns share the rest equally, so the
   inputs line up down the page across all three people. */
.roster-hours-table th:first-child { width: 90px; }
.roster-hours-table th { color: var(--text-faint); font-size: .6875rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; text-align: left; }
.roster-hours-table tbody th { padding: 6px 8px 6px 0; font-size: .8125rem; font-weight: 600; letter-spacing: 0; text-transform: none; white-space: nowrap; }
.roster-hours-table td { padding: 3px 2px; }
.roster-hours-table input { width: 100%; min-width: 0; height: 32px; padding: 0 4px; border: 1px solid var(--border-dark); border-radius: 7px; color: var(--grey); background: var(--surface); font-size: 11px; }
.roster-hours-table input:focus { border-color: var(--orange); outline: 0; box-shadow: 0 0 0 3px rgba(255,117,26,.1); }

.roster-member-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 12px; padding: 12px 21px; border-top: 1px solid var(--hairline); }
.roster-member-row:first-child { border-top: 0; }
/* Dimmed rather than hidden: somebody who has left the roster is still on last year's nights,
   and the way back on is this row. */
.roster-member-row.is-inactive { opacity: .6; }
.roster-member-who b { display: block; font-size: .9375rem; font-weight: 600; }
.roster-member-who span { color: var(--text-faint); font-size: .8125rem; }

/* The change log. Dense on purpose: it is read when somebody is looking for one row among a
   hundred, and a card per entry would mean scrolling past six to see the seventh. */
.roster-audit-row { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 12px; padding: 10px 21px; border-top: 1px solid var(--hairline); font-size: .875rem; }
.roster-audit-row:first-child { border-top: 0; }
.roster-audit-when { color: var(--text-faint); font-size: .8125rem; font-variant-numeric: tabular-nums; }
.roster-audit-row b { color: var(--grey); font-weight: 600; }
.roster-audit-by { margin-left: 8px; color: var(--text-faint); font-size: .8125rem; }
.roster-audit-detail { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 3px; }
.roster-audit-pair { color: var(--text-soft); font-size: .8125rem; }
.roster-audit-pair b { color: var(--text-faint); font-weight: 600; }

/* The three calendar feeds. A row says whether a feed is set up and when it last worked, and
   never anything about its URL, which is a credential. */
.roster-sync-row { display: grid; grid-template-columns: 140px minmax(0, 1fr) auto; align-items: baseline; gap: 12px; padding: 11px 21px; border-top: 1px solid var(--hairline); font-size: .875rem; }
.roster-sync-row:first-child { border-top: 0; }
.roster-sync-row b { color: var(--grey); font-weight: 600; }
.roster-sync-row span { color: var(--text-soft); }
.roster-sync-when { color: var(--text-faint); font-size: .8125rem; white-space: nowrap; }
.roster-sync-row.is-off b, .roster-sync-row.is-off span { color: var(--text-faint); }
.roster-sync-row.is-failing span:not(.roster-sync-when) { color: var(--coral-ink); }

.roster-holiday-table { width: 100%; border-collapse: collapse; font-size: .875rem; }
.roster-holiday-table th { padding: 8px 21px; color: var(--text-faint); font-size: .6875rem; font-weight: 600; letter-spacing: .04em; text-align: left; text-transform: uppercase; }
.roster-holiday-table td { padding: 9px 21px; border-top: 1px solid var(--hairline); }
.roster-holiday-table td:last-child { text-align: right; }

/* A label in a modal colours its span coral, which is the rule that draws the asterisk on a
   required field. A toggle row's span is its whole caption, so it has to opt out. */
.roster-member-modal .toggle-row > span, .roster-holiday-modal .toggle-row > span { color: var(--text-soft); }
.roster-member-modal .toggle-row b { color: var(--grey); }
/* A colour well, not a text field: full width it reads as a block of paint rather than a swatch. */
.roster-member-modal input[type="color"] { width: 64px; padding: 2px; cursor: pointer; }

/* The night editor, inside the day panel. Separated from the detail above it by a rule, because
   the lines above are what is true and the fields below are what somebody is about to change. */
.roster-night-edit { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--hairline); }
.roster-night-edit label { display: block; margin-bottom: 11px; color: var(--text-soft); font-size: 10px; font-weight: 700; }
.roster-night-edit input, .roster-night-edit select { width: 100%; height: 36px; margin-top: 6px; padding: 0 10px; border: 1px solid var(--border-dark); border-radius: 8px; color: var(--grey); background: var(--surface); font-size: 12px; }
.roster-night-edit input:focus, .roster-night-edit select:focus { border-color: var(--orange); outline: 0; box-shadow: 0 0 0 3px rgba(255,117,26,.1); }

@media (max-width: 1100px) {
  .roster-admin-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 760px) {
  /* The head's two halves stack, and the zone switch takes the width rather than keeping its
     three labels at full size: inside the panel's 21px inset there is no room for them beside
     Manage roster on a phone. */
  .roster-head-actions { flex-wrap: wrap; width: 100%; }
  .roster-shift-head .roster-zone-switch { flex: 1; min-width: 0; }
  .roster-shift-head .roster-zone-switch button { flex: 1; min-width: 0; padding-inline: 8px; }
  .roster-shift-head .secondary-button { flex: 1; min-width: 0; text-align: center; }
  /* One week per row, and the 520px track has to go with it: an auto-fit minimum wider than the
     screen cannot shrink, so the grid pushes the whole page sideways rather than its own table. */
  .roster-hours { grid-template-columns: minmax(0, 1fr); padding-inline: 14px; }
  /* Scroll each week rather than squash it, the way the escalation table already does: four
     time inputs compressed into a phone are four inputs nobody can read or hit. */
  .roster-hours-member { min-width: 0; overflow-x: auto; }
  .roster-hours-table { min-width: 460px; }
  .roster-member-row { grid-template-columns: auto minmax(0, 1fr); padding-inline: 14px; row-gap: 8px; }
  /* Narrow enough that the badge and the edit button each need their own line. Both start at the
     name's column, so the row still reads as one person rather than three stray controls. */
  .roster-member-link, .roster-member-row > :last-child { grid-column: 2 / -1; justify-self: start; }
  .roster-audit-row { grid-template-columns: minmax(0, 1fr); row-gap: 2px; padding-inline: 14px; }
  .roster-sync-row { grid-template-columns: minmax(0, 1fr) auto; padding-inline: 14px; row-gap: 2px; }
  .roster-sync-row span:not(.roster-sync-when) { grid-column: 1 / -1; }
  .roster-holidays { overflow-x: auto; }
  .roster-holiday-table { min-width: 430px; }
  .roster-holiday-table th, .roster-holiday-table td { padding-inline: 14px; }
  .roster-holiday-table td:first-child { white-space: nowrap; }
}

/* On a phone the cell is about forty pixels across, and at the size above the longest of the
   three first names still ends up as "Br...". Everything that is not the name gives up its
   space before the name does. */
@media (max-width: 520px) {
  .roster-cal-cell { padding: 3px 1px 3px 3px; }
  .roster-calendar { gap: 2px; }
  .roster-cal-date { font-size: .625rem; }
  .roster-cal-name { font-size: .625rem; letter-spacing: -.02em; }
}

/* ============================================================================
   Workspace navigation and page furniture, October 2026.

   Two changes live here. The first is the navigation: one 244px list of labels
   became a 72px icon rail plus a panel that only appears for the sections with
   sub-navigation of their own, which is Tickets. On every other page the
   workspace gets that width back. The second is the page furniture -- headings,
   cards, list rows, toolbars -- lifted to match the Style Guide: the coral-to-
   orange gradient on the few things that carry brand rather than state, heavier
   display type, and one card treatment everywhere.

   Everything is written in the tokens at the top of this file, so the dark theme
   needs no rules of its own. The literals that used to sit in the sidebar
   (#c3c8c6, #8f9693, #a7adaa) are now tokens, which is why the rail reads
   correctly in both themes rather than only against the fixed dark panel.
   ========================================================================== */

:root {
  --rail-width: 72px;
  --nav-panel-width: 214px;

  /* Ink on the dark navigation. Fixed values on purpose: the rail is dark in
     both themes, so these do not flip -- but they are named, so there is one
     place to change them. */
  --nav-ink: #c6cbd3;
  --nav-icon-rest: #969d9a;
  --nav-ink-strong: #fff;
  --nav-label: #8f9693;
  --nav-count: #a7adaa;
  --nav-hover: rgba(255,255,255,.07);
  --nav-divider: rgba(255,255,255,.1);
  --nav-panel-bg: #242424;
}
:root[data-theme="dark"] {
  --nav-panel-bg: #1d2026;
}

/* --- Shell ---------------------------------------------------------------- */

.app-shell .sidebar,
.sidebar {
  width: calc(var(--rail-width) + var(--nav-panel-width));
  padding: 0;
  flex-direction: row;
  background: var(--sidebar);
}
.app-shell:not(.nav-panel-open) .sidebar,
.sidebar:has(.nav-panel[hidden]) { width: var(--rail-width); }

.app-shell .main-content,
.main-content {
  width: calc(100% - var(--rail-width) - var(--nav-panel-width));
  margin-left: calc(var(--rail-width) + var(--nav-panel-width));
  transition: margin-left .18s ease, width .18s ease;
}
.app-shell:not(.nav-panel-open) .main-content {
  width: calc(100% - var(--rail-width));
  margin-left: var(--rail-width);
}

/* --- The rail ------------------------------------------------------------- */

.nav-rail {
  width: var(--rail-width);
  flex: 0 0 var(--rail-width);
  padding: 16px 0 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  background: var(--sidebar);
}
.rail-brand { display: block; width: 36px; height: 36px; border-radius: 11px; flex: none; }
.rail-brand img { width: 100%; height: 100%; display: block; }
.rail-brand:focus-visible { outline: 2px solid var(--orange); outline-offset: 3px; }

.rail-nav {
  flex: 1;
  min-height: 0;
  width: 100%;
  padding: 2px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  overflow-y: auto;
  scrollbar-width: none;
}
.rail-nav::-webkit-scrollbar { width: 0; }
.rail-divider { width: 28px; height: 1px; margin: 5px 0; background: var(--nav-divider); flex: none; }

/* The rail button. Same .nav-link the router drives, drawn as a tile: the label
   is kept in the DOM for screen readers and shown as a tooltip on hover, so
   nothing is lost by dropping it from the page. */
.app-shell .nav-link.rail-link,
.nav-link.rail-link {
  position: relative;
  width: 46px;
  height: 46px;
  min-height: 46px;
  padding: 0;
  border-radius: 14px;
  display: grid;
  place-items: center;
  color: var(--nav-ink);
  flex: none;
}
.nav-link.rail-link:hover { background: var(--nav-hover); color: var(--nav-ink-strong); }
.nav-link.rail-link.active {
  color: var(--on-brand);
  background: var(--brand-gradient);
  box-shadow: 0 6px 18px rgba(var(--coral-rgb), .3);
}
.nav-link.rail-link.active .nav-icon { color: var(--on-brand); }
/* .app-shell .nav-link is a three-column grid -- icon, label, count -- so a
   rail button that only draws the icon inherits a 22px first column and the
   icon lands against the left edge of the tile rather than in the middle of
   it. One column, no gap. */
.app-shell .nav-link.rail-link,
.nav-link.rail-link { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
.nav-link.rail-link .nav-icon { width: 21px; height: 21px; justify-self: center; }
.nav-link.rail-link .nav-icon svg { width: 21px; height: 21px; }
/* The icon takes the button's colour, so hover and the active tile move it. */
.nav-link.rail-link .nav-icon { color: inherit; }

/* The label, kept for assistive technology and shown as the hover tooltip. */
.rail-link .rail-text {
  position: absolute;
  left: calc(100% + 10px);
  top: 50%;
  z-index: 60;
  padding: 7px 11px;
  border-radius: 9px;
  color: var(--toast-ink);
  background: var(--toast-bg);
  box-shadow: 0 10px 26px rgba(0,0,0,.3);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-50%) translateX(-4px);
  transition: opacity .13s ease, transform .13s ease;
}
.rail-link:hover .rail-text,
.rail-link:focus-visible .rail-text { opacity: 1; transform: translateY(-50%) translateX(0); }
/* While the panel is open the tooltip would land on top of it. */
.app-shell.nav-panel-open .rail-link:hover .rail-text { z-index: 60; }

/* The count rides the corner of the tile rather than sitting after a label. */
.app-shell .nav-link.rail-link b,
.nav-link.rail-link b {
  position: absolute;
  /* Inside the tile, not hanging off it: at a negative offset the badge sat in
     the 4px gap above and read as belonging to the tile overhead -- against the
     active tile it looked clipped by it. */
  top: 2px;
  right: 2px;
  min-width: 14px;
  margin: 0;
  padding: 0 4px;
  border: 2px solid var(--sidebar);
  border-radius: 999px;
  color: var(--nav-ink-strong);
  background: rgba(255,255,255,.18);
  font-size: 8.5px;
  font-weight: 800;
  line-height: 15px;
}
/* Neutral on purpose: an open queue is the job, not an alarm. The states that
   do warrant one -- SLA at risk, spam -- carry their colour in the panel. */
.nav-link.rail-link b:empty,
.nav-link.rail-link b[hidden] { display: none; }

/* Zero is not news: the badge only appears once there is something in it. */
.nav-link.rail-link b[data-count="0"] { display: none; }

.nav-rail .sidebar-integration-button { width: 46px; padding: 0; justify-content: center; }
.nav-rail .sidebar-integration-button > div:last-child { display: none; }

.nav-rail .user-menu { width: 46px; flex: none; }
.nav-rail .user-card {
  width: 46px;
  min-height: 46px;
  padding: 0;
  border-top: 0;
  justify-content: center;
}
.nav-rail .user-card > div:nth-child(2),
.nav-rail .user-caret { display: none; }
.nav-rail .user-menu-panel { left: calc(100% + 10px); right: auto; bottom: 0; width: 230px; }

/* --- The contextual panel -------------------------------------------------- */

.nav-panel {
  width: var(--nav-panel-width);
  flex: 0 0 var(--nav-panel-width);
  min-width: 0;
  padding: 18px 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  border-left: 1px solid var(--nav-divider);
  background: var(--nav-panel-bg);
}
.nav-panel[hidden] { display: none; }
.nav-panel-head { padding: 0 10px; display: flex; flex-direction: column; gap: 3px; }
.nav-panel-title { margin: 0; color: var(--nav-ink-strong); font-size: 17px; font-weight: 800; letter-spacing: -.02em; }
.nav-panel .product-name { color: var(--nav-label); font-size: 9.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.nav-panel .main-nav { flex: 1; min-height: 0; overflow-y: auto; padding: 0; margin: 0; }
.nav-panel .nav-label { margin: 0 10px 8px; color: var(--nav-label); }
.nav-panel .nav-link { border-radius: 999px; padding: 0 13px; color: var(--nav-ink); }
.nav-panel .nav-link:hover { color: var(--nav-ink-strong); background: var(--nav-hover); }
.nav-panel .nav-link.active { color: var(--nav-ink-strong); background: rgba(var(--orange-rgb), .18); box-shadow: inset 0 0 0 1px rgba(var(--orange-rgb), .3); }
.nav-panel .nav-link b { color: var(--nav-count); background: rgba(255,255,255,.07); }

/* My to-dos: pinned under the views, taking the space it needs up to about half the panel and
   scrolling after that. */
.todo-panel { flex: 0 1 auto; min-height: 0; max-height: 48%; display: flex; flex-direction: column; gap: 8px; padding-top: 12px; border-top: 1px solid var(--nav-divider); }
.todo-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.todo-panel .nav-label { margin: 0 10px; }
.todo-new-badge { margin-right: 8px; padding: 2px 8px; border-radius: 999px; color: var(--on-orange, #fff); background: var(--orange); font-size: 10px; font-weight: 700; animation: todo-pulse 1.6s ease-in-out 3; }
@keyframes todo-pulse { 50% { box-shadow: 0 0 0 5px rgba(var(--orange-rgb), .25); } }
.todo-form { display: flex; gap: 6px; padding: 0 4px; }
.todo-form input { flex: 1; min-width: 0; height: 34px; padding: 0 11px; border: 1px solid rgba(255,255,255,.1); border-radius: 9px; color: var(--nav-ink-strong); background: rgba(255,255,255,.05); font: inherit; font-size: 12.5px; }
.todo-form input::placeholder { color: var(--nav-label); }
.todo-form input:focus { outline: none; border-color: rgba(var(--orange-rgb), .6); background: rgba(255,255,255,.08); }
.todo-assign-button { flex: none; width: 34px; height: 34px; display: grid; place-items: center; border: 1px solid rgba(255,255,255,.1); border-radius: 9px; color: var(--nav-ink); background: transparent; cursor: pointer; }
.todo-assign-button svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.todo-assign-button:hover { color: var(--nav-ink-strong); background: var(--nav-hover); }
.todo-assign-button.active { color: var(--orange); border-color: rgba(var(--orange-rgb), .5); background: rgba(var(--orange-rgb), .12); }
.todo-for { display: flex; align-items: center; gap: 8px; padding: 0 4px 0 10px; color: var(--nav-label); font-size: 11.5px; }
.todo-for[hidden] { display: none; }
.todo-for select { flex: 1; min-width: 0; height: 30px; padding: 0 8px; border: 1px solid rgba(255,255,255,.1); border-radius: 8px; color: var(--nav-ink-strong); background: var(--nav-panel-bg); font: inherit; font-size: 12px; }
.todo-list { min-height: 0; overflow-y: auto; margin: 0; padding: 0 2px; list-style: none; display: flex; flex-direction: column; gap: 2px; }
.todo-row { display: flex; align-items: flex-start; gap: 9px; padding: 6px 8px; border-radius: 8px; transition: opacity .3s ease, background .15s ease; }
.todo-row:hover { background: var(--nav-hover); }
/* The same box as the ticket queue's row checkboxes. */
.app-shell .todo-item .todo-check {
  appearance: none;
  flex: none;
  width: 17px;
  height: 17px;
  margin: 1px 0 0;
  border: 1px solid var(--border-dark);
  border-radius: 4px;
  display: grid;
  place-items: center;
  background: var(--surface);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .08);
  cursor: pointer;
  transition: border-color .12s ease, background-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.app-shell .todo-item .todo-check::after {
  content: "";
  width: 8px;
  height: 4px;
  border: solid #fff;
  border-width: 0 0 2px 2px;
  opacity: 0;
  transform: translateY(-1px) rotate(-45deg);
}
.app-shell .todo-item .todo-check:hover { border-color: var(--orange); transform: scale(1.06); }
.app-shell .todo-item .todo-check:checked {
  border-color: var(--orange);
  background: linear-gradient(145deg, var(--orange), var(--orange-hover));
  box-shadow: 0 2px 6px var(--orange-wash-border);
}
.app-shell .todo-item .todo-check:checked::after { opacity: 1; }
.todo-copy { flex: 1; min-width: 0; padding: 0; border: 0; display: flex; flex-direction: column; gap: 1px; color: var(--nav-ink); background: none; font: inherit; font-size: 12.5px; line-height: 1.4; text-align: left; overflow-wrap: anywhere; cursor: pointer; }
.todo-copy:hover, .todo-copy[aria-expanded="true"] { color: var(--nav-ink-strong); }
.todo-copy:focus-visible { outline: 2px solid rgba(var(--orange-rgb), .6); outline-offset: 2px; border-radius: 4px; }
.todo-from, .todo-when { color: var(--nav-label); font-size: 10.5px; }
.todo-item.has-reminder .todo-when::before, .todo-item.is-due .todo-when::before { content: "⏰ "; }
.todo-item.is-new .todo-row { background: rgba(var(--orange-rgb), .12); box-shadow: inset 2px 0 0 var(--orange); }
.todo-item.is-new .todo-copy { color: var(--nav-ink-strong); }
.todo-item.is-new .todo-from { color: var(--orange); }
.todo-item.has-reminder .todo-when { color: #8fb8ff; }
/* Due: the follow-up turns red until it is ticked off or the reminder is moved. */
.todo-item.is-due .todo-row { background: rgba(239, 83, 80, .14); box-shadow: inset 2px 0 0 #ef5350; }
.todo-item.is-due .todo-copy { color: #ffb4b0; }
.todo-item.is-due .todo-when { color: #ff8a85; font-weight: 700; }
.todo-item.is-done .todo-row { opacity: .4; }
.todo-item.is-done .todo-text { text-decoration: line-through; }
.todo-reminder-editor { margin: 2px 2px 8px; padding: 9px; display: flex; flex-direction: column; gap: 8px; border: 1px solid rgba(255,255,255,.1); border-radius: 10px; background: rgba(255,255,255,.04); }
.todo-reminder-title { margin: 0; color: var(--nav-label); font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.todo-reminder-presets { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 5px; }
.todo-reminder-editor button { height: 28px; padding: 0 6px; white-space: nowrap; border: 1px solid rgba(255,255,255,.12); border-radius: 7px; color: var(--nav-ink-strong); background: rgba(255,255,255,.05); font: inherit; font-size: 11.5px; cursor: pointer; }
.todo-reminder-editor button:hover { border-color: rgba(var(--orange-rgb), .55); background: rgba(var(--orange-rgb), .14); }
.todo-reminder-custom { display: flex; flex-wrap: wrap; gap: 5px; }
.todo-reminder-custom input { flex: 1 1 100%; min-width: 0; height: 28px; padding: 0 6px; border: 1px solid rgba(255,255,255,.12); border-radius: 7px; color: var(--nav-ink-strong); background: rgba(255,255,255,.05); font: inherit; font-size: 11.5px; color-scheme: dark; }
.todo-reminder-custom button[type="submit"] { flex: 1; color: var(--on-orange, #fff); border-color: var(--orange); background: var(--orange); }
.todo-reminder-editor .todo-reminder-clear { align-self: flex-start; border-color: transparent; background: none; color: #ff8a85; padding: 0 2px; }
.todo-reminder-avatar { display: grid; place-items: center; font-size: 15px; }
.todo-empty { margin: 0 10px; color: var(--nav-label); font-size: 11.5px; }
.todo-empty[hidden] { display: none; }
.nav-panel .nav-link.active b { color: #ffe6d5; background: rgba(var(--orange-rgb), .22); }

/* --- Page furniture -------------------------------------------------------- */

.app-shell .page-head h1 { font-size: clamp(30px, 2.1vw, 38px); font-weight: 800; letter-spacing: -.04em; line-height: 1.05; }
.app-shell .page-head > div > p:last-child { font-size: 14px; }
.app-shell .eyebrow { color: var(--link) !important; letter-spacing: .16em !important; }

/* One card treatment. The ticket view got this in the last change; this is the
   same set of values applied to every other panel on every other page. */
.app-shell .panel { border-radius: 18px; }

/* The brand gradient, on the one control per page that carries brand rather
   than state. Hover and active keep the flat orange so the press still reads. */
.app-shell .primary-button {
  border-color: transparent;
  background: var(--brand-gradient);
  box-shadow: 0 8px 22px rgba(var(--coral-rgb), .24);
}
.app-shell .primary-button:hover { border-color: transparent; background: var(--orange-hover); }
.app-shell .primary-button:active { border-color: transparent; background: var(--orange-active); }
.app-shell .primary-button.is-saved { background: var(--green); }
.app-shell .primary-button.is-saved:hover { background: var(--green-hover); }

/* The summary cards on Overview, and the smaller stat cards elsewhere: a full
   top edge in the accent colour instead of the clipped corner tab, and a
   numeral with enough weight to be the thing you see first. */
.app-shell .summary-card { border-radius: 18px; }
.app-shell .summary-card::after { top: 0; right: auto; left: 0; width: 100%; height: 4px; border-radius: 0; }
.app-shell .summary-card.accent-blue::after { background: var(--blue-ink); }
.app-shell .summary-card h2 { font-size: 40px; font-weight: 800; letter-spacing: -.055em; line-height: 1; }
.app-shell .summary-card p { font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }

/* Table headings read as headings rather than as faint noise. */
.app-shell :is(.ticket-table-head, .contact-table-head, .venue-table-head, .call-table-head, .kb-article-table-head) {
  color: var(--text-faint);
  background: var(--surface-head);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .1em;
}

.app-shell .table-footer { font-size: 11.5px; font-weight: 600; }
.app-shell .table-footer button { border-radius: 999px; }

.app-shell :is(.status-pill, .sla-pill, .priority-chip) { padding: 5px 11px; font-size: 10px; font-weight: 700; }

.app-shell .empty-state h3 { font-size: 17px; font-weight: 700; letter-spacing: -.02em; }
.app-shell .empty-state p { font-size: 12.5px; }

/* --- Narrow screens -------------------------------------------------------- */

@media (max-width: 1100px) {
  /* The panel's content folds into the drawer rather than sitting beside a rail
     that is itself off screen. */
  .app-shell .sidebar,
  .sidebar { width: 268px; }
  .app-shell .main-content,
  .app-shell:not(.nav-panel-open) .main-content,
  .main-content { width: 100%; margin-left: 0; }
  .nav-panel { border-left: 0; background: transparent; }
  .nav-panel[hidden] { display: flex; }
  .nav-rail { width: 62px; flex: 0 0 62px; }
}

/* --- The top bar's search ---------------------------------------------------

   The box used to run across the bar on every page, open whether it was wanted
   or not. It is a button now, and the box opens over the page where Ctrl K has
   always put the cursor. The bar gets about 460px back, which is where the open
   ticket pills now sit.                                                      */

.topbar-search-button {
  height: 40px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--text-faint);
  background: var(--surface-sunken);
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  transition: border-color .16s ease, background .16s ease, color .16s ease;
}
.topbar-search-button:hover { border-color: var(--border-hover); color: var(--text); background: var(--surface); }
.topbar-search-button .topbar-search-icon { font-size: 16px; line-height: 1; }
.topbar-search-button kbd {
  padding: 3px 7px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  font: inherit;
  font-size: 10px;
  font-weight: 700;
  color: var(--text-faint);
}

.search-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  justify-items: center;
  align-content: start;
  padding: clamp(60px, 12vh, 140px) 16px 24px;
}
.search-overlay[hidden] { display: none; }
.search-overlay-backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  padding: 0;
  /* Blurred as well as dimmed: the workspace behind this is dense, and a flat
     scrim alone left the rows legible enough to compete with the results. */
  background: var(--backdrop);
  backdrop-filter: blur(3px) saturate(.9);
  cursor: default;
  animation: search-overlay-fade .16s ease-out;
}

/* The box and its results are one panel, not two rectangles with a gap between
   them: the wrap carries the border, the radius and the single shadow, and the
   parts inside it give theirs up. */
.search-overlay .global-search-wrap {
  position: relative;
  width: min(640px, 100%);
  max-width: none;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 18px;
  background: var(--surface);
  box-shadow: 0 28px 70px rgba(16, 20, 28, .30), 0 2px 6px rgba(16, 20, 28, .10);
  animation: search-overlay-rise .18s cubic-bezier(.2, .9, .3, 1);
}
.search-overlay .global-search {
  height: 60px;
  padding: 0 18px;
  gap: 13px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.search-overlay .global-search input { font-size: 16px; }
.search-overlay .global-search input::placeholder { color: var(--text-faint); }
.search-overlay .global-search kbd { font-size: 9px; }
.search-overlay .global-search-icon { color: var(--orange); }
.search-overlay .global-search-icon svg { width: 21px; height: 21px; }
.search-overlay .global-search-results {
  /* In the bar this hung off the box as a dropdown. Inside the panel it is the
     lower half of the same card, so everything that made it float comes off. */
  position: static;
  width: 100%;
  margin: 0;
  max-height: min(56vh, 520px);
  border: 0;
  border-top: 1px solid var(--hairline);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.search-overlay .global-search-group:first-child > h3 { padding-top: 12px; }

/* Both of those carry a surface and a shadow of their own from the popover
   rules, which here would paint a panel inside a panel. */
:root[data-theme="dark"] .search-overlay .global-search-results,
.search-overlay .global-search-results { background: transparent; box-shadow: none; }
:root[data-theme="dark"] .search-overlay .global-search-wrap { background: var(--surface-overlay); box-shadow: 0 0 0 1px rgba(0, 0, 0, .3), 0 30px 70px rgba(0, 0, 0, .6); }

.topbar-search-icon svg,
.global-search-icon svg { width: 17px; height: 17px; display: block; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

@keyframes search-overlay-fade { from { opacity: 0; } }
@keyframes search-overlay-rise { from { opacity: 0; transform: translateY(-10px) scale(.985); } }
@media (prefers-reduced-motion: reduce) {
  .search-overlay-backdrop,
  .search-overlay .global-search-wrap { animation: none; }
}
/* The pills take the width the box gave up, so they get room to breathe before
   they start eliding. */
.app-shell .ticket-tab-strip { margin-left: 6px; }

@media (max-width: 760px) {
  /* Just the icon: the word and the shortcut are the first things to go. */
  .topbar-search-button { width: 40px; padding: 0; justify-content: center; }
  .topbar-search-button .topbar-search-label,
  .topbar-search-button kbd { display: none; }
  .search-overlay { padding-top: 56px; }
}

/* --- The rest of the screens -------------------------------------------------

   Overview, the queue, the ticket and the directory came first because they are
   built from the shared classes. These are the pages with furniture of their
   own -- Calls, Reports, the knowledge base, Settings and the sign-in page --
   brought onto the same card, numeral and radius as the rest.                 */

/* Calls. The clipped corner tab becomes a full edge, like every other stat card
   on the workspace, and the number is the thing you see first. */
.app-shell .call-summary-card { border-radius: 18px; }
.app-shell .call-summary-card::after { inset: 0 0 auto 0; width: 100%; height: 4px; border-radius: 0; }
.app-shell .call-summary-card strong { font-size: 34px; font-weight: 800; letter-spacing: -.05em; line-height: 1; }
.app-shell .call-summary-card p { font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.app-shell .call-summary-card small { font-size: 11.5px; font-weight: 600; }

/* Reports. The KPI cards are built by kpi.js against these classes. */
.app-shell .kpi-metric-card { border-radius: 18px; }
.app-shell .kpi-trend-panel,
.app-shell .kpi-team-dashboard,
.app-shell .kpi-agent-section { border-radius: 18px; }
.app-shell .kpi-dashboard-heading { font-size: 11px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--text-faint); }

/* Settings. The rail reads as navigation rather than a list of links, matching
   the pills in the workspace panel. */
.app-shell .settings-rail button { border-radius: 999px; padding-inline: 14px; font-weight: 600; }
.app-shell .settings-rail button.active { font-weight: 700; box-shadow: inset 0 0 0 1px var(--orange-tint); }
.app-shell .settings-rail-group { letter-spacing: .12em; }
.app-shell .settings-card { border-radius: 16px; }
.app-shell .settings-card > h3 { letter-spacing: -.01em; }

/* Knowledge base. */
.app-shell :is(.kb-admin-categories, .kb-manage) > * { border-radius: 16px; }
.app-shell .kb-admin-search { border-radius: 999px; }

/* Sign-in. The panel's warm corner was three literals mixed by hand; it is the
   ink token and the brand gradient now, so it follows the palette, and its copy
   uses the same named inks as the navigation. */
.login-brand-panel {
  border-radius: 0;
  background:
    radial-gradient(120% 90% at 115% 115%, rgba(var(--coral-rgb), .38) 0%, transparent 60%),
    linear-gradient(150deg, #282828 0%, var(--ink) 72%);
}
.login-brand-panel p:not(.eyebrow) { color: var(--nav-ink); }
.login-brand-panel > small { color: var(--nav-label); }
.login-shell { border-radius: 24px; }
.login-card > label input { border-radius: 12px; }
.login-submit { border-radius: 999px; }

/* ---- The ticket page, as the mockup draws it -------------------------------

   Three things were wrong against the approved design. The card began flush
   under the top bar, so the page opened with no breathing room at all. On a
   wide screen the card stopped at its natural height and left a band of empty
   page below it -- several hundred pixels of nothing on a tall monitor. And the
   header spent four stacked rows (breadcrumb, title, byline, chips) saying what
   the mockup says in three, which pushed the first message down the page.     */

.app-shell #ticketView .ticket-detail-grid { padding-top: clamp(12px, 1.1vw, 18px); }

@media (min-width: 1101px) {
  /* Both columns run to the foot of the window instead of ending where their
     content happens to stop. */
  .app-shell #ticketView .ticket-detail-grid { align-items: stretch; }
  .app-shell #ticketView .ticket-thread {
    height: 100%;
    max-height: 100%;
    /* A column, so the conversation takes whatever height is left over and the
       cards above it keep the height they need. */
    display: flex;
    flex-direction: column;
  }
  .app-shell #ticketView .ticket-thread > .conversation { flex: 1 0 auto; }
  .app-shell #ticketView .ticket-thread > .ticket-detail-bar,
  .app-shell #ticketView .ticket-thread > .request-header,
  .app-shell #ticketView .ticket-thread > .ticket-summary,
  .app-shell #ticketView .ticket-thread > .reply-box,
  .app-shell #ticketView .ticket-thread > .conversation-head { flex: none; }
}

/* The byline rides up beside the breadcrumb, which is one row back and puts the
   subject and the chips where the mockup has them. */
.app-shell #ticketView .request-header { padding: 16px 26px 14px; }
.app-shell #ticketView .request-header > p { margin-top: 5px; }
.app-shell #ticketView .ticket-chip-row { margin-top: 12px; }
.app-shell #ticketView .ticket-detail-bar { padding: 11px 26px; }

/* On a wide monitor the extra width went to the conversation, which already had
   more than it needed -- a one line message in a card 1500px across. The reading
   column keeps the width it has and the properties column takes the surplus, so
   the status, the contact and the service target are easier to work with rather
   than the message text stretching further. */
@media (min-width: 1500px) {
  .app-shell #ticketView .ticket-detail-grid { grid-template-columns: minmax(0, 1fr) minmax(360px, 460px); }
}

/* The ticket header, as the mockup draws it. The actions sat immediately after
   the breadcrumb, so on a wide card they floated in the middle of an otherwise
   empty row; they belong at the right edge. And the subject was set barely
   larger than a message's sender name, so the top of the card did not read as a
   header at all -- the mockup leans on that size difference to do it. */
.app-shell #ticketView .ticket-breadcrumb { flex: 1 1 auto; width: 100%; }
.app-shell #ticketView .ticket-title-copy { max-width: none; }
.app-shell #ticketView .ticket-detail-actions { margin-left: auto; flex: none; }

.app-shell #ticketView .request-title-line h2,
.app-shell #ticketView .subject-edit-input {
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -.025em;
  line-height: 1.15;
}

/* Renaming the ticket where its name is read. The pencil sits on the heading's
   line and the input takes the heading's place, with the same type at every
   size, so swapping the two moves nothing on the page. */
.app-shell #ticketView .request-title-line {
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  gap: 9px;
}
.app-shell #ticketView .request-title-line h2 { flex: 0 1 auto; }
.subject-edit-button {
  width: 30px;
  height: 30px;
  padding: 0;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: 9px;
  color: var(--muted);
  background: transparent;
  cursor: pointer;
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}
.subject-edit-button svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.subject-edit-button:hover {
  border-color: var(--orange-wash-border);
  color: var(--orange-ink);
  background: var(--orange-wash);
}
.subject-edit-button:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
}
.subject-edit-input {
  min-width: 0;
  flex: 1 1 100%;
  margin: -5px -10px;
  padding: 4px 9px;
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  background: var(--surface-sunken);
  font-family: inherit;
}
.subject-edit-input:focus {
  border-color: var(--orange);
  background: var(--surface);
  outline: none;
  box-shadow: 0 0 0 3px var(--orange-wash);
}
.app-shell #ticketView .request-header > p { font-size: 12.5px; }
.app-shell #ticketView .request-header > p b { font-weight: 700; }

@media (max-width: 1100px) {
  .app-shell #ticketView .request-title-line h2,
  .app-shell #ticketView .subject-edit-input { font-size: 22px; }
}
@media (max-width: 760px) {
  /* Back to a stacked bar on a phone: the actions get the row under the
     breadcrumb there, so margin-left has nothing to push against. */
  .app-shell #ticketView .ticket-detail-actions { margin-left: 0; }
  .app-shell #ticketView .request-title-line h2,
  .app-shell #ticketView .subject-edit-input { font-size: 20px; }
}

/* ---- Three cards, as the mockup has them -----------------------------------

   The thread was one tall card holding the header, the summary and the
   conversation, with hairlines standing in for the edges between them. The
   mockup makes each of the three a card of its own with the page showing
   through between them, which is what tells you the header is a header and the
   summary is an aside rather than the first thing in the thread.

   The parts are siblings, so the grouping is drawn rather than wrapped: each
   card's first child takes the top edge and radius, its last child the bottom,
   and everything in between keeps the side borders only. No markup moves, so
   every id and handler is where it was.                                      */

@media (min-width: 761px) {
  .app-shell #ticketView .ticket-thread {
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    /* No gap on the flow: the parts of one card have to touch, so the space
       between cards is a margin on the element that starts each one. */
    gap: 0;
    padding: 0;
  }

  /* Card one: the header. */
  .app-shell #ticketView .ticket-detail-bar {
    border: 1px solid var(--border);
    border-bottom: 0;
    border-radius: 16px 16px 0 0;
    position: static;
  }
  .app-shell #ticketView .request-header {
    border: 1px solid var(--border);
    border-top: 0;
    border-radius: 0 0 16px 16px;
    background: var(--surface);
    box-shadow: var(--shadow);
  }

  /* Card two: the summary, which already draws its own edge. */
  .app-shell #ticketView .ticket-summary {
    margin: 0;
    padding: 17px 20px;
    border-radius: 16px;
    box-shadow: var(--shadow);
  }

  /* Card three: the composer, which sits between the summary and the feed. */
  .app-shell #ticketView .reply-box {
    border: 1px solid var(--border);
    border-radius: 16px;
    box-shadow: var(--shadow);
  }

  /* Card four: the conversation, which now ends the thread. */
  .app-shell #ticketView .conversation-head {
    border: 1px solid var(--border);
    border-bottom: 0;
    border-radius: 16px 16px 0 0;
    background: var(--surface);
    padding-top: 18px;
  }

  .app-shell #ticketView .ticket-summary,
  .app-shell #ticketView .reply-box,
  .app-shell #ticketView .conversation-head { margin-top: clamp(12px, 1.1vw, 16px); }
  .app-shell #ticketView .ticket-thread > .conversation {
    border: 1px solid var(--border);
    border-top: 0;
    border-radius: 0 0 16px 16px;
    background: var(--surface);
    box-shadow: var(--shadow);
  }
}

/* The ticket actions, drawn as the mockup draws them: fully rounded, a size
   down from a page action, and Resolve carrying the green it sets the ticket
   to rather than looking like one more neutral button. */
.app-shell #ticketView .ticket-detail-actions .secondary-button {
  min-height: 36px;
  height: 36px;
  padding-inline: 15px;
  border-radius: 999px;
  font-size: 12px;
}
.app-shell #ticketView .ticket-detail-actions .more-button {
  width: 36px;
  height: 36px;
  border-radius: 999px;
}
.app-shell #ticketView #ticketResolveButton {
  border-color: var(--green-pale);
  color: var(--green-ink);
  background: var(--green-pale);
}
.app-shell #ticketView #ticketResolveButton:hover {
  border-color: var(--green);
  color: var(--green-ink);
  background: var(--green-pale);
}

/* ---- Contacts and Venues: one list pattern ---------------------------------------------------
   The two customer lists had grown apart. Venues sat in a panel card with its own heading,
   toolbar and internal scroller; Contacts had been pulled out of that card to sit flush on the
   page, scrolling with it. Same kind of page, two frames, and moving between them in the rail
   meant the whole page re-flowing around you.

   Venues is the one that matches Tickets and Calls, so Contacts comes back into the card (its
   full-bleed overrides are gone from the Contacts section above) and everything below is written
   against both views at once: the heading, the column heads, the row, the leading identity cell
   and the count. Anything genuinely particular to one list -- the Contacts checkbox column and
   its row actions, the Venues source badge -- keeps its own rules.

   Rows are a little shorter than the 84px the two lists used. 221 venues and 271 contacts are
   read by scanning, and the extra 20px bought nothing but four fewer rows per screen. */

.app-shell :is(#contactsView, #venuesView) .contacts-toolbar h2 {
  font-size: 19px;
  letter-spacing: -.015em;
}
.app-shell :is(#contactsView, #venuesView) .contacts-toolbar > div > span { font-size: 12px; }
.app-shell :is(#contactsView, #venuesView) .contact-search input { font-size: 12.5px; }

.app-shell :is(#contactsView .contact-table-head, #venuesView .venue-table-head) {
  min-height: 40px;
  font-size: 11.5px;
  letter-spacing: .065em;
}

.app-shell :is(#contactsView .contact-row, #venuesView .venue-row) {
  min-height: 64px;
  padding-block: 9px;
  transition: background .14s ease, box-shadow .14s ease;
}

/* One hover affordance across both lists: the row tints and takes the accent edge that says
   "this is the row you are about to open". */
.app-shell :is(#contactsView .contact-row, #venuesView .venue-row):hover {
  background: var(--surface-sunken);
  box-shadow: inset 3px 0 0 var(--orange);
}

/* The leading cell is the same shape in both: a monogram, then the name as the primary line.
   The venue monogram is toned from the same palette the contact avatars use. */
.app-shell :is(#contactsView, #venuesView) :is(.contact-person, .venue-name) .avatar {
  width: 32px;
  height: 32px;
  flex: none;
  font-size: 11px;
}
.app-shell #venuesView .venue-name b {
  color: var(--grey);
  font-size: 14px;
  line-height: 1.25;
  letter-spacing: -.01em;
}

/* The contact count on a venue and the ticket count on a contact are the same measure in the
   same position, so they read as the same pill rather than as a pill and a bare numeral. */
.app-shell :is(#contactsView, #venuesView) .contact-ticket-count {
  width: max-content;
  min-width: 28px;
  min-height: 28px;
  padding: 0 8px;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--text-soft);
  background: var(--surface-muted);
  font-size: 12px;
  font-weight: 750;
}

/* ---- The ticket's Update button --------------------------------------------
   Status, agent, priority and type are committed rather than saved as they are
   touched, so the panel ends in a button again. It is only in the panel while
   there is something to commit, and the line beside the heading turns from a
   quiet "Up to date" to "Unsaved changes" in the same moment, so a pending edit
   is said twice rather than once. */
.app-shell #ticketView .property-actions { padding: 0 17px 16px; }
.app-shell #ticketView .property-actions .primary-button {
  width: 100%;
  min-height: 38px;
  border-radius: 999px;
  font-size: 12.5px;
}
.app-shell .property-save-state.is-unsaved { color: var(--orange-ink); }


/* Below 650px the thread drops to a 16px inset, and the composer goes with it: its
   edges are the message cards' edges at every width. */
@media (max-width: 650px) {
  .app-shell .reply-box { padding-inline: 16px; }
}

/* The way out of the composer. It opens from one line and used to have no
   closing move at all: Send, or leave the ticket. The × puts the thread back
   the way it was -- the summary included -- and keeps whatever has been typed
   for when the line is clicked again. Escape does the same thing. */
.app-shell .reply-tabs { align-items: center; }
.app-shell .reply-close-button {
  width: 28px;
  height: 28px;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: 999px;
  display: grid;
  place-items: center;
  color: var(--text-faint);
  background: transparent;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
}
.app-shell .reply-close-button:hover { color: var(--text); background: var(--surface-muted); }
.app-shell .reply-close-button:focus-visible { outline: 2px solid var(--orange); outline-offset: 1px; }

/* Closed, the composer is the one-line invitation and nothing else: a card
   border around a pill drew the same edge twice. The pill carries the card. */
@media (min-width: 761px) {
  .app-shell #ticketView .reply-box.reply-collapsed {
    padding: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
  }
  .app-shell #ticketView .reply-box.reply-collapsed .reply-open-button {
    padding: 11px 11px 11px 16px;
    border-color: var(--border);
    border-radius: 999px;
    background: var(--surface);
    box-shadow: var(--shadow);
  }
  .app-shell #ticketView .reply-box.reply-collapsed .reply-open-button:hover {
    border-color: var(--border-dark);
  }
}

/* Send, and the status menu beside it, within reach of whatever is being
   written. A long reply against a long chain pushed the composer's last row
   past the foot of the window, so sending -- or setting the status on the way
   out -- meant scrolling the thread down to find the button. The row sticks to
   the bottom of whatever is on screen for as long as the composer is, and the
   editor scrolls underneath it. */
.app-shell #ticketView .reply-box > div:last-child {
  position: sticky;
  bottom: 0;
  z-index: 4;
  margin-top: 0;
  padding-top: 8px;
  background: var(--surface);
}
/* The menu drops from a button that is now usually near the foot of the
   window, where there is nothing below it to drop into: it opens upwards,
   over the editor, which is the one thing here that always has room. */
.app-shell #ticketView .reply-status-menu {
  top: auto;
  bottom: calc(100% + 6px);
}

/* Below 1100px the columns stack and the document is what scrolls, but the
   thread kept the hidden overflow it needed when it was one tall pane: that
   makes it the scrollport the composer's last row sticks to, which is a box
   that never scrolls, so the row never sticks. Each part of the thread draws
   its own edges now, so there is nothing left for the thread to clip. */
@media (max-width: 1100px) {
  .app-shell #ticketView .ticket-thread { overflow: visible; }
}

/* ==== Knowledge base guide wizard ============================================================
   Full-screen, three columns: the stages, the form for the current stage, and a live preview.
   The form follows the workspace theme; the preview is always the white page customers read. */
.kbw { position: fixed; inset: 0; z-index: 140; display: flex; flex-direction: column; color: var(--grey); background: var(--zircon); }
.kbw-header { min-height: 64px; padding: 10px 20px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 16px; background: var(--surface); }
.kbw-header-title { display: flex; align-items: center; gap: 12px; min-width: 0; }
.kbw-header-title b { display: block; font-size: 15px; }
.kbw-header-title small { display: block; margin-top: 2px; color: var(--muted); font-size: 11.5px; }
.kbw-mark { width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center; flex: none; color: #fff; background: linear-gradient(120deg, #ff8a1c, #f9483a); font-size: 16px; }
.kbw-header-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.kbw-header-actions .primary-button, .kbw-header-actions .secondary-button { min-height: 38px; padding: 0 15px; font-size: 12px; }
.kbw-more { position: relative; }
.kbw-more-menu { position: absolute; z-index: 5; top: calc(100% + 6px); right: 0; width: 220px; padding: 6px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-overlay); box-shadow: var(--floating-shadow); }
.kbw-more-menu button { width: 100%; padding: 10px 12px; border: 0; border-radius: 8px; display: block; color: var(--grey); background: transparent; cursor: pointer; font: inherit; font-size: 13px; text-align: left; }
.kbw-more-menu button:hover { background: var(--surface-hover); }

.kbw-body { min-height: 0; flex: 1; display: grid; grid-template-columns: 236px minmax(380px, 1fr) minmax(360px, 46%); }
.kbw-rail { padding: 18px 12px; overflow-y: auto; border-right: 1px solid var(--border); display: flex; flex-direction: column; gap: 4px; background: var(--surface); }
.kbw-rail-item { width: 100%; padding: 10px; border: 0; border-radius: 12px; display: flex; align-items: flex-start; gap: 11px; color: var(--text-soft); background: transparent; cursor: pointer; font: inherit; text-align: left; }
.kbw-rail-item:hover { background: var(--surface-hover); }
.kbw-rail-item.is-current { color: var(--grey); background: var(--orange-wash); box-shadow: inset 3px 0 0 var(--orange); }
.kbw-rail-item b { display: block; font-size: 13px; }
.kbw-rail-item small { display: block; margin-top: 2px; color: var(--muted); font-size: 11px; line-height: 1.35; }
.kbw-rail-number { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; flex: none; color: var(--text-soft); background: var(--surface-muted); font-size: 12px; font-weight: 800; }
.kbw-rail-item.is-current .kbw-rail-number { color: var(--on-orange); background: var(--orange); }
.kbw-rail-item.is-done .kbw-rail-number { color: var(--green-ink); background: var(--green-pale); }

.kbw-stage { min-width: 0; padding: 26px clamp(18px, 2.4vw, 36px) 40px; overflow-y: auto; outline: none; }
.kbw-stage-head { margin: 0 0 18px; }
.kbw-kicker { margin: 0 0 6px; color: var(--orange-ink); font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.kbw-stage-head h2 { margin: 0 0 6px; font-size: 24px; letter-spacing: -.02em; }
.kbw-stage-head p { margin: 0; max-width: 620px; color: var(--muted); font-size: 13.5px; line-height: 1.55; }
.kbw-card { margin: 0 0 16px; padding: 18px; border: 1px solid var(--border); border-radius: 16px; background: var(--surface); }
.kbw-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.kbw-field { margin: 0 0 14px; display: block; }
.kbw-field:last-child { margin-bottom: 0; }
.kbw-field > span { margin: 0 0 6px; display: block; color: var(--text-soft); font-size: 12px; font-weight: 700; }
.kbw-field > span em { color: var(--coral); font-style: normal; }
.kbw-field > small { margin: 6px 0 0; display: block; color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.kbw-field code { padding: 1px 4px; border-radius: 4px; background: var(--surface-muted); font-size: 11px; }
.kbw input, .kbw select, .kbw textarea {
  width: 100%;
  min-height: 40px;
  padding: 9px 12px;
  border: 1px solid var(--border-dark);
  border-radius: 10px;
  color: var(--grey);
  background: var(--surface);
  font: inherit;
  font-size: 13.5px;
  line-height: 1.5;
}
.kbw textarea { resize: vertical; }
.kbw input:focus, .kbw select:focus, .kbw textarea:focus { border-color: var(--orange); outline: 0; box-shadow: 0 0 0 3px rgba(var(--orange-rgb), .14); }
.kbw input[type="checkbox"] { width: auto; min-height: 0; }

.kbw-assist { margin: 0 0 16px; padding: 18px; border: 1px solid var(--violet-wash-border); border-radius: 16px; background: var(--violet-wash); }
.kbw-assist-head { margin: 0 0 12px; display: flex; gap: 12px; }
.kbw-assist-head > span { width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; flex: none; color: #fff; background: #7c5ce6; }
.kbw-assist-head b { display: block; font-size: 14px; }
.kbw-assist-head small { display: block; margin-top: 3px; color: var(--text-soft); font-size: 12px; line-height: 1.5; }
.kbw-assist-actions { margin-top: 10px; display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.kbw-assist-state { color: var(--text-soft); font-size: 12.5px; }
.kbw-gaps { margin-top: 14px; padding: 12px 14px; border: 1px solid var(--amber-wash); border-radius: 12px; background: var(--amber-wash); }
.kbw-gaps b { color: var(--amber-ink); font-size: 12.5px; }
.kbw-gaps ul { margin: 6px 0 0; padding-left: 18px; color: var(--grey); font-size: 12.5px; line-height: 1.55; }

.kbw-list { display: grid; gap: 8px; }
.kbw-list-row { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; align-items: start; gap: 8px; }
.kbw-list-marker { width: 26px; height: 26px; margin-top: 7px; border-radius: 50%; display: grid; place-items: center; color: var(--orange-ink); background: var(--orange-pale); font-size: 11px; font-weight: 800; }
.kbw-list-marker.is-numbered { color: #fff; background: var(--orange); }
.kbw-list-row textarea { min-height: 40px; }
.kbw-row-tools { display: flex; gap: 2px; }
.kbw-row-tools button, .kbw-icon { width: 30px; height: 30px; margin-top: 5px; border: 0; border-radius: 8px; color: var(--muted); background: transparent; cursor: pointer; font-size: 15px; }
.kbw-row-tools button:hover:not(:disabled), .kbw-icon:hover { color: var(--grey); background: var(--surface-hover); }
.kbw-row-tools button:disabled { opacity: .3; cursor: default; }
.kbw-add { padding: 8px 0; border: 0; color: var(--link); background: transparent; cursor: pointer; font: inherit; font-size: 13px; font-weight: 700; text-align: left; }
.kbw-add:hover { text-decoration: underline; }
.kbw-add.is-large { width: 100%; margin: 4px 0 18px; padding: 14px; border: 1.5px dashed var(--border-dark); border-radius: 14px; text-align: center; }
.kbw-add.is-large:hover { border-color: var(--orange); background: var(--orange-wash); text-decoration: none; }
.kbw-link { padding: 0; border: 0; color: var(--link); background: none; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 700; }
.kbw-link.is-danger { color: var(--coral-ink); }
.kbw-muted { color: var(--muted); font-size: 13px; }

.kbw-switch { margin: 0 0 16px; display: flex; align-items: center; gap: 12px; cursor: pointer; }
.kbw-switch input { position: absolute; opacity: 0; pointer-events: none; }
.kbw-switch span { width: 40px; height: 23px; padding: 3px; border-radius: 999px; flex: none; background: var(--neutral-mark); transition: .16s; }
.kbw-switch span::after { content: ""; width: 17px; height: 17px; border-radius: 50%; display: block; background: #fff; transition: .16s; }
.kbw-switch input:checked + span { background: var(--green); }
.kbw-switch input:checked + span::after { transform: translateX(17px); }
.kbw-switch input:focus-visible + span { outline: 2px solid var(--orange-ink); outline-offset: 2px; }
.kbw-switch b { font-size: 13.5px; }

.kbw-steps { display: grid; gap: 12px; margin: 0 0 4px; }
.kbw-step { border: 1px solid var(--border); border-radius: 16px; background: var(--surface); }
.kbw-step.is-open { border-color: var(--orange-wash-border); box-shadow: 0 0 0 3px var(--orange-wash); }
.kbw-step-head { padding: 8px 10px 8px 8px; display: flex; align-items: center; gap: 8px; }
.kbw-step-toggle { min-width: 0; padding: 8px; flex: 1; border: 0; border-radius: 10px; display: flex; align-items: center; gap: 10px; color: var(--grey); background: transparent; cursor: pointer; font: inherit; text-align: left; }
.kbw-step-toggle:hover { background: var(--surface-hover); }
.kbw-step-toggle b { min-width: 0; overflow: hidden; font-size: 14px; text-overflow: ellipsis; white-space: nowrap; }
.kbw-step-toggle small { margin-left: auto; color: var(--muted); font-size: 11.5px; white-space: nowrap; }
.kbw-step-badge { padding: 3px 10px; border-radius: 999px; flex: none; color: #fff; background: linear-gradient(120deg, #ff8a1c, #f9483a); font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.kbw-step-body { padding: 4px 18px 18px; border-top: 1px solid var(--hairline); }
.kbw-step-body > .kbw-field:first-child { margin-top: 14px; }

.kbw-images { display: grid; gap: 10px; }
.kbw-image { padding: 10px; border: 1px solid var(--border); border-radius: 12px; display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 12px; background: var(--surface-sunken); }
.kbw-image-thumb { height: 84px; overflow: hidden; border-radius: 8px; display: grid; place-items: center; background: #fff; }
.kbw-image-thumb img { width: 100%; height: 100%; object-fit: contain; }
.kbw-image-thumb span { padding: 8px; color: #e5590c; font-size: 10.5px; font-weight: 800; letter-spacing: .06em; text-align: center; text-transform: uppercase; }
.kbw-image-fields { display: grid; gap: 6px; }
.kbw-image-fields input { min-height: 34px; padding: 6px 10px; font-size: 12.5px; }
.kbw-image-actions { display: flex; gap: 14px; }
.kbw-drop { padding: 18px; border: 1.5px dashed var(--border-dark); border-radius: 12px; display: grid; gap: 3px; place-items: center; color: var(--text-soft); cursor: pointer; text-align: center; }
.kbw-drop:hover, .kbw-drop:focus-visible, .kbw-drop.is-over { border-color: var(--orange); color: var(--grey); background: var(--orange-wash); outline: 0; }
.kbw-drop b { font-size: 13px; }
.kbw-drop small { color: var(--muted); font-size: 11.5px; }

.kbw-extra { margin: 0 0 14px; padding: 10px 14px; border: 1px solid var(--border); border-radius: 12px; }
.kbw-extra summary { color: var(--text-soft); cursor: pointer; font-size: 12px; font-weight: 700; }
.kbw-extra[open] summary { margin-bottom: 12px; }
.kbw-callout { margin: 0 0 8px; padding: 10px; border: 1px solid var(--border); border-left-width: 4px; border-radius: 12px; display: grid; gap: 8px; background: var(--surface-sunken); }
.kbw-callout-tip { border-left-color: #21ad7e; }
.kbw-callout-important { border-left-color: #f08a24; }
.kbw-callout-warning { border-left-color: #e5484d; }
.kbw-callout-note { border-left-color: #5b7bd6; }
.kbw-callout-row { display: grid; grid-template-columns: 130px minmax(0, 1fr) 30px; gap: 8px; align-items: center; }
.kbw-callout-row .kbw-icon { margin: 0; }

.kbw-qa-head { margin: 0 0 10px; display: flex; align-items: center; justify-content: space-between; }
.kbw-qa-head b { font-size: 13px; }

.kbw-checks { margin: 0 0 14px; padding: 0; list-style: none; display: grid; gap: 8px; }
.kbw-checks li { display: flex; align-items: flex-start; gap: 10px; font-size: 13.5px; line-height: 1.45; }
.kbw-checks li > span { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; flex: none; font-size: 11px; font-weight: 900; }
.kbw-checks .is-ok > span { color: var(--green-ink); background: var(--green-pale); }
.kbw-checks .is-warning > span { color: var(--amber-ink); background: var(--amber-wash); }
.kbw-checks .is-blocking > span { color: var(--coral-ink); background: var(--coral-pale); }
.kbw-review-actions { margin-top: 14px; display: flex; gap: 10px; flex-wrap: wrap; }

.kbw-stage-foot { margin-top: 24px; padding-top: 18px; border-top: 1px solid var(--border); display: flex; justify-content: space-between; gap: 12px; }

.kbw-preview { min-width: 0; border-left: 1px solid var(--border); display: flex; flex-direction: column; background: var(--surface-sunken); }
.kbw-preview-head { min-height: 46px; padding: 0 18px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 12px; background: var(--surface); }
.kbw-preview-head b { font-size: 13px; }
.kbw-preview-head span { color: var(--muted); font-size: 11.5px; }
.kbw-preview-scroll { min-height: 0; flex: 1; padding: 20px; overflow-y: auto; }
.kbw-preview-paper { max-width: 760px; margin: 0 auto; padding: 28px 30px 34px; border-radius: 14px; color-scheme: light; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, .06), 0 18px 40px rgba(0, 0, 0, .12); }
.kbw-preview-paper .kb-guide { font-size: 14.5px; }
.kbw-preview-empty { margin: 30px 0; color: #697180; font-size: 13.5px; text-align: center; }

.kbw-toast { position: fixed; z-index: 150; left: 50%; bottom: 22px; max-width: min(560px, calc(100vw - 32px)); padding: 11px 16px; border-radius: 12px; color: var(--toast-ink); background: var(--toast-bg); box-shadow: var(--floating-shadow); font-size: 13px; transform: translateX(-50%); }
.kbw-toast.is-error { color: #fff; background: #b42326; }

.kb-guide-tag { margin-right: 4px; padding: 2px 7px; border-radius: 999px; color: var(--orange-ink); background: var(--orange-pale); font-size: 9.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; vertical-align: 1px; }

@media (max-width: 1180px) {
  .kbw-body { grid-template-columns: 200px minmax(0, 1fr); }
  .kbw-preview { display: none; }
}
@media (max-width: 760px) {
  .kbw-body { grid-template-columns: minmax(0, 1fr); }
  .kbw-rail { padding: 8px; border-right: 0; border-bottom: 1px solid var(--border); flex-direction: row; overflow-x: auto; }
  .kbw-rail-item { width: auto; flex: none; }
  .kbw-rail-item small { display: none; }
  .kbw-grid-2 { grid-template-columns: minmax(0, 1fr); }
  .kbw-image { grid-template-columns: minmax(0, 1fr); }
}

/* The second half of the Freshdesk panel: applying the rewritten articles. Set apart from the
   import above it because they are two jobs, run in order, and the second is safe to repeat. */
.kb-import-step {
  margin: 14px 0 4px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-muted);
}
.kb-import-step h3 { margin: 0 0 6px; font-size: 14px; font-weight: 700; }
.kb-import-step .kb-import-lead { margin: 0; }
.kb-import-step-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
