/*
 * Call Centre — operations console.
 *
 * Identifiers (extensions, numbers, session ids) are set in monospace
 * throughout: they are things people read digit by digit and compare, not
 * prose. Everything else is quiet on purpose — agents look at this for a
 * whole shift.
 */

:root {
    --ink:        #0d1a1d;
    --slate:      #12303a;
    --slate-soft: #1b4350;
    --paper:      #eceeed;
    --card:       #ffffff;
    --rule:       #d3d9d7;
    --muted:      #5c6a67;

    --bar:        #123f66;   /* top bar — a deeper sibling of the rail */
    --bar-edge:   #0d2f4e;
    --line:       #0f7a63;   /* live / confirmed */
    --amber:      #a86d0c;   /* pending / caution */
    --clay:       #a5382a;   /* destructive / failed */

    --role-master_admin: #6b4fa8;
    --role-tenant_admin: #0f7a63;
    --role-supervisor:   #1d6fa5;
    --role-agent:        #55665f;

    --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;

    --pad: 20px;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
}

body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--sans);
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--line); }

h1, h2, h3 { line-height: 1.2; margin: 0; font-weight: 650; letter-spacing: -0.01em; }
h1 { font-size: 22px; }
h2 { font-size: 17px; }

.mono, .num {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
}

/* ----------------------------------------------------------- app rail */

/*
 * A left rail rather than a top bar. Console operators live in one screen for
 * a whole shift, so vertical space is the scarce resource — a 58px top bar is
 * 58px of call list they do not get. The rail also gives room to group
 * navigation by what someone is doing (handling calls, configuring, running
 * the platform) rather than flattening it into one row.
 */

.shell {
    display: flex;
    min-height: 100vh;
    align-items: stretch;
}

.rail {
    width: 232px;
    flex: none;
    background: var(--slate);
    color: #cbd8d5;
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.rail__brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 18px 18px 16px;
    font-weight: 680;
    color: #fff;
    text-decoration: none;
    letter-spacing: -0.015em;
    font-size: 15.5px;
}

.brand__dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--line);
    box-shadow: 0 0 0 3px rgba(15, 122, 99, 0.28);
    flex: none;
}

.rail__group { padding: 6px 0 10px; }

.rail__heading {
    font-family: var(--mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: #7d928d;
    padding: 8px 18px 6px;
}

.rail a.rail__link {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 8px 18px;
    color: #bdcbc8;
    text-decoration: none;
    font-size: 14px;
    border-left: 3px solid transparent;
}

.rail a.rail__link:hover { color: #fff; background: rgba(255, 255, 255, 0.045); }

.rail a.rail__link[aria-current="page"] {
    color: #fff;
    background: rgba(255, 255, 255, 0.07);
    border-left-color: var(--line);
}

.rail__count {
    margin-left: auto;
    font-family: var(--mono);
    font-size: 11px;
    background: var(--clay);
    color: #fff;
    border-radius: 9px;
    padding: 1px 6px;
}

/* Identity sits at the foot of the rail, with the role band beside it. */

.rail__foot {
    margin-top: auto;
    padding: 14px 16px 16px;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
}

.identity {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-left: 11px;
    border-left: 3px solid var(--band, var(--role-agent));
    margin-bottom: 10px;
}

.identity__role {
    font-family: var(--mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--band, #b6c6c3);
    display: block;
}

.identity__who { font-size: 13px; color: #fff; display: block; }
.identity form { margin: 0; }

.identity__out {
    background: none;
    border: 0;
    color: #8fa4a0;
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
    padding: 2px;
    margin-left: auto;
}
.identity__out:hover { color: #fff; text-decoration: underline; }

.workspace { flex: 1; min-width: 0; }

/* ------------------------------------------------------------- layout */

.wrap {
    max-width: 1120px;
    margin: 0 auto;
    padding: 26px var(--pad) 60px;
}

.pagehead {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 18px;
    flex-wrap: wrap;
}

.pagehead p { margin: 4px 0 0; color: var(--muted); font-size: 14px; }

.card {
    background: var(--card);
    border: 1px solid var(--rule);
    border-radius: 3px;
}

.card__head {
    padding: 13px 16px;
    border-bottom: 1px solid var(--rule);
}

.card__body { padding: 16px; }

/* -------------------------------------------------------------- stats */

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 1px;
    background: var(--rule);
    border: 1px solid var(--rule);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 24px;
}

.stat { background: var(--card); padding: 15px 16px; }

.stat__label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
}

.stat__value {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 27px;
    font-weight: 600;
    margin-top: 3px;
    letter-spacing: -0.02em;
}

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

table { width: 100%; border-collapse: collapse; }

th {
    text-align: left;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
    font-weight: 600;
    padding: 10px 16px;
    border-bottom: 1px solid var(--rule);
    background: #f7f9f8;
}

td {
    padding: 12px 16px;
    border-bottom: 1px solid var(--rule);
    vertical-align: middle;
}

tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: #f7f9f8; }

.cell-actions { text-align: right; white-space: nowrap; }
.cell-actions form { display: inline; margin: 0; }

/* --------------------------------------------------------------- tags */

.tag {
    display: inline-block;
    font-family: var(--mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 3px 7px;
    border-radius: 2px;
    border: 1px solid currentColor;
    line-height: 1.35;
}

.tag--role       { color: var(--band, var(--role-agent)); }
.tag--active     { color: var(--line); }
.tag--invited    { color: var(--amber); }
.tag--suspended  { color: var(--clay); }
.tag--terminated { color: var(--clay); }

/* ------------------------------------------------------------- forms */

.field { margin-bottom: 15px; }

label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 5px;
}

.hint { font-size: 12.5px; color: var(--muted); font-weight: 400; margin-top: 4px; }

input[type=text], input[type=email], input[type=password], input[type=tel], select {
    width: 100%;
    padding: 9px 11px;
    border: 1px solid #b9c2bf;
    border-radius: 3px;
    font: inherit;
    font-size: 14.5px;
    background: #fff;
    color: var(--ink);
}

input[name=extension] { font-family: var(--mono); }

input:focus, select:focus, button:focus-visible, a:focus-visible {
    outline: 2px solid var(--line);
    outline-offset: 1px;
    border-color: var(--line);
}

.field--split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
}

.btn {
    display: inline-block;
    padding: 9px 16px;
    border: 1px solid var(--slate);
    background: var(--slate);
    color: #fff;
    border-radius: 3px;
    font: inherit;
    font-size: 14px;
    font-weight: 550;
    cursor: pointer;
    text-decoration: none;
}

.btn:hover { background: var(--slate-soft); }

.btn--quiet {
    background: #fff;
    color: var(--ink);
    border-color: #b9c2bf;
}
.btn--quiet:hover { background: #f2f5f4; }

.btn--link {
    background: none;
    border: 0;
    color: var(--line);
    padding: 4px 6px;
    font: inherit;
    font-size: 13.5px;
    cursor: pointer;
    text-decoration: underline;
}

.btn--danger { color: var(--clay); }

.actions {
    display: flex;
    gap: 10px;
    align-items: center;
    margin-top: 22px;
    padding-top: 16px;
    border-top: 1px solid var(--rule);
}

/* ------------------------------------------------------ notices */

.notice {
    padding: 11px 14px;
    border-radius: 3px;
    margin-bottom: 18px;
    font-size: 14px;
    border: 1px solid;
}

.notice--ok   { border-color: #a9cfc4; background: #eef7f4; color: #0b5a49; }
.notice--bad  { border-color: #dcb3ac; background: #fbf0ee; color: #8a2f22; }

.errors { margin: 0 0 18px; padding-left: 18px; }
.errors li { color: #8a2f22; font-size: 14px; }

/* -------------------------------------------------------- empty state */

.empty {
    padding: 44px 20px;
    text-align: center;
    color: var(--muted);
}

.empty h2 { margin-bottom: 6px; color: var(--ink); }
.empty p { margin: 0 0 16px; font-size: 14px; }

/* ------------------------------------------------------- guest screens */

.guest {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 28px 18px;
    background:
        linear-gradient(180deg, rgba(18, 48, 58, 0.04), rgba(18, 48, 58, 0)) ,
        var(--paper);
}

.guest__panel { width: 100%; max-width: 400px; }

.guest__brand {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
    font-weight: 680;
    font-size: 17px;
    letter-spacing: -0.015em;
}

.guest__foot {
    margin-top: 16px;
    font-size: 12.5px;
    color: var(--muted);
    text-align: center;
}

/* --------------------------------------------------------- pagination */

.pager { margin-top: 16px; font-size: 14px; }
.pager svg { width: 15px; height: 15px; }

@media (max-width: 900px) {
    .shell { flex-direction: column; }
    .rail {
        width: 100%;
        height: auto;
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        padding-bottom: 6px;
    }
    .rail__brand { padding: 14px 16px; }
    .rail__group { display: flex; padding: 0; overflow-x: auto; }
    .rail__heading { display: none; }
    .rail a.rail__link {
        border-left: 0;
        border-bottom: 3px solid transparent;
        white-space: nowrap;
        padding: 8px 12px;
    }
    .rail a.rail__link[aria-current="page"] {
        border-left: 0;
        border-bottom-color: var(--line);
    }
    .rail__foot { margin: 0 0 0 auto; border-top: 0; padding: 8px 14px; }
    .field--split { grid-template-columns: 1fr; }
    td, th { padding-left: 12px; padding-right: 12px; }
}

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}

/* --------------------------------------------------------- presence */

.presence {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
}

.presence__label {
    font-family: var(--mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: rgba(255, 255, 255, 0.6);
    margin: 0;
    font-weight: 400;
}

.presence__select {
    width: auto;
    padding: 4px 8px;
    font-size: 13px;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.24);
    color: #fff;
    border-radius: 3px;
}

.presence__select option { color: var(--ink); }

.presence__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
}

.presence__dot--available { background: #2fbf8f; box-shadow: 0 0 0 3px rgba(47,191,143,.22); }
.presence__dot--busy      { background: #d9a020; box-shadow: 0 0 0 3px rgba(217,160,32,.22); }
.presence__dot--away      { background: #8fa39e; }
.presence__dot--offline   { background: #5b6f6a; }

/* ------------------------------------------------------ agent picker */

.picker {
    border: 1px solid var(--rule);
    border-radius: 3px;
    max-height: 240px;
    overflow-y: auto;
}

.picker__row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--rule);
}

.picker__row:last-child { border-bottom: 0; }
.picker__row input { width: auto; margin: 0; }
.picker__row label { margin: 0; font-weight: 400; font-size: 14px; }

.picker__meta {
    margin-left: auto;
    font-family: var(--mono);
    font-size: 12px;
    color: var(--muted);
}

.strategy__note { font-size: 12.5px; color: var(--muted); margin-top: 6px; }

.vm__new { font-weight: 650; }
.vm__player { width: 260px; max-width: 100%; height: 34px; }

@media (max-width: 720px) {
    .presence { order: 2; margin-left: 0; }
    .presence__label { display: none; }
}

/* ----------------------------------------------------------- console */

/*
 * The console runs dark while the configuration screens stay light. Not a
 * style flourish: an operator stares at this for a whole shift, and the
 * screens either side of it get opened for a minute at a time. The rail keeps
 * both worlds joined.
 */

/*
 * The console bleeds the full width of the workspace. Written as a viewport
 * offset rather than negative margins because the wrap is centred with a max
 * width — negative padding-margins only reached the wrap's edges, leaving the
 * page background showing either side of the dark panel.
 */
.workspace:has(.console) > .wrap { max-width: none; padding-left: 0; padding-right: 0; padding-top: 0; }
/*
 * Console colours are variables so light mode is an override rather than a
 * second copy of every rule. Dark is the default because an operator is in
 * here for a whole shift — but it is a preference, not a decision: dark type
 * on dark backgrounds is genuinely harder to read with astigmatism.
 */
.console {
    --c-bg:      #0f1a1d;
    --c-surface: #16262a;
    --c-rule:    #24393f;
    --c-head:    #142125;
    --c-text:    #dbe6e3;
    --c-strong:  #ffffff;
    --c-muted:   #8ba39e;
    --c-hover:   #1a2d32;
    --c-input:   #0f1a1d;
    --c-border:  #2e454b;

    background: var(--c-bg);
    padding: 26px var(--pad) 60px;
    min-height: calc(100vh - 54px);
    color: var(--c-text);
}

[data-theme="light"] .console {
    --c-bg:      var(--paper);
    --c-surface: #ffffff;
    --c-rule:    var(--rule);
    --c-head:    #f7f9f8;
    --c-text:    var(--ink);
    --c-strong:  var(--ink);
    --c-muted:   var(--muted);
    --c-hover:   #f7f9f8;
    --c-input:   #ffffff;
    --c-border:  #b9c2bf;
}

.console > * { max-width: 1120px; margin-left: auto; margin-right: auto; }
.console h1, .console h2 { color: var(--c-strong); }
.console .card { background: var(--c-surface); border-color: var(--c-rule); }
.console .card__head { border-color: var(--c-rule); }
.console th { background: var(--c-head); color: var(--c-muted); border-color: var(--c-rule); }
.console td { border-color: var(--c-rule); }
.console tbody tr:hover { background: var(--c-hover); }
.console .pagehead p { color: var(--c-muted); }
.console .hint { color: var(--c-muted); }
.console input, .console select { background: var(--c-input); border-color: var(--c-border); color: var(--c-text); }
.console .empty { color: var(--c-muted); }
.console .empty h2 { color: var(--c-strong); }

.phone {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 3px;
    background: var(--c-surface);
    border: 1px solid var(--c-rule);
    font-size: 14px;
    margin-bottom: 18px;
}

.phone::before {
    content: '';
    width: 9px; height: 9px;
    border-radius: 50%;
    background: #5b6f6a;
    flex: none;
}

.phone[data-state="ready"]::before      { background: #2fbf8f; box-shadow: 0 0 0 3px rgba(47,191,143,.22); }
.phone[data-state="incoming"]::before   { background: #d9a020; box-shadow: 0 0 0 3px rgba(217,160,32,.22); }
.phone[data-state="oncall"]::before     { background: #2f8fbf; box-shadow: 0 0 0 3px rgba(47,143,191,.22); }
.phone[data-state="recovering"]::before { background: #d9a020; }
.phone[data-state="no-mic"]::before,
.phone[data-state="error"]::before,
.phone[data-state="unavailable"]::before { background: var(--clay); }

.callcard { text-align: center; padding: 34px 20px; }

.callcard__number {
    font-family: var(--mono);
    font-size: 38px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--c-strong);
}

.callcard__who { color: var(--c-muted); margin-top: 6px; font-size: 14.5px; }

.callcard__actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    margin-top: 22px;
    flex-wrap: wrap;
}

.btn--answer { background: #12855f; border-color: #12855f; }
.btn--answer:hover { background: #16a074; }
.btn--end { background: var(--clay); border-color: var(--clay); }

.console .btn--quiet { background: var(--c-hover); color: var(--c-text); border-color: var(--c-border); }
.console .btn--quiet:hover { background: var(--c-rule); }

.grid2 { display: grid; grid-template-columns: 1.7fr 1fr; gap: 18px; align-items: start; }

.peer { list-style: none; padding: 6px 0; font-size: 14px; border-bottom: 1px solid var(--c-rule); }
.peer:last-child { border-bottom: 0; }
.peer--available { color: #2fbf8f; }
.peer--busy      { color: #d9a020; }
.peer--away      { color: #8ba39e; }
.peer--offline   { color: #63756f; }

.dialpad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; max-width: 260px; }

.dialpad button {
    padding: 13px 0;
    font-family: var(--mono);
    font-size: 17px;
    background: var(--c-hover);
    color: var(--c-strong);
    border: 1px solid var(--c-border);
    border-radius: 3px;
    cursor: pointer;
}

.dialpad button:hover { background: var(--c-rule); }

.pop dt { font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--c-muted); margin-top: 12px; }
.pop dd { margin: 3px 0 0; font-size: 14.5px; }
.pop ul { list-style: none; padding: 0; margin: 6px 0 0; }
.pop li { font-size: 13.5px; color: var(--c-muted); padding: 3px 0; }

@supports not (selector(:has(*))) {
    .console { margin: -26px calc(var(--pad) * -1) -60px; padding-top: 26px; }
}

@media (max-width: 900px) {
    .grid2 { grid-template-columns: 1fr; }
    .console { padding-left: 14px; padding-right: 14px; }
}

/* ---------------------------------------------------------- top bar */

/*
 * The rail answers "where am I going". The bar answers "who am I, and what do
 * I control" — account, availability and settings. Splitting them this way
 * keeps the rail purely navigational, so adding a section later never pushes
 * the sign-out button somewhere new.
 */

.topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 var(--pad);
    height: 54px;
    background: var(--bar);
    border-bottom: 1px solid var(--bar-edge);
    position: sticky;
    top: 0;
    z-index: 20;
}

.topbar__context {
    font-size: 13.5px;
    color: rgba(255, 255, 255, 0.62);
}

.topbar__context strong { color: #fff; font-weight: 600; }

.topbar__right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
}

.topbar :focus-visible,
.topbar summary:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 1px;
}

.topbar__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 3px;
    color: rgba(255, 255, 255, 0.74);
    text-decoration: none;
    border: 1px solid transparent;
}

.topbar__icon:hover {
    background: rgba(255, 255, 255, 0.11);
    color: #fff;
    border-color: rgba(255, 255, 255, 0.2);
}

.topbar__icon[aria-current="page"] {
    color: #fff;
    background: rgba(255, 255, 255, 0.13);
    border-color: rgba(255, 255, 255, 0.24);
}
.topbar__icon svg { width: 18px; height: 18px; }

/* Account menu. A details element so it works with JavaScript disabled. */

.account { position: relative; }

.account > summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 4px 6px 4px 4px;
    border-radius: 3px;
    border: 1px solid transparent;
}

.account > summary::-webkit-details-marker { display: none; }
.account > summary:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.18);
}

.account[open] > summary {
    background: rgba(255, 255, 255, 0.13);
    border-color: rgba(255, 255, 255, 0.22);
}

/* The ring is the role colour — the one place "who am I acting as" lives. */
.avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #0b2740;
    color: #fff;
    font-size: 11.5px;
    font-weight: 650;
    letter-spacing: 0.02em;
    box-shadow: 0 0 0 2px var(--bar), 0 0 0 3.5px var(--band, var(--role-agent));
    flex: none;
}

.account__name { font-size: 13.5px; color: #fff; }
.account__caret { color: rgba(255, 255, 255, 0.6); font-size: 11px; }

.account__panel {
    position: absolute;
    right: 0;
    top: calc(100% + 7px);
    min-width: 232px;
    background: var(--card);
    border: 1px solid var(--rule);
    border-radius: 3px;
    box-shadow: 0 8px 24px rgba(13, 26, 29, 0.14);
    padding: 6px;
}

.account__who { padding: 9px 10px 10px; border-bottom: 1px solid var(--rule); margin-bottom: 6px; }
.account__who strong { display: block; font-size: 14px; }
.account__who span { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }

.account__role {
    font-family: var(--mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--band, var(--role-agent));
    margin-top: 5px;
    display: block;
}

.account__panel a,
.account__panel button {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px 10px;
    font: inherit;
    font-size: 14px;
    color: var(--ink);
    text-decoration: none;
    background: none;
    border: 0;
    border-radius: 2px;
    cursor: pointer;
}

.account__panel a:hover,
.account__panel button:hover { background: #f2f5f4; }
.account__panel form { margin: 0; }
.account__sep { height: 1px; background: var(--rule); margin: 6px 0; }

/* The bar sits above a dark console, so it keeps its own light surface. */
.workspace .wrap { padding-top: 24px; }

@media (max-width: 900px) {
    .topbar { padding: 0 12px; }
    .account__name { display: none; }
    .topbar__context { display: none; }
}


/* --------------------------------------------------- campaign desk */

.desk__contact { text-align: center; padding: 30px 20px; }

.desk__name {
    font-size: 25px;
    font-weight: 650;
    letter-spacing: -0.015em;
    color: var(--c-strong);
}

.desk__number {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 30px;
    margin-top: 8px;
    color: var(--c-strong);
}

.desk__meta { color: var(--c-muted); margin-top: 8px; font-size: 14px; }

.desk__script {
    text-align: left;
    max-width: 620px;
    margin: 22px auto 0;
    padding: 14px 16px;
    border-left: 3px solid var(--line);
    background: var(--c-hover);
    font-size: 14.5px;
    white-space: pre-wrap;
}

.desk__actions { display: flex; gap: 10px; justify-content: center; margin-top: 22px; flex-wrap: wrap; }

.progress {
    height: 6px;
    background: var(--rule);
    border-radius: 3px;
    overflow: hidden;
    margin-top: 10px;
}

.progress__fill { height: 100%; background: var(--line); }

/* Theme toggle in the bar. Two states, so a button rather than a select. */
.theme-toggle { display: inline-flex; }
.theme-toggle button {
    background: none;
    border: 1px solid transparent;
    color: rgba(255, 255, 255, 0.74);
    cursor: pointer;
    width: 34px;
    height: 34px;
    border-radius: 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}
.theme-toggle button:hover {
    background: rgba(255, 255, 255, 0.11);
    color: #fff;
    border-color: rgba(255, 255, 255, 0.2);
}
.theme-toggle svg { width: 18px; height: 18px; }

/* ------------------------------------------------------------ acting */

/*
 * Shown whenever a platform admin is working inside a customer's
 * organisation. Deliberately loud: the danger is not getting in, it is
 * forgetting you are there and changing a customer's live routing while
 * thinking you are in your own account.
 */
.acting {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 9px var(--pad);
    background: #6b4fa8;
    color: #fff;
    font-size: 13.5px;
}

.acting strong { font-weight: 650; }
.acting form { margin: 0 0 0 auto; }

.acting button {
    background: rgba(255, 255, 255, 0.16);
    border: 1px solid rgba(255, 255, 255, 0.34);
    color: #fff;
    font: inherit;
    font-size: 13px;
    padding: 4px 11px;
    border-radius: 3px;
    cursor: pointer;
    white-space: nowrap;
}

.acting button:hover { background: rgba(255, 255, 255, 0.26); }

@media (max-width: 720px) {
    .acting { flex-wrap: wrap; gap: 8px; padding: 8px 12px; }
    .acting form { margin-left: 0; }
}

/* -------------------------------------------------------- ring card */

/*
 * Fixed to the corner rather than taking over the screen. An agent finishing
 * notes on the last call should be interrupted, not blocked — and a
 * full-screen takeover on a mis-dial is worse than the call it announces.
 */
.ringcard {
    position: fixed;
    right: 22px;
    bottom: 22px;
    z-index: 60;
    width: 310px;
    max-width: calc(100vw - 32px);
    background: #16262a;
    border: 1px solid #2fbf8f;
    border-radius: 5px;
    padding: 18px 18px 16px;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);
    animation: ringcard-in 220ms ease-out;
}

[data-theme="light"] .ringcard {
    background: #fff;
    border-color: var(--line);
    box-shadow: 0 14px 40px rgba(13, 26, 29, 0.22);
}

@keyframes ringcard-in {
    from { transform: translateY(14px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

.ringcard__label {
    font-family: var(--mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: #2fbf8f;
    display: flex;
    align-items: center;
    gap: 7px;
}

/* A pulse, so a silent tab still reads as ringing. */
.ringcard__label::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #2fbf8f;
    animation: ringcard-pulse 1s ease-in-out infinite;
}

@keyframes ringcard-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: .35; transform: scale(.8); }
}

.ringcard__number {
    font-size: 23px;
    font-weight: 600;
    letter-spacing: 0.01em;
    margin-top: 9px;
    color: var(--c-strong, #fff);
}

[data-theme="light"] .ringcard__number { color: var(--ink); }

.ringcard__meta {
    font-size: 13px;
    color: var(--c-muted, #8ba39e);
    margin-top: 4px;
    min-height: 18px;
}

.ringcard__actions { display: flex; gap: 9px; margin-top: 15px; }
.ringcard__actions .btn { flex: 1; text-align: center; padding: 9px 10px; }

@media (prefers-reduced-motion: reduce) {
    .ringcard { animation: none; }
    .ringcard__label::before { animation: none; }
}

@media (max-width: 720px) {
    .ringcard { right: 12px; bottom: 12px; left: 12px; width: auto; }
}

/* -------------------------------------------------------- timeline */

.timeline { list-style: none; margin: 0; padding: 0 0 0 18px; position: relative; }

.timeline::before {
    content: '';
    position: absolute;
    left: 4px;
    top: 6px;
    bottom: 6px;
    width: 1px;
    background: var(--rule);
}

.timeline__item { position: relative; padding: 0 0 16px 0; }
.timeline__item:last-child { padding-bottom: 0; }

/* The dot is coloured by what kind of thing happened, so a long history can
   be skimmed for shape before it is read. */
.timeline__item::before {
    content: '';
    position: absolute;
    left: -18px;
    top: 5px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--muted);
    box-shadow: 0 0 0 3px var(--card);
}

.timeline__item--call::before      { background: var(--line); }
.timeline__item--voicemail::before { background: var(--amber); }
.timeline__item--callback::before  { background: var(--clay); }
.timeline__item--campaign::before  { background: #1d6fa5; }
.timeline__item--note::before      { background: #6b4fa8; }

.timeline__when {
    font-size: 11.5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.timeline__title { font-size: 14.5px; margin-top: 1px; }
.timeline__detail { font-size: 13.5px; color: var(--muted); margin-top: 2px; }

/* ========================================================== dialer */

/*
 * The floating softphone. Present on every screen for anyone holding a seat,
 * so an agent can open a contact record while a call is running.
 *
 * Deliberately not draggable. A panel that can be moved is a panel that gets
 * moved off-screen, and then someone cannot answer their phone.
 */

/*
 * The hidden attribute must win.
 *
 * `.dialer__party`, `.dialer__incoming` and `.dialer__controls` each set a
 * display, and a class selector beats the browser's own `[hidden]` rule. So
 * the dialler's JavaScript was setting `hidden = true` on all three and they
 * stayed on screen: Answer and Decline offered with nobody calling, "Unknown
 * caller" showing between calls, and in-call controls present while idle.
 *
 * The toggling was never broken; the stylesheet was quietly ignoring it. This
 * belongs here rather than in each rule, because the next element given a
 * display and a hidden attribute would have the same bug.
 */
[hidden] { display: none !important; }

.dialer {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 70;
    width: 296px;
    max-width: calc(100vw - 24px);
    background: #16262a;
    color: #dbe6e3;
    border: 1px solid #24393f;
    border-radius: 8px;
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.42);
    overflow: hidden;
    font-size: 14px;
}

[data-theme="light"] .dialer {
    background: #fff;
    color: var(--ink);
    border-color: var(--rule);
    box-shadow: 0 18px 48px rgba(13, 26, 29, 0.2);
}

.dialer[data-state="incoming"] { border-color: #2fbf8f; }
.dialer[data-state="oncall"]   { border-color: #2f8fbf; }

/* --------------------------------------------------------- title bar */

.dialer__bar {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 10px 12px;
    background: var(--bar);
    color: #fff;
    cursor: default;
}

.dialer__dot { width: 8px; height: 8px; border-radius: 50%; background: #5b6f6a; flex: none; }
.dialer[data-state="ready"]    .dialer__dot { background: #2fbf8f; }
.dialer[data-state="incoming"] .dialer__dot { background: #2fbf8f; animation: ringcard-pulse 1s infinite; }
.dialer[data-state="oncall"]   .dialer__dot { background: #2f8fbf; }
.dialer[data-state="dialling"] .dialer__dot { background: #d9a020; }
.dialer[data-state="no-mic"]   .dialer__dot,
.dialer[data-state="error"]    .dialer__dot { background: var(--clay); }

.dialer__title { font-size: 13px; font-weight: 600; }
.dialer__timer { margin-left: auto; font-size: 12.5px; opacity: .85; }

.dialer__min {
    background: none;
    border: 0;
    color: #fff;
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    opacity: .8;
}
.dialer__min:hover { opacity: 1; }

.dialer.is-collapsed .dialer__body { display: none; }
.dialer.is-collapsed { width: 232px; }

/* ------------------------------------------------------------ status */

/*
 * One height, whatever state the phone is in.
 *
 * The party card and the in-call controls appear and disappear with the call,
 * which made the panel grow and shrink by about 113px underneath the agent's
 * pointer — and left it looking stunted while idle. Reserving the space keeps
 * the Call button and the tabs where the hand expects them, and the panes
 * absorb the slack so the gap never shows up as a hole at the bottom.
 */
.dialer__body {
    padding: 12px;
    display: flex;
    flex-direction: column;
    min-height: 585px;
}

.dialer__panes { flex: 1 1 auto; display: flex; flex-direction: column; }
.dialer__panes > .dialer__pane { flex: 1 1 auto; display: flex; flex-direction: column; }

/* The keypad takes the slack rather than leaving a hole above the Call
   button, so the keys grow instead of the panel sprouting dead space. Bigger
   targets on the one control that gets hit most is no loss. */
.dialer .dialpad { flex: 1 1 auto; grid-auto-rows: 1fr; align-content: stretch; }

.dialer__status { font-size: 12.5px; color: var(--c-muted, #8ba39e); margin-bottom: 10px; }
[data-theme="light"] .dialer__status { color: var(--muted); }

.dialer__sound {
    font-size: 12.5px;
    background: rgba(217, 160, 32, .14);
    border: 1px solid rgba(217, 160, 32, .4);
    color: #d9a020;
    padding: 7px 9px;
    border-radius: 4px;
    margin-bottom: 10px;
}
.dialer__sound button {
    background: none; border: 0; color: inherit; text-decoration: underline;
    cursor: pointer; font: inherit; padding: 0;
}

/* ------------------------------------------------------------- party */

.dialer__party { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; }

.dialer__avatar {
    width: 40px; height: 40px; border-radius: 50%;
    background: var(--bar); color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 650; font-size: 13px; flex: none;
}

.dialer__who { min-width: 0; }
.dialer__name { font-weight: 600; font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dialer__number { font-size: 13px; opacity: .8; }
.dialer__meta { font-size: 12px; color: var(--c-muted, #8ba39e); margin-top: 2px; }

.dialer__incoming { display: flex; gap: 8px; margin-bottom: 12px; }
.dialer__incoming .btn { flex: 1; padding: 9px 6px; text-align: center; }

/* ---------------------------------------------------------- controls */

.dialer__controls {
    display: grid;
    /* auto-fit, not a fixed four: a provider without hold or transfer has two
       of these buttons, and a rigid four-column grid left them stranded in the
       left half with two empty cells beside them. */
    grid-template-columns: repeat(auto-fit, minmax(62px, 1fr));
    gap: 6px;
    margin-bottom: 12px;
}

.dialer__ctl {
    background: rgba(255, 255, 255, .06);
    border: 1px solid #2e454b;
    color: inherit;
    border-radius: 5px;
    padding: 8px 2px 6px;
    font-size: 10.5px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
}

[data-theme="light"] .dialer__ctl { background: #f2f5f4; border-color: #b9c2bf; }
.dialer__ctl:hover { background: rgba(255, 255, 255, .12); }
[data-theme="light"] .dialer__ctl:hover { background: #e7ecea; }
.dialer__ctl[data-on="true"] { background: var(--amber); border-color: var(--amber); color: #fff; }
.dialer__ctl-icon { font-size: 13px; }

/* ------------------------------------------------------------- panes */

.dialer__display { margin-bottom: 9px; }

.dialer__display input,
.dialer__display select,
.dialer__pane textarea {
    width: 100%;
    padding: 8px 10px;
    border-radius: 5px;
    border: 1px solid #2e454b;
    background: #0f1a1d;
    color: inherit;
    font: inherit;
    font-size: 14px;
}

[data-theme="light"] .dialer__display input,
[data-theme="light"] .dialer__display select,
[data-theme="light"] .dialer__pane textarea {
    background: #fff;
    border-color: #b9c2bf;
}

.dialer .dialpad { grid-template-columns: repeat(3, 1fr); gap: 6px; max-width: none; }

.dialer .dialpad button {
    padding: 9px 0 7px;
    line-height: 1.1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
}

.dialpad__digit { font-family: var(--mono); font-size: 16px; }
.dialpad__letters { font-size: 8.5px; letter-spacing: .09em; opacity: .55; }

.dialer__list { list-style: none; margin: 0; padding: 0; max-height: 210px; overflow-y: auto; }

.dialer__list li {
    padding: 8px 4px;
    border-bottom: 1px solid #24393f;
    font-size: 13.5px;
    display: flex;
    align-items: center;
    gap: 8px;
}

[data-theme="light"] .dialer__list li { border-color: var(--rule); }
.dialer__list li:last-child { border-bottom: 0; }
.dialer__empty { color: var(--c-muted, #8ba39e); }

.dialer__list button {
    margin-left: auto;
    background: none;
    border: 0;
    color: var(--line);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
}

.dialer__hint { font-size: 11.5px; color: var(--c-muted, #8ba39e); margin: 7px 0 0; }
.dialer__wide { width: 100%; margin-top: 8px; text-align: center; }

/* ------------------------------------------------------- call button */

.dialer__call,
.dialer__hangup {
    width: 100%;
    margin-top: 11px;
    padding: 11px;
    border: 0;
    border-radius: 6px;
    color: #fff;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.dialer__call   { background: #12855f; }
.dialer__call:hover { background: #16a074; }
.dialer__hangup { background: var(--clay); }

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

.dialer__tabs {
    display: flex;
    margin: 11px -12px -12px;
    border-top: 1px solid #24393f;
}

[data-theme="light"] .dialer__tabs { border-color: var(--rule); }

.dialer__tabs button {
    flex: 1;
    background: none;
    border: 0;
    border-top: 2px solid transparent;
    color: var(--c-muted, #8ba39e);
    padding: 9px 2px;
    font: inherit;
    font-size: 11px;
    cursor: pointer;
}

.dialer__tabs button.is-on { color: inherit; border-top-color: var(--line); }

@media (max-width: 720px) {
    .dialer { right: 8px; left: 8px; bottom: 8px; width: auto; }
    .dialer.is-collapsed { width: auto; }
}

@media (prefers-reduced-motion: reduce) {
    .dialer[data-state="incoming"] .dialer__dot { animation: none; }
}

/* ======================================================= dashboard */

.kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
    gap: 14px;
    margin-bottom: 20px;
}

.kpi {
    background: var(--card);
    border: 1px solid var(--rule);
    border-radius: 5px;
    padding: 15px 16px 14px;
    position: relative;
    overflow: hidden;
}

/* A colour bar rather than an icon: it names the measure without pretending
   a telephone glyph tells you anything a label does not. */
.kpi::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--muted);
}

.kpi--line::before { background: var(--line); }
.kpi--good::before { background: #2fbf8f; }
.kpi--bad::before  { background: var(--clay); }
.kpi--info::before { background: var(--role-supervisor); }

.kpi__label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
}

.kpi__value {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 27px;
    font-weight: 600;
    letter-spacing: -0.02em;
    margin-top: 3px;
}

.kpi__delta { font-size: 12px; margin-top: 4px; }
.kpi__delta.is-good  { color: var(--line); }
.kpi__delta.is-bad   { color: var(--clay); }
.kpi__delta.is-quiet { color: var(--muted); }

.is-bad { color: var(--clay); }
.is-quiet { color: var(--muted); }

/* ------------------------------------------------------------- grid */

.dash {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
    align-items: start;
}

.dash__wide { grid-column: span 2; }
.dash__tall { grid-row: span 2; }

@media (max-width: 1080px) {
    .dash { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .dash__wide { grid-column: span 2; }
    .dash__tall { grid-row: auto; }
}

@media (max-width: 760px) {
    .dash { grid-template-columns: 1fr; }
    .dash__wide { grid-column: span 1; }
}

/* ------------------------------------------------------------ chart */

.chart { width: 100%; height: auto; }
.chart__tick { font-size: 9px; fill: var(--muted); font-family: var(--mono); }

.legend { display: flex; gap: 16px; margin-top: 10px; font-size: 12.5px; color: var(--muted); }
.legend i, .keys i {
    display: inline-block;
    width: 9px; height: 9px;
    border-radius: 2px;
    margin-right: 6px;
    vertical-align: middle;
}

/* ------------------------------------------------------------ donut */

.donut__wrap { display: flex; gap: 16px; align-items: center; }
.donut { width: 132px; height: 132px; flex: none; }

.donut__figure {
    text-anchor: middle;
    font-family: var(--mono);
    font-size: 26px;
    font-weight: 600;
    fill: var(--ink);
}

.donut__caption {
    text-anchor: middle;
    font-size: 9px;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    fill: var(--muted);
}

.keys { list-style: none; margin: 0; padding: 0; font-size: 13.5px; flex: 1; min-width: 0; }
.keys li { padding: 4px 0; display: flex; align-items: center; }
.keys .num { margin-left: auto; font-family: var(--mono); color: var(--muted); }

/* ------------------------------------------------------------- feed */

.feed { list-style: none; margin: 0; padding: 0; }

.feed__item {
    display: flex;
    gap: 12px;
    padding: 11px 16px;
    border-bottom: 1px solid var(--rule);
    border-left: 3px solid transparent;
    font-size: 14px;
}

.feed__item:last-child { border-bottom: 0; }
.feed__item--answered { border-left-color: var(--line); }
.feed__item--missed   { border-left-color: var(--clay); }
.feed__item--other    { border-left-color: var(--muted); }

.feed__when { font-size: 12.5px; color: var(--muted); padding-top: 1px; flex: none; }
.feed__detail { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

/* --------------------------------------------------------- quality */

.score {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: 15px;
    padding: 1px 7px;
    border-radius: 3px;
    border: 1px solid currentColor;
}

.score--good { color: var(--line); }
.score--fair { color: var(--amber); }
.score--bad  { color: var(--clay); }

/* ------------------------------------------------------- price card */

.pricecard {
    border: 1px solid var(--rule);
    border-radius: 5px;
    padding: 16px;
    margin-bottom: 14px;
    background: var(--card);
}

.pricecard__head { display: flex; justify-content: space-between; gap: 14px; align-items: flex-start; }
.pricecard__name { font-weight: 650; font-size: 16px; }
.pricecard__tagline { font-size: 13px; color: var(--muted); margin-top: 2px; }
.pricecard__price { text-align: right; }
.pricecard__price > .mono { font-size: 19px; font-weight: 600; }
.pricecard__alt { font-size: 13px; color: var(--muted); }
.pricecard__per { font-size: 11.5px; color: var(--muted); }

.pricecard__list { list-style: none; padding: 0; margin: 12px 0 14px; font-size: 13.5px; }
.pricecard__list li { padding: 3px 0; color: var(--muted); }
.pricecard__list li::before { content: '✓ '; color: var(--line); }

/* --------------------------------------------------------- upgrade */

.upgrade {
    display: flex;
    gap: 18px;
    justify-content: space-between;
    align-items: flex-start;
    padding: 14px 0;
    border-bottom: 1px solid var(--rule);
}

.upgrade:last-of-type { border-bottom: 0; }
.upgrade__name { font-weight: 650; font-size: 15px; }

.upgrade__limits { list-style: none; padding: 0; margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.upgrade__limits li { padding: 1px 0; }
.upgrade__limits li::before { content: '· '; }

.upgrade__buy { text-align: right; min-width: 190px; }
.upgrade__price { font-size: 19px; font-weight: 600; }

@media (max-width: 640px) {
    .upgrade { flex-direction: column; }
    .upgrade__buy { text-align: left; min-width: 0; }
}

/* ------------------------------------------------------------ chat */

.chat { display: flex; flex-direction: column; gap: 10px; max-height: 460px; overflow-y: auto; }

.chat__row { display: flex; }
.chat__row--in  { justify-content: flex-start; }
.chat__row--out { justify-content: flex-end; }

.chat__bubble {
    max-width: 78%;
    padding: 9px 12px;
    border-radius: 10px;
    font-size: 14px;
    line-height: 1.45;
    background: #eef2f1;
    color: var(--ink);
}

.chat__row--out .chat__bubble { background: var(--bar); color: #fff; }

.chat__meta { font-size: 11px; margin-top: 4px; opacity: .7; }

.progress {
    height: 6px;
    background: var(--rule);
    border-radius: 3px;
    overflow: hidden;
    max-width: 160px;
}

.progress__fill { height: 100%; background: var(--line); }

.timeline__item--sms::before { background: #1d6fa5; }

/*
 * A key pressed on the keyboard lights the one on screen.
 *
 * Feedback matters most on a call, where the digit travels down the line
 * rather than into the box — without this there would be no sign at all that
 * a tone had been sent.
 */
.dialer .dialpad button.is-pressed {
    background: var(--line);
    border-color: var(--line);
    color: #fff;
}

@media (prefers-reduced-motion: no-preference) {
    .dialer .dialpad button { transition: background 90ms linear, color 90ms linear; }
}

/* ------------------------------------------- the phone in its own window */

/*
 * The window is the panel. No floating, no shadow, no corner — it fills what
 * the agent sized it to.
 */
.phonewindow { background: #0f1a1d; padding: 0; margin: 0; }

.phonewindow .dialer {
    position: static;
    width: 100%;
    max-width: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

.phonewindow .dialer__min[id="dialer-toggle"] { display: none; }

/* Shown on ordinary pages when another window holds the phone. */
.dialer__deferred {
    padding: 14px;
    border-top: 1px solid #24393f;
}

.dialer__deferred p {
    margin: 8px 0 12px;
    font-size: 12.5px;
    line-height: 1.5;
    color: #8ba39e;
}

.dialer[data-deferred="1"] .dialer__body { display: none; }


/* ------------------------------------------------ nav-drawer: mobile menu */

/*
 * The rail as a drawer on a narrow screen.
 *
 * The ≤900px rules further up turn the rail into a horizontal strip and give
 * each group its own `overflow-x: auto`. That works for one group. With six,
 * a phone shows six separate sideways-scrolling rows stacked on each other,
 * and the sections at the end are unreachable without scrolling every row.
 *
 * So below 900px the rail goes back to being what it is on a desktop and
 * slides in over the page instead of sitting above it. Nothing about the
 * desktop layout changes.
 *
 * Layering, deliberately: scrim 50, drawer 55, incoming call 60, softphone 70.
 * A live call outranks a menu, so neither the ring card nor the softphone is
 * dimmed or covered by it.
 */

.navtoggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    cursor: pointer;
    flex: none;
}

.navtoggle:hover { background: rgba(255, 255, 255, 0.2); }
.navtoggle svg { width: 18px; height: 18px; }
.navtoggle__close { display: none; }
body[data-nav="open"] .navtoggle__open { display: none; }
body[data-nav="open"] .navtoggle__close { display: block; }

@media (max-width: 900px) {
    .navtoggle { display: inline-flex; }

    .shell { flex-direction: row; }

    .rail {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        height: auto;
        width: min(284px, 84vw);
        flex-direction: column;
        flex-wrap: nowrap;
        align-items: stretch;
        padding-bottom: 0;
        overflow-y: auto;
        z-index: 55;
        transform: translateX(-100%);
        transition: transform 180ms ease;
        box-shadow: 0 0 40px rgba(0, 0, 0, 0.45);
    }

    body[data-nav="open"] .rail { transform: translateX(0); }

    .rail__brand { padding: 18px 18px 16px; }
    .rail__group { display: block; padding: 6px 0 10px; overflow: visible; }
    .rail__heading { display: block; }

    .rail a.rail__link {
        border-left: 3px solid transparent;
        border-bottom: 0;
        white-space: normal;
        padding: 10px 16px;
    }

    .rail a.rail__link[aria-current="page"] {
        border-left-color: var(--line);
        border-bottom-color: transparent;
    }

    .rail__foot {
        margin: auto 0 0 0;
        border-top: 1px solid rgba(255, 255, 255, 0.09);
        padding: 14px 16px 16px;
    }

    /* A pseudo-element, so the drawer needs no extra markup anywhere. */
    .workspace::before {
        content: "";
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        opacity: 0;
        pointer-events: none;
        transition: opacity 180ms ease;
        z-index: 50;
    }

    body[data-nav="open"] .workspace::before {
        opacity: 1;
        pointer-events: auto;
    }
}


/* ------------------------------------------------------ pricegrid: plans */

/*
 * Plans side by side.
 *
 * The sign-in panel is capped at 400px, which is right for a sign-in form and
 * is why the plans stacked into one tall column. Rather than give the pricing
 * page a layout of its own, the cap is lifted only where a .pricegrid is
 * actually present — so this file still knows nothing about routes, and no
 * other guest page moves a pixel.
 *
 * The cards also stop putting the name on the left and the price on the right.
 * In a 240px column that wraps into itself, which is how "KES 6" ended up
 * sitting on top of "$1.20".
 */

.guest__panel:has(.pricegrid) { max-width: 1060px; }

.pricegrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 14px;
    align-items: stretch;
}

/* Equal height, with the button on the floor of every card. */
.pricegrid .pricecard {
    margin-bottom: 0;
    display: flex;
    flex-direction: column;
}

.pricegrid .pricecard__list { flex: 1; }

.pricegrid .pricecard__head {
    display: block;
}

.pricegrid .pricecard__price {
    text-align: left;
    margin-top: 10px;
}

.pricegrid .pricecard__price > .mono { font-size: 21px; }

/* Flush with the headline price above it. The two are the same number in
   two currencies, so anything but a shared left edge reads as a misalignment. */
.pricegrid .pricecard__alt { font-size: 13px; }

/* One column on a phone, where side by side is just small type. */
@media (max-width: 560px) {
    .pricegrid { grid-template-columns: 1fr; }
}


/* =================================================== guest-design: front door */

/*
 * The pages somebody sees before they are signed in.
 *
 * Two different people arrive at the same URL. An agent opens this at the
 * start of every shift and wants the form and nothing else. A business owner
 * arrives having never seen the product and needs to be told what it is and
 * offered a way in. The old page served the first well and the second not at
 * all — a 400px card on grey, with the only route to signing up set as grey
 * small print beneath it.
 *
 * So: the sign-in card stays disciplined, because it is used daily, and gains
 * an explicit second action in a band of its own. Pricing gets room and
 * weight, because it is read once and has to do a job.
 *
 * Nothing here invents a colour. --line and --bar are overridden per
 * organisation for white-label, so neither is ever load-bearing for
 * legibility: if --line becomes orange tomorrow, every one of these rules
 * still reads.
 */

.guest {
    align-items: flex-start;
    padding: clamp(24px, 7vh, 72px) 18px 48px;
}

.guest__panel--wide { max-width: 940px; }

/* The wordmark, set in the face the product reads numbers in. */
.guest__brand {
    margin-bottom: 10px;
    font-family: var(--mono);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

/*
 * The live line.
 *
 * A rule with the node at its head — the same idiom as the dot beside the
 * name in the app's own rail, and the same thing the product is about: a
 * connection being made. One draw on load, then it holds still. This is the
 * only motion on the page and the only ornament; everything else earns its
 * place by carrying information.
 */
.guest__line {
    position: relative;
    height: 2px;
    margin-bottom: 18px;
    background: var(--rule);
    overflow: visible;
}

.guest__line span {
    position: absolute;
    inset: 0 auto 0 0;
    width: 100%;
    background: var(--line);
    transform-origin: left center;
    transform: scaleX(1);
}

.guest__line span::after {
    content: "";
    position: absolute;
    right: -3px;
    top: -3px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--line);
    /* Slate-based, not accent-based: --line is overridden per organisation
       for white-label, and a halo in last tenant's teal around this tenant's
       orange node is exactly the kind of detail that looks broken. */
    box-shadow: 0 0 0 3px rgba(18, 48, 58, 0.10);
}

@media (prefers-reduced-motion: no-preference) {
    .guest__line span {
        animation: guest-line 620ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
    }
}

@keyframes guest-line {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

.guest__title { font-size: 26px; letter-spacing: -0.02em; margin-bottom: 6px; }

/* A heading sitting straight on top of the first label reads as one block
   of text rather than a title and a form. */
.card__body > .guest__title + form,
.card__body > .guest__title + .notice { margin-top: 18px; }

.guest__lead {
    margin: 0 0 20px;
    color: var(--muted);
    font-size: 14.5px;
    max-width: 62ch;
}

.card__body > .guest__title:first-child { margin-top: 2px; }

/* A way back, where there used to be none. */
.backlink {
    display: inline-block;
    margin-bottom: 14px;
    font-size: 13px;
    color: var(--muted);
    text-decoration: none;
}

.backlink::before { content: "\2190"; margin-right: 6px; }
.backlink:hover { color: var(--ink); text-decoration: underline; }

/*
 * The second action, in a band of its own.
 *
 * Tinted rather than white so it reads as a different offer from the form
 * above it, and separated by a rule rather than by whitespace, because the
 * two are genuinely different things to do and not two steps of one thing.
 */
.guest__cardfoot {
    padding: 16px;
    border-top: 1px solid var(--rule);
    background: #f6f8f7;
    border-radius: 0 0 3px 3px;
}

.guest__cardfoot-lead {
    margin: 0 0 10px;
    font-size: 14px;
    font-weight: 600;
}

.btn--wide { display: block; width: 100%; text-align: center; padding: 11px 16px; }

.checkline {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 400;
    font-size: 13.5px;
    margin: 2px 0 18px;
}

.checkline input { width: auto; margin: 0; }

.guest__foot { margin-top: 18px; }
.guest__foot a { color: var(--line); }

/* ------------------------------------------------------------ the plans */

.pricegrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 16px;
    align-items: stretch;
    margin-bottom: 20px;
}

.pricegrid .pricecard {
    margin-bottom: 0;
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
}

.pricegrid .pricecard__head {
    display: block;
    padding: 16px 18px 14px;
    border-bottom: 1px solid var(--rule);
}

/*
 * One card carries the weight.
 *
 * Hierarchy by ink rather than by sticker: a "most popular" ribbon is a claim
 * about other customers that we have no numbers to support, while a heavier
 * head is just the shop pointing at a shelf.
 */
.pricegrid .pricecard--lead { border-color: var(--slate); }

.pricegrid .pricecard--lead .pricecard__head {
    background: var(--slate);
    border-bottom-color: var(--slate);
    color: #fff;
}

.pricegrid .pricecard--lead .pricecard__tagline { color: rgba(255, 255, 255, 0.72); }

.pricegrid .pricecard__name { font-size: 17px; font-weight: 650; }
.pricegrid .pricecard__tagline { margin-top: 3px; font-size: 13px; }

.pricegrid .pricecard__price { padding: 16px 18px 4px; text-align: left; }

.pricecard__amount {
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.1;
}

.pricegrid .pricecard__per { font-size: 13px; color: var(--muted); margin-left: 6px; }
.pricegrid .pricecard__alt { font-size: 13px; color: var(--muted); margin-top: 2px; }

.pricegrid .pricecard__list {
    flex: 1;
    margin: 14px 0 18px;
    padding: 0 18px;
    font-size: 14px;
    color: var(--ink);
}

/*
 * The tick is gone. It said nothing — every line is included, so a column of
 * ticks is one mark repeated. The number is the information, so the number
 * leads, in the face the rest of the product sets figures in.
 */
.pricegrid .pricecard__list li {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 5px 0;
    color: var(--ink);
}

.pricegrid .pricecard__list li::before { content: none; }

.pricecard__n {
    min-width: var(--planlines-col, 48px);
    font-weight: 600;
    font-size: 14.5px;
    color: var(--ink);
    text-align: right;
    flex: none;
}

.pricegrid .pricecard .btn { margin: 0 18px 18px; width: calc(100% - 36px); }

.pricefoot {
    margin: 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--muted);
    max-width: 72ch;
}

.pricefoot a { color: var(--line); }

/* Read aloud, never seen: the infinity glyph says "unlimited" to the eye and
   nothing useful to a screen reader. */
.vh {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* One column on a phone, where side by side is just small type. */
@media (max-width: 580px) {
    .pricegrid { grid-template-columns: 1fr; }
    .guest__title { font-size: 23px; }
}


/* The way back in, beside the password rather than buried under the card. */
.forgotline { margin: -8px 0 14px; font-size: 13px; text-align: right; }
.forgotline a { color: var(--muted); }
.forgotline a:hover { color: var(--line); }



/* ============================================ pricing: currency, own lines */

/*
 * The heading and the currency switch on one line, and under each other on a
 * phone where side by side leaves the switch hanging off the measure.
 */
.priceheader {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 18px;
    flex-wrap: wrap;
}

.priceheader > div:first-child { flex: 1 1 320px; }

/*
 * A segmented control made of links rather than a <select>.
 *
 * Two or three currencies is a choice you make by looking, not by opening a
 * menu — and links mean the page needs no script, survives a browser with
 * JavaScript off, and leaves a URL that can be pasted into an email showing
 * the same prices the sender saw.
 */
.curswitch {
    display: inline-flex;
    border: 1px solid var(--rule);
    border-radius: 8px;
    overflow: hidden;
    flex: 0 0 auto;
    margin-top: 4px;
}

.curswitch__opt {
    padding: 7px 14px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--muted);
    text-decoration: none;
    background: transparent;
    transition: background 120ms ease, color 120ms ease;
}

.curswitch__opt + .curswitch__opt { border-left: 1px solid var(--rule); }
.curswitch__opt:hover { color: var(--ink); background: rgba(0, 0, 0, 0.03); }

.curswitch__opt.is-on {
    background: var(--slate);
    color: #fff;
}

/*
 * Your own lines sit in the same list as the limits, but they are sentences
 * rather than counts, so they get no figure. They are indented to the text
 * column all the same — starting them at the card's left edge would leave the
 * list ragged down the middle, and a wrapped line has to come back to the
 * same place as the one above it.
 *
 * A hairline divides the two kinds. Above it, things the app counts. Below
 * it, things we are telling you.
 */
 * These rules live with .planlines further down, so that the public pricing
 * card and the in-app upgrade list describe a plan identically. Only the
 * font size differs here, because a pricing card has more room than a row in
 * a list.
 */
.pricegrid .pricecard__list li.pricecard__free { font-size: 13px; }


/* ================================================ number pricing: one table */

/*
 * One block per kind of number, rather than a row per field in a long form.
 * There are four kinds and six figures each, and a flat list of twenty-four
 * inputs is a form nobody can check their own work in.
 */
.pricerow {
    border: 1px solid var(--rule);
    border-radius: 10px;
    padding: 14px 16px;
    margin-bottom: 14px;
}

.pricerow__head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
    margin-bottom: 12px;
}

.pricerow__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 0 14px;
}

/* The currency pairs stay together when the row has to wrap. */
@media (max-width: 620px) {
    .pricerow__grid { grid-template-columns: repeat(2, 1fr); }
}


/* ======================================================= wallet: two balances */

/*
 * Two figures, side by side, because the whole point is that they are
 * different numbers meaning different things. Stacking them would invite the
 * reader to add them up, which is exactly the sum that is not true yet.
 */
.walletbar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 14px;
    margin-bottom: 18px;
}

.walletbar__box {
    background: var(--card);
    border: 1px solid var(--rule);
    border-radius: 10px;
    padding: 16px 18px;
}

.walletbar__label {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
}

.walletbar__figure {
    font-size: 26px;
    font-weight: 600;
    margin: 6px 0 4px;
    color: var(--ink);
}

.walletbar__note { font-size: 12.5px; color: var(--muted); line-height: 1.55; }

/*
 * One organisation per block, with the balance box right beside the name.
 * Loading credit means reading a figure off another screen and typing it
 * here, and anything that makes you scroll between the two is a chance to
 * type it against the wrong customer.
 */
.loadrow {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 18px;
    border-top: 1px solid var(--rule);
}

.loadrow__who { flex: 1 1 260px; }

.loadrow__form {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    flex-wrap: wrap;
}

.loadrow__form .field { min-width: 140px; }


/* ========================================== pricegrid: a fixed number across */

/*
 * auto-fit was doing the wrong thing with four plans.
 *
 * It fits as many columns as the width allows, which at this panel width is
 * three — so the fourth plan dropped to its own row, alone and full width,
 * reading as an afterthought rather than the top of the range. The count is
 * now explicit: four plans mean four columns, and the panel widens to hold
 * them.
 */
.pricegrid--2 { grid-template-columns: repeat(2, 1fr); }
.pricegrid--3 { grid-template-columns: repeat(3, 1fr); }
.pricegrid--4 { grid-template-columns: repeat(4, 1fr); }

.guest__panel:has(.pricegrid--4) { max-width: 1280px; }

/* Two by two on a laptop, where four columns would each be too narrow to
   read a feature line in. */
@media (max-width: 1100px) {
    .pricegrid--4 { grid-template-columns: repeat(2, 1fr); }
    .guest__panel:has(.pricegrid--4) { max-width: 760px; }
}

@media (max-width: 760px) {
    .pricegrid--3 { grid-template-columns: repeat(2, 1fr); }
}

/* One column on a phone, for every count. */
@media (max-width: 560px) {
    .pricegrid--2,
    .pricegrid--3,
    .pricegrid--4 { grid-template-columns: 1fr; }
}

/*
 * Bullets on the lines you write yourself.
 *
 * The counted lines above them lead with a figure, which is its own marker.
 * These are sentences, and without anything at the left edge they read as a
 * paragraph that happens to have line breaks.
 */
.planlines li.pricecard__free { position: relative; }

.planlines li.pricecard__free::before {
    content: '•';
    position: absolute;
    left: calc(var(--planlines-col) - 4px);
    color: var(--line);
}


/* ====================================================== pricing: centred */

/*
 * The heading, the lead and the footnote sit on the centre line.
 *
 * The switcher moves under the heading rather than out to the right: with
 * centred text beside it, a control pinned to one edge reads as having come
 * loose from the thing it belongs to.
 */
.priceheader {
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    text-align: center;
    gap: 12px;
}

.priceheader > div:first-child {
    flex: 0 1 auto;
    max-width: 68ch;
}

.priceheader .guest__lead {
    margin-left: auto;
    margin-right: auto;
}

.pricefoot {
    text-align: center;
    margin-left: auto;
    margin-right: auto;
}

/*
 * The two switches — billing cycle and currency — on one line under the
 * heading, wrapping to two on a phone.
 *
 * Side by side rather than stacked because they answer different questions
 * about the same number, and a reader who changes one usually wants to see
 * the other without hunting for it.
 */
.priceswitches {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    /* Wide enough that two segmented controls side by side read as two
       controls. At 10px the last cycle button and the first currency button
       sat against each other and looked like one row of five choices. */
    gap: 22px;
}

/*
 * The saving, under the price.
 *
 * Quiet on purpose. The figure that matters is the total above it; this is
 * the reassurance that the discount was applied, not a second headline
 * competing with the first.
 */
/* Consecutive footnotes are separate thoughts and need to look it. */
.pricefoot + .pricefoot { margin-top: 12px; }

.pricecard__save {
    margin: -6px 18px 14px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--muted);
}

.pricecard__pct {
    display: inline-block;
    margin-right: 6px;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--green-50, rgba(18, 122, 90, 0.10));
    color: var(--green-700, #0C6B4F);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
}

/* The lead card's head is dark; the chip needs to lift off it, not sink in. */
.pricecard--lead .pricecard__pct {
    background: rgba(18, 122, 90, 0.14);
}

@media (max-width: 640px) {
    .priceswitches { width: 100%; }
    .priceswitches .curswitch { flex: 1 1 auto; justify-content: center; }
    .curswitch__opt { flex: 1 1 auto; text-align: center; }
}

/* ============================================ pricing table: refinement pass
 *
 * Polish inside the existing language rather than a new one: flat cards, a
 * single dark head for the plan being pointed at, figures in the mono face.
 * The emphasis stays in one place — the lead card's head — so the other three
 * are left quiet. A drop shadow under all four would make the page louder
 * without making it clearer, and the lift would then be saying the same thing
 * the dark head already says.
 */

/* Air under the cycle switch. It was sitting on the cards, which read as the
   switch belonging to the first card rather than to all of them. */
.priceswitches { margin-top: 10px; margin-bottom: 34px; }

.pricegrid { gap: 18px; margin-bottom: 30px; }

.pricegrid .pricecard {
    border-radius: 10px;
    border-color: var(--rule);
    transition: border-color 140ms ease;
}

/*
 * Every head the same height, whether or not the plan has a tagline.
 *
 * Without this, a plan with no tagline has a shorter head and its price sits
 * at a different height from the others — which is the one thing a row of
 * prices must not do, because the eye compares them across.
 */
.pricegrid .pricecard__head {
    padding: 18px 20px 16px;
    min-height: 74px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* The lead card is the only thing raised off the page. */
.pricegrid .pricecard--lead {
    box-shadow: 0 10px 28px -14px rgba(18, 63, 102, 0.45);
}

/* The price, given room to be the thing you read first. */
.pricegrid .pricecard__price {
    padding: 20px 20px 2px;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 7px;
}

.pricecard__amount { font-size: 29px; letter-spacing: -0.025em; }
.pricegrid .pricecard__per { margin-left: 0; }

.pricecard__save { margin: 8px 20px 0; }

.pricegrid .pricecard__list { margin: 18px 0 20px; padding: 0 20px; }
.pricegrid .pricecard__list li { padding: 6px 0; }

.pricegrid .pricecard .btn {
    margin: 0 20px 20px;
    width: calc(100% - 40px);
    padding-top: 12px;
    padding-bottom: 12px;
}

/* A quiet acknowledgement that the card is pointed at, and nothing more. */
.pricegrid .pricecard:hover { border-color: var(--line); }
.pricegrid .pricecard--lead:hover { border-color: var(--slate); }

/*
 * The footnote runs the width of the plans above it and sits on their centre
 * line. Held to 72ch it stopped short of the table and read as a caption for
 * the left-hand card rather than a note about all four.
 */
.pricefoot {
    max-width: 90%;
    width: 90%;
    margin: 0 auto;
    text-align: center;
    text-wrap: pretty;
}

@media (max-width: 860px) {
    .pricegrid .pricecard__head { min-height: 0; }
    .pricefoot { max-width: 100%; width: 100%; }
}

/*
 * The saving, as two lines rather than one sentence that wraps wherever the
 * card width happens to put it.
 *
 * First line: the chip and the rate they are actually getting — that is the
 * pair being compared. Second line: the figure it replaces, quieter, because
 * it is the thing they are NOT paying.
 */
.pricecard__rate { font-weight: 600; color: var(--ink); margin-left: 7px; }

.pricecard__was {
    display: block;
    margin-top: 2px;
    font-size: 12px;
    color: var(--muted);
}

/* ============================================ plan lines, wherever they appear
 *
 * The structure the shared partial emits, written unscoped so it renders the
 * same in the public pricing card and in the in-app upgrade list. The rules
 * under .pricegrid stay as they are and still win inside a pricing card —
 * these are what make the list look like itself everywhere else.
 */
.planlines {
    list-style: none;
    padding: 0;
    /* The width of the figure column. Fixed rather than em-based: the figure
       and the free-text lines below it sit at different font sizes, so an em
       here means two different columns and text that does not line up. */
    --planlines-col: 48px;
}

.planlines li {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 4px 0;
}

/* The figure is the information, so it is inked even where the row is muted. */
.planlines .pricecard__n { color: var(--ink); }

/* No marker. The number already starts the line, and a bullet in front of it
   reads as a second, competing start. */
.planlines li::before { content: none; }

/*
 * Free-text lines sit under the figures rather than beside them: they are
 * sentences, not counts, so they get no number column — but they still begin
 * at the text column, because a wrapped line has to return to where the line
 * above it started.
 */
.planlines li.pricecard__free {
    padding-left: calc(var(--planlines-col) + 9px);
    color: var(--muted);
}

.planlines li:not(.pricecard__free) + li.pricecard__free {
    border-top: 1px solid var(--rule);
    margin-top: 7px;
    padding-top: 10px;
}

/* In the upgrade list the whole block is secondary to the price beside it. */
.upgrade__limits.planlines { margin: 10px 0 0; font-size: 13px; }
.upgrade__limits.planlines li { padding-top: 3px; padding-bottom: 3px; }
.upgrade__limits.planlines li.pricecard__free { font-size: 12.5px; }
