/* ==========================================================================
   Clara Codex design system — plain CSS, no build step.
   Mobile first: phone (~360px) → tablet (≥768px) → desktop (≥1024px).
   Tenant colours override --brand / --brand-strong / --brand-contrast.
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
    color-scheme: light;

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

    --text-xs: 0.75rem;
    --text-sm: 0.875rem;
    --text-md: 1rem;
    --text-lg: 1.125rem;
    --text-xl: 1.375rem;
    --text-2xl: 1.75rem;

    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;

    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 16px;

    --tap: 44px;
    --sidebar-width: 256px;
    --bottom-bar-height: 64px;
    --topbar-height: 56px;

    --brand: #2563eb;
    --brand-strong: #1d4ed8;
    --brand-soft: #dbeafe;
    --brand-contrast: #ffffff;

    --bg: #f4f6fa;
    --surface: #ffffff;
    --surface-2: #f8fafc;
    --surface-sunken: #eef1f6;
    --border: #dfe4ec;
    --border-strong: #c5cdd9;
    --text: #111827;
    --text-muted: #5b6474;
    --text-subtle: #8a93a3;

    --success: #15803d;
    --success-soft: #dcfce7;
    --success-bright: #22c55e; /* the ring and line around an Online badge (C230) */
    --warning: #b45309;
    --warning-soft: #fef3c7;
    --danger: #b91c1c;
    --danger-bright: #ef4444; /* … and an Offline one (C230) */
    --danger-soft: #fee2e2;
    --info: #1d4ed8;
    --info-soft: #dbeafe;

    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
    --shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
    --shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.18);
    --tip-bg: #1f2530; /* every tooltip: dark in both themes, like the browser's own (C140) */
    --tip-text: #f3f4f6;
    --tip-border: rgba(255, 255, 255, 0.14);
    --focus: 0 0 0 3px color-mix(in srgb, var(--brand) 35%, transparent);
}

/* Light is the default for everyone; dark only when chosen with the toggle (data-theme="dark"). */
:root[data-theme="dark"] {
    color-scheme: dark;
    --brand: #60a5fa;
    --brand-strong: #93c5fd;
    --brand-soft: #172a4a;
    --brand-contrast: #0b1220;
    --bg: #0b1016;
    --surface: #121922;
    --surface-2: #17202b;
    --surface-sunken: #0e141b;
    --border: #243040;
    --border-strong: #334155;
    --text: #e5e9f0;
    --text-muted: #a3adbd;
    --text-subtle: #768194;
    --success: #4ade80;
    --success-soft: #0f2a1a;
    --success-bright: #86efac;
    --warning: #fbbf24;
    --warning-soft: #2e2208;
    --danger: #f87171;
    --danger-bright: #fca5a5;
    --danger-soft: #331214;
    --info: #93c5fd;
    --info-soft: #132440;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.6);
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--text-md);
    line-height: 1.5;
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 var(--space-3); line-height: 1.25; font-weight: 650; }
h1 { font-size: var(--text-xl); }
h2 { font-size: var(--text-lg); }
h3 { font-size: var(--text-md); }
p { margin: 0 0 var(--space-3); }
a { color: var(--brand); text-underline-offset: 2px; }
a:hover { color: var(--brand-strong); }
code, .mono { font-family: var(--font-mono); font-size: 0.92em; }
hr { border: 0; border-top: 1px solid var(--border); margin: var(--space-5) 0; }
img, svg { max-width: 100%; }

:focus-visible { outline: none; box-shadow: var(--focus); border-radius: var(--radius-sm); }

.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.skip-link {
    position: absolute; left: var(--space-3); top: -100px; z-index: 100;
    background: var(--surface); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
}
.skip-link:focus { top: var(--space-3); }

.icon { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.icon-sm { width: 16px; height: 16px; }

.muted { color: var(--text-muted); }
.subtle { color: var(--text-subtle); }
.small { font-size: var(--text-sm); }
.nowrap { white-space: nowrap; }
.text-right { text-align: right; }
.num { font-variant-numeric: tabular-nums; }

/* ---------- App shell ---------- */
.app {
    min-height: 100vh;
    min-height: 100dvh;
    padding-bottom: calc(var(--bottom-bar-height) + env(safe-area-inset-bottom));
}

.topbar {
    position: sticky; top: 0; z-index: 30;
    display: flex; align-items: center; gap: var(--space-3);
    height: var(--topbar-height);
    padding: 0 var(--space-4);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}
.topbar-title { font-weight: 650; font-size: var(--text-md); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar .brand-mark { width: 32px; height: 32px; }

.brand { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; color: var(--text); font-weight: 700; }
.brand-mark {
    display: grid; place-items: center; width: 36px; height: 36px; flex: none;
    border-radius: var(--radius); background: var(--brand); color: var(--brand-contrast);
    font-weight: 800; font-size: var(--text-sm);
}
.brand-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Content uses the full width, with 5% space on each side. */
.main { padding: var(--space-4) max(var(--space-4), 2%); } /* 2% each side (owner), never under 16px on phones */

/* Sidebar (redesigned in 0.7.144, C143; the one before: docs/Original_Sidebar_Design.md). A drawer on phone and
   tablet, fixed on desktop and collapsible there to icons (remembered on the device). */
.sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 50;
    width: min(86vw, var(--sidebar-width));
    display: flex; flex-direction: column;
    background: var(--surface);
    border-right: 1px solid var(--border);
    transform: translateX(-100%);
    transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1), width 0.22s ease;
    visibility: hidden;
}
.sidebar.is-open { transform: none; visibility: visible; box-shadow: var(--shadow-lg); }
.sidebar-head { display: flex; align-items: center; gap: var(--space-2); min-height: 64px; padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); }
.sidebar-head .brand { flex: 1; min-width: 0; }
.sidebar-collapse, .brand-mark-collapsed { display: none; }
.sidebar-nav { position: relative; flex: 1; overflow-x: hidden; overflow-y: auto; padding: var(--space-2) var(--space-3) var(--space-3); scrollbar-width: thin; }
.nav-group + .nav-group { margin-top: var(--space-1); }
/* A group's heading opens and closes it (C144): in capitals, a chevron that turns; the items slide open and shut. */
.sidebar-section { display: flex; align-items: center; justify-content: space-between; width: 100%; min-height: 32px; margin: var(--space-2) 0 0; padding: 0 var(--space-3);
    border: 0; border-radius: var(--radius-sm); background: none; font: inherit; font-size: 13px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; /* headings in capitals (owner, C145), 13 px (C148) */
    color: var(--text-subtle); white-space: nowrap; overflow: hidden; cursor: pointer; transition: color 0.15s ease, background-color 0.15s ease; }
.sidebar-section:hover { color: var(--text); background: var(--surface-2); }
.sidebar-section { position: relative; }
/* A group heading's tracing border while hovered or focused (C147, app.js): a short brand-colour line going round. */
.heading-trace { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.heading-trace path { fill: none; stroke: var(--brand); stroke-width: 1.5; stroke-linecap: round; stroke-dasharray: 22 78; animation: heading-trace 1.6s linear infinite; }
@keyframes heading-trace { from { stroke-dashoffset: 0; } to { stroke-dashoffset: -100; } }
@media (prefers-reduced-motion: reduce) { .heading-trace path { animation: none; stroke-dasharray: none; } }
.sidebar-section .icon { flex: none; transform: rotate(90deg); transition: transform 0.31s ease; } /* 25% slower (owner, C161) */
.nav-group.is-closed .sidebar-section .icon { transform: rotate(0deg); }
.nav-group-items { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 0.35s cubic-bezier(0.2, 0.8, 0.2, 1); } /* 25% slower (owner, C161) */
.nav-group-items > div { min-height: 0; overflow: hidden; }
.nav-group.is-closed .nav-group-items { grid-template-rows: 0fr; }
.nav-group.is-closed .nav-group-items .nav-link { visibility: hidden; transition: visibility 0s 0.35s; } /* not reachable with Tab while shut */

.nav-link {
    position: relative;
    display: flex; align-items: center; gap: var(--space-3);
    min-height: 40px; margin: 2px 0; padding: 0 var(--space-3);
    border-radius: var(--radius);
    color: var(--text-muted); text-decoration: none; font-weight: 550; white-space: nowrap;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.nav-link .icon { flex: none; transition: transform 0.18s ease; }
.nav-link:hover { background: var(--surface-2); color: var(--text); }
.nav-link:hover .icon { transform: translateX(2px) scale(1.06); }
.nav-link[aria-current="page"] { background: var(--brand-soft); color: var(--brand-strong); font-weight: 650; }
.nav-label { overflow: hidden; text-overflow: ellipsis; text-transform: capitalize; } /* Title Case (owner, C144) */
/* A bar at the left of the current page's link that glides to the link under the mouse and back (app.js). */
.nav-marker { position: absolute; left: 4px; top: 0; z-index: 2; width: 3px; height: 0; border-radius: 3px; background: var(--brand); opacity: 0; pointer-events: none;
    transition: top 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), height 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.2s ease; }
.nav-marker.is-still { transition: none; }

.sidebar-footer { padding: var(--space-3); border-top: 1px solid var(--border); }
.user-card { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2); border-radius: var(--radius); background: var(--surface-2); }
.user-avatar { display: grid; place-items: center; width: 36px; height: 36px; flex: none; border-radius: 50%; background: var(--brand); color: var(--brand-contrast); font-weight: 700; font-size: var(--text-sm); }
.user-card-text { display: grid; flex: 1; min-width: 0; line-height: 1.25; }
.user-card-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-sm); font-weight: 650; color: var(--text); }
.user-card-id { font-size: var(--text-xs); color: var(--text-subtle); }
.user-card-actions { display: flex; gap: 2px; }
.user-card-actions .btn-icon { width: 36px; min-height: 36px; }
.sidebar-version { margin-top: var(--space-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; font-size: 11px; color: var(--text-subtle); }

/* Opening the drawer: the links slide in. */
.sidebar.is-open .nav-link { animation: nav-in 0.32s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
@keyframes nav-in { from { opacity: 0; transform: translateX(-10px); } }

.scrim { position: fixed; inset: 0; z-index: 40; background: rgba(15, 18, 25, 0.45); backdrop-filter: blur(2px); animation: scrim-in 0.2s ease; }
.scrim[hidden] { display: none; }
@keyframes scrim-in { from { opacity: 0; } }

/* Bottom tab bar (phone/tablet only) */
.tabbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    height: calc(var(--bottom-bar-height) + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
    background: var(--surface);
    border-top: 1px solid var(--border);
}
.tab {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    min-width: 0; padding: var(--space-1);
    border: 0; background: none; font: inherit; cursor: pointer;
    color: var(--text-muted); text-decoration: none; font-size: 11px; font-weight: 550;
}
.tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-transform: capitalize; } /* Title Case like the menu (C144) */
.tab[aria-current="page"] { color: var(--brand); }
.tab .icon { width: 22px; height: 22px; }

.user-menu { display: flex; align-items: center; gap: var(--space-2); }

@media (min-width: 1024px) {
    .app { padding-bottom: 0; padding-left: var(--sidebar-width); transition: padding-left 0.22s ease; }
    .sidebar { transform: none; visibility: visible; width: var(--sidebar-width); box-shadow: none; }
    .sidebar .drawer-close { display: none; }
    .sidebar-collapse { display: inline-flex; }
    .tabbar, .scrim { display: none !important; }
    .topbar .brand { display: none; }
    .main { padding: var(--space-6) max(var(--space-4), 2%); }

    /* Collapsed to icons (C143): the header's button; remembered on this device (partials/head, app.js). */
    :root[data-sidebar="collapsed"] { --sidebar-width: 76px; }
    :root[data-sidebar="collapsed"] .sidebar-head { flex-direction: column; padding: var(--space-3) var(--space-2); }
    :root[data-sidebar="collapsed"] .sidebar-head .brand { justify-content: center; }
    :root[data-sidebar="collapsed"] .brand-name, :root[data-sidebar="collapsed"] .brand-logo-sidebar,
    :root[data-sidebar="collapsed"] .nav-label, :root[data-sidebar="collapsed"] .user-card-text, :root[data-sidebar="collapsed"] .sidebar-version { display: none; }
    :root[data-sidebar="collapsed"] .brand-mark-collapsed { display: grid; }
    :root[data-sidebar="collapsed"] .sidebar-nav { overflow: visible; padding: var(--space-2); }
    :root[data-sidebar="collapsed"] .sidebar-section { height: 1px; min-height: 0; margin: var(--space-3) var(--space-2) var(--space-2); padding: 0; font-size: 0; background: var(--border); pointer-events: none; }
    :root[data-sidebar="collapsed"] .sidebar-section .icon { display: none; }
    :root[data-sidebar="collapsed"] .nav-group.is-closed .nav-group-items { grid-template-rows: 1fr; }
    :root[data-sidebar="collapsed"] .nav-group.is-closed .nav-group-items .nav-link { visibility: visible; }
    :root[data-sidebar="collapsed"] .nav-group-items > div { overflow: visible; }
    :root[data-sidebar="collapsed"] .nav-link { justify-content: center; padding: 0; }
    :root[data-sidebar="collapsed"] .user-card { flex-direction: column; padding: var(--space-1) 0; background: none; }
    :root[data-sidebar="collapsed"] .user-card-actions { flex-direction: column; }
    /* Collapsed: each link's name in a tooltip beside it (the tooltip standard, C140). */
    :root[data-sidebar="collapsed"] .nav-link::after {
        content: attr(data-label); position: absolute; left: calc(100% + 12px); top: 50%; z-index: 60; transform: translate(-4px, -50%);
        padding: 4px 10px; border-radius: var(--radius-sm); border: 1px solid var(--tip-border); box-shadow: var(--shadow-lg);
        background: var(--tip-bg); color: var(--tip-text); font-size: var(--text-sm); font-weight: 550; white-space: nowrap; text-transform: capitalize;
        opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.12s ease, transform 0.12s ease;
    }
    :root[data-sidebar="collapsed"] .nav-link:hover::after, :root[data-sidebar="collapsed"] .nav-link:focus-visible::after { opacity: 1; visibility: visible; transform: translate(0, -50%); }
}

/* ---------- Page header ---------- */
.page-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-5); }
.page-header h1 { margin: 0; font-size: var(--text-2xl); }
.page-header p { margin: var(--space-1) 0 0; color: var(--text-muted); }
.page-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); margin-left: auto; } /* at the far right, also when a long title pushes them onto their own line (C125) */
.page-actions .toolbar { margin-bottom: 0; justify-content: flex-end; } /* e.g. a dashboard's period, beside its heading (owner, C203) */
.back-link { display: inline-flex; align-items: center; gap: var(--space-1); min-height: 32px; margin-bottom: var(--space-2); font-size: var(--text-sm); color: var(--text-muted); text-decoration: none; }

/* ---------- Cards and layout helpers ---------- */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); }
.card-body { padding: var(--space-4); }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-4); border-bottom: 1px solid var(--border); }
.card-head h2 { margin: 0; font-size: var(--text-md); }
/* A card heading with an icon tile (x-card-title, C324): the theme colour; green / amber / red only where it means something.
   Not .card-title: that is the first cell of a table-cards row (C325). */
.card-heading { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.card-icon { display: grid; place-items: center; flex: none; width: 34px; height: 34px; border-radius: var(--radius-sm); background: var(--brand); color: var(--brand-contrast); box-shadow: 0 2px 6px color-mix(in srgb, var(--brand) 30%, transparent); }
.card-icon .icon { width: 18px; height: 18px; }
.card-icon-success { background: var(--success); color: var(--surface); box-shadow: none; }
.card-icon-warning { background: var(--warning); color: var(--surface); box-shadow: none; }
.card-icon-danger { background: var(--danger); color: var(--surface); box-shadow: none; }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.card-foot { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: flex-end; padding: var(--space-4); border-top: 1px solid var(--border); background: var(--surface-2); border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
/* Stacked cards get a gap; cards side by side in a grid use the grid gap instead. */
:not(.grid) > .card + .card, .stack > * + * { margin-top: var(--space-4); }

.grid { display: grid; gap: var(--space-4); }
/* A main column and a second one beside it on wide screens (e.g. Settings → Email: settings | test and log, half each); stacked below 1024px. */
.grid-aside { align-items: start; }
.grid-top { align-items: start; } /* columns keep their own height, e.g. the client's Account card: Owing and credit | the estimate (C271) */
@media (min-width: 1024px) {
    .grid-aside { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } /* half and half (owner) */
    /* The second column is never taller than the main one: its last card (e.g. a log) fills what is left and scrolls. */
    .grid-aside > .aside-fill { contain: size; align-self: stretch; display: flex; flex-direction: column; min-height: 0; }
    .aside-fill > :last-child { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
    .aside-fill > :last-child > .card-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--space-3); }
    .aside-fill .terminal { flex: 1 1 auto; min-height: 6rem; max-height: none; } /* shrinks to the room left in the card (it scrolls), never spills out of it (C109) */
}
.log-card .card-body { display: flex; flex-direction: column; gap: var(--space-3); }
[role="status"]:empty { display: none; }
/* A heading with something beside it on the same row (e.g. "Test" and its ✓ Sent …); what follows wraps under it. */
.heading-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); }
.heading-row > h2 { margin: 0; }
.heading-row > .heading-row-status { flex: 1 1 auto; }
.heading-row-status { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); line-height: 1.5; max-height: calc(5 * 1.5em + var(--space-4) * 2); overflow-y: auto; } /* at most 5 lines (plus padding when shown as a message box); longer scrolls */
.heading-row-status > .small { flex-basis: 100%; margin: 0; }
.card-head.heading-row { align-items: center; justify-content: space-between; row-gap: var(--space-4); } /* a heading with a button at the far right, e.g. Check log + Copy log (C109) */
.card-head .btn { margin-block: calc((1.5rem - var(--tap)) / 2); } /* a button in a card heading keeps its 44px tap size but doesn't make the heading taller than a text-only one (C109) */
/* The outcome of a connection test (partials.test-result): ✓ Sent … / ✗ Failed … */
.test-result { margin: 0; font-weight: 600; }
.test-result.is-ok { color: var(--success); }
.test-result.is-bad { color: var(--danger); }
.test-result-mark { font-size: 1.15em; margin-right: var(--space-1); }
.saved-mark { margin-left: var(--space-1); color: var(--success); font-weight: 700; } /* a secret already saved (x-field :saved) */ /* a live message area takes no room until it says something */
@media (min-width: 768px) {
    .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .card-body, .card-head, .card-foot { padding: var(--space-5); }
}
@media (min-width: 1024px) {
    .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .grid-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
@media (min-width: 768px) and (max-width: 1023px) {
    .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .grid-5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.stat { padding: var(--space-4); }
.stat-label { font-size: var(--text-sm); color: var(--text-muted); }
.stat-value { font-size: var(--text-2xl); font-weight: 700; font-variant-numeric: tabular-nums; }
/* Hover/tap explanation of anything with data-hint (stat cards, chart bars) */
[data-hint] { position: relative; cursor: help; }
[data-hint]:focus { outline: none; box-shadow: var(--focus); }
[data-hint]::after {
    content: attr(data-hint) / ""; /* read out once, from the .sr-only copy */
    position: absolute; left: var(--space-2); right: var(--space-2); top: calc(100% + 6px); z-index: 20;
    padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
    font-size: var(--text-sm); font-weight: 500; line-height: 1.45; white-space: pre-line; text-align: left;
    color: var(--tip-text); background: var(--tip-bg); border: 1px solid var(--tip-border); /* the tooltip standard (C140) */
    opacity: 0; visibility: hidden; transition: opacity 0.12s ease; pointer-events: none;
}
[data-hint]:hover::after, [data-hint]:focus::after { opacity: 1; visibility: visible; }
/* A tooltip with labelled rows (x-tip-table, C139): floats above the page (app.js), styled like the hint above. */
[data-tip-table] { cursor: help; }
.floating-tip { position: fixed; z-index: 1000; max-width: min(360px, calc(100vw - 16px)); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg); color: var(--tip-text); background: var(--tip-bg); border: 1px solid var(--tip-border); font-size: var(--text-sm); line-height: 1.45; pointer-events: none; } /* the tooltip standard (C140) */
.tip-table { border-collapse: collapse; width: 100%; }
.tip-table th, .tip-table td { padding: 2px 0; text-align: left; vertical-align: top; font-weight: 500; }
.tip-table th[scope="row"] { padding-right: var(--space-4); white-space: nowrap; opacity: 0.75; }
.tip-table td { font-weight: 650; font-variant-numeric: tabular-nums; }
.tip-table-section th { padding-top: var(--space-2); font-weight: 700; border-top: 1px solid color-mix(in srgb, currentColor 25%, transparent); }

/* Change against an earlier period, under a stat's number */
.stat-change { margin-top: var(--space-1); font-size: var(--text-sm); font-weight: 650; color: var(--text-muted); }
.stat-change.is-up { color: var(--success); }
.stat-change.is-down { color: var(--danger); }
.stat-change .muted { font-weight: 500; }

/* Heading above a group of cards */
.section-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); margin: var(--space-5) 0 var(--space-3); }
.section-head h2 { margin: 0; font-size: var(--text-lg); }

/* Bar chart (<x-bar-chart>): bar heights come from --h */
.bar-chart { margin: 0; }
.bar-chart-bars { display: flex; align-items: flex-end; gap: 3px; height: 160px; }
.bar-chart-col { flex: 1; height: 100%; display: flex; align-items: flex-end; border-radius: 3px 3px 0 0; }
.bar-chart-bar { width: 100%; height: var(--h); min-height: 2px; border-radius: 3px 3px 0 0; background: var(--brand); opacity: 0.85; }
.bar-chart-col:hover .bar-chart-bar, .bar-chart-col:focus .bar-chart-bar { opacity: 1; background: var(--brand-strong); }
.bar-chart-col[data-hint]::after { left: 50%; right: auto; top: auto; bottom: calc(100% + 6px); transform: translateX(-50%); width: max-content; max-width: 220px; }
.bar-chart-col:first-child[data-hint]::after, .bar-chart-col:nth-child(2)[data-hint]::after, .bar-chart-col:nth-child(3)[data-hint]::after { left: 0; transform: none; }
.bar-chart-col:last-child[data-hint]::after, .bar-chart-col:nth-last-child(2)[data-hint]::after, .bar-chart-col:nth-last-child(3)[data-hint]::after { left: auto; right: 0; transform: none; }
.bar-chart-labels { display: flex; gap: 3px; margin-top: var(--space-2); font-size: var(--text-xs); color: var(--text-muted); }
.bar-chart-labels span { flex: 1; white-space: nowrap; overflow: visible; }

/* Ranked list (<x-top-list>): the row's share drawn behind it from --share */
.top-row { background: linear-gradient(90deg, var(--brand-soft) var(--share), transparent var(--share)); }
.top-rank { display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--surface-sunken); font-size: var(--text-sm); font-weight: 700; flex: none; }

.dl { display: grid; gap: var(--space-3); margin: 0; }
.dl div { display: grid; gap: 2px; }
.dl dt { font-size: var(--text-sm); color: var(--text-muted); }
.dl dd { margin: 0; font-weight: 550; overflow-wrap: anywhere; }
@media (min-width: 768px) {
    .dl div { grid-template-columns: 200px 1fr; gap: var(--space-4); }
}
.dl.dl-stacked div { grid-template-columns: minmax(0, 1fr); gap: 2px; } /* each label above its value at every width, e.g. in narrow cards (a rate plan's prices, C211) */

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    min-height: var(--tap); padding: 0 var(--space-4);
    border: 1px solid transparent; border-radius: var(--radius);
    font: inherit; font-weight: 600; font-size: var(--text-sm); line-height: 1;
    text-decoration: none; cursor: pointer; white-space: nowrap;
    background: var(--surface); color: var(--text); border-color: var(--border-strong);
}
.btn:hover { background: var(--surface-2); color: var(--text); }
.btn-primary { background: var(--brand); border-color: var(--brand); color: var(--brand-contrast); }
.btn-primary:hover { background: var(--brand-strong); border-color: var(--brand-strong); color: var(--brand-contrast); }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover { filter: brightness(0.92); background: var(--danger); color: #fff; }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--surface-2); }
.btn-icon { width: var(--tap); padding: 0; }
.btn-block { width: 100%; }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* ---------- Forms ---------- */
.form { display: grid; gap: var(--space-4); }
.form-section + .form-section { margin-top: var(--space-5); padding-top: var(--space-5); border-top: 1px solid var(--border); }
.grid > .form-section + .form-section { margin-top: 0; padding-top: 0; border-top: 0; } /* side by side in a grid: the gap separates them */
/* A long form's sections in columns, using the full width (e.g. Settings → General, Invoices): 1 on phones, 2 from tablets, 3 from 1440px.
   Each section is its own card; cards in a row share one height (.grid.form-columns: wins over the "no padding between sections" rule above). */
.form-columns { align-items: stretch; }
.grid.form-columns > .form-section { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: var(--space-4); }
@media (min-width: 768px) { .grid.form-columns > .form-section { padding: var(--space-5); } }
@media (min-width: 768px) { .form-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1440px) { .form-columns { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1440px) { .form-columns.form-columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } } /* two columns at most (owner, C246: Settings → Invoices) */
.form-section h2 { margin-bottom: var(--space-1); }
.form-section > p { color: var(--text-muted); font-size: var(--text-sm); }
.form-subheading { margin: var(--space-3) 0 0; padding-top: var(--space-4); border-top: 1px solid var(--border); font-size: var(--text-md); } /* a section inside a card, e.g. Suggested for your server (C165) */
.grid.form-columns > .form-section-wide { grid-column: 1 / -1; } /* a card across the whole width (C166) */
.form-section .grid.form-columns > .form-section { box-shadow: none; } /* cards inside a card, e.g. a rate plan's number types (C213) */
.form-section .grid.form-columns > .form-section h3 { margin: 0 0 var(--space-2); }
/* A long card two rows tall in the three-column layout, beside two short ones (e.g. a client's billing address, C200). */
@media (min-width: 1440px) { .grid.form-columns > .form-section-tall { grid-row: span 2; } }
/* Two columns inside a card (C173), stacked below 1024 px; .log-column: a log that fills its column's height. */
.split-2 { display: grid; gap: var(--space-5); }
.log-column { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.log-column .terminal { flex: 1 1 auto; }
.log-column > .heading-row { justify-content: space-between; align-items: center; } /* the log's heading, its Copy log at the far right (C174) */
.log-column > .heading-row > h3 { margin: 0; }
@media (min-width: 1024px) {
    .split-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* A list in half a card (the client's Your account, C204): its rows kept together, each label above its value, */
    .split-2 .dl { align-content: start; }
    .split-2 .dl div { grid-template-columns: minmax(0, 1fr); gap: 2px; }
    .log-column { contain: size; } /* never taller than the left column: the log scrolls */
    .log-column .terminal { min-height: 8rem; max-height: none; }
}
@media (min-width: 1440px) { .split-2 .dl div { grid-template-columns: 7rem minmax(0, 1fr); gap: var(--space-3); } } /* ... or beside it once there's room */
/* A card that saves on its own (x-settings-card, C168): Save at its bottom right; outlined in the brand colour while it has unsaved changes. */
/* Save sits in the card's bottom-right corner, lined up across a row of cards of equal height (owner, C170). */
.grid.form-columns > form.form-section { display: flex; flex-direction: column; }
.form-section .card-save { margin-top: auto; padding-top: var(--space-5); justify-content: flex-end; }
.grid.form-columns > form.form-section.has-changes { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand), var(--shadow-sm); }
.field { display: grid; gap: var(--space-1); align-content: start; } /* side by side with a taller field (e.g. one with a hint), label and box stay at the top */
.field label, .label { font-size: var(--text-sm); font-weight: 600; }
.field .hint { font-size: var(--text-sm); color: var(--text-muted); }
.field-foot { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); } /* a box's hint and its character count on one line (C212) */
.field-foot .field-count { margin-left: auto; white-space: nowrap; }
.field .error { font-size: var(--text-sm); color: var(--danger); font-weight: 550; }
/* A labelled group of radio buttons (.check rows) */
.choice { border: 0; margin: 0; padding: 0; min-width: 0; }
.choice legend { padding: 0; margin-bottom: var(--space-1); font-size: var(--text-sm); font-weight: 600; }
.required-mark { color: var(--danger); }

.input, .select, .textarea {
    width: 100%; min-height: var(--tap);
    padding: 0 var(--space-3);
    font: inherit; font-size: 16px; /* 16px stops iOS zooming on focus */
    color: var(--text); background: var(--surface);
    border: 1px solid var(--border-strong); border-radius: var(--radius);
}
.textarea { padding: var(--space-3); min-height: 110px; resize: vertical; }
.input[type="file"] { padding: var(--space-2) var(--space-3); line-height: 1.8; }
/* The dropdown arrow, shared by .select and the searchable dropdown (.ts-control) */
.select, .ts-wrapper .ts-control, .ts-wrapper.single.input-active .ts-control { appearance: none; padding-right: var(--space-6);
    background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%), linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
    background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
    background-size: 5px 5px; background-repeat: no-repeat; }
.input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--brand); box-shadow: var(--focus); }
.input[aria-invalid="true"], .select[aria-invalid="true"] { border-color: var(--danger); }
.input[readonly] { background: var(--surface-sunken); color: var(--text-muted); }

.check { display: flex; align-items: flex-start; gap: var(--space-3); min-height: var(--tap); padding: var(--space-2) 0; cursor: pointer; }
.check input { width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--brand); flex: none; }
.check-title { font-weight: 550; }
.check-inline { display: inline-flex; min-height: 0; padding: 0; margin-right: var(--space-2); vertical-align: middle; }
.check-desc { display: block; font-size: var(--text-sm); color: var(--text-muted); }

.checks-group { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3) var(--space-4); }
.checks-group legend { padding: 0 var(--space-2); font-weight: 650; font-size: var(--text-sm); }
.permission-checklist { display: grid; gap: var(--space-2); }
.permission-checklist > h2 { margin: 0; }

.form-actions { display: flex; flex-direction: column-reverse; gap: var(--space-2); }
.form-actions > .btn-primary { order: 10; } /* the main action: on the right (on phones: on top), wherever it is in the code */
@media (min-width: 768px) {
    .form-actions { flex-direction: row; justify-content: flex-end; }
    .form-actions > .form-actions-start { margin-right: auto; } /* e.g. "Test the connection": on the far left */
    .form-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
    .form-row-3 { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr); } /* three fields, the middle one wider (e.g. street number | name | type) */
}
@media (max-width: 767px) {
    .form-row { display: grid; gap: var(--space-4); }
    .form-actions .btn { width: 100%; }
}

/* ---------- Alerts and badges ---------- */
.alert { display: flex; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-radius: var(--radius); border: 1px solid transparent; margin-bottom: var(--space-4); font-size: var(--text-sm); }
.alert-success { background: var(--success-soft); color: var(--success); border-color: color-mix(in srgb, var(--success) 25%, transparent); }
.alert-danger { background: var(--danger-soft); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 25%, transparent); }
.alert-warning { background: var(--warning-soft); color: var(--warning); border-color: color-mix(in srgb, var(--warning) 25%, transparent); }
.alert-info { background: var(--info-soft); color: var(--info); border-color: color-mix(in srgb, var(--info) 25%, transparent); }
.alert ul { margin: 0; padding-left: var(--space-4); }
.alert strong { color: inherit; }
.alert > div:first-child { flex: 1 1 auto; min-width: 0; }
/* The ✕ on a message (partials/alert-close; C68) and its fade when it closes */
.alert-close { flex: none; align-self: flex-start; margin: -10px -12px -10px 0; width: 44px; height: 44px; border: 0; border-radius: var(--radius-sm); background: transparent; color: inherit; font-size: 20px; line-height: 1; cursor: pointer; opacity: 0.7; }
.alert-close:hover, .alert-close:focus-visible { opacity: 1; background: color-mix(in srgb, currentColor 12%, transparent); }
.alert { transition: opacity 0.3s ease; }
/* Time left before a message closes (C68): seconds beside the ✕, a bar along the bottom; paused under the pointer */
.alert[data-autoclose] { position: relative; overflow: hidden; }
.alert-timer { flex: none; align-self: flex-start; font-size: var(--text-xs); font-variant-numeric: tabular-nums; opacity: 0.75; padding-top: 2px; min-width: 2.5em; text-align: right; }
.alert-progress { position: absolute; left: 0; bottom: 0; height: 3px; width: 100%; background: currentColor; opacity: 0.35; transform-origin: left; animation: alert-countdown linear forwards; }
.alert-paused .alert-progress { animation-play-state: paused; }
@keyframes alert-countdown { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) { .alert-progress { display: none; } }
.alert.alert-closing { opacity: 0; }

.badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 10px; border-radius: 999px; font-size: var(--text-xs); font-weight: 650; background: var(--surface-sunken); color: var(--text-muted); white-space: nowrap; }
.badge-success { background: var(--success-soft); color: var(--success); }
.badge-danger { background: var(--danger-soft); color: var(--danger); }
.badge-warning { background: var(--warning-soft); color: var(--warning); }
.badge-info { background: var(--info-soft); color: var(--info); }
/* A badge that is a link: a rectangle in the brand's colours (the tenant's own, both themes), filled on hover and
   focus (e.g. the call map's number types, which open those calls: owner, 0.7.194). */
a.badge.badge-link { border-radius: var(--radius-sm); padding: 3px 10px; font-size: var(--text-sm); background: var(--brand-soft); color: var(--brand-strong);
    border: 1px solid color-mix(in srgb, var(--brand) 30%, transparent); text-decoration: none; cursor: pointer; transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease; }
a.badge.badge-link:hover, a.badge.badge-link:focus-visible { background: var(--brand); color: var(--brand-contrast); border-color: var(--brand); }
/* Its tip as wide as its words, not the badge, and above it: the mouse pointer hangs down from its tip and covered a
   tip under a small badge (owner, 0.7.195). */
a.badge.badge-link[data-hint]::after { left: 0; right: auto; top: auto; bottom: calc(100% + 6px); width: max-content; }

/* A highlighted date range (<x-date-range>), e.g. the period of a list */
.date-range { display: inline-flex; align-items: center; gap: var(--space-1); padding: 2px 10px; border-radius: 999px;
    background: var(--brand-soft); color: var(--brand-strong); font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }
.date-range .icon { width: 15px; height: 15px; }
.id-chip { display: inline-block; padding: 2px 8px; border-radius: var(--radius-sm); background: var(--surface-sunken); font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; letter-spacing: 0.02em; }

/* ---------- Tables ---------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* A long table that shows about 10 rows, then scrolls, with its header kept in view */
.table-scroll { max-height: calc(10 * 61px + 45px); overflow-y: auto; }
.table-scroll thead th { position: sticky; top: 0; z-index: 2; background: var(--surface-2); }
/* Lazy lists (<x-lazy-table>, <x-lazy-list>): search box above, status line at the end */
.lazy-search { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); }
.lazy-status:empty { display: none; }
.lazy-status { margin: 0; padding: var(--space-3) var(--space-4); text-align: center; }
.list-scroll { max-height: calc(10 * 70px); overflow-y: auto; }
.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table th, .table td { padding: var(--space-3) var(--space-4); text-align: left; vertical-align: middle; border-bottom: 1px solid var(--border); }
.table th { font-size: var(--text-xs); font-weight: 650; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); background: var(--surface-2); white-space: nowrap; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover td { background: var(--surface-2); }
/* Every other row in a tint of the theme colour (owner, C325: the Invoices list); the hovered row a little stronger. */
.table-striped tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--brand-soft) 45%, transparent); }
/* A rate deck comparison's changed codes (C336): a light amber, like a warning. */
.table tr.row-changed td { background: color-mix(in srgb, var(--warning-soft) 45%, transparent); }
.table-striped tbody tr:hover td { background: color-mix(in srgb, var(--brand-soft) 85%, transparent); }
.table .row-link { font-weight: 600; text-decoration: none; }
.link-quiet { color: inherit; text-decoration: none; } /* a name that opens its page, e.g. the client on Invoices (C278) */
.link-quiet:hover { color: var(--brand); text-decoration: underline; }
.contact-link { display: inline-flex; align-items: center; gap: var(--space-1); vertical-align: middle; text-decoration: none; } /* a phone or email with its icon, centred on the text (C278) */
.contact-link:hover span { text-decoration: underline; }
.masked-address { cursor: pointer; letter-spacing: 1px; user-select: none; } /* a hidden PBX address: triple-click shows it for 30 seconds (C287) */
.masked-address.is-shown { letter-spacing: normal; user-select: text; }
.input.is-masked { color: transparent; } /* a hidden PBX address in a form (C287): its text hidden, the masking text over it (C288) */
.reveal-mask { display: none; position: absolute; left: calc(var(--space-3) + 1px); top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--text-muted); }
.input.is-masked + .reveal-mask { display: block; }
.masked-address.is-shown { display: inline-block; padding: 2px 8px; margin: 0 8px; } /* room for the line around it: 8px + its 6px side gap = 14px each side, centred (C288 to C290, C292) */
.reveal-wrap { display: block; }
.masked-address[data-copied]::after { content: attr(data-copied); position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%); padding: 2px 8px; border-radius: 6px;
    background: var(--tip-bg); color: var(--tip-text); border: 1px solid var(--tip-border); font: 600 12px/1.6 var(--font-sans); letter-spacing: normal; white-space: nowrap; pointer-events: none; } /* a click copied it (C291) */
.masked-address.is-shown { cursor: copy; }
.reveal-trace { color: var(--brand); } /* the line around a shown PBX address, running down over its 30 seconds (C288) */
.reveal-trace path { filter: drop-shadow(0 0 2px var(--brand)); }
.table .actions { text-align: right; white-space: nowrap; }

/* Priority columns: .col-optional is hidden on phones */
@media (max-width: 767px) {
    .table-priority .col-optional { display: none; }
}

/* Card layout on phones: each row becomes a card, cells use data-label */
@media (max-width: 767px) {
    .table-cards thead { display: none; }
    .table-cards, .table-cards tbody, .table-cards tr, .table-cards td { display: block; width: 100%; }
    .table-cards tr { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); }
    .table-cards tbody tr:hover td { background: none; }
    .table-striped.table-cards tbody tr:nth-child(even) { background: color-mix(in srgb, var(--brand-soft) 45%, transparent); } /* the whole card, not each cell (C325) */
    .table-striped.table-cards tbody tr td { background: none; }
    .table-cards td { display: flex; justify-content: space-between; gap: var(--space-3); padding: var(--space-1) 0; border: 0; text-align: right; }
    .table-cards td::before { content: attr(data-label); color: var(--text-muted); font-weight: 550; text-align: left; }
    .table-cards td[data-label=""]::before, .table-cards td:not([data-label])::before { content: none; }
    .table-cards td.card-title { display: block; text-align: left; font-size: var(--text-md); padding-bottom: var(--space-2); }
    .table-cards td.actions { justify-content: flex-end; padding-top: var(--space-2); }
}

/* Horizontal scroll with sticky first column (wide admin tables) */
.table-sticky th:first-child, .table-sticky td:first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); box-shadow: 1px 0 0 var(--border); }
.table-sticky th:first-child { background: var(--surface-2); }

.empty { padding: var(--space-6) var(--space-4); text-align: center; color: var(--text-muted); }
.empty .icon { width: 32px; height: 32px; margin-bottom: var(--space-2); color: var(--text-subtle); }

/* ---------- Toolbar, filters and bottom sheet ---------- */
.toolbar { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; margin-bottom: var(--space-4); }
.toolbar .input { width: auto; flex: 1 1 160px; }
.toolbar .search { flex: 1 1 220px; }
.toolbar .input-narrow { flex: 0 1 110px; }
.tax-rate-row { margin-bottom: var(--space-2); }
.tax-rate-new { margin: var(--space-3) 0 0; padding-top: var(--space-3); border-top: 1px solid var(--border); } /* adding a rate, under the list */
.card-foot.toolbar { margin-bottom: 0; }
/* A draft's Add line (owner, 0.7.270): Quantity and Price half their old width (min-width 0: an input won't shrink below its
   built-in width otherwise), From your items 10% wider, the description takes the rest */
.line-add .input-narrow { flex: 0 0 103px; min-width: 0; }
.line-add .ts-wrapper, .line-add > .select { flex: 0 0 198px; min-width: 0; }
/* the description 10% narrower, its 10% to Price so a price like 12000.00 shows in full (owner, 0.7.271) */
.line-add #line-description { flex: 9 1 180px; min-width: 0; }
.line-add #line-price { flex: 1 0 123px; }
/* A draft bill's calls under its lines: which are on it and why the client's others aren't (C227) */
.bill-calls { border-top: 1px solid var(--border); }
.bill-calls h3 { margin: 0 0 var(--space-2); font-size: var(--text-md); }
.bill-calls ul { display: grid; gap: var(--space-1); margin: 0; padding-left: 1.2em; }
/* Settings → Invoices */
.pre-line { white-space: pre-line; }
/* A terminal-style log (e.g. Settings → Email → Connection log): always dark, scrolls inside itself. */
.terminal { margin: 0; padding: var(--space-3); min-height: 16rem; max-height: 560px; overflow: auto; border-radius: var(--radius-sm); background: #0b1020; color: #d1e7d6; font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
/* A log of an update (Administration → Upgrade, C322): 25 lines, then it scrolls. */
/* The Update log's line opening each update ("== Upgrade · Done · …", C326): white and bold, a gap above it. */
.term-head { color: #f8fafc; font-weight: 700; }
.term-head::before { content: ""; display: block; height: 0.6em; }
.terminal > .term-head:first-child::before { display: none; }
/* Line colours and the cursor of a terminal log (app.js: data-terminal). */
.term-client { color: #7dd3fc; }   /* what we send */
.term-server { color: #bbf7d0; }   /* what the server answers */
.term-error { color: #fca5a5; font-weight: 600; }
.term-info { color: #94a3b8; }     /* connection steps */
.term-cursor { display: inline-block; width: 0.6em; height: 1.1em; vertical-align: text-bottom; background: #d1e7d6; animation: term-blink 1s steps(1) infinite; }
@keyframes term-blink { 50% { opacity: 0; } }
/* A PBX's next connection check (x-pbx-connection, C130, C251): the line around the badge fills clockwise until the check
   (.wait-trace, app.js); the dot shows only while the check runs, pulsing. */
.next-check { display: none; width: 9px; height: 9px; margin-left: 6px; vertical-align: 0; border-radius: 50%; background: currentColor; }
.next-check.is-due { display: inline-block; animation: next-check-pulse 1s ease-in-out infinite; }
.badge.has-wait, .masked-address.has-wait, .reveal-wrap { position: relative; }
.wait-trace { position: absolute; inset: -3px; width: calc(100% + 6px); height: calc(100% + 6px); max-width: none; overflow: visible; pointer-events: none; } /* wider than its element: not capped by img, svg max-width (C292) */
.wait-trace { transition: opacity 0.4s; }
.wait-trace path { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: butt; stroke-dasharray: 0 100; transition: stroke-dasharray 1s linear;
    animation: wait-pulse 10s ease-in-out infinite; } /* a short pulse every 10 seconds (owner, C253) */
@keyframes wait-pulse { 0%, 12%, 100% { stroke-width: 2; } 5% { stroke-width: 3.5; filter: drop-shadow(0 0 3px currentColor) drop-shadow(0 0 8px currentColor); } } /* brighter, never dimmer (C254) */
.wait-trace.is-hidden { opacity: 0; } /* while the check runs: only the pulsing dot (owner, C252) */
@keyframes next-check-pulse { 50% { opacity: 0.25; transform: scale(0.7); } }
@media (prefers-reduced-motion: reduce) { .next-check.is-due { animation: none; } .wait-trace path { transition: none; animation: none; } }
/* The ring and the line around an Online / Offline badge (owner, C230): the badge's colour, much brighter and glowing, so the
   badge looks calm and the ring and line stand out. */
.badge-success .next-check, .badge-success .wait-trace { color: var(--success-bright); }
/* Online (owner, C237): the badge in the theme (brand) colour, soft; its ring and line in the full colour, glowing. */
.badge-online { background: var(--brand-soft); color: var(--brand-strong); }
.badge-online .next-check, .badge-online .wait-trace { color: var(--brand); }
.badge-online .next-check, .badge-online .wait-trace path { filter: drop-shadow(0 0 3px var(--brand)); }
.badge-danger .next-check, .badge-danger .wait-trace { color: var(--danger-bright); }
.badge .next-check, .badge .wait-trace path { filter: drop-shadow(0 0 2px currentColor); }
@media (prefers-reduced-motion: reduce) { .term-cursor { animation: none; } }
.terminal:focus-visible { outline: none; box-shadow: var(--focus); }
.recovery-codes { list-style: none; padding: 0; margin: 0 0 var(--space-3); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); font-size: var(--text-md); }
.qr svg { width: 200px; height: 200px; background: #fff; padding: 8px; border-radius: var(--radius); }
.brand-logo { max-height: 56px; max-width: 220px; object-fit: contain; }
.brand-logo-sidebar { max-height: 40px; max-width: 100%; } /* the tenant's logo in its portal (C110) */
.brand-logo-topbar { max-height: 32px; max-width: 140px; }
.sidebar-head .brand-align-left, .sidebar-head .brand-align-center, .sidebar-head .brand-align-right { flex: 1; min-width: 0; } /* the logo's place across the menu header (C114) */
.brand-align-center { justify-content: center; }
.brand-align-right { justify-content: flex-end; }
.total-amount { font-size: var(--text-lg, 1.25rem); font-weight: 700; }
.logo-preview { display: block; height: 80px; width: auto; max-width: 240px; object-fit: contain; margin-bottom: var(--space-2); padding: var(--space-2); background: #fff; border: 1px solid var(--border); border-radius: var(--radius); }
.favicon-preview { display: block; width: 80px; height: 80px; object-fit: contain; margin-bottom: var(--space-2); padding: var(--space-4); background: #fff; border: 1px solid var(--border); border-radius: var(--radius); } /* C110; as tall as the logo's preview, so the boxes under them line up (C115) */
.copy-text { display: inline-flex; align-items: center; gap: var(--space-3); padding: 1px var(--space-2); border: 1px dashed currentColor; border-radius: var(--radius-sm); background: transparent; color: inherit; font-size: inherit; line-height: inherit; cursor: pointer; max-width: 100%; overflow-wrap: anywhere; text-align: start; } /* text that copies itself (x-copy-text, C127); a long one wraps inside its box on a phone (0.7.209) */
.dns-record { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-1) var(--space-4); margin: var(--space-2) 0; align-items: center; } /* a DNS record to add: Type / Name / Points to (C128) */
.dns-record dt { font-weight: 600; }
.dns-records { display: grid; gap: var(--space-3) var(--space-6, 2rem); }
@media (min-width: 768px) { .dns-records-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } } /* CNAME | A record side by side (C128) */
.dns-record dd { margin: 0; overflow-wrap: anywhere; }
.alert .dns-record + p, .alert p.small { margin: var(--space-2) 0 0; }
.copy-text:hover { background: color-mix(in srgb, currentColor 10%, transparent); }
.colour-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); } /* an SVG logo's colours, each with its picker (C112) */
.input-color { padding: var(--space-1); max-width: 120px; }
.input-group .input-color { flex: none; width: 64px; }
.input-group .input-hex { flex: 0 1 120px; font-family: var(--font-mono); text-transform: lowercase; } /* the colour as hex, beside its picker */
.filter-count { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--brand); color: var(--brand-contrast); font-size: var(--text-xs); }

.sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    max-height: 85vh; overflow-y: auto;
    padding: var(--space-4) var(--space-4) calc(var(--space-4) + env(safe-area-inset-bottom));
    background: var(--surface); border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: var(--shadow-lg);
    transform: translateY(100%); transition: transform 0.2s ease; visibility: hidden;
}
.sheet.is-open { transform: none; visibility: visible; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-3); }
.sheet-head h2 { margin: 0; }
.sheet::before { content: ""; display: block; width: 40px; height: 4px; margin: 0 auto var(--space-3); border-radius: 4px; background: var(--border-strong); }
@media (min-width: 768px) {
    .sheet { left: 50%; right: auto; bottom: auto; top: 50%; width: min(560px, 92vw); border-radius: var(--radius-lg); transform: translate(-50%, -46%); opacity: 0; transition: opacity 0.15s ease, transform 0.15s ease; }
    .sheet.is-open { transform: translate(-50%, -50%); opacity: 1; }
    .sheet::before { display: none; }
}

/* ---------- Pagination ---------- */
.pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--border); font-size: var(--text-sm); color: var(--text-muted); }
.pagination-links { display: flex; gap: var(--space-2); }

/* ---------- Guest (login) layout ---------- */
.guest { min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: var(--space-4); }
.guest-card { width: 100%; max-width: 420px; }
.guest-card .brand { justify-content: center; margin-bottom: var(--space-5); font-size: var(--text-lg); }
/* Forgot your password? · Forgot your Login ID? under a guest form (C304). */
.auth-links { margin: var(--space-4) 0 0; text-align: center; }
.captcha-box { padding: var(--space-3) var(--space-4); border-radius: var(--radius); background: var(--surface-2); border: 1px dashed var(--border-strong); }
.captcha-box[hidden] { display: none; }

/* ---------- Audit values ---------- */
.diff { display: grid; gap: var(--space-2); font-size: var(--text-sm); }
.diff-row { display: grid; gap: 2px; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--surface-2); overflow-wrap: anywhere; }
.diff-key { font-weight: 650; }
.diff-old { color: var(--danger); text-decoration: line-through; }
.diff-new { color: var(--success); }
@media (min-width: 768px) {
    .diff-row { grid-template-columns: 180px 1fr 1fr; gap: var(--space-3); }
}

/* ---------- Print ---------- */
@media print {
    .sidebar, .tabbar, .topbar, .page-actions, .scrim { display: none !important; }
    .app { padding: 0; }
    body { background: #fff; }
}

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

button.nav-link { width: 100%; border: 0; background: none; font: inherit; text-align: left; cursor: pointer; }
.input-group { display: flex; gap: var(--space-2); }
.input-group .input { flex: 1; min-width: 0; }
.form-narrow { max-width: 720px; }
/* Four columns on a desktop (two on a tablet, one on a phone), boxes in a row the same height: permission groups (user form, Roles → Edit permissions) */
.auto-columns { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); align-items: stretch; } /* boxes in a row share one height */
@media (min-width: 768px) { .auto-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .auto-columns { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.uppercase { text-transform: uppercase; }
.center { text-align: center; }

/* ---------- Link lists ---------- */
.section-gap { margin-top: var(--space-4); }
.list-row { display: flex; align-items: center; gap: var(--space-3); min-height: var(--tap); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); color: var(--text); text-decoration: none; }
.list-row:last-child { border-bottom: 0; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
.list-row:hover { background: var(--surface-2); color: var(--text); }
.list-row-main { flex: 1; min-width: 0; }
/* A row with its own buttons: the link is the main part, buttons sit beside it */
.list-row-link { display: flex; align-items: center; gap: var(--space-3); flex: 1; min-width: 0; color: inherit; text-decoration: none; }
.list-row-link:hover { color: inherit; }
form.inline { display: inline; } /* a button's own form, next to other buttons (e.g. Edit · Delete) */
/* "Test again" result (<x-retest-button>) */
.btn.is-ok { color: var(--success); border-color: var(--success); }
.btn.is-bad { color: var(--danger); border-color: var(--danger); }

/* PBX Play / Pause / Stop (<x-pbx-controls>) */
/* Each button has its colour (--c). The current state is solid; actions are tinted; the rest faded. */
.pbx-controls { display: inline-flex; gap: var(--space-2); }
.pbx-controls .btn { --c: var(--text-muted); color: var(--c); border-color: color-mix(in srgb, var(--c) 45%, transparent);
    background: color-mix(in srgb, var(--c) 12%, var(--surface)); }
.pbx-controls .btn .icon { fill: currentColor; stroke-width: 1.5; }
.pbx-controls .btn:not(:disabled):hover { background: color-mix(in srgb, var(--c) 22%, var(--surface)); color: var(--c); }
.pbx-controls .btn.is-current { background: var(--c); border-color: var(--c); color: #fff; opacity: 1; cursor: default; }
.pbx-controls .btn:disabled:not(.is-current) { --c: var(--text-subtle); opacity: 0.45; cursor: not-allowed; background: var(--surface); }
.pbx-play  { --c: var(--success) !important; }
.pbx-pause { --c: var(--warning) !important; }
.pbx-stop  { --c: var(--danger) !important; }
.pbx-controls .btn:disabled:not(.is-current).pbx-play,
.pbx-controls .btn:disabled:not(.is-current).pbx-pause,
.pbx-controls .btn:disabled:not(.is-current).pbx-stop { --c: var(--text-subtle) !important; }
.list-row-main > span { display: block; overflow-wrap: anywhere; }

/* ---------- Setup pages (install.php / upgrade.php) ---------- */
.guest-card.setup-card { max-width: 720px; }
.setup-group { margin: var(--space-5) 0 var(--space-2); font-size: var(--text-sm); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.setup-log { display: grid; gap: var(--space-3); margin: var(--space-4) 0; }
.setup-log pre, .setup-pre { margin: var(--space-2) 0 0; padding: var(--space-3); overflow-x: auto; border-radius: var(--radius-sm); background: var(--surface-sunken); font-family: var(--font-mono); font-size: var(--text-xs); white-space: pre-wrap; overflow-wrap: anywhere; }
.plain-list { list-style: none; margin: 0 0 var(--space-2); padding: 0; display: grid; gap: var(--space-1); }
.danger-gap { margin-top: var(--space-5); padding-top: var(--space-3); border-top: 1px solid var(--border); } /* a Delete kept apart from the Save above it (C361) */
/* What a tenant pays the platform, a table (C364, C366, C368): the package with its icon tile and details, the costs in one
   column, the total a month as the last row in the theme's tint. Cards on phones (table-cards). */
.paid-packages { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.paid-packages .table { margin: 0; }
.paid-package { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.paid-package-name { display: grid; gap: 2px; min-width: 0; }
.paid-package-meta { display: block; font-size: var(--text-sm); font-weight: 400; color: var(--text-muted); }
.paid-packages td.num strong { font-variant-numeric: tabular-nums; }
.paid-package-total td { background: color-mix(in srgb, var(--brand) 8%, var(--surface)); }
.paid-package-total td.num strong { font-size: 1.15rem; color: var(--brand-strong); }
@media (max-width: 767px) {
    .paid-package-total { background: color-mix(in srgb, var(--brand) 8%, var(--surface)); }
    .paid-package-total td { background: none; }
    .paid-package-filler { display: none !important; }
}
details.card-foot > summary { color: var(--text); width: fit-content; }
details > summary { min-height: var(--tap); display: flex; align-items: center; cursor: pointer; font-weight: 600; color: var(--text-muted); }

/* A whole card that is a link (e.g. stat tiles) */
a.list-row-plain { color: inherit; text-decoration: none; }
a.list-row-plain:hover { border-color: var(--brand); }

/* ---------- Tabs ---------- */
/* The bottom line is drawn inside the bar (inset shadow) so the active tab's underline never overflows it:
   no stray scrollbar. Tabs can still be swiped sideways on a narrow phone. */
.tabs { display: flex; gap: var(--space-1); margin-bottom: var(--space-4); box-shadow: inset 0 -1px 0 var(--border);
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs a { display: inline-flex; align-items: center; min-height: var(--tap); padding: 0 var(--space-4); border-bottom: 2px solid transparent; color: var(--text-muted); font-weight: 600; text-decoration: none; white-space: nowrap; }
.tabs a:hover { color: var(--text); }
.tabs a[aria-current="page"] { color: var(--brand); border-bottom-color: var(--brand); }
/* Tabs within a page (buttons, app.js [data-tabs], C206): the same look; [aria-selected] is the one shown. In a card, under its heading. */
.tabs button { display: inline-flex; align-items: center; min-height: var(--tap); padding: 0 var(--space-4); border: 0; border-bottom: 2px solid transparent; background: none;
    color: var(--text-muted); font: inherit; font-weight: 600; white-space: nowrap; cursor: pointer; }
.tabs button:hover { color: var(--text); }
.tabs button[aria-selected="true"] { color: var(--brand); border-bottom-color: var(--brand); }
.card > .tabs { margin-bottom: 0; padding: 0 var(--space-2); }
.toolbar .select { width: auto; min-width: 180px; }

/* ---------- Call direction / status icons ---------- */
/* Each meaning has its own colour (--c); the background is a light tint of it. */
.call-icon { --c: var(--text-muted); display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; vertical-align: middle;
    color: var(--c); background: color-mix(in srgb, var(--c) 14%, transparent); }
.call-icon .icon { width: 17px; height: 17px; stroke-width: 2.2; }
.call-icon-in       { --c: #0284c7; } /* inbound: sky blue */
.call-icon-out      { --c: #7c3aed; } /* outbound: violet */
.call-icon-internal { --c: #475569; } /* internal: slate */
.call-icon-transfer { --c: #ea580c; } /* transferred: orange */
.call-icon-divert   { --c: #c026d3; } /* diverted: purple */
.call-icon-ok       { --c: #15803d; } /* answered: green */
.call-icon-vm       { --c: #0f766e; } /* voicemail: teal */
.call-icon-missed   { --c: #b45309; } /* missed: amber */
.call-icon-busy     { --c: #be185d; } /* busy: pink */
.call-icon-bad      { --c: #b91c1c; } /* failed: red */
.call-icon-cancel   { --c: #6b7280; } /* cancelled: grey */
:root[data-theme="dark"] .call-icon-in       { --c: #38bdf8; }
:root[data-theme="dark"] .call-icon-out      { --c: #a78bfa; }
:root[data-theme="dark"] .call-icon-internal { --c: #94a3b8; }
:root[data-theme="dark"] .call-icon-transfer { --c: #fb923c; }
:root[data-theme="dark"] .call-icon-divert   { --c: #e879f9; }
:root[data-theme="dark"] .call-icon-ok       { --c: #4ade80; }
:root[data-theme="dark"] .call-icon-vm       { --c: #2dd4bf; }
:root[data-theme="dark"] .call-icon-missed   { --c: #fbbf24; }
:root[data-theme="dark"] .call-icon-busy     { --c: #f472b6; }
:root[data-theme="dark"] .call-icon-bad      { --c: #f87171; }
:root[data-theme="dark"] .call-icon-cancel   { --c: #9ca3af; }

/* ---------- Help ---------- */
.help-layout { display: grid; gap: var(--space-4); }
.help-toc ol { margin: 0; padding-left: var(--space-5); display: grid; gap: var(--space-1); }
.help-toc a { display: inline-block; min-height: 32px; padding: 4px 0; }
.help-topic { scroll-margin-top: calc(var(--topbar-height) + var(--space-4)); }
.help-topic ul, .help-topic ol { margin: 0 0 var(--space-3); padding-left: var(--space-5); display: grid; gap: var(--space-2); }
.help-topic h3 { font-size: var(--text-sm); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.icon-legend { list-style: none; padding: 0 !important; }
/* A Help topic's picture (owner, C351): the screen it is about, with made-up data; opens full size in a new tab. */
.help-shot { margin: var(--space-4) 0 0; }
.help-shot img { display: block; width: 100%; height: auto; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.help-shot figcaption { margin-top: var(--space-2); font-size: var(--text-xs); color: var(--text-muted); }
.icon-legend li { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
@media (min-width: 1024px) {
    .help-layout { grid-template-columns: 260px minmax(0, 1fr); align-items: start; }
    .help-toc { position: sticky; top: calc(var(--topbar-height) + var(--space-4)); }
}

/* ---------- Searchable dropdowns (Tom Select, public/lib/tom-select) ---------- */
/* Every <select> becomes searchable (see app.js). Five options show; the rest scroll. */
.ts-wrapper.select { padding: 0; border: 0; background: none; min-height: 0; box-shadow: none; }
.ts-wrapper .ts-control {
    min-height: var(--tap); align-items: center; padding: 0 var(--space-6) 0 var(--space-3) !important;
    font: inherit; font-size: 16px; line-height: 1.3; color: var(--text); background-color: var(--surface);
    border: 1px solid var(--border-strong); border-radius: var(--radius); cursor: pointer;
}
.ts-wrapper .ts-control .item { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.ts-wrapper.focus .ts-control, .plugin-dropdown_input.focus.dropdown-active .ts-control { border-color: var(--brand); box-shadow: var(--focus); }
select[aria-invalid="true"] + .ts-wrapper .ts-control { border-color: var(--danger); }
.ts-wrapper.disabled .ts-control { opacity: 0.6; background-color: var(--surface-sunken); }
.input-group .ts-wrapper { flex: 1; min-width: 0; }
.toolbar .ts-wrapper { min-width: 180px; }
.toolbar .select-wide { min-width: 281px; } /* wider (180px + 25% + 25%), e.g. the Client filter on Calls */

.ts-dropdown {
    z-index: 70; /* above sheets and the drawer */
    margin-top: 4px; font: inherit; font-size: var(--text-md); line-height: 1.3; color: var(--text);
    background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-lg); overflow: hidden;
}
.ts-dropdown .dropdown-input {
    min-height: var(--tap); padding: 0 var(--space-3); font: inherit; font-size: 16px; color: var(--text);
    background: var(--surface-sunken); border-bottom: 1px solid var(--border);
}
.ts-dropdown .dropdown-input:focus { outline: none; }
.ts-dropdown-content { max-height: calc(var(--tap) * 5); }
.ts-dropdown.is-above { margin-top: 0; } /* opened upwards (app.js placeDropdown) */
.ts-dropdown .option, .ts-dropdown .no-results { display: flex; align-items: center; min-height: var(--tap); padding: var(--space-2) var(--space-3); }
.ts-dropdown .option.selected { font-weight: 600; color: var(--brand); }
.ts-dropdown .active { background: var(--brand-soft); color: var(--text); }
.ts-dropdown .no-results { color: var(--text-muted); }
.ts-dropdown [data-selectable] .highlight { background: color-mix(in srgb, var(--warning) 25%, transparent); color: inherit; border-radius: 2px; }
.ts-dropdown .optgroup-header { font-size: var(--text-sm); font-weight: 650; color: var(--text-muted); background: var(--surface); }

.pay-amount { font-size: var(--text-xl); } /* the amount due on the quick-pay page (C67) */

/* ---- Call map (C180, C181): the dashboards' map card (public/js/call-map.js, jsVectorMap in public/lib/jsvectormap).
   The map and the side panel side by side on wide screens, stacked (map shorter) on phones and tablets. The map's
   heights (owner, 0.7.185: 25% taller) use two classes so they win over jsVectorMap's own ".jvm-container
   { height: 100% }" (loaded after this file), which made the map only as tall as the side panel. ---- */
.call-map { margin-bottom: var(--space-4); } /* at the top of the dashboard, above the figures (owner, 0.7.183) */
.call-map [hidden] { display: none; } /* the map and table until there are calls to show */
.call-map-controls { margin-bottom: var(--space-3); }
.call-map-status { margin: 0 0 var(--space-3); display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.call-map-status.error { color: var(--danger); font-weight: 550; }
.call-map-body { display: grid; gap: var(--space-4); align-items: start; }
.call-map .call-map-canvas { position: relative; height: 350px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2); overflow: hidden; }
.call-map-side-title { margin: 0 0 var(--space-1); font-size: var(--text-sm); }
.call-map-side-hint { margin: 0 0 var(--space-2); }
.call-map-list { list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.call-map-list li { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 0 var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
.call-map-list li > :first-child { white-space: nowrap; } /* "1300 numbers" on one line; the figures go under it, right, when there's no room */
.call-map-list li > :last-child { margin-left: auto; }
.call-map-table { margin-top: var(--space-4); }
.call-map-table summary { cursor: pointer; font-weight: 600; min-height: var(--tap); display: flex; align-items: center; }
@media (min-width: 768px) { .call-map .call-map-canvas { height: 475px; } }
@media (min-width: 1024px) {
    /* The side panel as wide as its longest line (never narrower than 260px), so a number type and its figures stay on
       one row; the map takes the rest (owner, 0.7.194). Its notes wrap to that width instead of widening it. */
    .call-map-body { grid-template-columns: minmax(0, 1fr) auto; }
    .call-map-side { min-width: 260px; }
    .call-map-side .call-map-side-note { width: 0; min-width: 100%; }
    .call-map-list li { flex-wrap: nowrap; }
    .call-map-list li > :last-child { white-space: nowrap; }
    .call-map .call-map-canvas { height: 550px; }
}
/* jsVectorMap's tooltip in the standard tooltip look: dark in both themes (--tip-*, C140); its zoom buttons tap-sized. */
body .jvm-tooltip { background: var(--tip-bg); color: var(--tip-text); border: 1px solid var(--tip-border); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); font-size: var(--text-sm); line-height: 1.4; box-shadow: var(--shadow); z-index: 60; }
/* Google's GeoChart (C207), when it draws the call map: its HTML tooltips in the same dark style. */
.call-map .call-map-canvas .google-visualization-tooltip { background: var(--tip-bg); color: var(--tip-text); border: 1px solid var(--tip-border); border-radius: var(--radius-sm);
    padding: var(--space-2) var(--space-3); font-size: var(--text-sm); line-height: 1.4; box-shadow: var(--shadow); white-space: nowrap; width: auto !important; height: auto !important; }
/* Google writes its own black text and a first line with the marker's latitude and longitude (C228): our text, no coordinates. */
.call-map .call-map-canvas .google-visualization-tooltip-item-list { margin: 0; padding: 0; list-style: none; }
.call-map .call-map-canvas .google-visualization-tooltip-item { margin: 0; padding: 0; }
.call-map .call-map-canvas .google-visualization-tooltip-item-list .google-visualization-tooltip-item:first-child:not(:last-child) { display: none; }
.call-map .call-map-canvas .google-visualization-tooltip span { color: var(--tip-text) !important; font-family: inherit !important; font-size: inherit !important; }
/* A place's nearby places in its tooltip (both maps, C228). */
.call-map-near { display: block; margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--tip-border); }
.call-map-near-title { display: block; font-weight: 650; }
.call-map-canvas .jvm-zoom-btn { width: 32px; height: 32px; line-height: 32px; left: 8px; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 18px; }
.call-map-canvas .jvm-zoom-btn.jvm-zoomin { top: 8px; }
.call-map-canvas .jvm-zoom-btn.jvm-zoomout { top: 46px; }


/* Anything with the hidden attribute stays hidden, whatever its class sets (C246: Try again showed while a PDF was still being made). */
[hidden] { display: none !important; }

/* The loaders' preview in Settings → Invoices (C246): a box the chosen loader shows in (the overlay dims only the box). */
.loader-previews { position: relative; display: flex; align-items: center; justify-content: center; min-height: 190px; padding: var(--space-4); border: 1px dashed var(--border); border-radius: var(--radius); overflow: hidden; }
.loader-previews > .loader:not(.loader-overlaid) { max-width: 360px; }

/* A name changed by double-clicking it (C247, app.js "Rename in place"): a dotted line says it can be edited. */
.inline-edit { cursor: text; border-bottom: 1px dotted var(--text-muted); }
/* In a tick box's label too (.check input sizes tick boxes): a full-size box with the text visible (C248). */
.inline-edit-input, .check .inline-edit-input { display: inline-block; width: min(280px, 60vw); height: auto; min-height: 36px; margin: 0; padding: 4px 10px; font: inherit; font-weight: 500; vertical-align: middle; accent-color: auto; }

/* A custom invoice's lines (C267): quantity and price stay small, so the description has the room. */
.invoice-lines-form .input-narrow { width: 7.5rem; max-width: 100%; }
/* A rate plan's Call prices (C313, C318): a price box with its unit (/min, /call, /month) or a per-minute / per-call
   choice after it; the received prices from a landline and a mobile stacked in one cell. */
.input-suffix { display: flex; align-items: center; gap: var(--space-2); }
.input-suffix > span { white-space: nowrap; }
.plan-prices th { white-space: normal; }
.plan-prices .input-price { width: 5.75rem; max-width: 100%; }
.plan-prices td[data-label="Calls to"] .select, .plan-prices td[data-label="Calls to"] .ts-wrapper { min-width: 9.5rem; }
.plan-prices .select-unit, .plan-prices .ts-wrapper.select-unit { width: 5.25rem; min-width: 5.25rem; }
.received-prices { display: grid; gap: var(--space-1); }
.received-from { display: inline-block; width: 3.6rem; }
/* The /min or /call under the boxes, lined up with them (past the Landline / Mobile labels). */
.received-prices > .select-unit, .received-prices > .ts-wrapper.select-unit { margin-left: calc(3.6rem + var(--space-2)); }
@media (min-width: 768px) { .invoice-lines-form td[data-label="Description"] { width: 40%; } }

/* A form row: a wide field, a narrow one and a tick box, on one line from tablets (Items → Add an item, C269). */
@media (min-width: 768px) {
    .form-row.form-row-item { grid-template-columns: minmax(0, 4fr) minmax(0, 1fr) auto; align-items: end; } /* the price 25% narrower again (owner) */
    .form-row-item .form-row-check { display: flex; align-items: center; min-height: var(--tap); margin-bottom: var(--space-1); }
}
