/**
 * Gviabcua.LiveSupport workspace.
 *
 * One stylesheet for operators and administrators. Hand-written, no build step:
 * the theme works straight after `git clone`. Tokens are declared once on
 * :root, overridden for dark mode, and everything else consumes them.
 */

/* ── Tokens ─────────────────────────────────────────────────────────────── */

:root {
    /* Grusher palette: blue-grey neutrals around the brand navy. */
    --bg: #f4f6fa;
    --surface: #ffffff;
    --surface-2: #eef2f8;
    --surface-3: #e2e8f2;
    --border: #dde3ee;
    --border-strong: #bcc6d8;
    --text: #16203a;
    --text-2: #4a5673;
    --muted: #5d6884;

    --primary: #3a5999;
    --primary-hover: #2c4478;
    --primary-ink: #ffffff;
    --primary-soft: #eaeef8;
    --primary-border: #c3cfe8;

    /* Grusher lime: a signal colour for marks and dots, never for text on white. */
    --accent: #afdb32;
    --accent-ink: #16203a;

    --danger: #b42318;
    --danger-soft: #fbeaea;
    --warn: #a15c07;
    --warn-soft: #fdf5e4;
    --ok: #4f6b0a;
    --ok-soft: #f1f8de;
    --info: #2969b0;
    --info-soft: #e9f1fa;

    /* The navigation rail is the brand's one dark surface in the light themes. */
    --rail-bg: #16203a;
    --rail-fg: #c3cce0;
    --rail-strong: #ffffff;
    --rail-muted: #8b97b4;
    --rail-line: rgba(255, 255, 255, .08);
    --rail-hover: rgba(255, 255, 255, .06);
    --rail-active: rgba(139, 166, 224, .18);
    --rail-field: rgba(255, 255, 255, .07);
    --rail-mark: var(--accent);

    /* Small radii and flat surfaces, as on grusher.com.ua. */
    --r-sm: 4px;
    --ch-web-bg: #e6efff; --ch-web-fg: #1b4dc1;
    --ch-telegram-bg: #e3f1fb; --ch-telegram-fg: #0d6ba8;
    --ch-whatsapp-bg: #e5f7ec; --ch-whatsapp-fg: #0f8b45;
    --ch-meta-bg: #efe9fb; --ch-meta-fg: #6229c4;
    --ch-email-bg: #fdf0e3; --ch-email-fg: #a35b12;
    --ch-social-bg: #fbe9f2; --ch-social-fg: #b2276d;

    --r: 6px;
    --r-lg: 8px;
    --r-xl: 12px;

    /* Cards sit on borders, not shadows; only floating layers cast one. */
    --sh-1: none;
    --sh-2: 0 1px 2px rgba(22, 32, 58, .06);
    --sh-3: 0 2px 6px rgba(22, 32, 58, .08);
    --sh-4: 0 10px 24px -6px rgba(22, 32, 58, .18), 0 2px 6px rgba(22, 32, 58, .06);
    --sh-5: 0 20px 40px -8px rgba(22, 32, 58, .24), 0 4px 10px rgba(22, 32, 58, .08);

    --rail: 232px;
    --rail-mini: 60px;
    --ease: cubic-bezier(.2, .6, .25, 1);
    --font: "Geologica", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, sans-serif;
    --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]):not([data-theme="slate"]):not([data-theme="contrast"]) {
        /* Native parts - the open list of a <select>, scrollbars, the date
           picker - follow this, not the tokens; without it they stay light. */
        color-scheme: dark;
    }

    /* Only when no explicit theme is chosen: "system" follows the OS. */
    :root:not([data-theme]),
    :root[data-theme="system"] {
        --bg: #0b1220;
        --surface: #131c2e;
        --surface-2: #1a2437;
        --surface-3: #232f46;
        --border: #253048;
        --border-strong: #3a4863;
        --text: #e2e8f4;
        --text-2: #a6b2c8;
        --muted: #8794ad;

        --primary: #8ba6e0;
        --primary-hover: #a6bcea;
        --primary-ink: #0b1020;
        --primary-soft: #1a2540;
        --primary-border: #2f4170;

        --danger: #f08585;
        --danger-soft: #2a1616;
        --warn: #f2b45a;
        --warn-soft: #2a2010;
        --ok: #afdb32;
        --ok-soft: #22300c;
        --info: #7fb2ee;
        --info-soft: #12233b;

        --rail-bg: #0e1626;
        --rail-line: #1f2a40;

        --sh-1: none;
        --sh-2: 0 1px 2px rgba(0, 0, 0, .35);
        --sh-3: 0 2px 8px rgba(0, 0, 0, .4);
        --sh-4: 0 12px 28px -6px rgba(0, 0, 0, .6);
        --sh-5: 0 20px 40px -8px rgba(0, 0, 0, .65);
    }
}

:root[data-theme="dark"],
:root[data-theme="midnight"] {
    --bg: #0b1220;
    --surface: #131c2e;
    --surface-2: #1a2437;
    --surface-3: #232f46;
    --border: #253048;
    --border-strong: #3a4863;
    --text: #e2e8f4;
    --text-2: #a6b2c8;
    --muted: #8794ad;

    --primary: #8ba6e0;
    --primary-hover: #a6bcea;
    --primary-ink: #0b1020;
    --primary-soft: #1a2540;
    --primary-border: #2f4170;

    --danger: #f08585;
    --danger-soft: #2a1616;
    --warn: #f2b45a;
    --warn-soft: #2a2010;
    --ok: #afdb32;
    --ok-soft: #22300c;
    --info: #7fb2ee;
    --info-soft: #12233b;

    --rail-bg: #0e1626;
    --rail-line: #1f2a40;

    --sh-1: none;
    --sh-2: 0 1px 2px rgba(0, 0, 0, .35);
    --sh-3: 0 2px 8px rgba(0, 0, 0, .4);
    --sh-4: 0 12px 28px -6px rgba(0, 0, 0, .6);
    --sh-5: 0 20px 40px -8px rgba(0, 0, 0, .65);
}

/* Older rules still reference these names. */
:root { --radius: var(--r); --radius-lg: var(--r-lg); --shadow: var(--sh-3); }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

* { box-sizing: border-box; }

/* Layout rules below use display, which beats the UA [hidden] rule. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 14px/1.55 var(--font);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: "cv02", "cv03", "cv04", "cv11";
}

/* One visible focus treatment everywhere, instead of per-component guesses. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 6px; border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: content-box; }

body.ls-dense { font-size: 13px; }

/* ── Shell ──────────────────────────────────────────────────────────────── */

.ls-shell {
    display: grid;
    grid-template-columns: var(--rail) minmax(0, 1fr);
    height: 100vh;
}

.ls-rail__avatar,
.ls-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 50%;
    background: var(--surface-3);
    color: var(--text);
    font-size: 12px;
    font-weight: 700;
    overflow: hidden;
    text-decoration: none;
}

.ls-avatar img, .ls-rail__avatar img { width: 100%; height: 100%; object-fit: cover; }
.ls-avatar--lg { width: 84px; height: 84px; font-size: 26px; }

.ls-main { overflow: hidden; display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ls-body { display: flex; flex-direction: column; min-width: 0; min-height: 0; }

/* ── Inbox ──────────────────────────────────────────────────────────────── */

.ls-inbox {
    display: grid;
    grid-template-columns: 320px minmax(0, 1fr) 300px;
    height: 100%;
    min-height: 0;
}

.ls-queue,
.ls-side { display: flex; flex-direction: column; min-height: 0; background: var(--surface); }
.ls-queue { border-right: 1px solid var(--border); }
.ls-side { border-left: 1px solid var(--border); overflow-y: auto; padding: 12px; gap: 12px; }
/* Folding sections clip with overflow: hidden, which drops their flex
   min-height to 0: without this a long panel squeezes them instead of
   scrolling, and the bottom rows of each section disappear. */
.ls-side > * { flex-shrink: 0; }
.ls-side > .ls-panel { margin-bottom: 0; }

/* Shown only where the side panel cannot sit beside its list. */
.ls-icon-btn.ls-conv__side, .ls-side > .ls-side__close, .ls-side > .ls-split__back { display: none; }
.ls-side__close, .ls-split__back { align-self: flex-start; }

.ls-queue__head { display: flex; gap: 6px; padding: 10px; border-bottom: 1px solid var(--border); }

/* Shown only where the list and the conversation cannot sit side by side. */
.ls-conv__back { display: none; flex: none; align-items: center; justify-content: center; height: 34px; font-size: 16px; }


.ls-icon-btn {
    width: 34px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2);
    color: var(--text);
    cursor: pointer;
}

.ls-tabs { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px 10px; border-bottom: 1px solid var(--border); }

.ls-tab {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 9px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--muted);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

.ls-tab:hover { background: var(--surface-2); }
.ls-tab.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.ls-tab--danger.is-active { background: var(--danger-soft); color: var(--danger); }

.ls-views { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 10px 8px; }

.ls-pill {
    padding: 3px 9px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--text);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

.ls-pill--ghost { background: transparent; color: var(--muted); border-style: dashed; }

.ls-list { flex: 1; overflow-y: auto; }

.ls-list__item {
    display: block;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    border-bottom: 1px solid var(--border);
    border-left: 3px solid transparent;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.ls-list__item:hover { background: var(--surface-2); }
.ls-list__item.is-active { background: var(--primary-soft); border-left-color: var(--primary); }
.ls-list__item.is-breached { border-left-color: var(--danger); }
.ls-list__item.is-risk { border-left-color: var(--warn); }

.ls-list__top { display: flex; justify-content: space-between; gap: 8px; }
.ls-list__name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-list__time { color: var(--muted); font-size: 12px; flex: none; }
.ls-list__sub { color: var(--muted); font-size: 13px; margin: 2px 0 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-list__meta { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.ls-list__op { color: var(--muted); font-size: 12px; }
.ls-list__op.is-free { color: var(--warn); }
.ls-list__tags { display: flex; gap: 4px; margin-top: 5px; flex-wrap: wrap; }

.ls-tag {
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--surface-3);
    color: var(--muted);
    font-size: 11px;
}

/* ── Conversation ───────────────────────────────────────────────────────── */

.ls-conv { position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--bg); }

/* "New messages", floating just above the composer.
   A message arriving while the operator is reading further up must not drag
   the view away from them - but it must not pass unnoticed either, which is
   what silently staying put would mean. */
.ls-newmsg {
    position: absolute;
    left: 50%;
    bottom: 150px;
    z-index: 4;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    transform: translateX(-50%);
    border: 0;
    border-radius: 999px;
    background: var(--primary);
    color: var(--primary-ink);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 6px 18px -6px rgba(16, 24, 40, .45);
    animation: ls-newmsg-in .18s var(--ease);
}

.ls-newmsg:hover { filter: brightness(1.06); }
.ls-newmsg__icon { font-size: 13px; line-height: 1; }

@keyframes ls-newmsg-in {
    from { opacity: 0; transform: translate(-50%, 8px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .ls-newmsg { animation: none; }
}

.ls-conv__placeholder {
    margin: auto;
    text-align: center;
    color: var(--muted);
}

.ls-conv__placeholder-icon { font-size: 44px; opacity: .5; }

.ls-conv__head {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 12px 16px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}

.ls-conv__title { flex: 1; min-width: 0; }
.ls-conv__title h2 { margin: 0 0 4px; font-size: 16px; }
.ls-conv__actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

.ls-conv__readonly {
    padding: 14px 16px;
    background: var(--warn-soft);
    color: var(--warn);
    border-top: 1px solid var(--border);
}

.ls-messages { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; }

.ls-msg { max-width: 76%; }
.ls-msg--operator, .ls-msg--bot { align-self: flex-end; }
.ls-msg--system { align-self: center; max-width: 90%; }

.ls-msg__meta {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 3px;
    font-size: 11px;
    color: var(--muted);
}

.ls-msg__body {
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    overflow-wrap: anywhere;
}

.ls-msg__body p { margin: 0 0 .5em; }
.ls-msg__body p:last-child { margin-bottom: 0; }
.ls-msg__body a { color: var(--primary); }

.ls-msg--operator .ls-msg__body { background: var(--primary-soft); border-color: transparent; }
.ls-msg--internal .ls-msg__body { background: var(--warn-soft); border-color: var(--warn); border-style: dashed; }
.ls-msg--system .ls-msg__body { background: transparent; border-style: dashed; color: var(--muted); text-align: center; }

.ls-msg__files { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

.ls-file {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 9px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font-size: 12px;
    text-decoration: none;
}

.ls-file--pending { background: var(--surface-2); }
.ls-file__x { border: 0; background: none; color: var(--danger); cursor: pointer; font-size: 14px; }

.ls-delivery { font-size: 11px; }
.ls-delivery--failed, .ls-delivery--permanently_failed { color: var(--danger); font-weight: 600; }
.ls-delivery--read { color: var(--ok); }

/* The "take it first" notice carries its own way out, so it needs room for a
   button beside the sentence. */
.ls-composer__hint--action {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.ls-composer__hint--action > span { flex: 1 1 260px; }

/* A scrolling list of things to choose from inside a dialog. */
.ls-picker { display: flex; flex-direction: column; gap: 10px; }

.ls-picker__list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 46vh;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 6px;
}

.ls-picker__item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 8px;
    border-radius: var(--radius);
    cursor: pointer;
}

.ls-picker__item:hover { background: var(--surface-2); }
.ls-picker__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-picker__item .ls-file__thumb { width: 28px; height: 28px; object-fit: cover; border-radius: 4px; }

/* ── Emoji field ────────────────────────────────────────────────────────────
   An icon field that does not require knowing your OS's emoji shortcut. The
   text input stays, so anything can still be pasted; the picker is the faster
   route to the same value. */

.ls-emoji { display: flex; flex-direction: column; gap: 6px; }
.ls-emoji__row-top { display: flex; align-items: center; gap: 8px; }
.ls-emoji__input { flex: 1; min-width: 0; }

.ls-emoji__current {
    flex: 0 0 auto;
    width: var(--control-h);
    height: var(--control-h);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface-2);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.ls-emoji__current:hover { border-color: var(--primary); }

.ls-emoji__grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    max-height: 240px;
    overflow-y: auto;
}

.ls-emoji__group { display: flex; flex-direction: column; gap: 4px; }

.ls-emoji__group-label {
    font-size: 10.5px;
    font-weight: 700;
    color: var(--muted);
}

.ls-emoji__row { display: flex; flex-wrap: wrap; gap: 3px; }

.ls-emoji__item {
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
}

.ls-emoji__item:hover { background: var(--primary-soft); }

.ls-emoji__clear {
    align-self: flex-start;
    border: 0;
    background: none;
    padding: 0;
    color: var(--muted);
    font-size: 12px;
    cursor: pointer;
    text-decoration: underline;
}

/* ── Side panel ─────────────────────────────────────────────────────────────
   Four folding sections instead of six open cards. What an operator needs
   without asking stays open; the rest answers its own headline from the
   closed heading. */

.ls-panel--who { display: flex; flex-direction: column; gap: 8px; }
.ls-panel__stack { display: flex; flex-direction: column; gap: 8px; }

.ls-badges { display: flex; flex-wrap: wrap; gap: 4px; }
.ls-badges:empty { display: none; }

.ls-fold { padding: 0; overflow: hidden; }

.ls-fold__head {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
    padding: 9px 11px;
    border: 0;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 12.5px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}

.ls-fold__head:hover { background: var(--surface-2); }
.ls-fold__title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ls-fold__caret {
    font-size: 10px;
    color: var(--muted);
    transition: transform .14s var(--ease);
}

.ls-fold__head.is-open .ls-fold__caret { transform: rotate(90deg); }

.ls-fold__body { padding: 0 11px 11px; }

/* Inside a folding section the facts are already introduced by the heading,
   so they get a tighter rhythm than a standalone card's. */
.ls-fold__body .ls-facts { font-size: 12.5px; }

@media (prefers-reduced-motion: reduce) {
    .ls-fold__caret { transition: none; }
}

/* A nudge for somebody who signed in offline and has not noticed. Sits above
   everything, looks like an offer rather than an error. */
.ls-onlinebar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    background: var(--warn-soft);
    border-bottom: 1px solid color-mix(in srgb, var(--warn) 35%, transparent);
    color: var(--warn);
    font-size: 13px;
}

.ls-onlinebar__dot {
    width: 8px;
    height: 8px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: currentColor;
    opacity: .6;
}

.ls-onlinebar__text { flex: 1; min-width: 0; }

.ls-onlinebar__close {
    border: 0;
    background: none;
    color: inherit;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    opacity: .6;
}

.ls-onlinebar__close:hover { opacity: 1; }

/* Unclaimed conversations, visible from every screen. Absent when the queue
   is empty, so it reads as a signal rather than as part of the chrome. */
.ls-topbar__bell {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 30px;
    padding: 0 10px 0 8px;
    border-radius: 999px;
    background: var(--warn-soft);
    color: var(--warn);
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
    font-variant-numeric: tabular-nums;
}

.ls-topbar__bell:hover { filter: brightness(.97); }
.ls-topbar__bell-icon { font-size: 13px; line-height: 1; }

/* Something has been waiting past the installation's own threshold. */
.ls-topbar__bell.is-overdue {
    background: var(--danger-soft);
    color: var(--danger);
    animation: ls-bell-pulse 1.8s var(--ease) infinite;
}

@keyframes ls-bell-pulse {
    0%, 100% { box-shadow: 0 0 0 0 transparent; }
    50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 18%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
    .ls-topbar__bell.is-overdue { animation: none; }
}

/* The attach-a-letter dialog: what it matched, and the search when it did
   not match anything. */
.ls-attach__status { display: flex; flex-direction: column; gap: 6px; }
.ls-attach__status .ls-alert { margin: 0; }
.ls-attach__search { display: flex; flex-direction: column; gap: 8px; }
.ls-attach__search[hidden] { display: none; }

/* Picker rows are buttons here rather than checkboxes: one choice, taken on
   click. */
button.ls-picker__item {
    border: 0;
    background: none;
    font: inherit;
    text-align: left;
    width: 100%;
}

/* ── Dragging to reorder ────────────────────────────────────────────────────
   The handle is deliberately a separate, obvious target: making the whole row
   draggable fights with selecting the text in it. */

.ls-drag {
    cursor: grab;
    color: var(--muted);
    font-size: 14px;
    line-height: 1;
    user-select: none;
    padding: 0 2px;
}

.ls-drag:active { cursor: grabbing; }
.ls-drag-cell { width: 28px; text-align: center; }

.is-dragging {
    opacity: .55;
    background: var(--primary-soft);
}

/* Merging two customer records: the two side by side, with what the merge
   would change marked. The one thing worse than a split customer is a wrongly
   joined one, so the comparison is the dialog rather than a footnote in it. */
.ls-merge { display: flex; flex-direction: column; gap: 10px; }
.ls-merge__table { font-size: 12.5px; }
.ls-merge__table td:first-child { width: 120px; }
.ls-merge__table tr.is-fill { background: var(--ok-soft); }

.ls-panel__tools { display: inline-flex; gap: 10px; }

/* Access dialog: sessions and history, stacked. */
.ls-access { display: flex; flex-direction: column; gap: 16px; }
.ls-access__block { display: flex; flex-direction: column; gap: 8px; }
.ls-access__block h3 { margin: 0; font-size: 13.5px; }
.ls-access .ls-table { font-size: 12.5px; }
.ls-access tr.is-muted { opacity: .55; }

/* A share-of-the-whole bar inside a table cell. Relative to the biggest row,
   so the comparison stays visible when one row dominates. */
.ls-usage__cell { width: 130px; }

.ls-usage {
    position: relative;
    display: flex;
    align-items: center;
    height: 18px;
    border-radius: 4px;
    background: var(--surface-3);
    overflow: hidden;
}

.ls-usage__fill { position: absolute; inset: 0 auto 0 0; background: var(--primary); opacity: .3; }
.ls-usage__fill.is-warn { background: var(--warn); opacity: .38; }
.ls-usage__fill.is-danger { background: var(--danger); opacity: .34; }

.ls-usage__text {
    position: relative;
    padding: 0 6px;
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: var(--text-2);
}

/* A plain bulleted list inside a card or an alert. */
.ls-list { margin: 6px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; font-size: 13px; }

/* Applied filters, shown so an empty queue is never a mystery. */
.ls-views--filters:empty { display: none; }
.ls-pill--active { background: var(--primary-soft); color: var(--primary); border-color: var(--primary-border); }

/* A two-column dialog for forms that are a list of narrow choices. */
.ls-form--grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 14px; }
.ls-form--grid .ls-field--inline { grid-column: 1 / -1; }

@media (max-width: 620px) {
    .ls-form--grid { grid-template-columns: minmax(0, 1fr); }
}

/* ── Mail reader ────────────────────────────────────────────────────────── */

.ls-mail__actions { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }

.ls-mail__html { display: flex; flex-direction: column; gap: 8px; }

.ls-mail__images {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 7px 10px;
    border: 1px solid var(--warn);
    border-radius: var(--radius);
    background: var(--warn-soft);
    font-size: 12.5px;
}

.ls-mail__images > span { flex: 1 1 260px; }

/* The frame is sandboxed without same-origin, so its height cannot be
   measured from here. A generous box with its own scrollbar beats a guess
   that clips the end of every second letter. */
.ls-mail__frame {
    width: 100%;
    min-height: 420px;
    height: 62vh;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: #fff;
}

.ls-chip--link { text-decoration: none; }
.ls-chip--link:hover { background: var(--surface-3); }

/* Actions that belong to a side panel rather than to the page. */
.ls-panel__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 10px;
}

/* A withdrawn message stays in the transcript - a review of "what did we tell
   this customer" needs to see that something was said and taken back. It just
   stops looking like something still standing. */
.ls-msg--deleted .ls-msg__body {
    text-decoration: line-through;
    opacity: .55;
}

.ls-msg--deleted .ls-msg__files { opacity: .55; }

/* An edit by the operator is bookkeeping; an edit by the customer changes what
   was asked, so the two do not get the same colour. */
.ls-edited {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: 11px;
    color: var(--muted);
    cursor: help;
}

.ls-edited--contact { color: var(--warn); font-weight: 600; }

/* A bubble that changed under the operator's eyes says so for a moment. The
   alternative - silently swapping the text - is how somebody ends up
   answering a question that was rewritten a minute ago. */
@keyframes ls-revised {
    0%   { background: var(--warn-soft); box-shadow: 0 0 0 3px var(--warn-soft); }
    70%  { background: var(--warn-soft); box-shadow: 0 0 0 3px var(--warn-soft); }
    100% { background: transparent; box-shadow: 0 0 0 3px transparent; }
}

.ls-msg.is-revised, .ls-sysmsg.is-revised {
    border-radius: var(--radius);
    animation: ls-revised 2.4s var(--ease) forwards;
}

@media (prefers-reduced-motion: reduce) {
    .ls-msg.is-revised, .ls-sysmsg.is-revised { animation-duration: 1ms; }
}

/* ── Composer ───────────────────────────────────────────────────────────── */

.ls-composer {
    position: relative;
    padding: 10px 14px 12px;
    background: var(--surface);
    border-top: 1px solid var(--border);
}

.ls-composer__input {
    width: 100%;
    padding: 9px 11px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    resize: vertical;
}

.ls-composer__input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.ls-composer__row { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.ls-composer__toggle { display: inline-flex; gap: 6px; align-items: center; color: var(--muted); font-size: 13px; }
.ls-composer__files { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.ls-spacer { flex: 1; }

.ls-canned {
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 100%;
    max-height: 240px;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    z-index: 5;
}

.ls-canned__item {
    display: flex;
    gap: 8px;
    width: 100%;
    padding: 8px 12px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.ls-canned__item:hover { background: var(--surface-2); }

/* ── Panels, pages, cards ───────────────────────────────────────────────── */

.ls-page { flex: 1; overflow-y: auto; padding: 20px 24px; min-height: 0; }
.ls-page__head { display: flex; gap: 16px; align-items: flex-start; justify-content: space-between; margin-bottom: 16px; flex-wrap: wrap; }
.ls-page__head h1 { margin: 0 0 4px; font-size: 21px; }
.ls-page__head p { margin: 0; }
.ls-page__actions { display: flex; gap: 8px; align-items: center; }

.ls-split { display: grid; grid-template-columns: minmax(0, 1fr) 320px; height: 100%; min-height: 0; }

.ls-panel {
    padding: 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: 12px;
}

.ls-panel__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.ls-panel__head h3 { margin: 0; font-size: 12px; font-weight: 600; color: var(--muted); }

.ls-card {
    padding: 16px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
    margin-bottom: 16px;
}

.ls-card__title { margin: 0 0 12px; font-size: 15px; }
.ls-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; margin-bottom: 16px; }

.ls-kpi { margin: 0; }
.ls-kpi__label { color: var(--muted); font-size: 12px; font-weight: 600; }
.ls-kpi__value { font-size: 26px; font-weight: 700; line-height: 1.2; margin-top: 4px; }
.ls-kpi__sub { color: var(--muted); font-size: 12px; margin-top: 2px; }
.ls-kpi__delta { font-size: 12px; margin-top: 4px; font-weight: 600; }
.ls-kpi__delta.is-up { color: var(--ok); }
.ls-kpi__delta.is-down { color: var(--danger); }
.ls-kpi.is-warn .ls-kpi__value { color: var(--warn); }
.ls-kpi.is-new .ls-kpi__value { color: var(--primary); }

/* ── Tables ─────────────────────────────────────────────────────────────── */

.ls-table-host { min-height: 120px; }
.ls-table-scroll { overflow-x: auto; }

.ls-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

.ls-table th, .ls-table td { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--border); vertical-align: middle; }
.ls-table th { background: var(--surface-2); color: var(--muted); font-size: 11px; font-weight: 600; }
.ls-table tbody tr:last-child td { border-bottom: 0; }
.ls-table tbody tr.is-muted { opacity: .55; }
.ls-table tbody tr.is-full { background: var(--danger-soft); }
.ls-table__actions { white-space: nowrap; text-align: right; }
.ls-table__actions .ls-link + .ls-link { margin-left: 10px; }

/* Six actions per operator do not fit one line next to the rest; they wrap
   into a compact block instead of pushing the table past the screen. */
.ls-table--operators .ls-table__actions { white-space: normal; width: 1%; min-width: 200px; }
.ls-table--operators .ls-table__actions > * { display: inline-block; margin: 2px 0 2px 10px; }
.ls-op-login { font-size: 12.5px; }

.ls-row-clickable { cursor: pointer; }
.ls-row-clickable:hover { background: var(--surface-2); }
.ls-row-clickable.is-active { background: var(--primary-soft); }

.ls-cell-user { display: flex; gap: 9px; align-items: center; }
.ls-pager { display: flex; gap: 10px; align-items: center; justify-content: center; padding: 12px; }

/* ── Facts, history ─────────────────────────────────────────────────────── */

.ls-facts { display: grid; grid-template-columns: minmax(80px, 40%) 1fr; gap: 4px 10px; margin: 0; font-size: 13px; }
.ls-facts dt { color: var(--muted); }
.ls-facts dd { margin: 0; overflow-wrap: anywhere; }

.ls-note { margin: 8px 0 0; padding: 8px 10px; background: var(--warn-soft); border-radius: var(--radius); font-size: 13px; }
.ls-footprint, .ls-history { margin: 8px 0 0; padding-left: 16px; font-size: 13px; color: var(--muted); }
.ls-footprint li, .ls-history li { margin-bottom: 4px; }
.ls-footprint span + span { margin-left: 6px; }
.ls-identities { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }

/* ── Controls ───────────────────────────────────────────────────────────── */

.ls-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 13px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
}

.ls-btn:hover { background: var(--surface-2); }
.ls-btn:disabled { opacity: .5; cursor: default; }
.ls-btn--primary { background: var(--primary); border-color: var(--primary); color: var(--primary-ink); }
.ls-btn--primary:hover { filter: brightness(1.08); }
.ls-btn--danger { color: var(--danger); border-color: var(--danger); background: transparent; }
.ls-btn--danger:hover { background: var(--danger-soft); }

.ls-link { border: 0; background: none; color: var(--primary); font: inherit; cursor: pointer; padding: 0; text-decoration: none; }
.ls-link:hover { text-decoration: underline; }
.ls-link--danger { color: var(--danger); }

.ls-input {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font: inherit;
}

.ls-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.ls-input--slim { width: auto; padding: 5px 8px; font-size: 13px; }
.ls-input--mono { font-family: var(--mono); font-size: 12px; }

.ls-form { display: flex; flex-direction: column; gap: 12px; }
.ls-field { display: flex; flex-direction: column; gap: 4px; }
.ls-field--inline { flex-direction: row; align-items: center; gap: 7px; }
.ls-field__label { color: var(--muted); font-size: 12px; font-weight: 600; }
.ls-field__hint { margin: 0; color: var(--muted); font-size: 12px; }

.ls-filters { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 16px; }
.ls-filter { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
.ls-inline-form { display: flex; gap: 8px; align-items: center; margin-top: 8px; }

.ls-checklist { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.ls-checklist__item { display: inline-flex; gap: 6px; align-items: center; font-size: 13px; }

/* ── Chips, dots, badges ────────────────────────────────────────────────── */

.ls-chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--surface-3);
    color: var(--muted);
    font-size: 11px;
    white-space: nowrap;
}

/*
 * Channel colours come from tokens, not from literals: a chip painted with a
 * pale blue stays readable on a white card and turns into a bright smudge on a
 * dark one. The tokens are redefined once per theme, below.
 */
.ls-chip--web { background: var(--ch-web-bg); color: var(--ch-web-fg); }
.ls-chip--telegram { background: var(--ch-telegram-bg); color: var(--ch-telegram-fg); }
.ls-chip--whatsapp { background: var(--ch-whatsapp-bg); color: var(--ch-whatsapp-fg); }
.ls-chip--facebook, .ls-chip--instagram { background: var(--ch-meta-bg); color: var(--ch-meta-fg); }
.ls-chip--email { background: var(--ch-email-bg); color: var(--ch-email-fg); }
.ls-chip--social { background: var(--ch-social-bg); color: var(--ch-social-fg); }
.ls-chip--danger, .ls-chip--urgent { background: var(--danger-soft); color: var(--danger); }
.ls-chip--warn, .ls-chip--high { background: var(--warn-soft); color: var(--warn); }
.ls-chip--ok { background: var(--ok-soft); color: var(--ok); }
.ls-chip--info { background: var(--primary-soft); color: var(--primary); }
.ls-chip--low { background: var(--surface-3); color: var(--muted); }
.ls-chip--role-admin { background: var(--danger-soft); color: var(--danger); }
.ls-chip--role-supervisor { background: var(--warn-soft); color: var(--warn); }
.ls-chip--role-moderator { background: var(--primary-soft); color: var(--primary); }
.ls-chip--role-operator { background: var(--primary-soft); color: var(--primary); }
.ls-chip--status-pending { background: var(--warn-soft); color: var(--warn); }
.ls-chip--status-active { background: var(--ok-soft); color: var(--ok); }
.ls-chip--status-closed { background: var(--surface-3); color: var(--muted); }
.ls-chip--action-deleted { background: var(--danger-soft); color: var(--danger); }
.ls-chip--action-created { background: var(--ok-soft); color: var(--ok); }

.ls-badge {
    min-width: 19px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-size: 11px;
    line-height: 19px;
    text-align: center;
    font-weight: 600;
}

.ls-badge--soft { background: var(--surface-3); color: var(--muted); }

.ls-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
.ls-dot--online { background: var(--ok); }
.ls-dot--busy { background: var(--danger); }
.ls-dot--away { background: var(--warn); }
.ls-dot--offline { background: var(--border-strong); }

.ls-live-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--ok); animation: ls-pulse 2s infinite; }
@keyframes ls-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

.ls-muted { color: var(--muted); }
.ls-error { color: var(--danger); }

/* ── Load bars, charts ──────────────────────────────────────────────────── */

.ls-load { display: flex; gap: 7px; align-items: center; }
.ls-load__track { width: 70px; height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.ls-load__fill { height: 100%; background: var(--ok); }
.ls-load__fill.is-high { background: var(--warn); }
.ls-load__fill.is-full { background: var(--danger); }

.ls-bars { display: flex; flex-direction: column; gap: 8px; }
.ls-bar { display: grid; grid-template-columns: 100px 1fr 40px; gap: 10px; align-items: center; }
.ls-bar__track { height: 10px; border-radius: 5px; background: var(--surface-3); overflow: hidden; }
.ls-bar__fill { height: 100%; background: var(--primary); }

.ls-chart-wrap { overflow-x: auto; }
.ls-chart { width: 100%; min-width: 560px; height: 260px; }
.ls-chart__grid { stroke: var(--border); stroke-width: 1; }
.ls-chart__axis { fill: var(--muted); font-size: 10px; }
.ls-chart__bar--created { fill: var(--primary); }
.ls-chart__bar--closed { fill: var(--ok); }
.ls-legend { display: flex; gap: 16px; margin-bottom: 8px; font-size: 12px; color: var(--muted); }
.ls-legend__swatch { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; }
.ls-legend__swatch--created { background: var(--primary); }
.ls-legend__swatch--closed { background: var(--ok); }
.ls-status-pill { display: inline-flex; gap: 6px; align-items: center; font-size: 13px; }

/* ── Permission matrix ──────────────────────────────────────────────────── */

.ls-perm-matrix { display: flex; flex-direction: column; gap: 16px; }
.ls-perm-group h4 { margin: 0 0 6px; font-size: 13px; color: var(--muted); font-weight: 600; }
.ls-perm-rows { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 6px; }

.ls-perm-row {
    display: flex;
    gap: 9px;
    align-items: center;
    padding: 5px 8px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.ls-perm-row.is-on { border-color: var(--ok); background: var(--ok-soft); }
.ls-perm-row__label { display: flex; flex-direction: column; font-size: 13px; }
.ls-perm-row__label code { color: var(--muted); font-size: 11px; font-family: var(--mono); }
.ls-perm-list { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.ls-perm { padding: 2px 7px; border-radius: 5px; background: var(--surface-2); font-family: var(--mono); font-size: 11px; }
.ls-details summary { cursor: pointer; color: var(--primary); }

/* ── Modal, toast ───────────────────────────────────────────────────────── */

.ls-overlay {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(16, 24, 40, .5);
    backdrop-filter: blur(2px);
}

.ls-modal {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 480px;
    max-height: 88vh;
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
    overflow: hidden;
}

.ls-modal--wide { max-width: 780px; }
.ls-modal__head { display: flex; justify-content: space-between; align-items: center; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.ls-modal__head h2 { margin: 0; font-size: 16px; }
.ls-modal__x { border: 0; background: none; color: var(--muted); font-size: 22px; cursor: pointer; line-height: 1; }
.ls-modal__body { padding: 18px; overflow-y: auto; }
.ls-modal__text { margin: 0; }
.ls-modal__foot { display: flex; gap: 8px; justify-content: flex-end; padding: 12px 18px; border-top: 1px solid var(--border); background: var(--surface-2); }

.ls-toasts { position: fixed; right: 16px; bottom: 16px; z-index: 200; display: flex; flex-direction: column; gap: 8px; }

.ls-toast {
    display: flex;
    gap: 12px;
    align-items: center;
    padding: 10px 14px;
    border-radius: var(--radius);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    box-shadow: var(--shadow);
    max-width: 380px;
}

.ls-toast__close { border: 0; background: none; color: inherit; cursor: pointer; font-size: 17px; line-height: 1; }

/* ── Misc ───────────────────────────────────────────────────────────────── */

.ls-loading { display: flex; gap: 10px; align-items: center; justify-content: center; padding: 40px; color: var(--muted); }

.ls-spinner {
    width: 16px;
    height: 16px;
    border: 2px solid var(--border-strong);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: ls-spin .7s linear infinite;
}

@keyframes ls-spin { to { transform: rotate(360deg); } }

.ls-empty { padding: 34px 16px; text-align: center; color: var(--muted); }
.ls-fatal { max-width: 520px; margin: 14vh auto; padding: 24px; text-align: center; }

.ls-code {
    padding: 12px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow-x: auto;
    font-family: var(--mono);
    font-size: 12px;
    white-space: pre-wrap;
    word-break: break-all;
}

.ls-domains { list-style: none; margin: 8px 0; padding: 0; }
.ls-domains li { display: flex; gap: 8px; align-items: center; padding: 5px 0; border-bottom: 1px solid var(--border); }

/* ── Login / public ─────────────────────────────────────────────────────── */

body.ls-blank, body.ls-public { background: var(--bg); color: var(--text); font: 14px/1.55 var(--font); margin: 0; }

.ls-login {
    max-width: 380px;
    margin: 12vh auto;
    padding: 26px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-top: 3px solid var(--accent);
    border-radius: var(--radius-lg);
    box-shadow: var(--sh-5);
}

/* The sign-in page stands on the same navy as the rail inside: it is the
   first thing an operator sees of the brand. */
body.ls-blank:has(.ls-login) { min-height: 100vh; background: var(--rail-bg); }

@media (max-width: 440px) {
    .ls-login { margin: 6vh 12px; }
}

.ls-login h1 { margin: 0 0 4px; font-size: 20px; text-align: center; }
.ls-login__form { display: flex; flex-direction: column; gap: 6px; margin-top: 16px; }
.ls-login__label { color: var(--muted); font-size: 12px; font-weight: 600; }
.ls-login__submit { margin-top: 12px; justify-content: center; }
.ls-login__error { margin: 6px 0 0; padding: 8px 10px; border-radius: var(--radius); background: var(--danger-soft); color: var(--danger); font-size: 13px; }

/* ── Responsive ─────────────────────────────────────────────────────────── */

@media (max-width: 1240px) {
    .ls-inbox { grid-template-columns: 290px minmax(0, 1fr); position: relative; }
    .ls-inbox .ls-side { display: none; }
    .ls-split { grid-template-columns: minmax(0, 1fr); }
    .ls-split .ls-side { display: none; }

    /* The customer panel slides over the conversation instead of vanishing:
       contact details, session and history used to be out of reach here. */
    .ls-inbox.has-chat .ls-conv__side { display: grid; }
    .ls-inbox.is-side-open .ls-side {
        display: flex;
        position: absolute;
        inset: 0 0 0 auto;
        width: min(340px, 100%);
        z-index: 30;
        box-shadow: var(--sh-5);
    }
    .ls-inbox.is-side-open .ls-side__close,
    .ls-split.is-detail .ls-split__back { display: inline-flex; }

    /* Contacts: the card replaces the list, as contacts.js expects. */
    .ls-split.is-detail > .ls-page { display: none; }
    .ls-split.is-detail > .ls-side { display: flex; border-left: 0; }
}

@media (max-width: 900px) {
    /* One pane at a time: the list, or the conversation opened from it. The
       list used to be hidden outright here, which left a phone with a
       conversation area and no way to pick a conversation. */
    .ls-inbox { grid-template-columns: minmax(0, 1fr); }
    .ls-inbox .ls-conv { display: none; }
    .ls-inbox.has-chat .ls-queue { display: none; }
    .ls-inbox.has-chat .ls-conv { display: flex; }
    .ls-conv__back { display: inline-flex; }
    .ls-page { padding: 14px; }
}

/* ── Channel-native elements (buttons, quick replies, media) ───────────── */

.ls-msg__kbd { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }

.ls-kbd {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border: 1px dashed var(--border-strong);
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--muted);
    font-size: 12px;
    text-decoration: none;
}

a.ls-kbd:hover { color: var(--primary); border-color: var(--primary); }
.ls-kbd--pressed { border-style: solid; background: var(--ok-soft); color: var(--ok); }

.ls-thumb {
    display: inline-block;
    max-width: 220px;
    border-radius: var(--radius);
    overflow: hidden;
    border: 1px solid var(--border);
}

.ls-thumb img { display: block; width: 100%; height: auto; }

/* ── Media in the transcript ────────────────────────────────────────────────
   Everything the browser can play, played where it was sent. An operator
   should not have to download a four-second voice message to find out what
   the customer asked. */

.ls-media {
    position: relative;
    display: inline-block;
    max-width: 320px;
    border-radius: var(--radius);
    overflow: hidden;
    border: 1px solid var(--border);
    background: #000;
}

.ls-media video { display: block; width: 100%; height: auto; max-height: 320px; }

/* A GIF loops silently and needs no controls; the tag says what it is. */
.ls-media--animation video { pointer-events: none; }

.ls-media__tag {
    position: absolute;
    top: 6px;
    left: 6px;
    padding: 1px 5px;
    border-radius: 4px;
    background: rgba(0, 0, 0, .6);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .04em;
}

.ls-media__time {
    position: absolute;
    right: 6px;
    bottom: 6px;
    padding: 1px 5px;
    border-radius: 4px;
    background: rgba(0, 0, 0, .6);
    color: #fff;
    font-size: 11px;
}

/* Telegram's round video message is round everywhere else; a square crop
   makes it read as an ordinary video, which it is not. */
.ls-media--round {
    width: 220px;
    height: 220px;
    max-width: 220px;
    border-radius: 50%;
}

.ls-media--round video { width: 100%; height: 100%; object-fit: cover; max-height: none; }

.ls-audio {
    display: flex;
    align-items: center;
    gap: 9px;
    max-width: 380px;
    padding: 7px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2);
}

.ls-audio__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.ls-audio__title { font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ls-audio .ls-media__time { position: static; flex: none; background: none; color: var(--muted); }

/* Our own controls, not the browser's: Chrome's audio bar is 54px tall and
   was clipped by the card; its timeline for a MediaRecorder WebM did not move. */
.ls-audio__play {
    position: relative;
    flex: none;
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: 50%;
    background: var(--primary);
    cursor: pointer;
}

.ls-audio__play::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-35%, -50%);
    border-style: solid;
    border-width: 7px 0 7px 11px;
    border-color: transparent transparent transparent #fff;
}

.ls-audio__play.is-playing::before {
    width: 10px;
    height: 12px;
    transform: translate(-50%, -50%);
    border: 0;
    border-inline: 3.5px solid #fff;
}

.ls-audio__play:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.ls-audio__seek {
    --progress: 0%;
    width: 100%;
    height: 14px;
    margin: 0;
    background: transparent;
    cursor: pointer;
    appearance: none;
}

.ls-audio__seek:disabled { cursor: default; }

.ls-audio__seek::-webkit-slider-runnable-track {
    height: 4px;
    border-radius: 2px;
    background: linear-gradient(to right, var(--primary) var(--progress), var(--border-strong) var(--progress));
}

.ls-audio__seek::-moz-range-track {
    height: 4px;
    border-radius: 2px;
    background: linear-gradient(to right, var(--primary) var(--progress), var(--border-strong) var(--progress));
}

.ls-audio__seek::-webkit-slider-thumb {
    width: 12px;
    height: 12px;
    margin-top: -4px;
    border: 0;
    border-radius: 50%;
    background: var(--primary);
    appearance: none;
}

.ls-audio__seek::-moz-range-thumb {
    width: 12px;
    height: 12px;
    border: 0;
    border-radius: 50%;
    background: var(--primary);
}

.ls-audio__seek:disabled::-webkit-slider-thumb { visibility: hidden; }
.ls-audio__seek:disabled::-moz-range-thumb { visibility: hidden; }

.ls-audio__save {
    flex: none;
    align-self: center;
    padding: 2px 4px;
    color: var(--muted);
    font-size: 13px;
    text-decoration: none;
}

.ls-audio__save:hover { color: var(--primary); }

.ls-media--round video { cursor: pointer; }

/* The corner tag sat outside the circle and was clipped away. */
.ls-media--round .ls-media__time { right: 50%; bottom: 12px; transform: translateX(50%); }

.ls-sticker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    max-width: 160px;
}

.ls-sticker img, .ls-sticker video { display: block; width: 100%; height: auto; max-height: 160px; }

/* .tgs is gzipped Lottie: nothing in a browser draws it without a player we
   do not ship. The emoji the sticker carries is the meaning, so that is what
   is shown instead of a broken image. */
.ls-sticker--lottie {
    flex-direction: column;
    gap: 2px;
    padding: 10px 14px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
}

.ls-sticker__emoji { font-size: 44px; line-height: 1.1; }
.ls-sticker__label { font-size: 11px; color: var(--muted); }
.ls-sticker__save { font-size: 11px; }

/* Once the Lottie player has something to show, the placeholder is replaced
   and the dashed box goes with it. */
.ls-sticker__lottie { width: 140px; height: 140px; }
.ls-sticker__lottie svg { display: block; width: 100% !important; height: 100% !important; }

/* ══════════════════════════════════════════════════════════════════════════
   Refinements - polish over the base layout above
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Dashboard ────────────────────────────────────────────────────────────*/

/*
 * The dashboard is a grid of blocks the operator arranges, so the page itself
 * knows nothing about what is on it. Masonry: rows are 1px and every block
 * spans as many as it is tall (set by masonry() in ui.js), so a short block no
 * longer leaves a hole under itself the height of its tallest neighbour. A
 * block asked to be wide spans the whole row.
 */
.ls-dash {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
    grid-auto-rows: 1px;
    align-items: start;
    gap: 0 14px;
}

.ls-widget { margin: 0; min-width: 0; }
.ls-widget.is-full { grid-column: 1 / -1; }

.ls-widget__head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.ls-widget__head .ls-card__title { margin: 0; flex: 1; display: flex; align-items: center; gap: 8px; }
.ls-widget__head .ls-card__link { margin-left: auto; }

/* Tiles bring their own frame; inside a block they would be a box in a box. */
.ls-widget--bare { padding: 0; background: none; border: 0; box-shadow: none; }
.ls-widget--bare .ls-widget__head { margin-bottom: 8px; padding: 0 2px; }
.ls-widget--bare .ls-card__title { font-size: 12px; font-weight: 600; color: var(--muted); }

.ls-widget__body { min-width: 0; }
.ls-widget__more { display: inline-block; margin-top: 8px; font-size: 12px; background: none; border: 0; padding: 0; cursor: pointer; }

/* The handle and the two tools appear only while the dashboard is being arranged. */
.ls-widget__grip, .ls-widget__tools { display: none; }

.ls-dash.is-editing .ls-widget {
    border-style: dashed;
    border-color: var(--primary);
    cursor: grab;
}

.ls-dash.is-editing .ls-widget--bare { border-style: dashed; border-width: 1px; padding: 10px; }
.ls-dash.is-editing .ls-widget__grip { display: inline-block; color: var(--muted); cursor: grab; }
.ls-dash.is-editing .ls-widget__tools { display: inline-flex; gap: 4px; }
.ls-dash.is-editing .ls-widget.is-dragging { opacity: .4; }

.ls-widget__tool {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    color: var(--muted);
    font-size: 12px;
    cursor: pointer;
}

.ls-widget__tool:hover { color: var(--text); border-color: var(--primary); }

.ls-dash__picker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
    padding: 12px 14px;
    background: var(--surface);
    border: 1px dashed var(--border);
    border-radius: var(--r-lg);
}

.ls-dash__picker-main { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; flex: 1; min-width: 240px; }
.ls-dash__picker-actions { display: flex; gap: 8px; }
.ls-dash__picker-hint { flex-basis: 100%; margin: 0; font-size: 12px; }

/*
 * Today by the hour. Columns rather than a line: the question is where the day
 * peaks, and a bar makes an empty hour visibly empty where a line would simply
 * pass through it.
 */
.ls-hours { display: flex; align-items: flex-end; gap: 2px; height: 120px; }
.ls-hours__col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; min-width: 0; }
.ls-hours__pair { display: flex; align-items: flex-end; justify-content: center; gap: 1px; height: 100%; }

.ls-hours__bar {
    width: 45%;
    min-height: 2px;
    border-radius: 2px 2px 0 0;
    transition: height .2s var(--ease);
}

.ls-hours__bar.is-created { background: var(--primary); }
.ls-hours__bar.is-closed { background: var(--ok); }
.ls-hours__col:hover .ls-hours__bar { filter: brightness(1.15); }
.ls-hours__label { height: 14px; font-size: 10px; color: var(--muted); text-align: center; }

.ls-healthlist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.ls-healthlist li { display: flex; align-items: flex-start; gap: 9px; }
.ls-healthlist .ls-dot { margin-top: 5px; flex: none; }

.ls-rating-stars { flex: none; font-size: 13px; letter-spacing: 1px; color: var(--muted); }
.ls-rating-stars.is-high { color: var(--ok); }
.ls-rating-stars.is-low { color: var(--danger); }

.ls-dash__row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: 12px;
}

/* Two figures above a list inside one block (complaints). */
.ls-dash__row--compact {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-bottom: 12px;
}


/* A tile links somewhere as <a> and filters the inbox as <button>; both have to
   look like the plain tile they wrap. */
.ls-tile-link {
    display: block;
    width: 100%;
    padding: 0;
    text-align: left;
    font: inherit;
    color: inherit;
    text-decoration: none;
    background: none;
    border: 0;
    cursor: pointer;
}

.ls-tile {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    height: 100%;
    padding: 14px 16px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-1);
    transition: box-shadow .18s var(--ease), transform .18s var(--ease), border-color .18s var(--ease);
}

.ls-tile-link:hover .ls-tile { border-color: var(--primary-border); background: color-mix(in srgb, var(--primary-soft) 35%, var(--surface)); }

.ls-tile__icon {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: var(--r);
    background: var(--surface-2);
    color: var(--text-2);
}

.ls-tile__body { min-width: 0; }
.ls-tile__value { font-size: 24px; font-weight: 680; line-height: 1.15; letter-spacing: -.02em; }
.ls-tile__label { margin-top: 1px; font-size: 12.5px; font-weight: 550; color: var(--text-2); }
.ls-tile__caption { margin-top: 1px; font-size: 11.5px; color: var(--muted); }

.ls-tile--ok .ls-tile__icon { background: var(--ok-soft); color: var(--ok); }
.ls-tile--warn { border-color: color-mix(in srgb, var(--warn) 35%, var(--border)); }
.ls-tile--warn .ls-tile__icon { background: var(--warn-soft); color: var(--warn); }
.ls-tile--warn .ls-tile__value { color: var(--warn); }
.ls-tile--danger { border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); }
.ls-tile--danger .ls-tile__icon { background: var(--danger-soft); color: var(--danger); }
.ls-tile--danger .ls-tile__value { color: var(--danger); }

.ls-card__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.ls-card__head .ls-card__title { margin: 0; }
.ls-statuses { display: flex; gap: 10px; }
.ls-status-pill { display: inline-flex; gap: 5px; align-items: center; font-size: 12px; color: var(--muted); }

.ls-oplist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }

.ls-oplist__item {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 8px;
    border-radius: var(--r);
    transition: background .15s var(--ease);
}

.ls-oplist__item:hover { background: var(--surface-2); }
.ls-oplist__item.is-full { background: var(--danger-soft); }
.ls-oplist__meta { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.ls-oplist__meta strong { font-size: 13px; }
.ls-oplist__meta .ls-muted { font-size: 11.5px; }
.ls-oplist__load { display: flex; gap: 8px; align-items: center; }
.ls-avatar--sm { width: 28px; height: 28px; font-size: 10px; }

.ls-bar__label { display: flex; gap: 6px; align-items: center; font-size: 12.5px; color: var(--text-2); }
.ls-bar__fill--telegram { background: #229ed9; }
.ls-bar__fill--whatsapp { background: #25d366; }
.ls-bar__fill--facebook { background: #0084ff; }
.ls-bar__fill--instagram { background: linear-gradient(90deg, #f09433, #dc2743, #bc1888); }
.ls-bar__fill--email { background: #ea580c; }

.ls-minigrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 10px; }
.ls-mini { padding: 10px; background: var(--surface-2); border-radius: var(--r); text-align: center; }
.ls-mini__value { font-size: 19px; font-weight: 650; }
.ls-mini__label { font-size: 11px; color: var(--muted); }

/* ── Channel badge ────────────────────────────────────────────────────────*/

.ls-channel {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--surface-3);
    color: var(--text-2);
    font-size: 11.5px;
    font-weight: 550;
    white-space: nowrap;
}

/* Same per-theme channel tokens as the chips. The Telegram override used to sit
   outside the dark-mode query, so every theme but "light" drew a dark chip. */
.ls-channel--web { background: var(--ch-web-bg); color: var(--ch-web-fg); }
.ls-channel--telegram { background: var(--ch-telegram-bg); color: var(--ch-telegram-fg); }
.ls-channel--whatsapp { background: var(--ch-whatsapp-bg); color: var(--ch-whatsapp-fg); }
.ls-channel--facebook,
.ls-channel--instagram { background: var(--ch-meta-bg); color: var(--ch-meta-fg); }
.ls-channel--email { background: var(--ch-email-bg); color: var(--ch-email-fg); }
.ls-channel--social { background: var(--ch-social-bg); color: var(--ch-social-fg); }

/* ── Conversation list ────────────────────────────────────────────────────*/

.ls-list__item { padding: 11px 13px; transition: background .12s var(--ease); }
.ls-list__name { font-size: 13.5px; font-weight: 600; }
.ls-list__time { font-size: 11.5px; }
.ls-list__sub { font-size: 12.5px; }

.ls-list__item.is-active {
    background: var(--primary-soft);
    border-left-color: var(--primary);
}

/* ── Messages ─────────────────────────────────────────────────────────────*/

.ls-msg { position: relative; max-width: 74%; }
.ls-msg__meta { font-size: 11px; gap: 5px; }

.ls-msg__body {
    padding: 10px 13px;
    border-radius: 14px;
    box-shadow: var(--sh-1);
    font-size: 13.5px;
    line-height: 1.5;
}

.ls-msg--visitor .ls-msg__body { border-bottom-left-radius: 5px; }
.ls-msg--operator .ls-msg__body,
.ls-msg--bot .ls-msg__body { border-bottom-right-radius: 5px; }

.ls-msg--operator .ls-msg__body {
    background: var(--primary-soft);
    border-color: var(--primary-border);
    color: var(--text);
}

.ls-msg--internal .ls-msg__body {
    background: var(--warn-soft);
    border-color: color-mix(in srgb, var(--warn) 40%, transparent);
    border-style: solid;
    border-left-width: 3px;
}

/* Hover toolbar */
.ls-msg__acts {
    position: absolute;
    top: -8px;
    right: 6px;
    display: flex;
    gap: 2px;
    padding: 2px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    box-shadow: var(--sh-2);
    opacity: 0;
    pointer-events: none;
    transition: opacity .14s var(--ease);
    z-index: 2;
}

.ls-msg:hover .ls-msg__acts,
.ls-msg:focus-within .ls-msg__acts { opacity: 1; pointer-events: auto; }
.ls-msg--visitor .ls-msg__acts { right: auto; left: 6px; }

.ls-msg__act {
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: 999px;
    background: none;
    color: var(--muted);
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
}

.ls-msg__act:hover { background: var(--surface-2); color: var(--text); }

/* Reactions */
.ls-msg__reactions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }

.ls-reaction {
    display: inline-flex;
    gap: 4px;
    align-items: center;
    padding: 2px 8px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text-2);
    font-size: 12px;
    cursor: pointer;
    transition: all .14s var(--ease);
}

.ls-reaction:hover { border-color: var(--border-strong); }
.ls-reaction.is-mine { background: var(--primary-soft); border-color: var(--primary-border); color: var(--primary); }

.ls-reaction-picker {
    position: fixed;
    z-index: 300;
    display: flex;
    gap: 2px;
    padding: 5px;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    box-shadow: var(--sh-4);
}

.ls-reaction-picker__item {
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 999px;
    background: none;
    cursor: pointer;
    font-size: 17px;
    transition: transform .12s var(--ease), background .12s var(--ease);
}

.ls-reaction-picker__item:hover { background: var(--surface-2); transform: scale(1.18); }

/* Context menu */
.ls-ctxmenu {
    position: fixed;
    z-index: 300;
    min-width: 190px;
    padding: 5px;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r);
    box-shadow: var(--sh-4);
}

.ls-ctxmenu__item {
    display: flex;
    gap: 9px;
    align-items: center;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.ls-ctxmenu__item:hover { background: var(--surface-2); }
.ls-ctxmenu__item span { width: 16px; text-align: center; color: var(--muted); }
.ls-ctxmenu__item--danger,
.ls-ctxmenu__item--danger span { color: var(--danger); }

/* ── Composer ─────────────────────────────────────────────────────────────*/

.ls-composer { padding: 12px 16px 10px; }
.ls-composer--whisper { background: var(--warn-soft); border-top-color: color-mix(in srgb, var(--warn) 35%, transparent); }

.ls-composer__hint {
    margin-bottom: 8px;
    padding: 7px 10px;
    border-radius: var(--r);
    background: var(--surface);
    border: 1px dashed color-mix(in srgb, var(--warn) 50%, transparent);
    color: var(--warn);
    font-size: 12.5px;
}

.ls-composer__input { border-radius: var(--r); font-size: 13.5px; }
.ls-composer__toggle.is-locked { color: var(--warn); font-weight: 550; }

.ls-quickbar {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 9px;
    padding-top: 9px;
    border-top: 1px dashed var(--border);
}

.ls-quick {
    padding: 4px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--text-2);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
    white-space: nowrap;
    transition: all .14s var(--ease);
}

.ls-quick:hover { background: var(--primary-soft); border-color: var(--primary-border); color: var(--primary); }
.ls-quick--add { border-style: dashed; background: transparent; }
.ls-quick-empty { font-size: 12px; }

.ls-icon-btn {
    width: 34px;
    height: 34px;
    flex: none;
    display: grid;
    place-items: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--r);
    background: var(--surface);
    color: var(--text-2);
    cursor: pointer;
    font-size: 14px;
    transition: all .14s var(--ease);
}

.ls-icon-btn:hover { background: var(--surface-2); color: var(--text); }
.ls-icon-btn--danger:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); }

/* Voice input in the composer: red and pulsing while it listens. */
.ls-dictation { position: relative; display: inline-flex; }
.ls-dictation__btn.is-recording {
    border-color: var(--danger);
    color: var(--danger);
    background: var(--danger-soft);
    animation: ls-pulse 1.4s ease-in-out infinite;
}
.ls-dictation__menu {
    position: absolute;
    bottom: calc(100% + 6px);
    right: 0;
    z-index: 40;
    min-width: 150px;
    padding: 4px;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border-strong);
    border-radius: var(--r);
    background: var(--surface);
    box-shadow: var(--shadow);
}
.ls-dictation__menu button {
    padding: 6px 10px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text);
    text-align: left;
    cursor: pointer;
    font: inherit;
}
.ls-dictation__menu button:hover { background: var(--surface-2); }
.ls-dictation__menu button.is-active { color: var(--primary); font-weight: 600; }

/* ── Buttons dialog preview ───────────────────────────────────────────────*/

.ls-btn-preview {
    padding: 12px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--r);
}

.ls-btn-preview__bubble {
    display: inline-block;
    max-width: 100%;
    padding: 9px 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px 14px 14px 5px;
    font-size: 13px;
}

.ls-btn-preview__keys { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.ls-btn-preview__keys.is-quick { padding-top: 8px; border-top: 1px dashed var(--border-strong); }

/* ── Setup wizard ─────────────────────────────────────────────────────────*/

.ls-setup { display: flex; flex-direction: column; gap: 20px; }
.ls-setup__summary { margin: 0; color: var(--text-2); }
.ls-setup__section { display: flex; flex-direction: column; gap: 10px; }
.ls-setup__section h3 { margin: 0; font-size: 13px; font-weight: 600; color: var(--muted); }

.ls-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.ls-steps__item { display: flex; gap: 12px; }

.ls-steps__num {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    flex: none;
    border-radius: 999px;
    background: var(--primary-soft);
    color: var(--primary);
    font-size: 12px;
    font-weight: 650;
}

.ls-steps__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.ls-steps__body h4 { margin: 0; font-size: 13.5px; }
.ls-steps__body p { margin: 0; color: var(--text-2); font-size: 13px; }

.ls-code-wrap { position: relative; }

.ls-api-guide { margin-top: 16px; }
.ls-api-guide > summary { cursor: pointer; font-size: 15px; font-weight: 600; }
.ls-api-guide[open] > summary { margin-bottom: 16px; }
.ls-api-guide .ls-facts { grid-template-columns: minmax(110px, max-content) 1fr; }
.ls-api-guide .ls-table { box-shadow: none; }

@media (max-width: 600px) {
    .ls-api-guide .ls-facts { grid-template-columns: 1fr; gap: 2px; }
    .ls-api-guide .ls-facts dd { margin-bottom: 8px; }
}

.ls-copy {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
    font-size: 12px;
}

.ls-copy:hover { color: var(--primary); border-color: var(--primary); }

.ls-alert { padding: 10px 12px; border-radius: var(--r); font-size: 13px; }
.ls-alert--warn { background: var(--warn-soft); color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); }

.ls-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.ls-req { color: var(--danger); margin-left: 3px; }

/* ── Structured field editors ─────────────────────────────────────────────*/

.ls-schedule { display: flex; flex-direction: column; gap: 6px; }

.ls-schedule__row {
    display: grid;
    grid-template-columns: 96px 1fr auto 1fr;
    gap: 8px;
    align-items: center;
}

.ls-schedule__day { display: inline-flex; gap: 7px; align-items: center; font-size: 13px; }
.ls-input--time { width: 100%; padding: 5px 8px; }

.ls-repeater { display: flex; flex-direction: column; gap: 6px; }
.ls-repeater__row { display: flex; gap: 6px; align-items: center; }
.ls-repeater__row .ls-input { flex: 1; }
.ls-btn--sm { padding: 4px 10px; font-size: 12.5px; align-self: flex-start; }

/* ── Tables, cards, chips ─────────────────────────────────────────────────*/

.ls-card { border-radius: var(--r-lg); box-shadow: var(--sh-1); }
.ls-card__title { font-size: 14px; font-weight: 620; letter-spacing: -.01em; }

.ls-table { border-radius: var(--r-lg); box-shadow: var(--sh-1); font-size: 13px; }
.ls-table th { font-size: 12px; font-weight: 600; }
.ls-table tbody tr { transition: background .12s var(--ease); }
.ls-table tbody tr:hover { background: var(--surface-2); }
.ls-cell-wrap { max-width: 620px; overflow-wrap: anywhere; }

.ls-chip--level-error { background: var(--danger-soft); color: var(--danger); }
.ls-chip--level-warning { background: var(--warn-soft); color: var(--warn); }
.ls-chip--level-info { background: var(--info-soft); color: var(--info); }
.ls-chip--level-debug { background: var(--surface-3); color: var(--muted); }

.ls-page__head h1 { font-size: 22px; font-weight: 660; letter-spacing: -.02em; }

.ls-btn {
    border-radius: var(--r);
    font-size: 13px;
    transition: all .14s var(--ease);
    box-shadow: var(--sh-1);
}

.ls-btn:hover { box-shadow: var(--sh-2); }
.ls-btn--primary { background: var(--primary); border-color: var(--primary); }
.ls-btn--primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); filter: none; }

.ls-input { border-radius: var(--r); font-size: 13.5px; transition: border-color .14s var(--ease), box-shadow .14s var(--ease); }
.ls-input:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent); }

.ls-modal { border-radius: var(--r-xl); box-shadow: var(--sh-5); }
.ls-modal__head { padding: 16px 20px; }
.ls-modal__body { padding: 20px; }
.ls-modal__foot { padding: 14px 20px; }
.ls-overlay { background: rgba(12, 14, 18, .55); }

.ls-toast { border-radius: var(--r); box-shadow: var(--sh-4); }

@media (max-width: 1100px) {
}

/* ══════════════════════════════════════════════════════════════════════════
   Shell v2: top bar + grouped compact rail
   ══════════════════════════════════════════════════════════════════════════ */

:root { --topbar: 52px; }

.ls-svg { display: block; }

/* Top bar --------------------------------------------------------------- */

.ls-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: var(--topbar);
    flex: none;
    padding: 0 18px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}

.ls-topbar__title { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.ls-topbar__section { font-size: 14px; font-weight: 640; letter-spacing: -.01em; }
.ls-topbar__right { display: flex; align-items: center; gap: 10px; }

.ls-topbar__me {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 10px 3px 3px;
    border-radius: 999px;
    color: var(--text);
    text-decoration: none;
    transition: background .15s var(--ease);
}

.ls-topbar__me:hover { background: var(--surface-2); }
.ls-topbar__name { font-size: 13px; font-weight: 550; }

.ls-topbar__logout {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
    transition: all .15s var(--ease);
}

.ls-topbar__logout:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); }

/* The inbox and split views fill what is left under the bar. */
.ls-main > .ls-inbox,
.ls-main > .ls-split { height: calc(100vh - var(--topbar)); }

/* Channel badge with a real mark ---------------------------------------- */

.ls-channel { gap: 4px; padding: 2px 8px 2px 6px; }
.ls-channel .ls-svg { flex: none; }
.ls-svg--telegram { color: #229ed9; }
.ls-svg--whatsapp { color: #25d366; }
.ls-svg--facebook { color: #0084ff; }
.ls-svg--instagram { color: #c13584; }
.ls-svg--email { color: #ea580c; }
.ls-svg--web { color: var(--info); }

/* Dashboard: live chat lists -------------------------------------------- */


.ls-minilist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }

.ls-minilist__item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px;
    border-radius: 8px;
    color: inherit;
    text-decoration: none;
    transition: background .14s var(--ease);
}

.ls-minilist__item:hover { background: var(--surface-2); }
.ls-minilist__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ls-minilist__name { font-size: 13px; font-weight: 570; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-minilist__sub { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-minilist__side { display: flex; align-items: center; gap: 6px; flex: none; }

.ls-card__link { font-size: 12px; }

/* Settings page ---------------------------------------------------------- */

.ls-settings { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 18px; align-items: start; }

.ls-settings__nav {
    display: flex; flex-direction: column; gap: 2px; position: sticky; top: 0;
    /* Never taller than the screen it sticks to - see .ls-help__side. */
    max-height: calc(100vh - var(--topbar) - 40px);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.ls-settings__tab {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 11px;
    border: 0;
    border-radius: 8px;
    background: none;
    color: var(--text-2);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.ls-settings__tab:hover { background: var(--surface-2); }
.ls-settings__tab.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }

.ls-settings__panel { display: flex; flex-direction: column; gap: 16px; }

.ls-imagegrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }

.ls-imageslot {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--r);
    background: var(--surface-2);
    text-align: center;
}

.ls-imageslot__preview {
    display: grid;
    place-items: center;
    min-height: 68px;
    border-radius: var(--r-sm);
    background: var(--surface);
}

.ls-imageslot__preview img { max-width: 100%; max-height: 60px; object-fit: contain; }
.ls-imageslot__label { font-size: 12px; font-weight: 600; }
.ls-imageslot__hint { font-size: 11px; color: var(--muted); }
.ls-imageslot__actions { display: flex; gap: 6px; justify-content: center; }

.ls-fieldgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.ls-fieldgrid .ls-field--wide { grid-column: 1 / -1; }

.ls-swatch { display: flex; gap: 8px; align-items: center; }
.ls-swatch input[type="color"] { width: 44px; height: 34px; padding: 2px; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--surface); cursor: pointer; }

/* Profile: two balanced columns instead of one tall one ------------------ */

.ls-profile { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.ls-profile__col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

@media (max-width: 1100px) {
    .ls-profile { grid-template-columns: minmax(0, 1fr); }
}
.ls-profile .ls-card { margin: 0; }
.ls-profile__wide { grid-column: 1 / -1; }
.ls-profile__wide { margin-bottom: 16px; }
.ls-profile__head { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.ls-profile__avatar { position: relative; flex: none; }
.ls-profile__avatar .ls-avatar--lg { width: 88px; height: 88px; box-shadow: 0 0 0 1px var(--border); }

/* Presence on the avatar itself, ringed in the card colour so it reads on any face. */
.ls-profile__presence {
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 16px;
    height: 16px;
    box-shadow: 0 0 0 3px var(--surface);
}

.ls-profile__identity { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 6px; }
.ls-profile__identity h2 { margin: 0; font-size: 22px; line-height: 1.2; font-weight: 600; letter-spacing: -.01em; }
.ls-profile__identity .ls-chips { margin-top: 2px; }
.ls-profile__handle { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; margin: 0; font-size: 13.5px; }
.ls-profile__login, .ls-op-login { color: var(--primary); font-weight: 600; overflow-wrap: anywhere; }

.ls-avatar-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; align-self: flex-start; }
.ls-avatar-actions .ls-btn { white-space: nowrap; }

.ls-profile__facts {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px 20px;
    margin: 18px 0 0;
    padding-top: 14px;
    border-top: 1px solid var(--border);
}

.ls-profile__fact { min-width: 0; }
.ls-profile__fact dt { font-size: 12px; color: var(--muted); margin-bottom: 2px; }
.ls-profile__fact dd { margin: 0; font-size: 13.5px; overflow-wrap: anywhere; }
.ls-profile__fact code { font-family: inherit; font-weight: 600; }

@media (max-width: 900px) {
    .ls-profile__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 600px) {
    .ls-profile__head { gap: 14px; }
    .ls-profile__avatar .ls-avatar--lg { width: 68px; height: 68px; font-size: 22px; }
    .ls-profile__identity h2 { font-size: 19px; }
    .ls-avatar-actions { width: 100%; }
    .ls-avatar-actions .ls-btn { flex: 1 1 auto; justify-content: center; min-height: 44px; }
    .ls-profile__facts { gap: 10px 14px; }
}

/* Forms in the profile end in one button, sized to its label. */
.ls-form__foot { display: flex; gap: 8px; justify-content: flex-start; padding-top: 4px; }

/* Sound picker ----------------------------------------------------------- */

.ls-soundrow { display: flex; gap: 8px; align-items: center; }
.ls-soundrow .ls-input { flex: 1; }

@media (max-width: 1000px) {
    .ls-settings { grid-template-columns: minmax(0, 1fr); }
    .ls-settings__nav { flex-direction: row; overflow-x: auto; overflow-y: hidden; position: static; max-height: none; }
}

@media (max-width: 900px) {
    .ls-topbar__name { display: none; }
}

/* Conversation window: search, tags, timeline --------------------------- */

.ls-conv__id { margin-left: 8px; color: var(--muted); font-size: 12px; font-weight: 400; }

.ls-convsearch {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 8px 16px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
}

.ls-convsearch .ls-input { flex: 1; }

.ls-msg.is-match .ls-msg__body {
    outline: 2px solid var(--warn);
    outline-offset: 2px;
    background: var(--warn-soft);
}

.ls-timeline { list-style: none; margin: 0; padding: 0 0 0 6px; display: flex; flex-direction: column; gap: 12px; }

.ls-timeline__item {
    position: relative;
    display: flex;
    gap: 12px;
    padding-left: 16px;
    border-left: 2px solid var(--border);
    font-size: 13px;
}

.ls-timeline__dot {
    position: absolute;
    left: -6px;
    top: 4px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--border-strong);
}

.ls-timeline__dot--created { background: var(--info); }
.ls-timeline__dot--assigned { background: var(--primary); }
.ls-timeline__dot--closed { background: var(--muted); }
.ls-timeline__dot--reopened { background: var(--warn); }
.ls-timeline__dot--rated { background: var(--ok); }
.ls-timeline__dot--transferred { background: var(--warn); }

.ls-card.is-warn { border-color: color-mix(in srgb, var(--warn) 35%, var(--border)); }
.ls-card.is-danger { border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); }
.ls-card__title .ls-badge { margin-left: 8px; }

/* ══════════════════════════════════════════════════════════════════════════
   Service messages and day separators in the transcript
   ══════════════════════════════════════════════════════════════════════════ */

.ls-msg-day {
    display: flex;
    align-items: center;
    gap: 10px;
    align-self: stretch;
    margin: 10px 0 2px;
    color: var(--muted);
    font-size: 11px;
}

.ls-msg-day::before,
.ls-msg-day::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--border);
}

.ls-sysmsg {
    align-self: center;
    display: flex;
    align-items: center;
    gap: 7px;
    max-width: 92%;
    margin: 3px 0;
    padding: 5px 12px;
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--muted);
    font-size: 12px;
    line-height: 1.35;
    text-align: center;
}

.ls-sysmsg__icon { font-size: 12px; line-height: 1; }
.ls-sysmsg__text strong { color: var(--text); font-weight: 600; }
.ls-sysmsg__time { opacity: .7; font-size: 10px; }

.ls-sysmsg__tag {
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--warn-soft);
    color: var(--warn);
    font-size: 10px;
    font-weight: 600;
    white-space: nowrap;
}

.ls-sysmsg--internal {
    background: transparent;
    border: 1px dashed var(--border-strong);
}

/* ══════════════════════════════════════════════════════════════════════════
   Queue filters, toasts, template library
   ══════════════════════════════════════════════════════════════════════════ */

/* Filter tabs ------------------------------------------------------------- */

.ls-tabs {
    gap: 6px;
    padding: 10px;
    background: var(--surface);
}

.ls-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border: 1px solid transparent;
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 12.5px;
    line-height: 1.2;
    cursor: pointer;
    transition: background .13s var(--ease), color .13s var(--ease), border-color .13s var(--ease);
}

/* Inside the queue they are rows in a list, so they fill the width and put
   the count at the end. */

.ls-tab__icon { font-size: 12px; line-height: 1; opacity: .9; }

.ls-tab__count {
    min-width: 20px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--surface-3);
    color: var(--text-2);
    font-size: 11px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.ls-tab:hover { background: var(--surface-3); color: var(--text); }

.ls-tab.is-active {
    background: var(--primary-soft);
    border-color: var(--primary-border);
    color: var(--primary);
    font-weight: 600;
}

.ls-tab.is-active .ls-tab__count { background: var(--primary); color: var(--primary-ink); }

/* A queue with something waiting in it should read as waiting. */
.ls-tab--warn.has-count .ls-tab__count { background: var(--warn); color: #fff; }
.ls-tab--warn.has-count { border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.ls-tab--warn.is-active { background: var(--warn-soft); border-color: var(--warn); color: var(--warn); }

.ls-tab--danger.has-count .ls-tab__count { background: var(--danger); color: #fff; }
.ls-tab--danger.has-count { border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.ls-tab--danger.is-active { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }

.ls-tab--ok.is-active { background: var(--ok-soft); border-color: var(--ok); color: var(--ok); }

/* Queue selector ----------------------------------------------------------
   One row: my conversations, the queue, everything open, and the finished
   folders behind a select. The alarms under it exist only while they count
   something, so a quiet queue costs one line of height. */

.ls-folders {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    border-bottom: 1px solid var(--border);
    background: var(--surface);
}

.ls-seg {
    display: flex;
    gap: 2px;
    padding: 3px;
    border-radius: calc(var(--radius) + 2px);
    background: var(--surface-2);
    border: 1px solid var(--border);
}

.ls-seg__btn,
.ls-seg__more {
    /* Sized by content, not split equally: "Мої 9" and "Відкриті 14" are
       not the same width, and equal thirds truncate the longer one. */
    flex: 1 1 auto;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    height: 30px;
    padding: 0 4px;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-2);
    font: inherit;
    font-size: 12.5px;
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    transition: background .13s var(--ease), color .13s var(--ease), box-shadow .13s var(--ease);
}

.ls-seg__label { overflow: hidden; text-overflow: ellipsis; }

.ls-seg__btn:hover,
.ls-seg__more:hover { background: var(--surface-3); color: var(--text); }

.ls-seg__btn.is-active,
.ls-seg__more.is-active {
    background: var(--surface);
    color: var(--text);
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .08), 0 0 0 1px var(--border);
}

.ls-seg__count {
    flex: none;
    min-width: 18px;
    padding: 1px 5px;
    border-radius: 999px;
    background: var(--surface-3);
    color: var(--text-2);
    font-size: 11px;
    font-weight: 700;
    line-height: 1.35;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.ls-seg__btn--primary.is-active .ls-seg__count { background: var(--primary); color: var(--primary-ink); }

/* Somebody waiting in the queue is the one number that should read as
   urgent from across the room, selected or not. */
.ls-seg__btn--warn.has-count .ls-seg__count { background: var(--warn); color: #fff; }

.ls-seg__more {
    /* A native select is as wide as its longest option. Sized to the option
       actually shown instead, so "Ще" does not squeeze the three folders that
       are used all day; browsers without field-sizing get a fixed width. */
    flex: 0 0 auto;
    field-sizing: content;
    max-width: 40%;
    padding: 0 18px 0 8px;
    justify-content: flex-start;
    overflow: hidden;
    appearance: none;
    -webkit-appearance: none;
    text-overflow: ellipsis;
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
        linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 11px) 13px, calc(100% - 7px) 13px;
    background-size: 4px 4px, 4px 4px;
    background-repeat: no-repeat;
}

.ls-seg__more.is-active { background-color: var(--surface); }

@supports not (field-sizing: content) {
    .ls-seg__more { flex-basis: 58px; }
    .ls-seg__more.is-active { flex-basis: 92px; }
}
.ls-seg__more:focus-visible,
.ls-seg__btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

.ls-folders__alerts { display: flex; flex-wrap: wrap; gap: 6px; }

.ls-alertchip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 4px 3px 10px;
    border: 1px solid transparent;
    border-radius: 999px;
    font: inherit;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background .13s var(--ease), border-color .13s var(--ease);
}

.ls-alertchip__count {
    min-width: 18px;
    padding: 1px 6px;
    border-radius: 999px;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.ls-alertchip--warn { background: var(--warn-soft); color: var(--warn); }
.ls-alertchip--warn .ls-alertchip__count { background: var(--warn); }
.ls-alertchip--danger { background: var(--danger-soft); color: var(--danger); }
.ls-alertchip--danger .ls-alertchip__count { background: var(--danger); }

.ls-alertchip:hover { border-color: currentColor; }
.ls-alertchip.is-active { border-color: currentColor; box-shadow: inset 0 0 0 1px currentColor; font-weight: 600; }

/* Buttons with icons ------------------------------------------------------ */

.ls-btn__icon { font-size: 12px; line-height: 1; }
.ls-btn { display: inline-flex; align-items: center; gap: 6px; }

/* Toasts ------------------------------------------------------------------
   The tinted background is gone. A toast is a notice, not a state the page is
   in, and four full-bleed colours stacked in the corner read as an error log.
   The surface stays neutral, the accent is a bar down the side and the icon,
   and the remaining time is drawn rather than guessed at. */

.ls-toast {
    position: relative;
    align-items: flex-start;
    gap: 10px;
    padding: 11px 13px 13px;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--border-strong);
    color: var(--text);
    box-shadow: 0 10px 28px -12px rgba(16, 24, 40, .38);
    animation: ls-toast-in .18s var(--ease);
}

.ls-toast.is-leaving {
    animation: ls-toast-out .18s var(--ease) forwards;
}

@keyframes ls-toast-in {
    from { opacity: 0; transform: translateY(10px) scale(.98); }
    to { opacity: 1; transform: none; }
}

@keyframes ls-toast-out {
    from { opacity: 1; transform: none; }
    to { opacity: 0; transform: translateX(12px); }
}

/* How long is left, and it stops while the pointer is on the toast - which
   is exactly when somebody is reading it. */
.ls-toast__bar {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 100%;
    transform-origin: left center;
    background: currentColor;
    opacity: .4;
    animation-name: ls-toast-bar;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}

@keyframes ls-toast-bar {
    from { transform: scaleX(1); }
    to { transform: scaleX(0); }
}

@media (prefers-reduced-motion: reduce) {
    .ls-toast, .ls-toast.is-leaving { animation-duration: 1ms; }
}

.ls-toast__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    font-size: 12px;
    font-weight: 700;
    color: #fff;
}

.ls-toast__text { flex: 1 1 auto; font-size: 13px; }

/* The kind shows in the edge and the icon; the text stays readable text. */
.ls-toast--success { border-left-color: var(--ok); }
.ls-toast--success .ls-toast__icon { background: var(--ok); }
.ls-toast--success .ls-toast__bar { color: var(--ok); }

.ls-toast--error { border-left-color: var(--danger); }
.ls-toast--error .ls-toast__icon { background: var(--danger); }

.ls-toast--warn { border-left-color: var(--warn); }
.ls-toast--warn .ls-toast__icon { background: var(--warn); }
.ls-toast--warn .ls-toast__bar { color: var(--warn); }

.ls-toast--info { border-left-color: var(--info); }
.ls-toast--info .ls-toast__icon { background: var(--info); }
.ls-toast--info .ls-toast__bar { color: var(--info); }

.ls-toast__close { opacity: .5; transition: opacity .12s var(--ease); }
.ls-toast__close:hover { opacity: 1; }

/* Canned templates strip -------------------------------------------------- */

.ls-quickbar { align-items: center; }

.ls-quick {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ls-quick--all { font-weight: 600; background: var(--primary-soft); color: var(--primary); border-color: var(--primary-border); }

.ls-quick__count {
    padding: 0 6px;
    border-radius: 999px;
    background: var(--primary);
    color: var(--primary-ink);
    font-size: 10px;
    font-weight: 700;
}

.ls-quick__clip { opacity: .7; font-size: 11px; }

.ls-file--canned {
    background: var(--info-soft);
    border-color: color-mix(in srgb, var(--info) 30%, var(--border));
    color: var(--info);
}

/* Template library modal -------------------------------------------------- */

.ls-lib { display: flex; flex-direction: column; gap: 12px; }

.ls-lib__cats { display: flex; flex-wrap: wrap; gap: 6px; }

.ls-lib__cat {
    padding: 4px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text-2);
    font-size: 12px;
    cursor: pointer;
}

.ls-lib__cat.is-active { background: var(--primary-soft); border-color: var(--primary-border); color: var(--primary); font-weight: 600; }

.ls-lib__list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 46vh;
    overflow-y: auto;
    padding-right: 4px;
}

.ls-lib__item {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    text-align: left;
    cursor: pointer;
    transition: border-color .12s var(--ease), background .12s var(--ease);
}

.ls-lib__item:hover { border-color: var(--primary-border); background: var(--primary-soft); }

.ls-lib__head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.ls-lib__short { color: var(--muted); font-family: var(--mono); font-size: 11px; }
.ls-lib__text { margin: 0; color: var(--text-2); font-size: 12.5px; line-height: 1.45; }
.ls-lib__foot { display: flex; justify-content: flex-end; border-top: 1px solid var(--border); padding-top: 10px; }
.ls-lib__files { display: flex; flex-wrap: wrap; gap: 6px; }

/* ══════════════════════════════════════════════════════════════════════════
   Presence, permissions, passwords, secrets
   ══════════════════════════════════════════════════════════════════════════ */

/* Presence pill ----------------------------------------------------------- */

.ls-status-pill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text-2);
    font-size: 12.5px;
    line-height: 1.2;
    white-space: nowrap;
}

.ls-status-pill.is-button { cursor: pointer; transition: border-color .12s var(--ease), background .12s var(--ease); }
.ls-status-pill.is-button:hover { background: var(--surface-2); border-color: var(--border-strong); }

.ls-status-pill__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border-strong);
    flex: 0 0 auto;
}

.ls-status-pill__caret { font-size: 9px; opacity: .6; }

.ls-status-pill--online { border-color: color-mix(in srgb, var(--ok) 40%, var(--border)); background: var(--ok-soft); color: var(--ok); }
.ls-status-pill--online .ls-status-pill__dot,
.ls-status-pill__dot--online { background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 20%, transparent); }

.ls-status-pill--busy { border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); background: var(--danger-soft); color: var(--danger); }
.ls-status-pill--busy .ls-status-pill__dot,
.ls-status-pill__dot--busy { background: var(--danger); }

.ls-status-pill--away { border-color: color-mix(in srgb, var(--warn) 35%, var(--border)); background: var(--warn-soft); color: var(--warn); }
.ls-status-pill--away .ls-status-pill__dot,
.ls-status-pill__dot--away { background: var(--warn); }

.ls-status-pill--offline .ls-status-pill__dot,
.ls-status-pill__dot--offline { background: var(--muted); }

.ls-status-pill--disabled { background: var(--surface-2); color: var(--muted); text-decoration: line-through; }

.ls-status-menu {
    position: fixed;
    z-index: 220;
    display: flex;
    flex-direction: column;
    min-width: 240px;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    box-shadow: var(--sh-4);
}

.ls-status-menu__item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.ls-status-menu__item:hover { background: var(--surface-2); }
.ls-status-menu__item.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.ls-status-menu__hint { margin-left: auto; color: var(--muted); font-size: 11px; }

/* Operator table ---------------------------------------------------------- */

.ls-cell-stack { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }

.ls-chip--custom {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 1px solid color-mix(in srgb, var(--warn) 40%, var(--border));
    background: var(--warn-soft);
    color: var(--warn);
    cursor: pointer;
    font-weight: 600;
}

.ls-chip--custom:hover { border-color: var(--warn); }

.ls-chip__num { padding: 0 5px; border-radius: 999px; font-size: 10px; font-weight: 700; }
.ls-chip__num.is-grant { background: var(--ok); color: #fff; }
.ls-chip__num.is-revoke { background: var(--danger); color: #fff; }

.ls-chip--grant { background: var(--ok-soft); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, var(--border)); }
.ls-chip--revoke { background: var(--danger-soft); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); }

/* Permission matrix ------------------------------------------------------- */

.ls-perm-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-2);
}

.ls-perm-group h4 {
    margin: 14px 0 6px;
    font-size: 12px;
    color: var(--muted);
}

.ls-perm-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 10px;
    border: 1px solid transparent;
    border-left: 3px solid transparent;
    border-radius: var(--r-sm);
    transition: background .12s var(--ease), border-color .12s var(--ease);
}

.ls-perm-row:hover { background: var(--surface-2); }
.ls-perm-row__label { display: flex; flex-direction: column; gap: 1px; font-size: 13px; }
.ls-perm-row__label code { color: var(--muted); font-family: var(--mono); font-size: 10.5px; }

.ls-perm-row__state {
    margin-left: auto;
    font-size: 11px;
    font-weight: 600;
    color: var(--muted);
    white-space: nowrap;
}

.ls-perm-row.is-on .ls-perm-row__state { color: var(--ok); }

.ls-perm-row.is-grant {
    background: var(--ok-soft);
    border-left-color: var(--ok);
}

.ls-perm-row.is-grant .ls-perm-row__state { color: var(--ok); }

.ls-perm-row.is-revoke {
    background: var(--danger-soft);
    border-left-color: var(--danger);
}

.ls-perm-row.is-revoke .ls-perm-row__state { color: var(--danger); }

/* Just changed, not yet saved. */
.ls-perm-row.is-changed {
    border-color: var(--primary-border);
    animation: ls-perm-flash .5s var(--ease);
}

@keyframes ls-perm-flash {
    from { background: var(--primary-soft); }
    to { background: transparent; }
}

/* Passwords --------------------------------------------------------------- */

.ls-pw__row { display: flex; gap: 6px; align-items: center; }
.ls-pw__row .ls-input { flex: 1 1 auto; font-family: var(--mono); }

.ls-pw__strength { display: flex; align-items: center; gap: 8px; margin-top: 6px; }

.ls-pw__meter {
    flex: 1 1 auto;
    height: 5px;
    border-radius: 999px;
    background: var(--surface-3);
    overflow: hidden;
}

.ls-pw__meter span {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: var(--danger);
    transition: width .18s var(--ease), background .18s var(--ease);
}

.ls-pw__meter[data-score="2"] span { background: var(--warn); }
.ls-pw__meter[data-score="3"] span { background: var(--info); }
.ls-pw__meter[data-score="4"] span { background: var(--ok); }
.ls-pw__meter-label { font-size: 11px; color: var(--muted); min-width: 92px; }

.ls-pw__rules {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
}

.ls-pw__rule { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted); }
.ls-pw__rule.is-ok { color: var(--ok); }
.ls-pw__tick { font-size: 11px; }

.ls-pw__gen {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 8px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-2);
}

.ls-pw__genrow { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-size: 12px; }
.ls-pw__range { flex: 1 1 140px; }
.ls-pw__len { font-family: var(--mono); font-weight: 600; min-width: 22px; text-align: right; }
.ls-pw__opt { display: inline-flex; align-items: center; gap: 5px; }

/* Secrets ----------------------------------------------------------------- */

.ls-secretrow { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.ls-secretrow .ls-input { flex: 1 1 260px; font-family: var(--mono); }

/* ══════════════════════════════════════════════════════════════════════════
   Error log
   ══════════════════════════════════════════════════════════════════════════ */

.ls-table--errors td { vertical-align: top; }
.ls-errrow { cursor: pointer; }
.ls-errrow__when { white-space: nowrap; color: var(--muted); }
.ls-errrow__head { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; }

.ls-errrow__type {
    font-family: var(--mono);
    font-size: 11px;
    color: var(--danger);
    background: var(--danger-soft);
    padding: 1px 6px;
    border-radius: var(--r-sm);
}

.ls-errrow__msg {
    /* One error is one line in the list; the whole text lives in the detail. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    max-width: 720px;
    font-size: 13px;
    line-height: 1.45;
}

.ls-errrow__origin {
    margin-top: 3px;
    font-family: var(--mono);
    font-size: 11px;
    color: var(--muted);
}

.ls-chip--level-error { background: var(--danger-soft); color: var(--danger); }
.ls-chip--level-warning { background: var(--warn-soft); color: var(--warn); }
.ls-chip--level-info { background: var(--info-soft); color: var(--info); }
.ls-chip--level-debug { background: var(--surface-2); color: var(--muted); }

.ls-errdetail { display: flex; flex-direction: column; gap: 14px; }
.ls-errdetail__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

.ls-errdetail__message {
    margin: 0;
    padding: 12px 14px;
    border-left: 3px solid var(--danger);
    border-radius: var(--r-sm);
    background: var(--danger-soft);
    color: var(--text);
    font-size: 13.5px;
    line-height: 1.5;
    overflow-wrap: anywhere;
}

.ls-errdetail__section h4 {
    margin: 0 0 6px;
    font-size: 11px;
    color: var(--muted);
}

.ls-errdetail__origin { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-family: var(--mono); font-size: 12px; }

.ls-errdetail .ls-code {
    max-height: 220px;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.ls-trace {
    display: flex;
    flex-direction: column;
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--r);
}

.ls-trace__toggle { display: inline-flex; align-items: center; gap: 4px; margin-bottom: 8px; font-size: 12px; color: var(--muted); }

.ls-trace__frame {
    display: flex;
    gap: 10px;
    padding: 7px 10px;
    border-bottom: 1px solid var(--border);
    font-size: 12px;
    opacity: .62;
}

.ls-trace__frame:last-child { border-bottom: 0; }
.ls-trace__frame.is-app { opacity: 1; background: var(--primary-soft); }
.ls-trace__index { flex: 0 0 auto; color: var(--muted); font-family: var(--mono); }
.ls-trace__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ls-trace__call { font-family: var(--mono); overflow-wrap: anywhere; }
.ls-trace__file { color: var(--muted); font-family: var(--mono); font-size: 11px; overflow-wrap: anywhere; }

/* ══════════════════════════════════════════════════════════════════════════
   Filter bars and page rhythm - one layout for every list screen
   ══════════════════════════════════════════════════════════════════════════ */

.ls-filters {
    align-items: center;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--sh-1);
}

/* A filter bar is a row of controls, not a stack: inputs size to content
   unless they are the search box, which takes what is left. */
.ls-filters .ls-input { width: auto; min-width: 130px; }
.ls-filters .ls-search { flex: 1 1 220px; min-width: 180px; }
.ls-filters .ls-input--date { min-width: 150px; }
.ls-filters select.ls-input { max-width: 220px; }
.ls-filters .ls-btn { white-space: nowrap; }
.ls-filters .ls-checklist__item { color: var(--text-2); }

.ls-count { margin: -6px 0 12px; font-size: 12px; }

/* Page heads: same spacing and the same alignment on every screen. */
.ls-page__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.ls-page__head h1 { margin: 0 0 2px; font-size: 20px; line-height: 1.25; }
.ls-page__head .ls-muted { margin: 0; font-size: 13px; }
.ls-page__actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* Profile: avatar gallery and personal figures -------------------------- */

.ls-avatar-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
    gap: 8px;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--border);
}

.ls-avatar-gallery__item {
    padding: 0;
    border: 2px solid transparent;
    border-radius: 50%;
    background: none;
    cursor: pointer;
    line-height: 0;
    transition: border-color .12s var(--ease);
}

.ls-avatar-gallery__item img { width: 100%; height: auto; border-radius: 50%; display: block; }
.ls-avatar-gallery__item:hover { border-color: var(--border-strong); }
.ls-avatar-gallery__item:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.ls-avatar-gallery__item.is-active { border-color: var(--primary); }

.ls-stat-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 10px;
}

.ls-stat-tile {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-2);
}

.ls-stat-tile strong { font-size: 19px; line-height: 1.15; font-variant-numeric: tabular-nums; }
.ls-stat-tile span { font-size: 11.5px; color: var(--muted); }
.ls-stat-tile em { font-size: 10.5px; color: var(--muted); font-style: normal; opacity: .8; }

/* Maintenance panel -------------------------------------------------------- */

.ls-maint { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }

.ls-maint__row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    cursor: pointer;
}

.ls-maint__row:hover { border-color: var(--border-strong); background: var(--surface-2); }
.ls-maint__row span { display: flex; flex-direction: column; gap: 2px; }
.ls-maint__row strong { font-size: 13px; font-weight: 600; }
.ls-maint__row em { font-style: normal; font-size: 11.5px; color: var(--muted); }

.ls-hintlist { margin: 8px 0 0; padding-left: 18px; color: var(--text-2); font-size: 13px; line-height: 1.6; }

.ls-yes { color: var(--ok); font-weight: 700; }
.ls-no { color: var(--muted); }

/* ══════════════════════════════════════════════════════════════════════════
   Conversation header: two rows of fixed height that never reflow
   ══════════════════════════════════════════════════════════════════════════ */

.ls-conv__head {
    flex-wrap: wrap;
    row-gap: 8px;
}

.ls-conv__title { flex: 1 1 100%; min-width: 0; }

.ls-conv__title h2 {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 16px;
    line-height: 1.3;
}

.ls-conv__id { color: var(--muted); font-size: 12px; font-weight: 500; }

.ls-conv__actions {
    flex: 1 1 100%;
    justify-content: flex-start;
    align-items: center;
    gap: 6px;
    row-gap: 6px;
}

/* On a wide screen the actions sit beside the title again. */
@media (min-width: 1500px) {
    .ls-conv__title { flex: 1 1 auto; }
    .ls-conv__actions { flex: 0 0 auto; justify-content: flex-end; }
}

.ls-conv__actions .ls-btn { padding: 6px 10px; font-size: 12.5px; }
.ls-conv__actions select.ls-input { padding: 5px 8px; font-size: 12.5px; max-width: 150px; }

/* ══════════════════════════════════════════════════════════════════════════
   Switches: every checkbox in the workspace is a toggle
   ══════════════════════════════════════════════════════════════════════════ */

input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex: 0 0 auto;
    width: 36px;
    height: 20px;
    margin: 0;
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    background: var(--surface-2);
    cursor: pointer;
    transition: background .15s var(--ease), border-color .15s var(--ease);
    vertical-align: middle;
}

input[type="checkbox"]::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--surface);
    box-shadow: 0 1px 2px rgba(16, 24, 40, .3);
    transition: transform .16s var(--ease);
}

input[type="checkbox"]:checked {
    background: var(--primary);
    border-color: var(--primary);
}

input[type="checkbox"]:checked::after { transform: translateX(16px); }
input[type="checkbox"]:disabled { opacity: .5; cursor: default; }
input[type="checkbox"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Radio buttons keep their own shape. */
input[type="radio"] { accent-color: var(--primary); }

/* Rows that pair a switch with its label ---------------------------------- */

.ls-switchgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 8px 16px;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}

.ls-switchrow {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    cursor: pointer;
    transition: border-color .12s var(--ease), background .12s var(--ease);
}

.ls-switchrow:hover { border-color: var(--border-strong); background: var(--surface-2); }
.ls-switchrow__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ls-switchrow__text span { font-size: 13px; }
.ls-switchrow__text em { font-style: normal; font-size: 11.5px; color: var(--muted); line-height: 1.4; }

/* Inline checkboxes elsewhere (filters, checklists) keep a compact row. */
.ls-field--inline,
.ls-checklist__item { display: inline-flex; align-items: center; gap: 8px; }

/* One rhythm for the action row of every settings card -------------------- */

.ls-settings__form { display: block; }

.ls-card--settings { display: flex; flex-direction: column; }
.ls-card--settings .ls-card__title { margin-bottom: 2px; }
.ls-card--settings > .ls-muted { margin: 0 0 16px; }

.ls-page__actions--sticky {
    margin-top: auto;
    padding-top: 16px;
}

.ls-settings__panel .ls-card { min-height: 100%; }

/* ══════════════════════════════════════════════════════════════════════════
   Social mentions
   ══════════════════════════════════════════════════════════════════════════ */

.ls-mentions { display: flex; flex-direction: column; gap: 10px; }

.ls-srcstrip { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }

.ls-src {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    min-width: 220px;
}

.ls-src.is-off { opacity: .55; }
.ls-src.is-error { border-color: var(--danger); background: var(--danger-soft); }

.ls-src__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    flex: 0 0 auto;
    border-radius: 8px;
    background: var(--surface-2);
    font-size: 13px;
    font-weight: 700;
}

.ls-src__body { display: flex; flex-direction: column; min-width: 0; font-size: 12.5px; }
.ls-src__body .ls-muted { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 220px; }

.ls-mention {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--border-strong);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--sh-1);
}

.ls-mention.is-negative { border-left-color: var(--danger); }
.ls-mention.is-positive { border-left-color: var(--ok); }
.ls-mention.is-neutral { border-left-color: var(--border-strong); }

.ls-mention__head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.ls-mention__who { display: flex; flex-direction: column; min-width: 0; margin-right: auto; }
.ls-mention__who strong { font-size: 13.5px; }
.ls-mention__who .ls-muted { font-size: 11.5px; }

.ls-stars { color: #f59e0b; letter-spacing: 1px; font-size: 13px; }

.ls-mention__parent {
    margin: 0;
    padding-left: 10px;
    border-left: 2px solid var(--border);
    color: var(--muted);
    font-size: 12px;
}

.ls-mention__body { margin: 0; font-size: 13.5px; line-height: 1.55; white-space: pre-wrap; }
.ls-mention__keywords { display: flex; flex-wrap: wrap; gap: 5px; }

.ls-mention__reply {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px;
    border-radius: var(--r);
    background: var(--primary-soft);
    font-size: 13px;
}

.ls-mention__reply strong { font-size: 11px; font-weight: 600; color: var(--primary); }
.ls-mention__reply p { margin: 0; }
.ls-mention__reply .ls-muted { font-size: 11px; }

.ls-mention__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.ls-mention__actions .ls-btn { padding: 6px 10px; font-size: 12.5px; }

.ls-mention__quote {
    margin: 0;
    padding: 10px 12px;
    border-left: 3px solid var(--border-strong);
    border-radius: 0 var(--r) var(--r) 0;
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 13px;
    white-space: pre-wrap;
}

.ls-chip--sent-negative { background: var(--danger-soft); color: var(--danger); }
.ls-chip--sent-positive { background: var(--ok-soft); color: var(--ok); }
.ls-chip--sent-neutral { background: var(--surface-2); color: var(--muted); }

.ls-card--hint { display: flex; align-items: center; gap: 14px; padding: 14px 16px; margin-bottom: 14px; }
.ls-card--hint p { margin: 0; color: var(--muted); }

/* Setup notes that are prose, not code: wrap and keep the line height. */
.ls-code--wrap {
    white-space: pre-wrap;
    word-break: break-word;
    font-family: var(--font);
    font-size: 12.5px;
    line-height: 1.6;
    max-height: 220px;
    overflow-y: auto;
}

/* The header is two fixed rows: nothing inside it may change its height, or
   the transcript below jumps every time a tag or a priority is set. */
.ls-conv__head {
    display: block;
    padding: 0;
    flex-wrap: nowrap;
}

.ls-conv__bar {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 52px;
    padding: 0 14px;
}

.ls-conv__title {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
}

.ls-conv__title h2 {
    display: block;
    margin: 0;
    font-size: 15.5px;
    font-weight: 650;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ls-conv__actions {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    flex-wrap: nowrap;
    gap: 4px;
}

.ls-conv__actions .ls-btn { height: 32px; padding: 0 12px; font-size: 12.5px; white-space: nowrap; }
.ls-conv__actions .ls-icon-btn { width: 32px; height: 32px; flex: 0 0 auto; }
.ls-conv__actions .ls-icon-btn.is-active { background: var(--primary-soft); color: var(--primary); }

/* One scrolling meta line, always present so the height is constant. */
.ls-conv__meta {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 34px;
    padding: 0 14px;
    border-top: 1px solid var(--border);
    background: var(--surface-2);
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    white-space: nowrap;
}

.ls-conv__meta::-webkit-scrollbar { display: none; }
.ls-conv__meta > * { flex: 0 0 auto; }
.ls-conv__meta .ls-muted { font-size: 12px; }

.ls-ctxmenu__item.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }

.ls-dot--low { background: var(--muted); }
.ls-dot--normal { background: var(--info); }
.ls-dot--high { background: var(--warn); }
.ls-dot--urgent { background: var(--danger); }

/* ══════════════════════════════════════════════════════════════════════════
   Form controls: one height, one radius, one rhythm - everywhere
   ══════════════════════════════════════════════════════════════════════════ */

:root { --control-h: 38px; }

.ls-input,
select.ls-input,
input.ls-input {
    height: var(--control-h);
    padding: 0 11px;
    font-size: 13.5px;
    line-height: 1.2;
}

/* Multi-line controls grow instead, but keep the same box treatment. */
textarea.ls-input {
    height: auto;
    min-height: 84px;
    padding: 9px 11px;
    line-height: 1.5;
    resize: vertical;
}

/* ── Search fields ──────────────────────────────────────────────────────────
   Every search box in the workspace, styled once.
   They used to be plain text inputs that happened to say "Пошук…" in the
   placeholder, which left them looking like a field to fill in rather than a
   field to search with - and inconsistent with each other besides, since some
   sit in a filter bar and some stand alone in a sidebar. One magnifier, one
   clear button, one set of proportions, wherever they appear. */

input.ls-search {
    /* `flex: 1` alone stretched these vertically in the column-flex sidebars
       of the help and knowledge-base screens: in a column, flex-grow works on
       height. Growing along the row is what was meant. */
    flex: 1 1 auto;

    /* Matched to `input.ls-input` above, which is specific enough to win a
       bare `.ls-search` and would put the text back under the magnifier. */
    padding: 0 11px 0 32px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23667085' stroke-width='1.6' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='4.4'/%3E%3Cpath d='M10.4 10.4 14 14'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 10px center;
    background-size: 15px 15px;
}

/* In a column-flex container there is no row to grow into, and growing would
   stretch the box instead. */
.ls-help__side .ls-search,
.ls-faq__side .ls-search { flex: 0 0 auto; }

/* Next to a page's button the search keeps its own width; growing pushed the
   button onto a line of its own under it. */
.ls-page__actions .ls-search { flex: 0 1 auto; width: 260px; min-width: 160px; }

/* The browser's own clear button is a different shape and size in every
   engine, and invisible in dark mode in some. */
.ls-search::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    margin-left: 4px;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23667085' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M4.5 4.5l7 7M11.5 4.5l-7 7'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 11px 11px;
    opacity: .6;
}

.ls-search::-webkit-search-cancel-button:hover { opacity: 1; }

/* Firefox has no cancel button at all; Escape is the affordance there, so the
   field at least says so. */
.ls-search::placeholder { opacity: .85; }

select.ls-input {
    /* A native arrow renders at a different size in every browser; one drawn
       chevron keeps selects the same width and height as text inputs. */
    appearance: none;
    -webkit-appearance: none;
    padding-right: 32px;
    background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                      linear-gradient(135deg, var(--muted) 50%, transparent 50%);
    background-position: calc(100% - 17px) center, calc(100% - 12px) center;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    cursor: pointer;
}

/* Browsers that draw the open list themselves (Chrome and Firefox on Windows
   and Linux) take the option colours from here. */
select.ls-input option,
select.ls-input optgroup {
    background-color: var(--surface);
    color: var(--text);
}

/* Number spinners change the control width; the value is typed, not spun. */
input.ls-input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input.ls-input[type="number"]::-webkit-outer-spin-button,
input.ls-input[type="number"]::-webkit-inner-spin-button { appearance: none; margin: 0; }

input.ls-input[type="color"] { padding: 3px; width: 46px; }
input.ls-input[type="date"],
input.ls-input[type="time"] { padding-right: 8px; }

.ls-input--slim { height: 30px; padding: 0 9px; font-size: 12.5px; }
.ls-input--time { height: 32px; padding: 0 8px; }

.ls-swatch input[type="color"] { height: var(--control-h); width: 46px; }

/* Field blocks line up on a grid of equal columns, so no row is ragged. */
.ls-fieldgrid {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 14px 18px;
    align-items: start;
}

.ls-field { min-width: 0; }
.ls-field__label {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 18px;
    line-height: 1.3;
}

.ls-field__hint { line-height: 1.4; }

/* Buttons share the control height so a row of mixed controls reads level. */
.ls-btn {
    height: var(--control-h);
    padding: 0 14px;
    font-size: 13.5px;
    line-height: 1;
}

.ls-btn--sm { height: 30px; padding: 0 10px; font-size: 12.5px; }
.ls-icon-btn { width: var(--control-h); height: var(--control-h); }

.ls-filters .ls-input,
.ls-filters .ls-btn { height: var(--control-h); }

/* Readable JSON: key/value pairs and chips instead of a serialised blob. */
.ls-jsonmap { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; margin: 0; font-size: 12.5px; }
.ls-jsonmap dt { color: var(--muted); }
.ls-jsonmap dd { margin: 0; overflow-wrap: anywhere; }
.ls-jsonlist { display: flex; flex-wrap: wrap; gap: 4px; }

.ls-table--diff td { vertical-align: top; font-size: 13px; }
.ls-diff__before { color: var(--muted); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--muted) 45%, transparent); }
.ls-diff__after { color: var(--text); font-weight: 500; }

/* ══════════════════════════════════════════════════════════════════════════
   Themes
   Every palette redefines the same tokens; nothing else in the stylesheet
   needs to know which one is in force.
   ══════════════════════════════════════════════════════════════════════════ */

:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* Deep blue night: same contrast as dark, calmer at 3am. */
:root[data-theme="midnight"] {
    color-scheme: dark;
    --bg: #05080f;
    --surface: #0b111d;
    --surface-2: #111a2a;
    --surface-3: #18233a;
    --border: #18223a;
    --border-strong: #2a3854;
    --text: #dfe6f3;
    --text-2: #a3b0c9;
    --muted: #8391ad;
    --primary: #7f9be0;
    --primary-hover: #9db3e8;
    --primary-soft: #141e36;
    --primary-border: #283a66;
    --rail-bg: #03060c;
    --rail-line: #141d30;
}

/* Warm neutral grey for bright rooms and cheap monitors. */
:root[data-theme="slate"] {
    color-scheme: light;
    --bg: #eceef1;
    --surface: #fbfbfc;
    --surface-2: #f0f1f4;
    --surface-3: #e2e5ea;
    --border: #dcdfe5;
    --border-strong: #b9bfc9;
    --text: #1b1f27;
    --text-2: #414a58;
    --muted: #5c6575;
    --primary: #3f4a63;
    --primary-hover: #333c52;
    --primary-soft: #e6e9ef;
    --primary-border: #c3cad8;
    --rail-bg: #2a303b;
    --rail-active: rgba(255, 255, 255, .12);
    --rail-mark: #c9d1de;
}

/* Maximum separation: for poor lighting and for people who need it. */
:root[data-theme="contrast"] {
    color-scheme: light;
    --bg: #ffffff;
    --surface: #ffffff;
    --surface-2: #f2f2f2;
    --surface-3: #e4e4e4;
    --border: #767676;
    --border-strong: #1a1a1a;
    --text: #000000;
    --text-2: #1a1a1a;
    --muted: #3d3d3d;
    --primary: #0b3ea8;
    --primary-hover: #082e7d;
    --primary-soft: #dce6ff;
    --primary-border: #0b3ea8;
    --danger: #b3001b;
    --ok: #14600f;
    --warn: #7a4a00;
    --info: #0b3ea8;
    --rail-bg: #ffffff;
    --rail-fg: #1a1a1a;
    --rail-strong: #000000;
    --rail-muted: #3d3d3d;
    --rail-line: #1a1a1a;
    --rail-hover: #f2f2f2;
    --rail-active: #dce6ff;
    --rail-field: #ffffff;
    --rail-mark: #0b3ea8;
}

:root[data-theme="contrast"] .ls-card,
:root[data-theme="contrast"] .ls-input,
:root[data-theme="contrast"] .ls-btn { border-width: 2px; }

/*
 * Channel colours per theme.
 *
 * The light set lives with the base palette; the dark themes need their own,
 * because a pale tint that separates a chip from a white card disappears into
 * a near-black one. The contrast theme drops the tints altogether and relies
 * on the border and the text, which is the whole point of that theme.
 */
:root[data-theme="dark"],
:root[data-theme="midnight"] {
    --ch-web-bg: #16223c; --ch-web-fg: #93b4fd;
    --ch-telegram-bg: #102a38; --ch-telegram-fg: #7cc9ec;
    --ch-whatsapp-bg: #10281c; --ch-whatsapp-fg: #5fd39b;
    --ch-meta-bg: #221a3a; --ch-meta-fg: #b49bfa;
    --ch-email-bg: #2c2110; --ch-email-fg: #f2c078;
    --ch-social-bg: #2d1626; --ch-social-fg: #f08ec0;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]):not([data-theme="slate"]):not([data-theme="contrast"]) {
        --ch-web-bg: #16223c; --ch-web-fg: #93b4fd;
        --ch-telegram-bg: #102a38; --ch-telegram-fg: #7cc9ec;
        --ch-whatsapp-bg: #10281c; --ch-whatsapp-fg: #5fd39b;
        --ch-meta-bg: #221a3a; --ch-meta-fg: #b49bfa;
        --ch-email-bg: #2c2110; --ch-email-fg: #f2c078;
        --ch-social-bg: #2d1626; --ch-social-fg: #f08ec0;
    }
}

:root[data-theme="contrast"] {
    --ch-web-bg: #ffffff; --ch-web-fg: #0b3ea8;
    --ch-telegram-bg: #ffffff; --ch-telegram-fg: #0b3ea8;
    --ch-whatsapp-bg: #ffffff; --ch-whatsapp-fg: #14600f;
    --ch-meta-bg: #ffffff; --ch-meta-fg: #4b0082;
    --ch-email-bg: #ffffff; --ch-email-fg: #7a4a00;
    --ch-social-bg: #ffffff; --ch-social-fg: #8a0b52;
}

:root[data-theme="contrast"] .ls-chip { border: 1px solid currentColor; }

/* ══════════════════════════════════════════════════════════════════════════
   Top bar: freshness, connection, theme
   ══════════════════════════════════════════════════════════════════════════ */

.ls-topbar__fresh { color: var(--muted); font-size: 11.5px; white-space: nowrap; }
.ls-topbar__fresh.is-stale { color: var(--warn); }

.ls-topbar__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 1px solid var(--border);
    border-radius: 9px;
    background: var(--surface);
    color: var(--text-2);
    font-size: 14px;
    cursor: pointer;
    transition: background .12s var(--ease), border-color .12s var(--ease);
}

.ls-topbar__icon:hover { background: var(--surface-2); border-color: var(--border-strong); }

.ls-theme-menu {
    position: fixed;
    z-index: 240;
    display: flex;
    flex-direction: column;
    min-width: 190px;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface);
    box-shadow: var(--sh-4);
}

.ls-theme-menu__item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.ls-theme-menu__item:hover { background: var(--surface-2); }
.ls-theme-menu__item.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }

.ls-conn { display: inline-flex; align-items: center; }
.ls-conn__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); }
.ls-conn--slow .ls-conn__dot { background: var(--warn); animation: ls-pulse 1.4s infinite; }
.ls-conn--lost .ls-conn__dot { background: var(--danger); animation: ls-pulse .9s infinite; }

.ls-offline-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 18px;
    background: var(--danger-soft);
    color: var(--danger);
    border-bottom: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
    font-size: 13px;
}

.ls-offline-bar.is-slow { background: var(--warn-soft); color: var(--warn); border-bottom-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.ls-offline-bar__dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; animation: ls-pulse 1s infinite; }
.ls-offline-bar .ls-btn { margin-left: auto; }

/* ══════════════════════════════════════════════════════════════════════════
   Navigation rail and badges
   ══════════════════════════════════════════════════════════════════════════ */

/* Badges: one height, tabular digits, never wider than the rail allows. */
.ls-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-size: 10.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    flex: 0 0 auto;
}

/* ══════════════════════════════════════════════════════════════════════════
   Motion
   Animations are on by default and can be switched off per operator; the
   system-level "reduce motion" preference always wins.
   ══════════════════════════════════════════════════════════════════════════ */

@keyframes ls-fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes ls-slide-in { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: none; } }
@keyframes ls-pop { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }

/*
 * Entrance animations play when a screen is opened, never when it refreshes.
 *
 * Every live screen rebuilds its own DOM on a poll. If the animation lived on
 * the card itself it would replay on each of those rebuilds, and a dashboard
 * that fades and shifts every few seconds is unreadable. The `ls-enter` marker
 * is set on the screen root by ui.js at mount time and removed once the
 * animation has run, so a refresh renders straight into place.
 */
.ls-enter.ls-page { animation: ls-fade-in .18s var(--ease) both; }
.ls-enter .ls-card { animation: ls-fade-in .2s var(--ease) both; }
.ls-enter .ls-list__item { animation: ls-slide-in .16s var(--ease) both; }
.ls-enter .ls-mention { animation: ls-fade-in .18s var(--ease) both; }
.ls-modal { animation: ls-pop .16s var(--ease) both; }

/*
 * A message animates when it arrives, not when the transcript is drawn: the
 * pane is marked ready once its history is on screen, so only what is appended
 * after that point slides in.
 */
.ls-messages.is-ready .ls-msg,
.ls-messages.is-ready .ls-sysmsg { animation: ls-fade-in .16s var(--ease) both; }

.ls-btn, .ls-icon-btn, .ls-tab, .ls-nav__item, .ls-switchrow, .ls-input {
    transition: background .14s var(--ease), color .14s var(--ease),
                border-color .14s var(--ease), box-shadow .14s var(--ease),
                transform .12s var(--ease);
}

.ls-btn:active:not(:disabled) { transform: translateY(1px); }

:root[data-motion-off] *,
:root[data-motion-off] *::before,
:root[data-motion-off] *::after {
    animation-duration: .001ms !important;
    animation-delay: 0ms !important;
    transition-duration: .001ms !important;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}

.ls-permrow { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

/* ══════════════════════════════════════════════════════════════════════════
   Earlier conversations, loaded above the current transcript
   ══════════════════════════════════════════════════════════════════════════ */

.ls-history { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }

.ls-history__btn {
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 30px;
    padding: 0 14px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text-2);
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
}

.ls-history__btn:hover:not(:disabled) { background: var(--surface-2); border-color: var(--border-strong); }
.ls-history__btn:disabled { opacity: .6; cursor: default; }
.ls-history__icon { font-size: 11px; }

.ls-history__item {
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-2);
    overflow: hidden;
}

.ls-history__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
    padding: 9px 12px;
    border: 0;
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 12.5px;
    text-align: left;
    cursor: pointer;
}

.ls-history__head:hover { background: var(--surface-3); }
.ls-history__chevron { color: var(--muted); font-size: 10px; width: 10px; }
.ls-history__body { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; background: var(--surface); }
.ls-history__body .ls-msg { max-width: 88%; }

/* Files waiting to be sent, with a look at what they are. */
.ls-composer__files { display: flex; flex-wrap: wrap; gap: 6px; }

.ls-file--pending {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    max-width: 260px;
    padding: 4px 6px 4px 4px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    font-size: 12px;
}

.ls-file__thumb { width: 28px; height: 28px; object-fit: cover; border-radius: 6px; display: block; }
.ls-file__icon { display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 6px; background: var(--surface-2); }
.ls-file__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px; }
.ls-file__x { border: 0; background: none; color: var(--muted); font-size: 15px; line-height: 1; cursor: pointer; padding: 0 2px; }
.ls-file__x:hover { color: var(--danger); }

/* ══════════════════════════════════════════════════════════════════════════
   Files, block list, knowledge base
   ══════════════════════════════════════════════════════════════════════════ */

.ls-filecell { display: flex; align-items: center; gap: 10px; }
.ls-filecell__thumb { width: 36px; height: 36px; object-fit: cover; border-radius: 8px; flex: 0 0 auto; }

.ls-filecell__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex: 0 0 auto;
    border-radius: 8px;
    background: var(--surface-2);
    font-size: 16px;
}

.ls-filecell strong { font-size: 13px; word-break: break-all; }
.ls-filecell .ls-muted { font-size: 11px; }

.ls-filepreview { display: flex; flex-direction: column; gap: 14px; }
.ls-filepreview img { max-width: 100%; max-height: 50vh; border-radius: var(--r); align-self: center; }

.ls-cell-wrap { max-width: 320px; white-space: normal; }

/* Knowledge base ---------------------------------------------------------- */

.ls-faq { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 18px; align-items: start; }

@media (max-width: 1000px) {
    .ls-faq { grid-template-columns: minmax(0, 1fr); }
}

.ls-faq__side { display: flex; flex-direction: column; gap: 10px; position: sticky; top: 0; }
.ls-faq__cats { display: flex; flex-direction: column; gap: 2px; }

.ls-faq__cat {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--text-2);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.ls-faq__cat:hover { background: var(--surface-2); color: var(--text); }
.ls-faq__cat.is-active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }

/* The category row carries its own edit and delete controls. They stay out of
   the way until the row is hovered or something inside it has keyboard focus,
   so the rail still reads as a filter list rather than as a toolbar. */
.ls-faq__catrow { display: flex; align-items: center; gap: 2px; }
.ls-faq__catrow .ls-faq__cat { flex: 1 1 auto; min-width: 0; }
.ls-faq__catrow .ls-faq__cat > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ls-faq__catactions {
    display: flex;
    gap: 2px;
    opacity: 0;
    transition: opacity .12s ease;
}

.ls-faq__catrow:hover .ls-faq__catactions,
.ls-faq__catrow:focus-within .ls-faq__catactions { opacity: 1; }

.ls-icon-btn--sm { width: 26px; height: 26px; font-size: 13px; flex: 0 0 auto; }

/* Touch has no hover, so the controls are always visible there. */
@media (hover: none) {
    .ls-faq__catactions { opacity: 1; }
}

.ls-faq__list { display: flex; flex-direction: column; gap: 10px; }

.ls-faq__item {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--sh-1);
}

.ls-faq__item header { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.ls-faq__item h3 { margin: 0; font-size: 14.5px; font-weight: 600; margin-right: auto; }
.ls-faq__excerpt { margin: 0; color: var(--text-2); font-size: 13px; line-height: 1.5; }
.ls-faq__item footer { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; font-size: 12px; }

.ls-faq__answer { font-size: 14px; line-height: 1.6; }
.ls-faq__answer p:first-child { margin-top: 0; }
.ls-faq__meta { display: flex; align-items: center; gap: 12px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }

/* ══════════════════════════════════════════════════════════════════════════
   System health
   ══════════════════════════════════════════════════════════════════════════ */

.ls-diag { display: block; }
.ls-diag__stack { display: flex; flex-direction: column; gap: 16px; }

.ls-gauges { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }

.ls-gauge {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--sh-1);
}

.ls-gauge__title { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.ls-gauge__value { font-size: 22px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.ls-gauge__caption { font-size: 11.5px; color: var(--muted); }

.ls-gauge__bar { height: 6px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.ls-gauge__bar span { display: block; height: 100%; border-radius: 999px; background: var(--ok); transition: width .3s var(--ease); }
.ls-gauge.is-warn .ls-gauge__bar span { background: var(--warn); }
.ls-gauge.is-danger .ls-gauge__bar span { background: var(--danger); }
.ls-gauge.is-danger .ls-gauge__value { color: var(--danger); }

.ls-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin-top: 12px; }

/* ── Load over time ─────────────────────────────────────────────────────────
   A row per metric instead of a grid of squares: the current value, the shape
   of the period, the peak and the change, on one line each. Four charts side
   by side made none of those comparable.

   Deliberately not named `.ls-chart` - that belongs to the reports page's bar
   chart, whose `min-width: 560px` and `height: 260px` used to apply here too
   and blew the drawings out of their container entirely. */

.ls-metrics { display: flex; flex-direction: column; gap: 2px; }

.ls-metric {
    display: grid;
    grid-template-columns: minmax(180px, 1.2fr) minmax(0, 1.4fr) auto;
    align-items: center;
    gap: 14px;
    padding: 7px 8px;
    border-radius: var(--radius);
}

.ls-metric:hover { background: var(--surface-2); }

.ls-metric__head { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.ls-metric__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--text-2); }
.ls-metric__value { font-size: 14px; font-variant-numeric: tabular-nums; white-space: nowrap; }

.ls-metric__delta {
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Up is not automatically bad - more open conversations is a busy day, not a
   fault - so the direction is stated and the colour stays neutral-warm. */
.ls-metric__delta.is-up { color: var(--warn); }
.ls-metric__delta.is-down { color: var(--ok); }
.ls-metric__delta.is-flat { color: var(--muted); }

.ls-metric__chart { min-width: 0; }

/* The plot, its scale labels and the crosshair share one positioned box. */
.ls-metric__plot { position: relative; min-width: 0; }
.ls-metric__svg { width: 100%; height: 58px; display: block; }
.ls-metric__grid { stroke: var(--border-strong); stroke-width: .5; stroke-dasharray: 2 3; opacity: .7; }

.ls-metric__axis {
    position: absolute;
    right: 2px;
    padding: 0 3px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    font-size: 10px;
    line-height: 1.3;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

.ls-metric__axis--high { top: 0; }
.ls-metric__axis--low { bottom: 0; }

.ls-metric__marker {
    position: absolute;
    width: 7px;
    height: 7px;
    margin: -4px 0 0 -4px;
    border-radius: 50%;
    background: var(--surface);
    border: 2px solid currentColor;
    pointer-events: none;
}

.ls-metric__tip {
    position: absolute;
    top: -6px;
    z-index: 3;
    padding: 3px 7px;
    border-radius: 5px;
    background: var(--text);
    color: var(--surface);
    font-size: 11px;
    white-space: nowrap;
    pointer-events: none;
    font-variant-numeric: tabular-nums;
}

.ls-metric__peak {
    font-size: 11px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

@media (max-width: 760px) {
    .ls-metric { grid-template-columns: minmax(0, 1fr) auto; }
    .ls-metric__chart { grid-column: 1 / -1; }
}

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

.ls-alert {
    margin: 10px 0 0;
    padding: 9px 12px;
    border-radius: var(--r);
    font-size: 13px;
}

.ls-alert--ok { background: var(--ok-soft); color: var(--ok); }
.ls-alert--danger { background: var(--danger-soft); color: var(--danger); }
.ls-alert--warn { background: var(--warn-soft); color: var(--warn); }
.ls-alert--info { background: var(--info-soft); color: var(--info); }

.ls-query { display: block; max-width: 460px; white-space: pre-wrap; word-break: break-all; font-size: 11.5px; }

.ls-phpinfo { max-height: 60vh; overflow: auto; font-size: 12px; }
.ls-phpinfo table { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
.ls-phpinfo td, .ls-phpinfo th { border: 1px solid var(--border); padding: 4px 7px; word-break: break-word; }
.ls-phpinfo h2 { font-size: 14px; margin: 14px 0 6px; }
.ls-phpinfo img { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   Help centre
   ══════════════════════════════════════════════════════════════════════════ */

.ls-help { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 20px; align-items: start; }

@media (max-width: 1050px) {
    .ls-help { grid-template-columns: minmax(0, 1fr); }
}

.ls-help__side { display: flex; flex-direction: column; gap: 10px; position: sticky; top: 0; }
.ls-help__nav { display: flex; flex-direction: column; gap: 3px; }

.ls-help__link {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 9px 11px;
    border: 1px solid transparent;
    border-radius: var(--r);
    background: none;
    color: var(--text-2);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.ls-help__link:hover { background: var(--surface-2); color: var(--text); }
.ls-help__link.is-active { background: var(--primary-soft); border-color: var(--primary-border); color: var(--primary); }
.ls-help__link strong { display: block; font-size: 13px; font-weight: 600; }
.ls-help__link em { display: block; font-style: normal; font-size: 11.5px; color: var(--muted); line-height: 1.35; margin-top: 2px; }
.ls-help__link.is-active em { color: color-mix(in srgb, var(--primary) 70%, var(--muted)); }
.ls-help__icon { font-size: 15px; line-height: 1.4; }

.ls-help__body {
    padding: 22px 26px;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--sh-1);
    max-width: 860px;
    font-size: 14px;
    line-height: 1.65;
}

.ls-help__body h2 { margin: 0 0 4px; font-size: 19px; }
.ls-help__summary { margin: 0 0 18px; color: var(--muted); }
.ls-help__body p { margin: 0 0 14px; }
.ls-help__list, .ls-help__steps { margin: 0 0 16px; padding-left: 20px; }
.ls-help__list li, .ls-help__steps li { margin-bottom: 7px; }
.ls-help__body .ls-alert { margin: 0 0 16px; }
.ls-help__body .ls-table { margin-bottom: 16px; }
.ls-help__body .ls-table td { vertical-align: top; }

.ls-help__shot { margin: 0 0 18px; }

.ls-help__shot img {
    width: 100%;
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--sh-2);
    display: block;
}

.ls-help__shot figcaption { margin-top: 7px; color: var(--muted); font-size: 12.5px; text-align: center; }

.ls-help-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    margin-left: 8px;
    border-radius: 50%;
    background: var(--surface-2);
    color: var(--muted);
    font-size: 12px;
    font-weight: 700;
    text-decoration: none;
    vertical-align: middle;
}

.ls-help-link:hover { background: var(--primary-soft); color: var(--primary); }

/*
 * The sidebars stick beside the article, so they may never be taller than the
 * screen. The help list is: pinned at the top of a page that scrolled past it,
 * its lower half was out of reach until the very end of the article, and
 * every click on it snapped the list back to its first entry. The list now
 * scrolls on its own, inside the height that is actually visible.
 */
.ls-help__side,
.ls-faq__side { max-height: calc(100vh - var(--topbar) - 40px); }

.ls-help__nav,
.ls-faq__cats { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }

/* A sticky sidebar only makes sense beside the content, never above it. */
@media (max-width: 1050px) {
    .ls-help__side, .ls-faq__side { position: static; max-height: none; }
    .ls-help__nav, .ls-faq__cats { overflow: visible; }
    .ls-help__body { padding: 18px; }
}

/* The help mark sits on the same line as the heading it explains. */
.ls-page__head h1 { display: inline-flex; align-items: center; }
.ls-page__head h1 + .ls-help-link { vertical-align: super; }
.ls-page__head > div > .ls-help-link { margin-left: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   Conversation register: row selection and the mass action bar
   ══════════════════════════════════════════════════════════════════════════ */

/*
 * Every checkbox in the workspace is a toggle switch, which is right for a
 * setting and wrong for a table: forty sliders in a column read as forty
 * settings. Row selection gets a plain square box back.
 */
.ls-check[type="checkbox"] {
    width: 16px;
    height: 16px;
    border-radius: 4px;
    background: var(--surface);
    border: 1px solid var(--border-strong);
}

.ls-check[type="checkbox"]::after {
    top: 1px;
    left: 4px;
    width: 4px;
    height: 8px;
    border: solid var(--surface);
    border-width: 0 2px 2px 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    opacity: 0;
    transform: rotate(45deg);
    transition: opacity .12s var(--ease);
}

.ls-check[type="checkbox"]:checked::after { opacity: 1; transform: rotate(45deg); }

.ls-table--select .ls-table__check { width: 36px; text-align: center; padding-right: 0; }
/* A selected row is marked by a rail, not a wash: a tinted row would swallow
   the channel and priority chips it contains. */
.ls-table--select tbody tr.is-selected { background: var(--surface-2); }
.ls-table--select tbody tr.is-selected td:first-child { box-shadow: inset 3px 0 0 var(--primary); }

/* Chips for the states the register shows that the inbox never did. */
.ls-chip--status-bot { background: var(--primary-soft); color: var(--primary); }
.ls-chip--status-on_hold { background: var(--warn-soft); color: var(--warn); }
.ls-chip--status-archived { background: var(--surface-3); color: var(--muted); }
.ls-chip--normal { background: var(--surface-3); color: var(--muted); }

/*
 * The action bar keeps a fixed height whether it holds two buttons or seven,
 * so revealing it never pushes the table down by a different amount.
 */
.ls-bulkbar {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 52px;
    margin-bottom: 12px;
    padding: 7px 14px;
    border: 1px solid var(--primary);
    border-radius: var(--r);
    background: var(--primary-soft);
}

.ls-bulkbar[hidden] { display: none; }
.ls-bulkbar__count { font-size: 13px; font-weight: 600; color: var(--primary); white-space: nowrap; }
.ls-bulkbar__actions { display: flex; flex-wrap: wrap; gap: 8px; flex: 1; }
.ls-bulkbar .ls-btn { background: var(--surface); }
.ls-btn--ghost { border-color: transparent; background: transparent; color: var(--muted); }
.ls-btn--ghost:hover { background: var(--surface-2); color: var(--text); }

/* A summary on the left, the action on the right: the button keeps its place
   whether the summary is one word or a sentence. */
.ls-page__actions--split { justify-content: space-between; width: 100%; margin-top: 14px; }

.ls-topbar__burger { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   Top bar: brand, breadcrumb and the two control clusters
   ══════════════════════════════════════════════════════════════════════════ */

.ls-topbar__title { align-items: center; gap: 12px; }

/* The brand belongs to the rail on a wide screen and to the header on a phone. */
.ls-topbar__brand {
    display: none;
    align-items: center;
    gap: 8px;
    min-width: 0;
    color: var(--text);
    text-decoration: none;
    font-weight: 700;
    font-size: 14px;
    letter-spacing: -.01em;
}

.ls-topbar__logo { flex: 0 0 auto; max-width: 22px; max-height: 22px; border-radius: 5px; object-fit: contain; }
.ls-topbar__logo--mark { color: var(--primary); font-size: 16px; }

/* Where you are, as an icon plus a name rather than a bare word. */
.ls-topbar__crumb { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ls-topbar__crumb-icon { display: grid; place-items: center; color: var(--muted); }
.ls-topbar__section { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/*
 * Two clusters on the right, separated by a hairline: what the workspace is
 * doing (connection, theme) and who is doing it (presence, profile, exit).
 * Grouping them stops the bar reading as five unrelated buttons in a row.
 */
.ls-topbar__tools {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-right: 12px;
    border-right: 1px solid var(--border);
}

.ls-topbar__identity { display: flex; align-items: center; gap: 10px; }

/* ══════════════════════════════════════════════════════════════════════════
   Mailbox: list and reader side by side, stacked on a phone
   ══════════════════════════════════════════════════════════════════════════ */

.ls-mail__toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-bottom: 12px; }
.ls-mail__toolbar .ls-search { flex: 1 1 240px; max-width: 420px; }
.ls-mail__toolbar .ls-pill.is-active { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); font-weight: 600; }

/*
 * Fixed proportions and independent scrolling: opening a long letter must not
 * push the list out of view, and a long list must not move the letter.
 */
.ls-mail {
    display: grid;
    grid-template-columns: minmax(280px, 380px) minmax(0, 1fr);
    gap: 14px;
    height: calc(100vh - var(--topbar) - 190px);
    min-height: 420px;
}

.ls-mail__list,
.ls-mail__reader {
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--r-lg, 12px);
    background: var(--surface);
}

.ls-mail__reader { padding: 18px 22px; }
.ls-mail__items { margin: 0; padding: 0; list-style: none; }

.ls-mail__item {
    display: flex;
    flex-direction: column;
    gap: 3px;
    width: 100%;
    padding: 10px 14px;
    border: 0;
    border-bottom: 1px solid var(--border);
    border-left: 3px solid transparent;
    background: none;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.ls-mail__item:hover { background: var(--surface-2); }
.ls-mail__item.is-active { background: var(--primary-soft); border-left-color: var(--primary); }
.ls-mail__row { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.ls-mail__from { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.ls-mail__time { flex: 0 0 auto; color: var(--muted); font-size: 11.5px; }
.ls-mail__subject { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-2); font-size: 12.5px; }

/* Unread is weight, not colour: it has to survive every theme. */
.ls-mail__item.is-unread .ls-mail__from,
.ls-mail__item.is-unread .ls-mail__subject { font-weight: 650; color: var(--text); }

.ls-mail__head { padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--border); }
.ls-mail__title { margin: 0 0 10px; font-size: 17px; line-height: 1.35; overflow-wrap: anywhere; }
.ls-mail__head .ls-facts { grid-template-columns: 72px minmax(0, 1fr); }
.ls-mail__back { display: none; margin-bottom: 8px; }
.ls-mail__files { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }

.ls-mail__body {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text);
}

@media (max-width: 900px) {
    /* One pane at a time: the list, or the letter that was opened from it. */
    .ls-mail { grid-template-columns: minmax(0, 1fr); height: auto; min-height: 0; }
    .ls-mail__list, .ls-mail__reader { max-height: none; }
    .ls-mail__reader:not(.is-open) { display: none; }
    .ls-mail:has(.ls-mail__reader.is-open) .ls-mail__list { display: none; }
    .ls-mail__back { display: inline-flex; }
    .ls-mail__reader { padding: 14px; }
}

/* Sign-in page: brand, the optional subtitle and notice, and the credit line. */
.ls-login__logo { display: block; max-width: 56px; max-height: 56px; margin: 0 auto 12px; object-fit: contain; }
.ls-login__subtitle { margin: -6px 0 16px; color: var(--muted); text-align: center; }
.ls-login__notice { margin: 0 0 14px; }
.ls-login__credit { margin: 18px 0 0; color: var(--muted); font-size: 12px; text-align: center; }

/* The author credit, wherever it appears. Understated by default and only
   obviously a link once somebody looks for one. */
.ls-credit-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    color: inherit;
    text-decoration: none;
    opacity: .75;
    transition: opacity .15s var(--ease), background-color .15s var(--ease), color .15s var(--ease);
}

.ls-credit-link:hover,
.ls-credit-link:focus-visible {
    opacity: 1;
    color: var(--primary);
    background: var(--primary-soft);
}

.ls-credit-link__mark { font-size: 10px; line-height: 1; }

@media (max-width: 768px) {
    .ls-topbar__burger { display: inline-flex; }

    /* Give the narrow screen back every pixel the chrome does not need. */
    .ls-page { padding: 12px; }
    .ls-topbar { padding: 0 10px; }
    .ls-topbar__name, .ls-topbar__fresh { display: none; }

    /*
     * The header on a phone: the drawer button, the brand, and the identity
     * controls. The section name is dropped - the page below already carries
     * it as a heading, and squeezing it in here only produced an ellipsis.
     */
    .ls-topbar__title { min-width: 0; gap: 8px; }
    .ls-topbar__crumb { display: none; }
    .ls-topbar__brand { display: flex; }
    .ls-topbar__brand-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .ls-topbar__right { gap: 6px; }
    .ls-topbar__tools { padding-right: 0; border-right: 0; }
    .ls-topbar__identity { gap: 4px; }

    /* Presence stays visible as a colour, without the word that will not fit. */
    .ls-status-pill__label, .ls-status-pill__caret { display: none; }
    .ls-status-pill.is-button { padding: 6px; }
    .ls-topbar__me { padding: 3px; }
    .ls-page__head { flex-wrap: wrap; gap: 10px; }
    .ls-filters { gap: 6px; }
    .ls-filters .ls-input { flex: 1 1 140px; min-width: 0; }
    .ls-stat-tiles, .ls-gauges { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }

    /* Wide tables scroll inside themselves instead of stretching the page. */
    .ls-table-host { overflow-x: auto; }
    .ls-table { min-width: 620px; }
}

/* A phone narrower than the counters leaves the brand two letters and a dot. */
@media (max-width: 420px) {
    .ls-topbar__brand-name { display: none; }
}

/* ── Visitors on the site ───────────────────────────────────────────────── */

/* A row that is information, not a link to somewhere. */
.ls-minilist__item.is-static { cursor: default; }
.ls-minilist__item.is-static:hover { background: none; }

.ls-visitor-dot {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    margin: 0 4px;
    border-radius: 50%;
    background: var(--info);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--info) 18%, transparent);
}

/* Somebody already talking to us is a different kind of presence. */
.ls-visitor-dot.is-chatting {
    background: var(--ok);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 18%, transparent);
}

.ls-card--browsing .ls-minilist__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Where the visitor is at this moment, inside the conversation panel. */
.ls-nowpage {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 10px 0 0;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-2);
    font-size: 12.5px;
    line-height: 1.5;
}

.ls-nowpage .ls-visitor-dot { margin-top: 5px; }
.ls-nowpage__text { min-width: 0; overflow-wrap: anywhere; }

/*
 * The footprint reads as "page, then when": the rule that spaced the two only
 * matched adjacent spans, so a linked page title sat flush against its time.
 */
.ls-footprint li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 8px;
}

.ls-footprint li > :first-child { min-width: 0; overflow-wrap: anywhere; }
.ls-footprint li > .ls-muted { margin-left: auto; white-space: nowrap; font-size: 11.5px; }

/* ── Report filters ─────────────────────────────────────────────────────── */

/*
 * Thirteen filters is a panel, not a row. They wrap into a grid of fixed
 * columns so the controls line up on every screen and adding one more never
 * shifts the ones already there.
 */
.ls-filters--report {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(165px, 1fr));
    align-items: end;
    gap: 10px 12px;
}

.ls-filters--report .ls-input { width: 100%; }
.ls-filters--report .ls-field--inline { grid-column: 1 / -1; }
.ls-filters--report .ls-btn { width: 100%; }

.ls-chips--presets { gap: 6px; margin-bottom: 10px; }
.ls-chips--presets .ls-pill.is-active { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); font-weight: 600; }

/* An orientation note: where the rest of a scattered setting group lives. */
.ls-orient {
    position: relative;
    margin: 0 0 18px;
    padding: 12px 14px;
    border: 1px solid var(--primary-border, var(--border));
    border-radius: var(--r);
    background: var(--primary-soft);
    font-size: 12.5px;
    line-height: 1.55;
}

.ls-orient p { margin: 0 0 8px; }
.ls-orient ul { margin: 0; padding-left: 18px; }
.ls-orient li + li { margin-top: 4px; }
.ls-orient .ls-help-link { position: absolute; top: 10px; right: 10px; }

/* Several jumps from one help section, wrapping on a narrow screen. */
.ls-help__links { display: flex; flex-wrap: wrap; gap: 8px; }

/* ── Command console ──────────────────────────────────────────────────────
 *
 * Each command is a card: what it does, the parameters it needs and one
 * button. The equivalent CLI line stays visible underneath, so the screen
 * teaches the command rather than hiding it - somebody who does get shell
 * access later already knows what to type.
 */
.ls-cmdgroup { margin-top: 18px; }

.ls-cmdgroup__title {
    margin: 0 0 8px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-3, var(--text-2));
}

.ls-cmd {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    margin-bottom: 10px;
    border: 1px solid var(--border);
    border-radius: var(--r-md, 10px);
    background: var(--surface);
}

.ls-cmd--danger { border-color: var(--danger-soft, var(--border)); }

.ls-cmd__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
}

.ls-cmd__head > div { min-width: 0; flex: 1 1 320px; }
.ls-cmd__title { margin: 0 0 2px; font-size: 14px; font-weight: 600; }
.ls-cmd__head .ls-muted { margin: 0; font-size: 13px; line-height: 1.45; }

.ls-cmd__fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 10px;
}

.ls-cmd__cli {
    display: block;
    padding: 6px 8px;
    border-radius: var(--r-sm);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 12px;
    overflow-x: auto;
}

.ls-cmdout.is-ok { border-left: 3px solid var(--ok, var(--primary)); }
.ls-cmdout.is-fail { border-left: 3px solid var(--danger); }

.ls-code--output {
    max-height: 420px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 12.5px;
    line-height: 1.5;
}

/* ── Channel diagnostics ──────────────────────────────────────────────────
 *
 * A findings list, not a table: each row is one boundary on the inbound path,
 * and the row that failed carries the instruction that fixes it. The status
 * glyph is what actually distinguishes them - colour alone would not survive
 * a colour-blind reader or a printed screenshot.
 */
.ls-setup__diag { margin-top: 10px; }

.ls-checks { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.ls-check {
    display: flex;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--surface);
}

.ls-check__mark {
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    font-size: 12px;
    font-weight: 700;
    background: var(--surface-2);
    color: var(--text-2);
}

.ls-check--ok .ls-check__mark { background: var(--ok-soft, var(--surface-2)); color: var(--ok, var(--primary)); }
.ls-check--warn .ls-check__mark { background: var(--warn-soft, var(--surface-2)); color: var(--warn, var(--text)); }
.ls-check--fail .ls-check__mark { background: var(--danger-soft, var(--surface-2)); color: var(--danger); }

.ls-check--fail { border-color: var(--danger-soft, var(--border)); }

.ls-check__body { min-width: 0; flex: 1 1 auto; }
.ls-check__body > strong { display: block; font-size: 13px; }
.ls-check__body > p { margin: 3px 0 0; font-size: 13px; line-height: 1.45; color: var(--text-2); word-break: break-word; }

.ls-check__fix {
    margin-top: 6px !important;
    padding: 6px 8px;
    border-radius: var(--r-sm);
    background: var(--surface-2);
    color: var(--text) !important;
}

.ls-facts--tight { margin: 8px 0 0; font-size: 12px; }
.ls-facts--tight dd { word-break: break-all; }

.ls-setup__events { margin-top: 14px; }
.ls-setup__events summary { cursor: pointer; font-size: 13px; color: var(--text-2); }
.ls-setup__events summary:hover { color: var(--text); }
.ls-setup__events .ls-table { margin-top: 8px; font-size: 12px; }

.ls-setup__secret { display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap; }
.ls-setup__secret .ls-code-wrap { flex: 1 1 260px; min-width: 0; }

/* Header counters: operators online, unread messages -------------------- */

.ls-topbar__stats { display: flex; align-items: center; gap: 6px; }

.ls-topbar__stat {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 28px;
    padding: 0 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text-2);
    font-size: 12px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.ls-topbar__stat-value { font-variant-numeric: tabular-nums; color: var(--text); }
.ls-topbar__stat-label { font-weight: 500; color: var(--muted); }
.ls-topbar__stat-icon { display: inline-flex; color: var(--ok); }
.ls-topbar__stat-icon svg { width: 13px; height: 13px; }

.ls-topbar__stat.is-danger { border-color: var(--danger); background: var(--danger-soft); }
.ls-topbar__stat.is-danger .ls-topbar__stat-icon { color: var(--danger); }
.ls-topbar__stat.is-danger .ls-topbar__stat-value,
.ls-topbar__stat.is-danger .ls-topbar__stat-label { color: var(--danger); }

.ls-topbar__stat.is-info { border-color: var(--primary-border); background: var(--primary-soft); color: var(--primary); }
.ls-topbar__stat.is-info .ls-topbar__stat-value { color: var(--primary); }
.ls-topbar__stat.is-info:hover { border-color: var(--primary); }

/* The words go first when the header gets tight; the numbers stay. */
@media (max-width: 1100px) {
    .ls-topbar__stat-label { display: none; }
}

/* The counters open a panel, so they are buttons. */
button.ls-topbar__stat,
button.ls-topbar__bell { border-style: solid; font-family: inherit; cursor: pointer; }
button.ls-topbar__bell { border: 0; }
button.ls-topbar__stat:hover { border-color: var(--primary-border); }
button.ls-topbar__stat:focus-visible,
button.ls-topbar__bell:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Who is behind the counters - see openPresencePanel(). */
.ls-pop {
    position: fixed;
    z-index: 220;
    display: flex;
    flex-direction: column;
    width: min(360px, calc(100vw - 16px));
    max-height: min(70vh, 560px);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--sh-4);
    color: var(--text);
    font-size: 13px;
}

.ls-pop__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
}

.ls-pop__close {
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--muted);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.ls-pop__close:hover { background: var(--surface-2); color: var(--text); }

.ls-pop__body { overflow-y: auto; padding: 6px; }
.ls-pop__empty { margin: 0; padding: 14px 8px; color: var(--muted); }

.ls-pop__operator { padding: 6px; }
.ls-pop__operator + .ls-pop__operator { border-top: 1px solid var(--border); }

.ls-pop__who { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ls-pop__name { flex: 1; min-width: 0; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.ls-pop__status { display: inline-flex; align-items: center; gap: 5px; color: var(--muted); font-size: 12px; white-space: nowrap; }

.ls-pop__load {
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 11.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.ls-pop__load.is-full { background: var(--warn-soft); color: var(--warn); }

.ls-pop__chats { display: flex; flex-direction: column; margin-top: 4px; }
.ls-pop__operator .ls-pop__chats { margin-left: 32px; }

.ls-pop__chat {
    display: flex;
    align-items: center;
    gap: 7px;
    min-height: 32px;
    padding: 4px 8px;
    border-radius: var(--r-sm);
    color: var(--text);
    text-decoration: none;
}

.ls-pop__chat:hover { background: var(--surface-2); }
.ls-pop__chat:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.ls-pop__chat-icon { display: inline-flex; color: var(--muted); }
.ls-pop__chat-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-pop__chat-time { color: var(--muted); font-size: 11.5px; white-space: nowrap; }
.ls-pop__chat.is-overdue .ls-pop__chat-time { color: var(--danger); font-weight: 600; }

.ls-pop__unread {
    min-width: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--primary);
    color: var(--primary-ink);
    font-size: 11px;
    font-weight: 700;
    text-align: center;
}

.ls-pop__tag {
    max-width: 120px;
    overflow: hidden;
    padding: 1px 6px;
    border-radius: var(--r-sm);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 11px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ls-pop__none { margin: 2px 0 0 40px; color: var(--muted); font-size: 12px; }

.ls-pop__more {
    display: block;
    margin: 6px 2px 2px;
    padding: 8px;
    border-radius: var(--r-sm);
    color: var(--primary);
    font-weight: 600;
    text-align: center;
    text-decoration: none;
}

.ls-pop__more:hover { background: var(--primary-soft); }

@media (max-width: 600px) {
    .ls-pop { right: 8px !important; }
    .ls-pop__chat { min-height: 44px; }
}

/* The offline bar also covers busy and away - tinted by what it says. */
.ls-onlinebar[data-status="busy"] .ls-onlinebar__dot,
.ls-onlinebar[data-status="away"] .ls-onlinebar__dot { background: var(--warn); }


/* A correction the customer never received ------------------------------ */

.ls-msg--edit-failed { box-shadow: inset 3px 0 0 var(--danger); }

.ls-msg__alert {
    margin-top: 8px;
    padding: 8px 10px;
    border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
    border-radius: var(--radius);
    background: var(--danger-soft);
    color: var(--danger);
    font-size: 12.5px;
    line-height: 1.45;
}

/* What an edit changed -------------------------------------------------- */

.ls-diff {
    margin-top: 8px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface-2);
    font-size: 12.5px;
}

.ls-diff--contact { border-color: var(--warn); background: var(--warn-soft); }

.ls-diff__head {
    padding: 5px 10px;
    color: var(--text-2);
    font-weight: 600;
    cursor: pointer;
    user-select: none;
}

.ls-diff__body {
    padding: 0 10px 8px;
    color: var(--text-2);
    line-height: 1.55;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.ls-diff__del {
    background: color-mix(in srgb, var(--danger) 14%, transparent);
    color: var(--danger);
    text-decoration: line-through;
    border-radius: 3px;
}

.ls-diff__ins {
    background: color-mix(in srgb, var(--ok) 16%, transparent);
    color: var(--ok);
    text-decoration: none;
    border-radius: 3px;
}

/* Library picker tabs --------------------------------------------------- */

.ls-picker__tabs {
    display: flex;
    gap: 2px;
    margin-bottom: 10px;
    padding: 3px;
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) + 2px);
    background: var(--surface-2);
}

.ls-picker__tabs[hidden] { display: none; }

.ls-picker__tab {
    flex: 1 1 0;
    height: 30px;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-2);
    font: inherit;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
}

.ls-picker__tab:hover { background: var(--surface-3); color: var(--text); }

.ls-picker__tab.is-active {
    background: var(--surface);
    color: var(--text);
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .08), 0 0 0 1px var(--border);
}

/* Media and its caption as one bubble ----------------------------------- */

.ls-msg__body--media { padding: 6px; }
.ls-msg__body--media .ls-msg__files { margin-top: 0; flex-direction: column; align-items: flex-start; gap: 6px; }
.ls-msg__caption { padding: 6px 7px 2px; }
.ls-msg__caption p { margin: 0 0 .5em; }
.ls-msg__caption p:last-child { margin-bottom: 0; }

/* A picture or a sticker with nothing under it needs no bubble around it. */
.ls-msg__body--media.is-bare:has(> .ls-msg__files > .ls-sticker:only-child) {
    padding: 0;
    border-color: transparent;
    background: transparent;
    box-shadow: none;
}

/* Inside the bubble the cards drop their own frame: one frame per message. */
.ls-msg__body--media .ls-audio {
    width: 100%;
    min-width: 240px;
    max-width: 360px;
    padding: 6px 8px;
    border: 0;
    background: color-mix(in srgb, var(--surface) 70%, transparent);
}

.ls-audio__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.ls-audio__head .ls-media__time { font-size: 11px; font-variant-numeric: tabular-nums; }

.ls-msg__body--media .ls-thumb,
.ls-msg__body--media .ls-media { border: 0; }
.ls-msg__body--media .ls-thumb { max-width: 280px; }

.ls-msg__body--media .ls-file {
    width: 100%;
    max-width: 360px;
    border-color: transparent;
    background: color-mix(in srgb, var(--surface) 70%, transparent);
}

/* A document in the transcript: the extension as a coloured badge, name and
   size beside it. */
.ls-msg__files .ls-file { max-width: 360px; min-width: 0; }
.ls-msg__files .ls-file__meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.ls-msg__files .ls-file__name { max-width: none; font-weight: 600; }
.ls-msg__files .ls-file__icon { flex: none; width: 34px; height: 34px; font-size: 9.5px; font-weight: 700; letter-spacing: .02em; }

.ls-file__icon--pdf { --file-hue: #e5484d; }
.ls-file__icon--doc { --file-hue: #3e63dd; }
.ls-file__icon--sheet { --file-hue: #30a46c; }
.ls-file__icon--archive { --file-hue: #d9822b; }
.ls-file__icon--image,
.ls-file__icon--media { --file-hue: #8e4ec6; }

.ls-msg__files .ls-file__icon[class*="ls-file__icon--"]:not(.ls-file__icon--other) {
    color: var(--file-hue);
    background: color-mix(in srgb, var(--file-hue) 14%, transparent);
}

/* Composer toolbar that fits its column ---------------------------------
   The row did not wrap, so in a narrow conversation column (a laptop with
   the customer panel open) "Надіслати" ended up over the side panel. It now
   wraps, the note toggle never breaks into two lines, Send stays at the
   right edge, and below ~620px of conversation width the two labelled tools
   drop their words and keep their icons (the title still says what they do). */

.ls-conv { container: conv / inline-size; }

.ls-composer__row { flex-wrap: wrap; row-gap: 6px; min-width: 0; }
.ls-composer__toggle { flex: none; white-space: nowrap; }
.ls-composer__send { margin-left: auto; flex: none; }

@container conv (max-width: 620px) {
    .ls-composer__row .ls-btn__text { display: none; }
    .ls-composer__row .ls-btn { padding-inline: 10px; }
}

/* An unsent draft in the conversation list. */
.ls-list__draft {
    display: inline-flex;
    align-items: center;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--warn-soft);
    color: var(--warn);
    font-size: 10.5px;
    font-weight: 600;
}

.ls-list__draft[hidden] { display: none; }

/* Replies: the quote in the bubble and the target above the composer ----- */

.ls-quote {
    display: flex;
    flex-direction: column;
    gap: 1px;
    width: 100%;
    margin: 0 0 6px;
    padding: 5px 9px;
    border: 0;
    border-left: 3px solid var(--primary);
    border-radius: 6px;
    background: color-mix(in srgb, var(--primary) 8%, transparent);
    color: inherit;
    font: inherit;
    font-size: 12.5px;
    line-height: 1.35;
    text-align: left;
    cursor: pointer;
}

.ls-quote:hover { background: color-mix(in srgb, var(--primary) 14%, transparent); }
.ls-quote--visitor { border-left-color: var(--ok); background: color-mix(in srgb, var(--ok) 9%, transparent); }
.ls-quote.is-missing { cursor: default; border-left-color: var(--border-strong); background: var(--surface-2); }
.ls-quote.is-deleted .ls-quote__text { text-decoration: line-through; }
.ls-quote__who { font-weight: 650; color: var(--text); }
.ls-quote__text {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    color: var(--text-2);
}

.ls-msg__body--media .ls-quote { margin: 2px 2px 6px; width: auto; }

.ls-msg.is-flash .ls-msg__body { animation: ls-flash 1.5s var(--ease); }

@keyframes ls-flash {
    0%, 30% { box-shadow: 0 0 0 3px var(--primary); }
    100% { box-shadow: 0 0 0 0 transparent; }
}

.ls-composer__reply {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 8px;
    padding: 6px 8px 6px 10px;
    border-left: 3px solid var(--primary);
    border-radius: var(--radius);
    background: var(--primary-soft);
    font-size: 12.5px;
}

.ls-composer__reply[hidden] { display: none; }
.ls-composer__reply-icon { color: var(--primary); font-size: 15px; }
.ls-composer__reply-body { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.ls-composer__reply-body strong { color: var(--primary); font-weight: 650; }
.ls-composer__reply-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-2); }
.ls-composer__reply-x { border: 0; background: none; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; }
.ls-composer__reply-x:hover { color: var(--danger); }

/* A deleted message is struck through, but its edit history stays readable. */
.ls-msg--deleted .ls-diff { opacity: 1; text-decoration: none; }

/* Changelog (System health → Changelog) --------------------------------- */

.ls-changelog { display: flex; flex-direction: column; gap: 14px; max-width: 900px; }
.ls-changelog__lead { margin: 0; }

.ls-changelog__release { padding: 18px 20px; }
.ls-changelog__release.is-current { border-color: var(--primary-border); box-shadow: 0 0 0 1px var(--primary-border); }

.ls-changelog__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.ls-changelog__head h2 { margin: 0; font-size: 18px; font-variant-numeric: tabular-nums; }
.ls-changelog__head time { margin-left: auto; font-size: 12.5px; }

.ls-changelog__section { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 10px; padding: 8px 0; border-top: 1px solid var(--border); }
.ls-changelog__section:first-of-type { border-top: 0; }
.ls-changelog__section ul { margin: 0; padding-left: 18px; }
.ls-changelog__section li { margin: 3px 0; line-height: 1.5; }
.ls-changelog__section code { padding: 1px 5px; border-radius: 4px; background: var(--surface-2); font-family: var(--mono); font-size: 12px; }

.ls-changelog__type {
    align-self: start;
    justify-self: start;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 11px;
    font-weight: 700;
}

.ls-changelog__type--added { background: var(--ok-soft); color: var(--ok); }
.ls-changelog__type--changed { background: var(--info-soft); color: var(--info); }
.ls-changelog__type--fixed { background: var(--warn-soft); color: var(--warn); }
.ls-changelog__type--security,
.ls-changelog__type--removed { background: var(--danger-soft); color: var(--danger); }

@media (max-width: 600px) {
    .ls-changelog__section { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* The narrowest phones: unread count goes (the Inbox badge carries it too);
   operators online stays, because red there is the one alarm worth the room. */
@media (max-width: 420px) {
    .ls-topbar__stat.is-info { display: none; }
    .ls-topbar__stat { padding: 0 8px; }
}

/* Production readiness (System health → Overview) ----------------------- */

.ls-ready.is-fail { border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
.ls-ready.is-warn { border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.ls-ready__head { display: flex; align-items: center; gap: 10px; cursor: pointer; list-style: none; }
.ls-ready__head::-webkit-details-marker { display: none; }
.ls-ready__head .ls-card__title { margin: 0; }
.ls-ready__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 8px; margin: 12px 0 0; padding: 0; list-style: none; }

.ls-ready__item {
    display: flex;
    gap: 9px;
    padding: 9px 11px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.ls-ready__mark {
    flex: none;
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--ok-soft);
    color: var(--ok);
    font-size: 11px;
    font-weight: 800;
}

.ls-ready__item--warn .ls-ready__mark { background: var(--warn-soft); color: var(--warn); }
.ls-ready__item--fail { border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.ls-ready__item--fail .ls-ready__mark { background: var(--danger-soft); color: var(--danger); }
.ls-ready__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12.5px; }
.ls-ready__fix { align-self: flex-start; margin-top: 3px; padding: 1px 6px; border-radius: 4px; background: var(--surface-2); font-family: var(--mono); font-size: 11.5px; overflow-wrap: anywhere; }

/* ── Widget preview page (/widget-preview/:key) ─────────────────────────── */

.ls-preview { max-width: 760px; margin: 32px auto; padding: 0 16px; }
.ls-preview__note { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); color: var(--muted); }
.ls-preview__note strong { color: var(--text); font-size: 16px; }
.ls-preview__page { margin-top: 18px; padding: 24px; border: 1px dashed var(--border); border-radius: var(--radius-lg); }
.ls-preview__bar { height: 22px; width: 40%; border-radius: 6px; background: var(--border); margin-bottom: 18px; }
.ls-preview__line { height: 10px; border-radius: 5px; background: var(--border); opacity: .6; margin-bottom: 10px; }
.ls-preview__line--short { width: 60%; }

/* A section title inside a long modal form (e.g. one widget's settings). */
.ls-form__section { margin: 10px 0 -2px; padding-top: 12px; border-top: 1px solid var(--border); font-size: 14px; font-weight: 650; color: var(--muted); }
.ls-form > .ls-form__section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* Assistant test dialog */
.ls-bot-test__answer { padding: 12px 14px; border-radius: var(--radius); background: var(--surface-2, var(--bg)); border: 1px solid var(--border); white-space: pre-wrap; }

/* Repeatable records (assistant data sources, integration headers) -------- */

.ls-rows { display: flex; flex-direction: column; gap: 10px; margin-bottom: 8px; }

.ls-rows__item {
    position: relative;
    padding: 12px 44px 12px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface-2, var(--surface));
}

.ls-rows__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 12px;
}

.ls-rows__cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ls-rows__cell.is-wide { grid-column: 1 / -1; }
.ls-rows__label { font-size: 12px; color: var(--muted); }
.ls-rows__remove { position: absolute; top: 8px; right: 8px; }

@media (max-width: 640px) {
    .ls-rows__grid { grid-template-columns: minmax(0, 1fr); }
}

/* Integration preview and delivery log ------------------------------------ */

.ls-integration__output:empty { display: none; }
.ls-integration__logs { display: flex; flex-direction: column; gap: 6px; }

.ls-integration__log {
    border: 1px solid var(--border);
    border-left-width: 3px;
    border-radius: 8px;
    padding: 8px 10px;
}

.ls-integration__log.is-ok { border-left-color: var(--ok); }
.ls-integration__log.is-failed { border-left-color: var(--danger); }
.ls-integration__log summary { cursor: pointer; font-size: 13px; }
.ls-integration__log .ls-code { max-height: 260px; overflow: auto; white-space: pre-wrap; word-break: break-word; }

/* ══════════════════════════════════════════════════════════════════════════
   Navigation rail
   The one place every rule for the rail lives. It is the brand's dark band
   (navy in the light themes, deeper still in the dark ones, plain in the
   contrast theme), so it reads as "the menu" at a glance and the work area
   keeps all of the colour.
   ══════════════════════════════════════════════════════════════════════════ */

.ls-shell {
    grid-template-columns: var(--rail) minmax(0, 1fr);
    transition: grid-template-columns .18s var(--ease);
}

:root[data-rail-mini] .ls-shell { grid-template-columns: var(--rail-mini) minmax(0, 1fr); }

.ls-rail {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--rail-bg);
    color: var(--rail-fg);
    border-right: 1px solid var(--rail-line);
    overflow: hidden;
}

/* Brand ------------------------------------------------------------------- */

.ls-rail__brand {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 10px;
    height: var(--topbar);
    padding: 0 16px;
    border-bottom: 1px solid var(--rail-line);
    color: var(--rail-strong);
    text-decoration: none;
    font-size: 15px;
    font-weight: 650;
    letter-spacing: -.01em;
}

.ls-rail__logo {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--r);
    background: var(--rail-mark);
    color: var(--rail-bg);
    font-size: 15px;
}

.ls-rail__logo-img { flex: 0 0 auto; max-width: 28px; max-height: 28px; border-radius: var(--r-sm); object-fit: contain; }
.ls-rail__brand-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Two logos: the rail is a dark surface except in the contrast theme. */
.ls-rail .ls-logo--on-light { display: none; }
:root[data-theme="contrast"] .ls-rail .ls-logo--on-light { display: block; }
:root[data-theme="contrast"] .ls-rail .ls-logo--on-dark { display: none; }

/* Find a section ---------------------------------------------------------- */

.ls-rail__find {
    position: relative;
    flex: 0 0 auto;
    padding: 12px 12px 4px;
}

.ls-rail__search {
    width: 100%;
    height: 34px;
    padding: 0 30px 0 32px;
    border: 1px solid transparent;
    border-radius: var(--r);
    background: var(--rail-field) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%238b97b4' stroke-width='1.6' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='4.4'/%3E%3Cpath d='M10.4 10.4 14 14'/%3E%3C/svg%3E") no-repeat 10px center / 15px 15px;
    color: var(--rail-strong);
    font: inherit;
    font-size: 13px;
    transition: border-color .12s var(--ease), background-color .12s var(--ease);
}

.ls-rail__search::placeholder { color: var(--rail-muted); opacity: 1; }
.ls-rail__search::-webkit-search-cancel-button { display: none; }
.ls-rail__search:hover { border-color: var(--rail-line); }

.ls-rail__search:focus {
    border-color: var(--rail-mark);
    outline: none;
}

.ls-rail__search:focus-visible { outline: none; }

.ls-rail__kbd {
    position: absolute;
    top: 50%;
    right: 20px;
    margin-top: 4px;
    transform: translateY(-50%);
    min-width: 18px;
    padding: 1px 5px;
    border: 1px solid var(--rail-line);
    border-radius: var(--r-sm);
    color: var(--rail-muted);
    font: inherit;
    font-size: 11px;
    line-height: 1.4;
    text-align: center;
    pointer-events: none;
}

.ls-rail__search:focus + .ls-rail__kbd,
.ls-rail__search:not(:placeholder-shown) + .ls-rail__kbd { display: none; }

/* No keyboard to press it on. */
@media (hover: none) { .ls-rail__kbd { display: none; } }

/* Groups and entries ------------------------------------------------------ */

.ls-nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 4px 8px 12px;
    scrollbar-width: thin;
    scrollbar-color: var(--rail-line) transparent;
}

.ls-nav::-webkit-scrollbar-thumb { background: var(--rail-line); background-clip: content-box; }

.ls-nav__group { margin-top: 8px; }

.ls-nav__group-label {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    height: 28px;
    padding: 0 8px 0 10px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--rail-muted);
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    transition: color .12s var(--ease), background .12s var(--ease);
}

.ls-nav__group-label:hover { color: var(--rail-strong); background: var(--rail-hover); }
.ls-nav__group-label:focus-visible { outline: 2px solid var(--rail-mark); outline-offset: -2px; }
.ls-nav__group-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ls-nav__group-caret {
    display: inline-flex;
    flex: 0 0 auto;
    opacity: .7;
    transition: transform .16s var(--ease);
}

.ls-nav__group.is-folded .ls-nav__group-caret { transform: rotate(-90deg); }

/* Folding hides the entries without removing them, so the rail keeps its
   scroll position and nothing below jumps by the height of the group. */
.ls-nav__group.is-folded .ls-nav__group-items { display: none; }

.ls-nav__item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 11px;
    height: 36px;
    margin-top: 1px;
    padding: 0 10px;
    border-radius: var(--r);
    color: var(--rail-fg);
    font-size: 13.5px;
    font-weight: 450;
    text-decoration: none;
    transition: background .12s var(--ease), color .12s var(--ease);
}

.ls-nav__item:hover { background: var(--rail-hover); color: var(--rail-strong); }

.ls-nav__item:focus-visible {
    outline: 2px solid var(--rail-mark);
    outline-offset: -2px;
    border-radius: var(--r);
}

.ls-nav__item.is-active {
    background: var(--rail-active);
    color: var(--rail-strong);
    font-weight: 600;
}

/* The current screen is marked by the lime bar as well as the fill, so it
   does not rely on a shade of blue alone. */
.ls-nav__item.is-active::before {
    content: "";
    position: absolute;
    left: -8px;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 0 2px 2px 0;
    background: var(--rail-mark);
}

.ls-nav__icon { display: inline-flex; flex: 0 0 auto; width: 18px; justify-content: center; opacity: .85; }
.ls-nav__item.is-active .ls-nav__icon,
.ls-nav__item:hover .ls-nav__icon { opacity: 1; }
.ls-nav__label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ls-nav .ls-badge,
.ls-rail__pinned .ls-badge { box-shadow: 0 0 0 2px var(--rail-bg); }

.ls-nav__empty { margin: 14px 10px; color: var(--rail-muted); font-size: 13px; }

/* Foot: help, collapse, version -------------------------------------------- */

.ls-rail__foot {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    gap: 2px;
    padding: 8px;
    border-top: 1px solid var(--rail-line);
}

.ls-rail__pinned .ls-nav__item.is-active::before { left: -8px; }

.ls-rail__collapse {
    display: flex;
    align-items: center;
    gap: 11px;
    height: 36px;
    padding: 0 10px;
    border: 0;
    border-radius: var(--r);
    background: none;
    color: var(--rail-fg);
    font: inherit;
    font-size: 13.5px;
    text-align: left;
    cursor: pointer;
    transition: background .12s var(--ease), color .12s var(--ease);
}

.ls-rail__collapse:hover { background: var(--rail-hover); color: var(--rail-strong); }
.ls-rail__collapse:focus-visible { outline: 2px solid var(--rail-mark); outline-offset: -2px; }
.ls-rail__collapse .ls-svg { flex: 0 0 auto; opacity: .85; }

/* On tablet widths the rail is icon-only by force; the switch would do nothing. */
:root[data-rail-auto] .ls-rail__collapse { display: none; }

.ls-rail__meta {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 6px 10px 2px;
    color: var(--rail-muted);
    font-size: 11px;
    line-height: 1.4;
}

.ls-rail__version {
    flex: 0 0 auto;
    padding: 1px 6px;
    border: 1px solid var(--rail-line);
    border-radius: var(--r-sm);
    color: var(--rail-fg);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-decoration: none;
}

a.ls-rail__version:hover { border-color: var(--rail-mark); color: var(--rail-strong); }
.ls-rail__foot-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-rail__foot-text a { color: inherit; text-decoration: none; }
.ls-rail__foot-text a:hover { color: var(--rail-strong); text-decoration: underline; }

/* Icon-only rail ------------------------------------------------------------
   Chosen in the foot of the rail, or forced on tablet widths. Group headings
   turn into thin dividers and every group stays open: a folded cluster of
   icons has no label left to say what went missing. Labels live on in the
   native tooltip (title) of every entry. */

@media (min-width: 769px) {
    :root[data-rail-mini] .ls-rail__brand { justify-content: center; padding: 0; }

    :root[data-rail-mini] .ls-rail__brand-name,
    :root[data-rail-mini] .ls-rail__find,
    :root[data-rail-mini] .ls-nav__label,
    :root[data-rail-mini] .ls-nav__group-label,
    :root[data-rail-mini] .ls-rail__collapse-text,
    :root[data-rail-mini] .ls-rail__foot-text { display: none; }

    :root[data-rail-mini] .ls-nav { padding: 8px 6px; scrollbar-width: none; }
    :root[data-rail-mini] .ls-nav::-webkit-scrollbar { display: none; }
    :root[data-rail-mini] .ls-nav__group.is-folded .ls-nav__group-items { display: block; }

    :root[data-rail-mini] .ls-nav__group + .ls-nav__group {
        margin-top: 8px;
        padding-top: 8px;
        border-top: 1px solid var(--rail-line);
    }

    :root[data-rail-mini] .ls-nav__group:first-child { margin-top: 0; }

    :root[data-rail-mini] .ls-nav__item,
    :root[data-rail-mini] .ls-rail__collapse { justify-content: center; padding: 0; }

    :root[data-rail-mini] .ls-nav__item.is-active::before { left: -6px; }

    /* The counter rides on the icon instead of pushing it off-centre. */
    :root[data-rail-mini] .ls-nav__item .ls-badge {
        position: absolute;
        top: 2px;
        right: 3px;
        min-width: 16px;
        height: 15px;
        padding: 0 4px;
        font-size: 9.5px;
    }

    :root[data-rail-mini] .ls-rail__foot { padding: 8px 6px; }
    :root[data-rail-mini] .ls-rail__meta { justify-content: center; padding: 6px 0 2px; }
    :root[data-rail-mini] .ls-rail__version { padding: 1px 3px; font-size: 9.5px; }
}

/* Phone: the rail becomes a drawer over the page ---------------------------- */

.ls-rail__backdrop { display: none; }

@media (max-width: 768px) {
    .ls-shell,
    :root[data-rail-mini] .ls-shell { grid-template-columns: minmax(0, 1fr); }

    .ls-rail {
        position: fixed;
        z-index: 60;
        top: 0;
        bottom: 0;
        left: 0;
        width: min(84vw, 290px);
        transform: translateX(-100%);
        transition: transform .2s var(--ease);
        box-shadow: var(--sh-5);
    }

    :root[data-rail-open] .ls-rail { transform: none; }

    /* The drawer has its own close gesture; collapsing it makes no sense. */
    .ls-rail__collapse { display: none; }

    /* Touch targets: a finger needs more than a mouse pointer. */
    .ls-nav__item { height: 44px; }

    .ls-rail__backdrop {
        display: block;
        position: fixed;
        z-index: 59;
        inset: 0;
        background: rgba(11, 18, 32, .5);
        opacity: 0;
        pointer-events: none;
        transition: opacity .2s var(--ease);
    }

    :root[data-rail-open] .ls-rail__backdrop { opacity: 1; pointer-events: auto; }
}

/* The top bar logo follows the theme. */
.ls-topbar .ls-logo--on-dark { display: none; }
:root[data-theme="dark"] .ls-topbar .ls-logo--on-light,
:root[data-theme="midnight"] .ls-topbar .ls-logo--on-light { display: none; }
:root[data-theme="dark"] .ls-topbar .ls-logo--on-dark,
:root[data-theme="midnight"] .ls-topbar .ls-logo--on-dark { display: block; }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme]) .ls-topbar .ls-logo--on-light,
    :root[data-theme="system"] .ls-topbar .ls-logo--on-light { display: none; }
    :root:not([data-theme]) .ls-topbar .ls-logo--on-dark,
    :root[data-theme="system"] .ls-topbar .ls-logo--on-dark { display: block; }
}
