/* Self-hosted brand fonts (SIL Open Font License; licenses in assets/fonts/). */
@font-face {
    font-family: "Work Sans";
    src: url("../fonts/work-sans-variable.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: Lato;
    src: url("../fonts/lato-400.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: Lato;
    src: url("../fonts/lato-700.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Brand tokens: Optimum Healthcare IT. See docs/branding.md before changing. */
:root {
    color-scheme: light;

    /* Palette (fixed brand colors, same in both themes) */
    --brand-navy: #021f4b;
    --brand-navy-deep: #081736;
    --brand-blue: #0d5b9a;
    --brand-blue-dark: #0a4a80;
    --brand-blue-light: #ecf7ff;
    --brand-orange: #f2633d;      /* accent only: fails contrast as small text on light backgrounds */
    --brand-gradient: linear-gradient(to right, var(--brand-navy), var(--brand-blue));

    /* Theme colors (light). Dark values are below. */
    --brand-orange-text: #b9401f; /* orange for text */
    --color-text: #333333;
    --color-text-muted: #5a6474;
    --color-heading: var(--brand-navy);
    --color-link: var(--brand-blue);
    --color-bg: #f4f7fa;
    --color-surface: #ffffff;
    --color-panel: #e9edf0;
    --color-line: #d9e0e7;
    --color-input-bg: #ffffff;
    --color-primary: var(--brand-blue);
    --color-primary-hover: var(--brand-blue-dark);
    --color-selected-bg: var(--brand-blue-light);
    --color-success: #1a7f4b;
    --color-success-text: #17663a;
    --color-success-bg: #e7f4ec;
    --color-warning-text: #8a4b00;
    --color-warning-bg: #fff1dc;
    --color-danger: #b42318;
    --color-danger-bg: #fdecea;
    --topbar-bg: var(--brand-gradient);
    --auth-bg: linear-gradient(160deg, var(--brand-navy-deep) 0%, var(--brand-navy) 55%, var(--brand-blue) 100%);
    --shadow-card: 0 1px 2px rgba(2, 31, 75, 0.06), 0 8px 24px rgba(2, 31, 75, 0.08);
    --shadow-auth: 0 20px 50px rgba(0, 0, 0, 0.35);
    --dialog-backdrop: rgba(2, 31, 75, 0.5);

    /* Typography */
    --font-sans-fallback: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-heading: "Work Sans", var(--font-sans-fallback);
    --font-body: Lato, var(--font-sans-fallback);
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Shape */
    --radius: 4px;
    --radius-lg: 8px;
    --focus-ring: 3px solid var(--brand-orange);
    --sidebar-width: 220px;
}

/* Dark theme: set on <html data-theme="dark"> by the theme script in the page head. */
:root[data-theme="dark"] {
    color-scheme: dark;

    /* Working areas (sidebar, pages, cards, tables) are neutral charcoal. Brand navy and blue
       stay on the top bar, the login page, buttons, and links. */
    --brand-orange-text: #f58a6c;
    --color-text: #e6e8ea;
    --color-text-muted: #a1a7ae;
    --color-heading: #ffffff;
    --color-link: #7cc0f5;
    --color-bg: #17191c;
    --color-surface: #1e2125;
    --color-panel: #26292e;
    --color-line: #363a40;
    --color-input-bg: #141619;
    --color-primary: #1a67a8;
    --color-primary-hover: #2275bd;
    --color-selected-bg: rgba(255, 255, 255, 0.07);
    --color-success: #4cc38a;
    --color-success-text: #4cc38a;
    --color-success-bg: rgba(76, 195, 138, 0.12);
    --color-warning-text: #f5b454;
    --color-warning-bg: rgba(245, 180, 84, 0.14);
    --color-danger: #ff8a80;
    --color-danger-bg: rgba(255, 138, 128, 0.12);
    --topbar-bg: linear-gradient(to right, var(--brand-navy-deep), #0a2f5c);
    --auth-bg: linear-gradient(160deg, #050d1f 0%, var(--brand-navy-deep) 60%, #0a2f5c 100%);
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-auth: 0 20px 50px rgba(0, 0, 0, 0.5);
    --dialog-backdrop: rgba(0, 0, 0, 0.6);
}

* { box-sizing: border-box; }

/* The hidden attribute wins. Without this, any class that sets display (.btn is inline-flex) paints
   an element JavaScript has hidden — which is how a "Show" fallback button stayed visible on a page
   with filters. Modules had been patching this one selector at a time. */
[hidden] { display: none !important; }

body {
    margin: 0;
    font-family: var(--font-body);
    font-size: 15px;
    line-height: 1.55;
    color: var(--color-text);
    background: var(--color-bg);
}

h1, h2, h3 { font-family: var(--font-heading); color: var(--color-heading); line-height: 1.25; }

a { color: var(--color-link); }
a:hover { text-decoration: underline; }

code { font-family: var(--font-mono); font-size: 0.85em; }

:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }

.visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.skip-link {
    position: absolute;
    left: 1rem;
    top: -3rem;
    z-index: 10;
    padding: 0.5rem 0.9rem;
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-link);
    font-weight: 700;
}
.skip-link:focus { top: 0.75rem; }

.muted { color: var(--color-text-muted); }

/* Top bar (always dark in both themes) */
.topbar {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    padding: 0.6rem 1.5rem;
    background: var(--topbar-bg);
    color: #fff;
    border-bottom: 3px solid var(--brand-orange);
}
.brand { display: flex; align-items: center; color: inherit; text-decoration: none; flex: none; }
.brand:hover { text-decoration: none; }
.brand-logo { display: block; height: 32px; width: auto; }

.section-nav { display: flex; align-items: stretch; gap: 0.25rem; min-width: 0; overflow-x: auto; }
.section-nav__link {
    padding: 0.55rem 0.85rem;
    border-radius: var(--radius);
    color: rgba(255, 255, 255, 0.85);
    font-family: var(--font-heading);
    font-size: 0.9rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}
.section-nav__link:hover { color: #fff; background: rgba(255, 255, 255, 0.1); text-decoration: none; }
.section-nav__link[aria-current="page"] { color: #fff; background: rgba(255, 255, 255, 0.14); box-shadow: inset 0 -3px 0 var(--brand-orange); }

.topbar-right { display: flex; align-items: center; gap: 1rem; margin-left: auto; flex: none; }
.topbar-right form { margin: 0; }
.user-name { font-size: 0.875rem; opacity: 0.9; }

/* Profile menu (top bar) */
.user-menu { position: relative; }
.user-menu__button {
    display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0.5rem 0.25rem 0.25rem;
    color: #fff; background: transparent; border: 1px solid transparent; border-radius: 999px; cursor: pointer; font: inherit;
}
.user-menu__button:hover, .user-menu__button[aria-expanded="true"] { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.25); }
.user-menu__avatar {
    display: inline-grid; place-items: center; width: 2rem; height: 2rem; border-radius: 50%;
    font-family: var(--font-heading); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.03em;
    color: var(--brand-navy, #021f4b); background: #fff;
}
.user-menu__caret { width: 1rem; height: 1rem; opacity: 0.8; }
.user-menu__panel {
    position: absolute; right: 0; top: calc(100% + 0.5rem); z-index: 50; min-width: 15rem; padding: 0.5rem 0;
    background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-line);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
}
.user-menu__name { margin: 0; padding: 0.5rem 1rem 0; font-weight: 700; }
.user-menu__company { margin: 0 0 0.5rem; padding: 0 1rem 0.6rem; font-size: 0.8125rem; color: var(--color-text-muted); border-bottom: 1px solid var(--color-line); }
.user-menu__panel form { margin: 0; }
.user-menu__item {
    display: block; width: 100%; padding: 0.55rem 1rem; text-align: left; font: inherit; font-size: 0.9rem;
    color: var(--color-text); background: none; border: 0; text-decoration: none; cursor: pointer;
}
.user-menu__item:hover, .user-menu__item:focus-visible { background: var(--color-panel); text-decoration: none; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; max-width: 560px; }
.form-row > div { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }
@media (max-width: 480px) { .form-row { grid-template-columns: 1fr; } }
.dialog .form-row { max-width: none; }

/* Phone inputs (<x-phone-input>, intl-tel-input) in HUB colors, light and dark.
   :root:root outranks the plugin's own :root defaults, which load after this file. */
:root:root {
    --iti-border-color: var(--color-line);
    --iti-country-selector-bg: var(--color-surface);
    --iti-hover-color: var(--color-panel);
    --iti-icon-color: var(--color-text-muted);
}
.form .iti { display: block; width: 100%; }
.form .iti input.phone-input { width: 100%; }
.iti__country-selector { color: var(--color-text); border-radius: var(--radius); box-shadow: var(--shadow-card); }
.iti__search-input { color: var(--color-text); background: var(--color-input-bg); border-bottom: 1px solid var(--color-line); }
/* Form and dialog input padding would otherwise cover the search and clear icons. */
.form .iti__search-input, .dialog .iti__search-input {
    padding: 10px calc(var(--iti-spacer-horizontal) * 2 + var(--iti-clear-icon-size)) 10px calc(var(--iti-spacer-horizontal) * 2 + var(--iti-globe-icon-size));
    border: 0; border-bottom: 1px solid var(--color-line); border-radius: var(--radius) var(--radius) 0 0;
}
.iti__search-input::placeholder { color: var(--color-text-muted); }
.iti__dial-code, .iti__selected-dial-code { color: var(--color-text-muted); }
.iti__selected-country:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: 2px; border-radius: var(--radius); }
[data-profile-required] { max-height: calc(100vh - 2rem); overflow-y: auto; }

/* App shell: optional sidebar + content */
.shell { min-height: calc(100vh - 64px); }
.shell--sidebar { display: grid; grid-template-columns: var(--sidebar-width) minmax(0, 1fr); }

.sidebar { background: var(--color-surface); border-right: 1px solid var(--color-line); padding: 1.5rem 0.75rem; }
.sidebar__title {
    margin: 0 0 0.6rem;
    padding: 0 0.75rem;
    font-family: var(--font-heading);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-text-muted);
}
.sidebar__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.sidebar__link {
    display: block;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius);
    border-left: 3px solid transparent;
    color: var(--color-text);
    font-family: var(--font-heading);
    font-size: 0.92rem;
    font-weight: 500;
    text-decoration: none;
}
.sidebar__link:hover { background: var(--color-panel); text-decoration: none; }
.sidebar__link[aria-current="page"] { background: var(--color-selected-bg); border-left-color: var(--brand-orange); color: var(--color-heading); font-weight: 600; }
/* Grouped sidebars (style "A, guide line", the user's choice, 2026-09-21): bold group headings;
   items indented under them, one step smaller and secondary-coloured, on a thin guide line that the
   active item's orange edge sits on. Used by the client users' menu and the staff sections. */
.sidebar__group + .sidebar__group { margin-top: 1.1rem; }
.sidebar__group-title { margin: 0 0 0.3rem; padding: 0 0.75rem; font-family: var(--font-heading); font-size: 0.875rem; font-weight: 700; color: var(--color-heading); }
.sidebar--grouped .sidebar__group:not(.sidebar__group--top) .sidebar__list {
    gap: 0.05rem; margin-left: 0.85rem; padding-left: 0; border-left: 1px solid var(--color-line);
}
.sidebar--grouped .sidebar__group:not(.sidebar__group--top) .sidebar__link {
    margin-left: -2px; padding: 0.35rem 0.75rem 0.35rem 0.85rem; border-radius: 0 var(--radius) var(--radius) 0;
    font-size: 0.8125rem; font-weight: 500; color: var(--color-text-muted);
}
.sidebar--grouped .sidebar__group:not(.sidebar__group--top) .sidebar__link:hover { color: var(--color-text); }
.sidebar--grouped .sidebar__group:not(.sidebar__group--top) .sidebar__link[aria-current="page"] { color: var(--color-heading); font-weight: 600; }
.sidebar--grouped .sidebar__group--top .sidebar__link { font-size: 0.875rem; font-weight: 600; }
.sidebar__link:focus-visible { outline: 3px solid var(--brand-orange); outline-offset: -3px; }
.topbar-company {
    align-self: center; padding-left: 1rem; margin-left: 0.25rem; border-left: 1px solid rgba(255, 255, 255, 0.3);
    font-family: var(--font-heading); font-weight: 600; font-size: 1rem; color: #fff;
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Pages fill the window; only reading-width blocks (page header text) stay narrow. */
.content { width: 100%; padding: 1.75rem 2rem 3rem; }

.breadcrumbs ol { display: flex; flex-wrap: wrap; gap: 0.4rem; list-style: none; margin: 0 0 1rem; padding: 0; font-size: 0.85rem; color: var(--color-text-muted); }
.breadcrumbs li + li::before { content: "›"; margin-right: 0.4rem; }
.breadcrumbs [aria-current="page"] { color: var(--color-text); }

/* Page header */
.page-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 1rem; margin-bottom: 1.5rem; }
.page-header__text { max-width: 760px; }
.page-header .lede { margin-bottom: 0; }
.page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }
.btn__icon { width: 1rem; height: 1rem; flex: none; }

.accent-bar { display: block; width: 40px; height: 3px; margin-bottom: 0.9rem; background: var(--brand-orange); border-radius: 2px; }
.eyebrow {
    margin: 0 0 0.35rem;
    font-family: var(--font-heading);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--brand-orange-text);
}
h1 { margin: 0 0 0.5rem; font-size: 1.75rem; font-weight: 700; }
.lede { margin: 0 0 2rem; color: var(--color-text-muted); }
.footnote { margin-top: 2rem; font-size: 0.8rem; color: var(--color-text-muted); }

.live { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; color: var(--color-text-muted); }
.live .dot { width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--color-success); box-shadow: 0 0 0 3px var(--color-success-bg); }
.live[data-state="down"] .dot { background: var(--color-danger); box-shadow: 0 0 0 3px var(--color-danger-bg); }

/* Buttons */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    font-family: var(--font-heading);
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.2;
    border-radius: var(--radius);
    padding: 0.65rem 1.15rem;
    border: 2px solid transparent;
    cursor: pointer;
    text-decoration: none;
}
.btn:hover { text-decoration: none; }
.btn-sm { padding: 0.35rem 0.75rem; font-size: 0.85rem; }
.btn-primary { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }
.btn-primary:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); }
.btn-secondary { background: transparent; border-color: var(--color-primary); color: var(--color-link); }
.btn-secondary:hover { background: var(--color-selected-bg); }
.btn-danger { background: transparent; border-color: var(--color-danger); color: var(--color-danger); }
.btn-danger:hover { background: var(--color-danger-bg); }
.btn-ghost { background: transparent; color: #fff; border-color: rgba(255, 255, 255, 0.4); padding: 0.35rem 0.8rem; font-size: 0.85rem; }
.btn-ghost:hover { background: rgba(255, 255, 255, 0.12); }
.btn-block { width: 100%; }
.btn-link {
    font: inherit;
    font-size: 0.9rem;
    padding: 0;
    border: 0;
    background: none;
    color: var(--color-link);
    text-decoration: underline;
    cursor: pointer;
}

/* Theme switch */
.theme-toggle {
    display: inline-grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.4);
    background: transparent;
    color: #fff;
    cursor: pointer;
}
.theme-toggle:hover { background: rgba(255, 255, 255, 0.12); }
.theme-toggle svg { width: 1.1rem; height: 1.1rem; }
.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* Panels */
.panel {
    background: var(--color-surface);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}
.panel--danger { border-color: var(--color-danger); box-shadow: none; }
.panel--danger p { margin-top: 0; }

/* Forms */
.form { display: flex; flex-direction: column; gap: 0.35rem; }
.form label { margin-top: 0.75rem; font-size: 0.875rem; font-weight: 700; color: var(--color-text); }
.form input[type="email"],
.form input[type="password"],
.form input[type="text"],
.form input[type="tel"],
.form input[type="url"],
.form input[type="date"],
.form input[type="number"],
.form select,
.form textarea {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.65rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    max-width: 100%;
}
.panel.form input[type="text"],
.panel.form input[type="email"],
.panel.form input[type="password"],
.panel.form input[type="url"],
.panel.form input[type="tel"],
.panel.form input[type="date"],
.panel.form input[type="number"],
.panel.form select,
.panel.form textarea { max-width: 560px; }
.form input:focus,
.form select:focus,
.form textarea:focus { border-color: var(--color-primary); }
.form [aria-invalid="true"] { border-color: var(--color-danger); }
.form .checkbox {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin: 1rem 0 1.1rem;
    font-weight: 400;
    cursor: pointer;
}
.form .checkbox input { width: 1.05rem; height: 1.05rem; margin: 0; accent-color: var(--color-primary); }
.label-note { font-weight: 400; color: var(--color-text-muted); }
.field-error { margin: 0; font-size: 0.85rem; color: var(--color-danger); }
.field-hint { margin: 0.1rem 0 0.4rem; font-size: 0.85rem; color: var(--color-text-muted); }
.form-submit { margin-top: 1.25rem; }
.form-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.5rem; }
.form-section-title { margin: 1.75rem 0 0.25rem; font-size: 1.1rem; }
.panel > .form-section-title:first-child { margin-top: 0; }

/* Dropdown lists (the user, 2026-09-28: "I can't use any of these on my macbook").
   A native <select> popup on macOS is drawn by the OS as a menu: it follows the Mac's own
   appearance and ignores the page, so a Mac in dark mode drew a dark grey popup over our light
   pages. color-scheme doesn't reach it (the control already computes as light, and it made no
   difference). Where the browser can draw the list itself instead — Chrome and Edge 135+, through
   appearance: base-select — we take it over, so the list matches the page in both themes.
   It stays a real <select>: keyboard, form submission and one change event on commit, all
   unchanged, and no JavaScript. Browsers without it keep the native popup.
   pointer: fine only — on a phone the native picker beats anything we would draw. */
@supports (appearance: base-select) {
    @media (pointer: fine) {
        /* Element-level, so .input and .form select keep their own padding and sizing. */
        select {
            appearance: base-select;
            font: inherit;
            color: var(--color-text);
            background: var(--color-input-bg);
            border: 1px solid var(--color-line);
            border-radius: var(--radius);
            padding: 0.55rem 0.75rem;
        }
        select::picker(select) {
            appearance: base-select;
            margin-top: 0.25rem;
            padding: 0.25rem;
            color: var(--color-text);
            background: var(--color-input-bg);
            border: 1px solid var(--color-line);
            border-radius: var(--radius);
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
        }
        select:focus-visible { border-color: var(--color-primary); }
        option {
            padding: 0.45rem 0.6rem;
            border-radius: 4px;
            background: transparent;
            color: var(--color-text);
        }
        option:checked { font-weight: 700; }
        /* :hover for the mouse, :focus for the arrow keys — the same row highlight either way. */
        option:hover,
        option:focus { background: var(--color-selected-bg); }
        option:disabled { color: var(--color-muted); }
    }
}

/* A section's heading with its action on the right (<x-section-header>): New/Add buttons belong
   here, not under the list. On a phone the action drops below the heading and fills the width. */
.section-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 0.5rem 1rem; margin-bottom: 0.9rem; }
.section-header__text { min-width: 0; }
.section-header > .section-header__text > .form-section-title { margin-top: 0; }
.section-header__lede { margin: 0.25rem 0 0; font-size: 0.875rem; color: var(--color-text-muted); }
.section-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-left: auto; }
.section-header__actions > details { margin: 0; }
@media (max-width: 560px) {
    .section-header { flex-direction: column; align-items: stretch; }
    .section-header__actions { margin-left: 0; }
    .section-header__actions > .btn,
    .section-header__actions > form,
    .section-header__actions > form > .btn,
    .section-header__actions > details,
    .section-header__actions > details > summary { width: 100%; justify-content: center; text-align: center; }
}

.fieldset { margin: 1.25rem 0 0; padding: 0; border: 0; min-width: 0; }
.fieldset legend { padding: 0; font-family: var(--font-heading); font-size: 1rem; font-weight: 600; color: var(--color-heading); }

.choice-list { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.4rem; }
.choice-list--columns { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.form .choice,
.choice {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    margin: 0;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    font-weight: 400;
    cursor: pointer;
}
.choice:hover { background: var(--color-panel); }
.choice:has(input:checked) { border-color: var(--color-primary); background: var(--color-selected-bg); }
.choice input { flex: none; width: 1.05rem; height: 1.05rem; margin: 0.15rem 0 0; accent-color: var(--color-primary); }
.choice--disabled { cursor: not-allowed; opacity: 0.65; }
.choice__label { display: block; font-weight: 700; }
.choice__description { display: block; font-size: 0.85rem; color: var(--color-text-muted); }
.choice__code { display: block; margin-top: 0.1rem; font-size: 0.75rem; color: var(--color-text-muted); }
/* A choice that carries its own control: the Client user type holds the "Choose client:" dropdown
   inside its card (the user, 2026-10-21). The wrapper takes the border and the selected state, and
   the inner .choice drops both, so one card is drawn rather than two nested ones — `.choice` itself
   is untouched, since groups, expenses, services and quotes all use it as-is. The control sits
   OUTSIDE the <label>: inside one, every click on the dropdown would activate the label and the
   option text would fold into the radio's accessible name. */
.choice-card { border: 1px solid var(--color-line); border-radius: var(--radius); }
.choice-card:has(input[type="radio"]:checked) { border-color: var(--color-primary); background: var(--color-selected-bg); }
.choice-card > .choice { border: 0; background: transparent; }
.choice-card > .choice:hover { background: transparent; }
/* Indented to the radio's text, not the card edge, so it reads as part of this choice: the gap is
   the radio's own width plus .choice's gap and padding. */
.choice-card__extra { padding: 0 0.75rem 0.7rem calc(0.75rem + 1.05rem + 0.6rem); }
.choice-card__extra[hidden] { display: none; }
.choice-card__extra label { display: block; margin-bottom: 0.25rem; font-size: 0.875rem; font-weight: 700; }
.choice-card__extra select { width: 100%; max-width: 22rem; }

.permission-section { margin: 1.5rem 0 0.6rem; font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-text-muted); }
.permission-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; }
.permission-module { margin: 0; padding: 0.9rem; border: 1px solid var(--color-line); border-radius: var(--radius-lg); display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
.permission-module legend { padding: 0 0.35rem; font-family: var(--font-heading); font-weight: 600; color: var(--color-heading); }
.permission-module .choice { border: 0; padding: 0.35rem; }
/* Section lock (Management access): set apart, since it gates everything under it. */
.permission-module--lock { margin-bottom: 1rem; border-color: var(--brand-orange); background: var(--color-warning-bg); }
.module-card--lock { border-top-color: var(--brand-orange); }

.permission-summary { list-style: none; margin: 1rem auto 0; padding: 0; max-width: 520px; text-align: left; display: flex; flex-direction: column; gap: 0.5rem; }
.permission-summary li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.permission-summary code { color: var(--color-text-muted); }

/* Tabs (links that switch views) */
.tabs { display: flex; gap: 0.25rem; margin: 0 0 1.25rem; border-bottom: 1px solid var(--color-line); overflow-x: auto; }
.tabs__tab {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.65rem 1rem;
    margin-bottom: -1px;
    border-bottom: 3px solid transparent;
    color: var(--color-text-muted);
    font-family: var(--font-heading);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.tabs__tab:hover { color: var(--color-heading); text-decoration: none; }
.tabs__tab[aria-current="page"] { color: var(--color-heading); border-bottom-color: var(--brand-orange); }
.tabs__count { padding: 0 0.45rem; border-radius: 999px; font-size: 0.75rem; background: var(--color-panel); color: var(--color-text-muted); }
.tabs__tab[aria-current="page"] .tabs__count { background: var(--color-selected-bg); color: var(--color-link); }

/* Permissions reference */
.permission-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.25rem; margin-bottom: 1rem; }
.permission-toolbar[hidden] { display: none; }
.input {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    width: 100%;
    max-width: 340px;
}
.input:focus { border-color: var(--color-primary); }
.switch { display: inline-flex; align-items: center; gap: 0.5rem; cursor: pointer; font-size: 0.9rem; }
.switch input { width: 1.05rem; height: 1.05rem; margin: 0; accent-color: var(--brand-orange); }

.module-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 460px), 1fr)); gap: 1rem; align-items: start; }
.module-card {
    background: var(--color-surface);
    border: 1px solid var(--color-line);
    border-top: 3px solid var(--brand-blue);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}
.module-card[hidden] { display: none; }
.module-card__header { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; padding: 1rem 1.1rem 0.85rem; border-bottom: 1px solid var(--color-line); }
.module-card__title { margin: 0; font-size: 1.1rem; }
.module-card__title a { color: var(--color-heading); text-decoration: none; }
.module-card__title a:hover { text-decoration: underline; }
.module-card__purpose { margin: 0.3rem 0 0; font-size: 0.85rem; line-height: 1.45; color: var(--color-text-muted); }
.module-card__note { margin: 0; padding: 0.9rem 1.1rem; font-size: 0.9rem; color: var(--color-text-muted); }

.permission-rows { list-style: none; margin: 0; padding: 0; }
.permission-row {
    padding: 0.7rem 1.1rem;
    border-left: 3px solid transparent;
}
.permission-row + .permission-row { border-top: 1px solid var(--color-line); }
.permission-row[hidden] { display: none; }
.permission-row--sensitive { border-left-color: var(--brand-orange); background: var(--color-warning-bg); }
/* A row is a stack of four things (the user, 2026-10-21): title with Sensitive pushed to the far
   right, one sentence, the key, then who has it. `.permission-row__main`, `__label` and `__facts`
   went with the markup that used them. */
.permission-row__title { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin: 0; }
.permission-row__name { font-weight: 700; }
.permission-row__description { margin: 0.15rem 0 0; font-size: 0.875rem; line-height: 1.45; color: var(--color-text-muted); }
/* The key line carries the audience after it, separated by a rule (the user, 2026-10-21). Text and
   separators, deliberately not pills: the group badges sit one line below, and two pill kinds in one
   row is the confusion this page was fixed for on 2026-10-20. */
/* The WHOLE line is monospace (the user, 2026-10-21: "I want it all to be that termianlfont it was
   before") — key, words and slashes alike, one size and one muted colour. The font goes on the line
   rather than on its parts, so nothing can drift onto a different face again. The key keeps
   font-size: inherit to cancel the base `code` rule's 0.85em, which would otherwise print it
   slightly smaller than the words beside it. */
.permission-row__meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.5rem; margin: 0.25rem 0 0; font-family: var(--font-mono); font-size: 0.8rem; color: var(--color-text-muted); }
.permission-row__key { font-size: inherit; color: inherit; }
.permission-row__audience::before { content: '/'; margin-right: 0.5rem; opacity: 0.45; }
.permission-row__assigned { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem; margin: 0.4rem 0 0; font-size: 0.8125rem; }
.permission-row__assigned-label { color: var(--color-text-muted); }

.perm-section { margin: 0 0 1rem; }
.perm-section__title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; margin: 0; font-size: 1.05rem; }
.perm-section__count { font-family: var(--font-body); font-size: 0.8rem; font-weight: 400; color: var(--color-text-muted); }
.perm-key { display: flex; flex-wrap: wrap; gap: 0.2rem 1.25rem; margin: 0.45rem 0 0; font-size: 0.8rem; }
.perm-key > div { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem; }
.perm-key dt { font-weight: 700; color: var(--color-text); }
.perm-key dd { margin: 0; color: var(--color-text-muted); }


.member-list { margin: 0.5rem 0 0; padding-left: 1.1rem; }
.member-list li { margin: 0.25rem 0; }

.alert {
    display: flex;
    gap: 0.6rem;
    padding: 0.75rem 0.9rem;
    border-radius: var(--radius);
    border-left: 4px solid currentColor;
    font-size: 0.9rem;
    margin-bottom: 1rem;
}
.alert svg { flex: none; width: 1.15rem; height: 1.15rem; margin-top: 0.1rem; }
.alert p { margin: 0; }
.alert strong { display: block; }
.alert-ok { background: var(--color-success-bg); color: var(--color-success-text); }
.alert-error { background: var(--color-danger-bg); color: var(--color-danger); }
.alert-warning { background: var(--color-warning-bg); color: var(--color-warning-text); }
/* Informational: no colour verdict, just a note worth reading. */
.alert-note { background: var(--color-selected-bg); color: var(--color-text); }
/* The success flash clears itself (app.js adds the button and the timer); nothing here hides an
   alert, so with JavaScript off the banner stays and stays readable. */
.alert__dismiss {
    flex: none; align-self: flex-start; margin-left: auto; padding: 0.15rem;
    color: inherit; background: none; border: 0; border-radius: var(--radius);
    opacity: 0.7; cursor: pointer; line-height: 0;
}
.alert__dismiss:hover { opacity: 1; }
.alert__dismiss svg { width: 1rem; height: 1rem; }
.alert--dismissing { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
    .alert--dismissing { transition: opacity 0.4s ease; }
}

/* Badges */
.badge {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-family: var(--font-heading);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.5;
    vertical-align: middle;
    white-space: nowrap;
    /* Dragging across a page shouldn't select badge text (the user, 2026-09-23). Screen readers
       still read it; only the mouse selection skips it. */
    -webkit-user-select: none;
    user-select: none;
    background: var(--color-panel);
    color: var(--color-text);
    /* A badge has to read as a pill against whatever is behind it, and the neutral fill doesn't:
       --color-panel sits 28/255 from a dark row and 18 from a light one, so the shape dissolves and
       only the label survives. The ring does the separating — 58 and 40 against the same rows —
       which is why it's on the base and not on each neutral variant. Six modules used the same
       weak recipe and three had already added this ring privately (Quotes, then Services, 2026-10-09);
       they can drop theirs, since a variant overriding background and color keeps this. */
    box-shadow: inset 0 0 0 1px var(--color-line);
}
.badge--admin { background: var(--brand-navy); color: #fff; }
:root[data-theme="dark"] .badge--admin { background: #e6e8ea; color: #17191c; }
.badge--staff { background: var(--color-selected-bg); color: var(--color-link); }
.badge--customer { background: var(--color-success-bg); color: var(--color-success-text); }
.badge--warning { background: var(--color-warning-bg); color: var(--color-warning-text); }
/* Moved below the base block on 2026-10-21. It had been declared ~40 lines ABOVE `.badge`, so at
   equal specificity the base's own `background`/`color` won on source order and this variant never
   applied: every "linked group" badge rendered as a plain neutral pill. Same family as
   `.detail-list.panel` and `.dialog input` (docs/branding.md) — a rule that loses to the one it was
   written to extend. Used only by the Permissions page and the gallery, both Web's. */
.badge--link { text-decoration: none; background: var(--color-selected-bg); color: var(--color-link); }
.badge--link:hover { text-decoration: underline; }
/* Placeholder figures until real data exists (the user's rule): <span class="badge badge--fake">FAKE</span> */
.badge--fake { background: var(--color-danger-bg); color: var(--color-danger); border: 1px dashed currentColor; letter-spacing: 0.08em; }

/* Tables */
/* position: relative keeps screen-reader-only text (absolutely positioned) inside the scroll box, so a
   wide table never widens the page. */
.table-wrap { position: relative; overflow-x: auto; background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); }
.table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
.table th {
    padding: 0.7rem 1rem;
    text-align: left;
    font-family: var(--font-heading);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
    background: var(--color-panel);
    border-bottom: 1px solid var(--color-line);
    white-space: nowrap;
}
.table td { padding: 0.75rem 1rem; border-bottom: 1px solid var(--color-line); vertical-align: top; }
.table tbody tr:last-child td { border-bottom: 0; }
/* A th inside tbody is the row's NAME, not a column heading, so it reads as a body cell. Without
   this it inherits .table th's column typography — 12px uppercase letter-spaced muted — and the most
   important cell in the row comes out smaller and fainter than the figures beside it. Pinning a
   column requires th scope="row", so adopting .table--pin used to silently reformat that cell:
   Time, Capacity and Accounts each hit it and two of them fixed it privately (found by Capacity on
   /preview, 2026-10-06). Modules with their own reset can drop it. */
.table tbody th {
    padding: 0.75rem 1rem;
    font-family: inherit;
    font-size: inherit;
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    color: var(--color-text);
    background: transparent;
    white-space: normal;
    vertical-align: top;
    border-bottom: 1px solid var(--color-line);
}
.table tbody tr:last-child th { border-bottom: 0; }
/* The pinned cell is the exception: figures slide underneath it, so it needs to stay opaque — and
   then it has to pick up the row's hover tint itself, since nothing shows through. */
.table.table--pin tbody th:first-child { background: var(--color-surface); }
.table.table--pin tbody tr:hover th:first-child { background: var(--color-selected-bg); }
.table tbody tr:hover { background: var(--color-selected-bg); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.cell-primary { display: block; font-weight: 700; }
.cell-secondary { display: block; font-size: 0.85rem; color: var(--color-text-muted); }
/* Whole-row links: app.js adds .row-link to rows it has wired up, so a row only looks clickable
   when it actually is (nothing claims it with JavaScript off). The row already highlights on hover;
   :focus-within shows the same highlight when the row's own link is tabbed to. */
.table tbody tr.row-link { cursor: pointer; }
.table tbody tr.row-link:focus-within { background: var(--color-selected-bg); }

/* A last column holding buttons (or a form with one) lines up hard right and takes only the width it
   needs, so row buttons sit under the panel's own button. :has() catches existing markup; add
   .col-actions (or .cell-actions) on the th/td to say so explicitly. Number columns keep .num. */
.table th:last-child:has(.btn),
.table td:last-child:has(.btn),
.table td:last-child:has(form),
.table .col-actions,
.cell-actions { text-align: right; white-space: nowrap; }
.table th:last-child:has(.btn),
.table td:last-child:has(.btn),
.table td:last-child:has(form),
.table th.col-actions,
.table td.col-actions,
.table th.cell-actions,
.table td.cell-actions { width: 1%; }
/* Buttons and their forms sit in one row, with a small gap. */
.table td:last-child:has(.btn) > form,
.table td:last-child:has(form) > form,
.table .col-actions > form,
.table .cell-actions > form { display: inline-block; margin: 0; vertical-align: middle; }
.table td:last-child:has(.btn) > * + *,
.table td:last-child:has(form) > * + *,
.table .col-actions > * + *,
.table .cell-actions > * + * { margin-left: 0.35rem; }

/* Wide tables: pin the first column so the row's name stays put while its figures scroll sideways
   (promoted from Time's .time-grid--pin, 2026-10-06, once Capacity became the second case).

   Borders don't travel with a sticky cell under border-collapse, so the right edge and the row line
   are drawn as inset shadows. A module that tints a row sets --pin-flag rather than re-declaring
   box-shadow — declaring it outright silently drops those edges, which is the trap in the version
   this came from. The cell keeps .table th's opaque background, so figures slide under it.
   Written as .table.table--pin deliberately, for weight rather than style: module CSS is appended to
   the end of this file, so a module's own row rule at equal specificity would win on source order
   alone and silently drop the edges (Time hit exactly that with a pre-pinning flag rule, 2026-10-06).
   The extra class makes the structure win and the flag go through --pin-flag, which is the supported
   way in; a flag that doesn't appear is noticed, a missing hairline edge is not. */
.table.table--pin th:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    box-shadow: var(--pin-flag, 0 0 0 transparent), inset -1px 0 0 var(--color-line), inset 0 -1px 0 var(--color-line);
}
@media (max-width: 640px) {
    /* On a phone a long name would pin half the screen: let it wrap in a narrower column. Same
       weight question — an older module `th[scope="row"] { white-space: nowrap }` later in the file
       beats a single-class rule. */
    .table.table--pin th[scope="row"] { white-space: normal; min-width: 8rem; max-width: 9rem; }
}

/* Empty state */
.empty-state {
    padding: 2.5rem 1.5rem;
    text-align: center;
    background: var(--color-surface);
    border: 1px dashed var(--color-line);
    border-radius: var(--radius-lg);
}
.empty-state__icon { width: 2.5rem; height: 2.5rem; color: var(--brand-orange); }
/* Scoped to its own wrapper on purpose, not for cascade reasons you can see here: a bare
   `.empty-state__title` is (0,1,0), so EVERY `.{module}-section__header h2` rule in this file — one
   per module, six of them — outranks it on specificity whatever the order, and a shared component
   dropped inside a module's section silently takes that module's heading size. It happened twice on
   2026-10-13, to this and to `.card h2`. At (0,2,0) a module's descendant rule can't reach it.
   `.card h2` can't be hardened the same way (its heading carries no class), so the rule that keeps
   it safe is modules naming their own children — docs/branding.md → Shared components. */
.empty-state .empty-state__title { margin: 0.5rem 0; font-size: 1.15rem; }
.empty-state__body { max-width: 620px; margin: 0 auto; color: var(--color-text-muted); }
.empty-state__body p { margin: 0.5rem 0; }

/* Component preview (/preview, local only). Deliberately plain: the page is scaffolding around the
   real components, and nothing here should style them. */
.preview { margin: 0; background: var(--color-bg); color: var(--color-text); }
.preview__bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 1.5rem; border-bottom: 1px solid var(--color-line); background: var(--color-surface); }
.preview__body { padding: 1.5rem; }
.preview__lede { max-width: 60ch; color: var(--color-text-muted); }
.preview__group { margin: 0 0 2.5rem; padding: 1.25rem; border: 1px dashed var(--color-line); border-radius: var(--radius-lg); }
.preview__group > h2 { margin-top: 0; }
.preview__note { max-width: 70ch; color: var(--color-text-muted); font-size: 0.9rem; }
.preview__spread { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }

/* Login and other full-page (no top bar) screens */
.auth-page {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 4.5rem 1rem 2rem;
    background: var(--auth-bg);
    position: relative;
}
.auth-page .theme-toggle { position: absolute; top: 1rem; right: 1rem; }
.auth-card {
    width: 100%;
    max-width: 420px;
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    border-top: 4px solid var(--brand-orange);
    box-shadow: var(--shadow-auth);
    padding: 2.25rem 2.25rem 2rem;
}
.auth-logo { display: block; height: 52px; width: auto; margin: 0 0 1.75rem; }
.auth-logo--dark { display: none; }
:root[data-theme="dark"] .auth-logo--light { display: none; }
:root[data-theme="dark"] .auth-logo--dark { display: block; }
.auth-card h1 { font-size: 1.35rem; margin-bottom: 0.25rem; }

.auth-card .lede { margin-bottom: 1.5rem; }
.auth-footnote { max-width: 420px; margin: 1.25rem 0 0; font-size: 0.85rem; text-align: center; color: rgba(255, 255, 255, 0.8); }
.auth-actions { margin-top: 1.5rem; }
.auth-actions form { margin: 0; }
.auth-actions--split { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 1.25rem; }
.auth-actions--split form:only-child { margin-left: auto; margin-right: auto; }

/* Status cards */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; }
.card {
    background: var(--color-surface);
    border: 1px solid var(--color-line);
    border-top: 3px solid var(--color-success);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 1.1rem 1.25rem;
}
.card-error { border-top-color: var(--color-danger); }
.card h2 {
    margin: 0 0 0.4rem;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
}
.card .value { margin: 0; font-family: var(--font-heading); font-size: 1.2rem; font-weight: 600; color: var(--color-heading); }
.card .meta { margin: 0.35rem 0 0; font-size: 0.85rem; color: var(--color-text-muted); overflow-wrap: anywhere; }

/* Stored secrets (<x-secret-field>): hidden unless revealed. */
.secret-field { display: flex; flex-direction: column; gap: 0.35rem; margin: 0.75rem 0; }
.secret-field__label { font-size: 0.875rem; font-weight: 700; }
.secret-field__status,
.secret-field__revealed { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; }
.secret-field__dots { color: var(--color-text-muted); letter-spacing: 0.15em; }
.secret-field__reveal { margin: 0; }
.secret-field__value { font-family: var(--font-mono); max-width: 34rem; flex: 1 1 18rem; border-color: var(--brand-orange); }

.secret-field__masked { font-family: var(--font-mono); color: var(--color-text); }
/* The row variant: <dt>/<dd> inside the caller's own <dl>, so the secret aligns with the
   identifiers above it. The dots wear the same boxed-code look as a value beside them. */
.secret-field__row-label { font-size: 0.85rem; font-weight: 700; color: var(--color-text-muted); }
.secret-field__cell { margin: 0; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.secret-field__dots--boxed {
    display: inline-block;
    padding: 0 0.35rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    background: var(--color-panel);
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    font-size: 0.8rem;
}

/* A control that is only an icon: no box, no padding to speak of, the glyph does the work (the
   user, 2026-10-08: "reveal should just be eyeball icon. We dont need massive button"). It keeps a
   real accessible name — the icon is decorative, the aria-label carries the meaning. docs/modules.md
   referenced this class for months before it existed, so a tooltip example rendered unstyled. */
.icon-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.25rem;
    min-width: 1.75rem;
    min-height: 1.75rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--color-text-muted);
    cursor: pointer;
    text-decoration: none;
}
.icon-button:hover { color: var(--color-text); background: var(--color-selected-bg); }
.icon-button:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }


.input-mono { font-family: var(--font-mono) !important; letter-spacing: 0.02em; }

/* Label/value pairs on detail pages. */
.detail-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr)); gap: 0.75rem 1.5rem; margin: 1rem 0 0; }
.detail-list dt { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); }
.detail-list dd { margin: 0.15rem 0 0; }
.detail-list__wide { grid-column: 1 / -1; }
/* A detail list that is also a card keeps the card's spacing. .detail-list sets `margin: 1rem 0 0`,
   which zeroes the bottom, and it is declared ~540 lines after .panel at equal specificity — so
   source order silently won and two stacked cards touched (the user, 2026-10-13: "theres no gap in
   the top card and middle card"). Only one page combines them today; this is here so the next one
   doesn't rediscover it. */
.detail-list.panel { margin-bottom: 1.5rem; }

.badge--danger { background: var(--color-danger-bg); color: var(--color-danger); }

/* Administration → Integrations */
.integration-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); gap: 1rem; }
.integration-card--pending { border-top-color: var(--color-line); }
.integration-card__action { margin: 0.9rem 0 0; }
/* In progress (<x-spinner>): a spinner, or a still dot with reduced motion. */
.spinner { text-transform: none; letter-spacing: normal; font-weight: 400; display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8125rem; color: var(--color-text-muted); white-space: nowrap; }
.spinner__mark {
    width: 0.85em; height: 0.85em; flex: none;
    border: 2px solid var(--color-line); border-top-color: var(--color-primary); border-radius: 50%;
    animation: spinner-turn 0.8s linear infinite;
}
@keyframes spinner-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .spinner__mark { animation: none; border-color: var(--color-primary); background: var(--color-primary); width: 0.6em; height: 0.6em; }
}

/* Filters above a list (GET form, so a filtered view can be bookmarked) */
.filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1rem; margin: 0 0 1.25rem; }
.filter-bar__field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.8rem; font-weight: 700; color: var(--color-text-muted); }
.filter-bar__field .input { min-width: 11rem; font-weight: 400; }
.filter-bar__actions { display: flex; align-items: center; gap: 0.75rem; padding-bottom: 0.2rem; font-size: 0.875rem; }
.filter-bar--auto .filter-bar__submit { display: none; }

/* Administration › Syncs */
.panel--warning { border-color: var(--color-warning-text); box-shadow: none; }
.sync-table th form, .sync-table td form { display: inline; }
.sync-table__head-action { margin-left: 0.5rem; }
.sync-table th[scope="col"] { white-space: nowrap; }
/* Body-header typography is shared now (.table tbody th); these two are the only differences —
   a slightly smaller row label and a floor on the column's width. Kept rather than dropped so the
   page looks exactly as it did; the rest was a copy of the shared reset. */
.sync-table tbody th, .sync-history tbody th { font-size: 0.875rem; min-width: 10rem; }
.sync-cell { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; }
.sync-cell .cell-secondary { flex-basis: 100%; }
.sync-cell__action { margin-top: 0.25rem; }
.sync-history { margin-top: 1.5rem; }
.sync-history__status { display: flex; flex-direction: column; align-items: flex-end; gap: 0.25rem; white-space: normal; }
.sync-history ul.field-hint { margin: 0.5rem 0 1rem; padding-left: 1.25rem; }
.credential--active { border-left: 3px solid var(--color-success); }
.credential__header { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.75rem; }
.credential__title { margin: 0; font-size: 1.15rem; }
.credential__sub { margin: 0.2rem 0 0; font-size: 0.875rem; }
.credential__badges { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: flex-start; }
.credential__secrets { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 24rem), 1fr)); gap: 0 1.5rem; margin-top: 0.75rem; }
.credential__actions form { margin: 0; }

/* An <x-icon> name the vendored Font Awesome doesn't have. Only ever rendered in local/debug, so a
   wrong name is seen while the page is written; in production the icon is simply absent. */
.icon-unknown { color: var(--color-warning-text); outline: 1px dashed var(--color-warning-text); outline-offset: 2px; }

/* Small dialogs (<x-dialog>). Behavior lives in app.js; see docs/modules.md. */
.dialog {
    width: min(26rem, calc(100vw - 2rem));
    padding: 1.35rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: var(--shadow-card);
}
.dialog__message { margin: 0; line-height: 1.5; overflow-wrap: anywhere; }
.dialog--confirm .form-actions { justify-content: flex-start; }
.dialog--wide { width: min(40rem, calc(100vw - 2rem)); }
/* Room for content that is genuinely side by side — a grouped "browse all" list in columns.
   A separate step rather than a wider --wide, which is a form width used elsewhere. The clamp keeps
   a phone sane; laying the content out in one column at that width belongs to the page. */
.dialog--roomy { width: min(60rem, calc(100vw - 2rem)); }
/* Form dialogs are rendered open so they work without JavaScript; until the script closes them (or
   when it never runs) they sit in the page as a plain panel rather than floating. */
.dialog--form[open]:not(:modal) { position: static; display: block; margin: 0 0 1.5rem; width: min(36rem, 100%); }
.dialog::backdrop { background: var(--dialog-backdrop); }
.dialog .dialog__title { margin: 0 0 0.5rem; font-size: 1.15rem; }   /* (0,2,0): see .empty-state__title above */
.dialog__intro { margin: 0 0 0.75rem; font-size: 0.875rem; color: var(--color-text-muted); }
.dialog label { display: block; margin-top: 0.75rem; margin-bottom: 0.35rem; font-size: 0.875rem; font-weight: 700; }
.dialog label:first-of-type { margin-top: 0; }
/* Radios and checkboxes size themselves and must be excluded: this is an element selector under a
   container class, so at (0,1,1) it ties with `.choice input` and wins on source order alone, giving
   a radio `width: 100%`, a padding and a border — it becomes a box and its text is pushed out of the
   flex row (the user's screenshot of Add a Referral, 2026-10-13). Deliberately a deny-list on the two
   control types rather than an allow-list of text-like types copied from `.form` above: `.form`'s
   list has no `file`, and the document upload field lives in a dialog, so copying it would have
   stripped that field. `.form .checkbox input` already protects checkboxes at (0,2,1); this covers a
   radio or checkbox in a dialog with no component class around it, which nothing else does. */
.dialog input:not([type="radio"]):not([type="checkbox"]),
.dialog select,
.dialog textarea {
    font: inherit;
    width: 100%;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.65rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
}
.panel.form .dialog input,
.panel.form .dialog select,
.panel.form .dialog textarea { max-width: 100%; }
.dialog input:focus, .dialog select:focus, .dialog textarea:focus { border-color: var(--color-primary); }
.dialog .form-actions { margin-top: 1.25rem; }

/* Tooltips: brand-styled replacement for the browser's title= bubble. CSS only.
   <button class="has-tooltip" data-tooltip="Unlock and change" aria-label="Unlock and change">
   The tooltip is decorative: keep the real name on the element (aria-label, or visible text),
   because it never appears on touch devices and is hidden from screen readers.
   The bubble sits BELOW the element (the user's decision, 2026-09-25). Add .has-tooltip--wrap for
   longer text.
   Alignment: centred and below by default; app.js flips it to --end or --start when the bubble would
   run past a side, and to --above when there isn't room below. Set those classes yourself to pin it.
   Inside a scrolling box (.table-wrap) the bubble is clipped, so put it on a cell's content. */
/* An icon with a tooltip: <x-icon> wraps the glyph in this, because Font Awesome draws with
   ::before and so does the tooltip's arrow — on the icon itself, the tooltip erases it. */
.icon-tooltip { display: inline-flex; }

.has-tooltip { position: relative; }
.has-tooltip::after,
.has-tooltip::before {
    position: absolute;
    left: 50%;
    z-index: 30;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}
.has-tooltip::after {
    content: attr(data-tooltip);
    top: calc(100% + 0.5rem);
    transform: translateX(-50%);
    padding: 0.3rem 0.55rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    background: var(--color-surface);
    box-shadow: var(--shadow-card);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: 0.8rem;
    font-weight: 400;
    line-height: 1.35;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
}
.has-tooltip::before {
    content: "";
    top: calc(100% + 0.2rem);
    width: 0.5rem;
    height: 0.5rem;
    transform: translateX(-50%) rotate(45deg);
    border-left: 1px solid var(--color-line);
    border-top: 1px solid var(--color-line);
    background: var(--color-surface);
}
.has-tooltip:hover::after,
.has-tooltip:hover::before,
.has-tooltip:focus-visible::after,
.has-tooltip:focus-visible::before { opacity: 1; visibility: visible; }

/* Above the element, when there isn't room below. app.js adds this; set it by hand to pin it. */
.has-tooltip--above::after { top: auto; bottom: calc(100% + 0.5rem); }
.has-tooltip--above::before {
    top: auto;
    bottom: calc(100% + 0.2rem);
    border: 0;
    border-right: 1px solid var(--color-line);
    border-bottom: 1px solid var(--color-line);
}

/* Longer text wraps instead of running off the screen */
.has-tooltip--wrap::after { white-space: normal; width: max-content; max-width: 16rem; text-align: center; }

/* Alignment: pin the bubble's right edge (near the right of the page) or its left edge.
   app.js sets these automatically; set them by hand when you already know. */
.has-tooltip--end::after { left: auto; right: 0; transform: none; text-align: right; }
.has-tooltip--end::before { left: auto; right: 0.6rem; transform: rotate(45deg); }
.has-tooltip--start::after { left: 0; transform: none; text-align: left; }
.has-tooltip--start::before { left: 0.6rem; transform: rotate(45deg); }

@media (prefers-reduced-motion: no-preference) {
    .has-tooltip::after,
    .has-tooltip::before { transition: opacity 0.15s ease, visibility 0.15s ease; }
}

/* Medium screens: drop the product name so the section menu fits */
@media (max-width: 1100px) {
}

/* Small screens: stack the shell, menus scroll sideways */
@media (max-width: 800px) {
    .topbar { flex-wrap: wrap; gap: 0.5rem 1rem; padding: 0.6rem 1rem; }
    .section-nav { order: 3; width: 100%; }
    .brand-logo { height: 26px; }
    .user-name { display: none; }
    .shell--sidebar { display: block; }
    .sidebar { border-right: 0; border-bottom: 1px solid var(--color-line); padding: 0.5rem 1rem; }
    .sidebar__title { display: none; }
    .sidebar__list { flex-direction: row; overflow-x: auto; }
    .sidebar__link { white-space: nowrap; border-left: 0; border-bottom: 3px solid transparent; border-radius: 0; }
    .sidebar__link[aria-current="page"] { border-bottom-color: var(--brand-orange); background: transparent; }
    .sidebar--grouped nav { display: flex; flex-direction: column; gap: 0.35rem; }
    .sidebar__group + .sidebar__group { margin-top: 0; }
    .sidebar--grouped .sidebar__group:not(.sidebar__group--top) .sidebar__list { margin-left: 0; border-left: 0; }
    .sidebar--grouped .sidebar__group:not(.sidebar__group--top) .sidebar__link { margin-left: 0; border-radius: 0; padding: 0.5rem 0.75rem; }
    .sidebar__group { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
    .sidebar__group-title { flex: none; padding: 0; margin: 0; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-muted); min-width: 4.5rem; }
    .sidebar--grouped .sidebar__list { min-width: 0; }
    .topbar-company { order: 2; font-size: 0.875rem; border-left: 0; margin-left: 0; padding-left: 0; flex-basis: 100%; }
    .content { padding: 1.25rem 1rem 2.5rem; }
    .auth-card { padding: 1.75rem 1.25rem 1.5rem; }
    .auth-logo { height: 42px; }
}

@media (prefers-reduced-motion: no-preference) {
    .btn, .theme-toggle, .form input, .sidebar__link, .section-nav__link { transition: background-color 0.15s ease, border-color 0.15s ease; }
}

/* Module: Accounts */
.acct-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1rem; margin: 0 0 1.25rem; }
.acct-filters__field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.8rem; font-weight: 700; color: var(--color-text-muted); }
.acct-filters__field .input { min-width: 11rem; }
.acct-filters__actions { display: flex; align-items: center; gap: 0.75rem; padding-bottom: 0.2rem; font-size: 0.875rem; }
/* Hidden by the scope toggle. A class rather than the `hidden` attribute, which the expand button
   already owns on the contract sub-rows. */
.table tr.acct-row--out-of-scope { display: none; }

/* Which clients are in the list, at the far right of the filter row. Radios drawn as a segmented
   control: the native input stays in the markup (and focusable) so it works with JavaScript off and
   reads as a radio group to a screen reader, while the label beside it carries the appearance. */
.acct-scope { display: inline-flex; margin: 0 0 0 auto; padding: 0; border: 1px solid var(--color-line); border-radius: var(--radius); overflow: hidden; }
.acct-scope__option { display: inline-flex; align-items: center; font-size: 0.8rem; font-weight: 700; color: var(--color-text-muted); cursor: pointer; }
.acct-scope__option + .acct-scope__option { border-left: 1px solid var(--color-line); }
.acct-scope__option input { position: absolute; opacity: 0; pointer-events: none; }
/* **Every rule below addresses the option's OWN span, never a descendant.** The label used to hold
   bare text; it now holds a nested `.acct-scope__count`, and a descendant `span` selector reaches
   that too — which cost two defects in one day (2026-10-20): the count took the label's padding, and
   then its hover background, a grey box inside the selected option's blue. Anything added inside the
   label will hit the same rules, so keep these child-scoped. */
.acct-scope__option > span { padding: 0.45rem 0.9rem; }
.acct-scope__option:hover > span { background: var(--color-panel); }
.acct-scope__option input:checked + span { background: var(--color-primary); color: var(--color-surface); }
.acct-scope__option input:focus-visible + span { outline: var(--focus-ring); outline-offset: -2px; }
/* The same switch inside a section heading, beside that section's Add button. */
.acct-section__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-left: auto; }
.acct-scope-form { display: flex; align-items: center; gap: 0.5rem; margin: 0; }
.acct-scope-form .acct-scope { margin: 0; }
/* Measured on /preview 2026-10-20: `padding: 0` here LOST to `.acct-scope__option span`, which is
   more specific, and the count rendered with a whole button's padding each side. Fixed above by
   making that rule a direct child; this one only has to not re-add any. */
.acct-scope__count { margin-left: 0.3rem; opacity: 0.7; font-variant-numeric: tabular-nums; }

.table td.acct-name-cell { min-width: 12rem; }
/* Headers that stack instead of stretching their column (the user, 2026-09-23). */
.table th.acct-th-stack { white-space: normal; }
.table th.acct-th-count { width: 1%; max-width: 5.5rem; }
.acct-name-row { display: flex; align-items: flex-start; gap: 0.5rem; }
.acct-expand-slot { flex: 0 0 1.25rem; display: flex; justify-content: center; padding-top: 0.1rem; } /* empty on rows that don't expand */
.acct-expand { display: inline-flex; align-items: center; justify-content: center; width: 1.25rem; height: 1.25rem; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--color-primary); cursor: pointer; }
.acct-expand:hover { color: var(--color-primary-hover); }
.acct-expand svg { width: 1.1rem; height: 1.1rem; }
.acct-expand .acct-expand__minus,
.acct-expand[aria-expanded="true"] .acct-expand__plus { display: none; }
.acct-expand[aria-expanded="true"] .acct-expand__minus { display: block; }
.acct-subrow td { background: var(--color-panel); font-size: 0.9rem; }
.table tfoot .acct-total > * { border-top: 2px solid var(--color-line); border-bottom: 0; font-weight: 700; text-align: left; vertical-align: top; background: var(--color-panel); padding: 0.75rem 1rem; } /* the header row's grey (.table th), across the whole row */
.table tfoot .acct-total > .num { text-align: right; }
.acct-total .cell-secondary { font-weight: 400; }
.acct-total__net { display: block; margin-top: 0.15rem; padding-top: 0.15rem; border-top: 1px solid var(--color-line); }
.acct-percent-input { max-width: 6rem; }
.acct-spend-input { max-width: 9rem; }
.table td.acct-basis-cell { min-width: 12rem; }

/* The outlook: the accounts list recalculated without the contracts that are ending (the user,
   2026-10-07). The toggle is an icon button in the header; the note has to be impossible to miss,
   because every figure under it is a projection of something that hasn't happened. */
.acct-outlook-toggle { display: inline-flex; align-items: center; justify-content: center; min-width: 2.4rem; }
.acct-outlook-toggle.is-active { background: var(--color-warning-bg); border-color: var(--color-warning-text); color: var(--color-warning-text); }
.acct-outlook-note { display: flex; align-items: flex-start; gap: 0.6rem; margin: 0 0 1rem; padding: 0.75rem 1rem;
    border-left: 4px solid var(--color-warning-text); background: var(--color-warning-bg); color: var(--color-warning-text); }
.acct-outlook-note__icon { margin-top: 0.15rem; flex: none; }
.acct-outlook-note a { color: inherit; }
/* The hit itself, on each card. Reads as the delta, not as another figure to act on. */
.acct-outlook-hit { color: var(--color-warning-text); font-weight: 600; }
.acct-outlook-hit--stale { color: var(--color-text-muted); font-weight: 400; }
/* A client with nothing left, and the contracts being taken out: still there to compare against,
   visibly not counted. Never removed — a row that vanishes can't be reconciled with the real page. */
.table tbody tr.acct-row--gone > td { opacity: 0.55; }
.table tbody tr.acct-subrow--excluded > td { opacity: 0.55; text-decoration: line-through; }
/* A consumption rate that hasn't been entered. The icon carries the whole message (the user,
   2026-10-06), so the button needs a hit area of its own — a bare glyph is a ~13px target — and the
   orange is the warning token, "needs entering", not a new colour. Focus comes from the global
   :focus-visible ring. */
.acct-basis-rate { display: inline-flex; align-items: center; justify-content: center; min-width: 1.75rem; min-height: 1.75rem; padding: 0; border: 0; border-radius: var(--radius-sm, 6px); background: none; color: var(--color-warning-text); cursor: pointer; }
.acct-basis-rate:hover { background: var(--color-warning-bg); }
.acct-reminder-note { max-width: 70ch; margin: 0 0 1rem; }
.acct-renewals { display: flex; flex-direction: column; gap: 1rem; }
.acct-renewal { padding: 1rem 1.25rem; }
.acct-renewal__head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.75rem 1.5rem; }
.acct-renewal__title { margin: 0; font-size: 1.05rem; }
.acct-renewal__when { text-align: right; }
.acct-renewal__date { font-weight: 700; color: var(--color-heading); }
.acct-renewal__warning { margin: 0.75rem 0 0; color: var(--color-warning-text); background: var(--color-warning-bg); padding: 0.5rem 0.75rem; border-radius: var(--radius-sm, 6px); }
.acct-timeline { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.9rem 0 0; padding: 0; list-style: none; }
.acct-timeline__item { flex: 1 1 13rem; display: grid; grid-template-columns: auto 1fr; gap: 0.15rem 0.5rem; align-content: start; padding: 0.7rem 0.85rem; border: 1px solid var(--color-line); border-radius: var(--radius-lg); background: var(--color-surface); }
.acct-timeline__item > form { grid-column: 2; margin-top: 0.45rem; }
.acct-timeline__item--sent { border-color: var(--color-success); }
.acct-timeline__item--skipped { color: var(--color-text-muted); }
.acct-timeline__mark { width: 1.1rem; height: 1.1rem; margin-top: 0.15rem; }
.acct-timeline__mark:not([data-marked]) { width: 0.6rem; height: 0.6rem; margin: 0.4rem 0 0; border-radius: 50%; border: 2px solid var(--color-line); }
.acct-timeline__item--sent .acct-timeline__mark { color: var(--color-success); }
.acct-timeline__body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.acct-timeline__label { font-weight: 700; }
.acct-audience { display: inline-flex; flex-wrap: wrap; gap: 0.25rem; }
/* Services on a contract (the user's design, 2026-09-23): every catalog line, green when it's on
   this contract and grey when it isn't, so what a client hasn't bought is visible too. */
.acct-services { display: flex; flex-direction: column; gap: 0.3rem; margin: 0.5rem 0 0; padding: 0; list-style: none; }
.acct-services__item form { display: block; }
.acct-services__toggle { display: flex; align-items: center; gap: 0.5rem; width: 100%; padding: 0.45rem 0.6rem; border: 1px solid var(--color-line); border-radius: var(--radius-lg); background: var(--color-panel); color: var(--color-text-muted); font: inherit; font-size: 0.9rem; text-align: left; cursor: pointer; }
.acct-services__toggle--static { cursor: default; }
.acct-services__item--on .acct-services__toggle { background: var(--color-success-bg); border-color: var(--color-success); color: var(--color-success-text); font-weight: 600; }
button.acct-services__toggle:hover { border-color: var(--color-primary); }
button.acct-services__toggle:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.acct-services__mark { flex: 0 0 1rem; height: 1rem; border-radius: 50%; border: 2px solid currentColor; opacity: 0.5; }
.acct-services__item--on .acct-services__mark { border: 0; opacity: 1; }
.acct-services__mark svg { width: 100%; height: 100%; }
/* A list of identifier badges with a × (Sage project ids). Same size step as the service rows. */
.acct-idlist { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.5rem 0 0; padding: 0; list-style: none; }
.acct-idlist__badge { display: inline-flex; align-items: flex-start; gap: 0.4rem; max-width: 100%; padding: 0.15rem 0.3rem 0.15rem 0.6rem; font-size: 0.85rem; line-height: 1.45; letter-spacing: normal; text-transform: none; white-space: normal; }
/* A long label wraps inside the badge; the number and the × never do (the user, 2026-09-24: a long
   label pushed the × past the card's edge). */
.acct-idlist__badge > form { flex: 0 0 auto; }
.acct-idlist__badge form { display: flex; }
.acct-idlist__remove { display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; padding: 0; border: 0; border-radius: 50%; background: none; color: inherit; opacity: 0.7; cursor: pointer; }
.acct-idlist__remove:hover { opacity: 1; background: var(--color-surface); }
.acct-idlist__remove:focus-visible { outline: 2px solid currentColor; outline-offset: 1px; }
.acct-idlist__remove svg { width: 0.7rem; height: 0.7rem; }
@media (pointer: coarse) {
    .acct-idlist__remove { width: 2rem; height: 2rem; margin: -0.3rem -0.25rem -0.3rem 0; }
}
.acct-sage-id { font-family: var(--font-mono); letter-spacing: 0.02em; white-space: nowrap; }
.acct-sage-label { color: var(--color-text-muted); font-weight: 400; min-width: 0; overflow-wrap: anywhere; }
}
}
.acct-timeline__state { font-size: 0.9rem; }
.acct-timeline svg { width: 100%; height: 100%; }
.acct-margin-warn { color: var(--color-warning-text); font-weight: 600; }
.acct-date--expired { color: var(--color-danger); font-weight: 700; }
.table td.acct-wrap-cell { min-width: 11rem; }
.table td.acct-type-cell { min-width: 7.5rem; }

.acct-code {
    display: inline-block;
    padding: 0 0.35rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    background: var(--color-panel);
    color: var(--color-heading);
    font-family: var(--font-mono);
    font-size: 0.8rem;
    letter-spacing: 0.05em;
}
.panel.form input.acct-code-input { max-width: 8rem; font-family: var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; }
.acct-code-suggest { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin-top: 0.5rem; font-size: 0.85rem; color: var(--color-text-muted); }
.acct-code-row { display: flex; align-items: center; gap: 0.5rem; }
.acct-form input[readonly] { color: var(--color-text-muted); background: var(--color-panel); }
.acct-lock { padding: 0.45rem 0.55rem; }
.acct-lock svg { width: 1.05rem; height: 1.05rem; }
.acct-code-suggest strong { font-family: var(--font-mono); letter-spacing: 0.08em; color: var(--color-heading); }

.acct-badge--draft { background: var(--color-panel); color: var(--color-text-muted); }
.acct-badge--active { background: var(--color-success-bg); color: var(--color-success-text); }
.acct-badge--expiring { background: var(--color-warning-bg); color: var(--color-warning-text); }
/* A state badge sits on a row tinted the same colour as the badge, so the plain token fill leaves it
   as bare text with no pill. A dark outline was tried and the user disliked it (2026-10-06): the pill
   should read as a deeper block of colour on the lighter row instead.

   Module-scoped on purpose — the palette at the top of this file is Web's. These are derived from the
   warning/danger tokens and namespaced; worth promoting to real tokens if another module wants the
   same treatment.

   "Darker" is a light-mode description. In dark mode the row tint is a translucent wash over a dark
   surface, so a literally darker fill would sink into it — the same disappearance from the other
   direction. There the separation comes from **more opacity** at the same hue. */
:root {
    /* Chosen by measuring, since none of us can see it: each separates from its row tint by about
       1.3:1 while keeping the badge's own text at 4.3:1 or better against it. Deeper than this starts
       costing text legibility. */
    --acct-state-warning-fill: #fdcd86;   /* 1.32:1 vs the row, text 4.62:1 */
    /* The middle rung. Deepening the fill costs the dark-brown label its contrast — they trade off
       directly — so 60 carries its own darker text and stays legible at 5.40:1 while sitting 1.57:1
       off the row, deeper than 90's 1.32:1. */
    --acct-due-60-fill: #f9b85b;
    --acct-due-60-text: #6b3a00;
    --acct-state-danger-fill: #f7c7c0;    /* 1.32:1 vs the row, text 4.35:1 */
}
:root[data-theme="dark"] {
    /* Over the dark surface these land at 1.47:1 and 1.38:1 against their row tints, text 4.46:1
       and 4.14:1 — the same separation, reached by opacity rather than by darkening. */
    --acct-state-warning-fill: rgba(245, 180, 84, 0.30);
    --acct-due-60-fill: rgba(245, 180, 84, 0.48);
    /* Dark reverses it: the label is the light amber, so darkening it would bury it. */
    --acct-due-60-text: var(--color-warning-text);
    --acct-state-danger-fill: rgba(255, 138, 128, 0.28);
}
.acct-badge--expired { background: var(--acct-state-danger-fill); color: var(--color-danger); }
.acct-badge--cancelled { background: var(--color-panel); color: var(--color-text-muted); }
/* Terminated early but not yet stopped: still counting, so it reads as urgent, not as finished. */
/* Amber, matching Not Renewing: a decided ending to act on, not a failure (the user, 2026-10-06). */
.acct-badge--ending { background: var(--acct-state-warning-fill); color: var(--color-warning-text); }
/* Running its full term and not being renewed: expected, so it reads like Expiring rather than
   like something cut short. */
.acct-badge--non_renewal { background: var(--acct-state-warning-fill); color: var(--color-warning-text); }

/* Sets a permanent action apart from the everyday ones next to it in a page header, so Delete never
   reads as a peer of Edit (the user put them in the same row, 2026-09-28). */
.acct-header-sep { align-self: stretch; width: 1px; margin: 0 0.35rem; background: var(--color-line); }
/* The shared .btn-danger is an outline, so Cancel and Delete would look identical side by side.
   Only the permanent one is filled. */
/* A referral is a separate fact, not a continuation of the MRR figure, so it takes its own line
   whatever the numbers are (the user, 2026-09-28). As inline-flex it only broke when the figures were
   long enough to wrap — Regent's looked right and Carolina's didn't, from the same markup. */
/* The status badge is a menu button: it looks like the badge it replaces, and says so by being a
   real <button> with a chevron rather than a span that only appears clickable. */
.acct-status { position: relative; display: inline-block; }
.acct-status__badge { display: inline-flex; align-items: center; gap: 0.3rem; border: 0; cursor: pointer; font: inherit; font-size: 0.8rem; font-weight: 700; }
.acct-status__badge svg { width: 0.9rem; height: 0.9rem; }
.acct-status__badge:hover { filter: brightness(0.96); }
/* The menu is the pills themselves — no box around them. Picking one shows you the badge you're
   about to get. */
.acct-status__menu { position: absolute; top: 100%; left: 0; z-index: 20; margin: 0.3rem 0 0; padding: 0;
    list-style: none; display: flex; flex-direction: column; align-items: flex-start; gap: 0.3rem; }
.acct-status__item { border: 0; cursor: pointer; font: inherit; font-size: 0.8rem; font-weight: 700;
    box-shadow: 0 2px 8px rgb(0 0 0 / 0.14); }
.acct-status__item:hover, .acct-status__item:focus-visible { filter: brightness(0.95); }
/* Why a client left, on the status card. The reason is free text someone typed, so it wraps and
   keeps its line breaks rather than running as one paragraph. */
.acct-deactivation { margin: 0.75rem 0 0; font-size: 0.85rem; }
.acct-deactivation dt { color: var(--color-text-muted); }
/* The reason spans both columns. `.acct-details` is a two-column grid with a label column of at
   least 8rem, and inside a summary card that left a sentence wrapping in a ~7rem ribbon — legible in
   the markup, unreadable on the page. Found on /preview, which is the only place this state exists
   until a client actually leaves. */
/* Beside its label, like the date above it (the user, 2026-10-12: "Reason value is below Reason
   label. Move it up"). No max-width: a 60ch cap forced a wrap inside a card with 160px to spare. */
.acct-deactivation__reason { white-space: pre-wrap; }

/* A former client reads red-tinted — and still says "Inactive", since colour is never the only signal. */
.acct-badge--inactive { background: var(--color-danger-bg); color: var(--color-danger); }

/* Contract history: the ending kinds carry the same colour language as the status badges, so a
   termination reads the same in the log as it does on the card above it. */
.acct-event--early_termination,
.acct-event--account_inactive { background: var(--color-danger-bg); color: var(--color-danger); }
.acct-event--non_renewal,
.acct-event--expired { background: var(--color-warning-bg); color: var(--color-warning-text); }
.acct-event--renewed { background: var(--color-success-bg, var(--color-panel)); color: var(--color-success-text, var(--color-text)); }
.acct-event--amended,
.acct-event--note { background: var(--color-panel); color: var(--color-text-muted); }

/* The contracts a deactivation will end, named in its confirmation. */
.acct-deactivate-list { margin: 0.5rem 0; padding-left: 1.1rem; font-size: 0.9rem; }
.acct-deactivate-list li { margin-bottom: 0.35rem; }
.acct-referral { display: flex; align-items: center; gap: 0.3rem; justify-content: flex-end; white-space: nowrap; }
.acct-referral__icon { font-size: 0.95rem; flex: none; }
/* The icon's own hit box: a 17px glyph is a poor hover target, so the span around it takes padding
   and pulls it back with a negative margin, leaving the line's spacing unchanged. */
.acct-referral__hit { display: inline-flex; align-items: center; padding: 0.3rem; margin: -0.3rem; }
.acct-btn-destroy { background: var(--color-danger); border-color: var(--color-danger); color: var(--color-surface); }
.acct-btn-destroy:hover { filter: brightness(0.92); background: var(--color-danger); }
/* Narrow: the rule would sit between two stacked buttons and read as decoration, so instead it
   becomes a line break — Delete gets its own row rather than sitting against Cancel, where both are
   red and a thumb is imprecise. */
@media (max-width: 640px) { .acct-header-sep { width: 100%; height: 0; margin: 0; background: none; } }

.acct-cards { margin-bottom: 1.5rem; }
/* A client who has left: Status takes the room the hidden cards leave, so the reason reads on one
   line, and Active contracts sits at the far right (the user, 2026-10-12). `auto-fit` would otherwise
   stretch two cards to half the row each. A long reason still wraps inside the card — the field takes
   2,000 characters and no width makes every reason fit. */
.acct-cards--ended { grid-template-columns: minmax(0, 1fr) minmax(240px, auto); }
.acct-cards .card { border-top-color: var(--color-primary); }

/* Portfolio cards above the accounts list. */
.acct-summary { grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); margin-bottom: 1.5rem; }
.acct-summary .card { border-top-color: var(--brand-orange); }
.acct-summary .value { font-size: 1.6rem; }
.acct-summary .card.acct-card--attention { border-top-color: var(--color-warning-text); }
.acct-summary .card.acct-card--attention .value { color: var(--color-warning-text); }
/* A card that filters the list. */
.acct-summary a.acct-card--link { display: block; color: inherit; text-decoration: none; cursor: pointer; }
.acct-summary a.acct-card--link:hover { border-color: var(--color-primary); }
.acct-summary a.acct-card--link .meta { color: var(--color-link); }
.acct-summary a.acct-card--link.is-active { border-color: var(--color-warning-text); background: var(--color-warning-bg); }

/* Accounts with a renewal inside the card's window, or a contract already past its end. */
.table tbody tr.acct-row--renewing > td { background: var(--color-warning-bg); }
.table tbody tr.acct-row--renewing > td:first-child { box-shadow: inset 3px 0 0 var(--color-warning-text); }
/* An ending of either kind: amber, like a renewal to chase, because it's a thing to act on rather
   than something already broken (the user asked for amber, 2026-10-06). One flag per row — see the
   view for which wins. */
.table tbody tr.acct-row--ending > td,
.table tbody tr.acct-row--non-renewal > td { background: var(--color-warning-bg); }
.table tbody tr.acct-row--ending > td:first-child,
.table tbody tr.acct-row--non-renewal > td:first-child { box-shadow: inset 3px 0 0 var(--color-warning-text); }
.table tbody tr.acct-row--expired > td { background: var(--color-danger-bg); }
.table tbody tr.acct-row--expired > td:first-child { box-shadow: inset 3px 0 0 var(--color-danger); }

/* Status with an expiry warning underneath. Urgency rises from amber to red to solid red. */
.acct-badge-stack { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 0.3rem; }
/* These three sit on amber renewing rows, and until 2026-10-06 due-90 was the SAME colour as the row
   with no outline — measured on /preview as rgb(255,241,220) on rgb(255,241,220): not a faint pill, no
   pill at all. I had left all three alone that morning saying "their rings tell 90 from 60 from 30
   apart"; 90 never had a ring. Now the ladder is three fills, deepening amber into red, the way the
   user asked ("make them just shade darker"), and no outlines. Verified on /preview in both themes. */
.acct-badge--due-90 { background: var(--acct-state-warning-fill); color: var(--color-warning-text); }
.acct-badge--due-60 { background: var(--acct-due-60-fill); color: var(--acct-due-60-text); }
.acct-badge--due-30 { background: var(--acct-state-danger-fill); color: var(--color-danger); }
.acct-badge-stack .acct-badge--expired { background: var(--color-danger); color: var(--color-surface); }

/* Placeholders: dashed and muted so they never read as real figures. */
.acct-summary .card.acct-card--placeholder { border-top: 3px dashed var(--color-line); box-shadow: none; }
.acct-summary .card.acct-card--placeholder .value { color: var(--color-text-muted); letter-spacing: 0.08em; }

.acct-lifecycle { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem 1.5rem; padding: 1rem 1.25rem; border-left: 4px solid var(--brand-orange); }
.acct-lifecycle p, .acct-lifecycle form { margin: 0; }
.acct-lifecycle-panel p { margin-top: 0; }

.acct-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); gap: 0 1.5rem; }
.acct-details { display: grid; grid-template-columns: minmax(8rem, max-content) 1fr; gap: 0.5rem 1.25rem; margin: 0.75rem 0 0; }
.acct-details--wide { grid-template-columns: minmax(10rem, max-content) 1fr; }
.acct-details dt { font-size: 0.85rem; font-weight: 700; color: var(--color-text-muted); }
.acct-details dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.acct-line { display: block; }
.acct-notes { white-space: pre-line; }

.acct-section { margin: 2rem 0; scroll-margin-top: 1rem; }
.acct-section__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; }
.acct-section__header h2 { margin: 0; font-size: 1.2rem; }

.acct-inline-form { display: inline; margin: 0 0 0 0.35rem; }
.acct-doc-actions { display: inline-flex; flex-wrap: wrap; gap: 0.35rem; }

/* Connections panel: one card per source (help desk, AWS, Azure). */
.acct-connections { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 1rem; align-items: start; }
.acct-connections .panel { margin-bottom: 0; }
/* The connection's identifiers, read outright now rather than masked. Two short rows, so a plain
   definition list rather than the account page's wide one. */
.acct-connection__ids { margin: 0 0 0.6rem; font-size: 0.85rem; }
.acct-connection__ids dt { color: var(--color-text-muted); }
/* The trashcan: an icon button, so it needs a hit area and an accessible name of its own. Danger
   colouring is the shared .btn-danger; only the sizing is here. */
.acct-connection__delete { display: inline-flex; align-items: center; justify-content: center; min-width: 2.1rem; }
.acct-connection__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.75rem; }
.acct-connection__header .acct-connection__title { margin: 0; flex: 1 1 12rem; }
.acct-connection__title { margin: 0 0 0.75rem; font-size: 1rem; display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.acct-connection__title .muted { font-family: var(--font-body); font-size: 0.8rem; font-weight: 400; }
.acct-connection__row { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; padding: 0.6rem 0; border-top: 1px solid var(--color-line); }
.acct-connection__row > div { min-width: 0; overflow-wrap: anywhere; }
/* One row (the user, 2026-10-08, twice). The actions on a connection are siblings — Edit, the on/off
   form, the trashcan — and each was block-level, so they stacked. The forms are inline-flex items here
   rather than block children, which is what was breaking the line. */
.acct-connection__edit { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0 0 0.5rem; }
/* Direct children only: both dialogs sit inside this container too, and their own forms are block
   layouts — a descendant selector would have turned every field in them into a flex row. */
.acct-connection__edit > form { display: inline-flex; margin: 0; }
.acct-connections__links { display: inline-flex; flex-wrap: wrap; gap: 0.5rem; }
.acct-header-form { margin: 0; display: inline-flex; }
.acct-icon-btn { padding: 0.5rem 0.6rem; }
.acct-icon-btn svg { width: 1.15rem; height: 1.15rem; display: block; }
.acct-delete-btn { display: inline-flex; align-items: center; gap: 0.45rem; }
.acct-delete-btn svg { width: 1.15rem; height: 1.15rem; }
/* The no-JavaScript fallback form only. It used to share .acct-status with the badge, which made one
   class mean two layouts — and the flex row it set moved the menu's static position so the absolutely
   positioned menu landed on top of the badge instead of under it. */
.acct-status-form { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0.35rem 0 0; }
.acct-status-form .acct-status__select { padding: 0.3rem 0.5rem; font-size: 0.9rem; }

.acct-form input[type="date"],
.acct-form input[type="number"],
.acct-form input[type="file"] {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    max-width: 100%;
}
.acct-form input[type="file"] { max-width: 560px; }
.acct-form .fieldset { display: flex; flex-direction: column; gap: 0.35rem; }
.acct-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap: 0 1rem; max-width: 560px; }
/* Fee and hours sit side by side at their own width, with no stretched columns between. */
.acct-form-row--terms { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.5rem 1rem; max-width: 720px; }
.acct-form-row--terms > div { flex: 0 1 13rem; }
.acct-form-row--terms > div:has(.acct-code-row) { flex: 0 1 16rem; }
.panel.form .acct-form-row--terms input { max-width: 100%; }
.acct-code-row input { flex: 1 1 auto; min-width: 0; }
.acct-form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr)); gap: 0 1rem; }
.acct-form-row > div,
.acct-form-grid > div { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }

.acct-list { list-style: none; margin: 0; padding: 0; background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius-lg); }
.acct-list li { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 1rem; }
.acct-list li + li { border-top: 1px solid var(--color-line); }
.acct-list form { margin: 0; }

/* Module: Employees */
.emp-summary { grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); margin-bottom: 1.5rem; }
.emp-summary .card { border-top-color: var(--brand-orange); }
.emp-summary .value { font-size: 1.6rem; }

.emp-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1rem; margin: 0 0 1.25rem; }
.emp-filters__field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.8rem; font-weight: 700; color: var(--color-text-muted); }
.emp-filters__field .input { min-width: 11rem; }
.emp-filters__actions { padding-bottom: 0.2rem; }

.emp-badge--active { background: var(--color-success-bg); color: var(--color-success-text); }
.emp-badge--inactive { background: var(--color-panel); color: var(--color-text-muted); }
.emp-badge--azure, .emp-badge--aws, .emp-badge--epic { background: var(--color-selected-bg); color: var(--color-link); }

.table tfoot .emp-total > * { border-top: 2px solid var(--color-line); font-weight: 700; text-align: left; }
/* Certifications someone holds, grouped by provider on their page. */
.emp-cert-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: 1rem 1.5rem; }
.emp-cert-group__title { margin: 0 0 0.4rem; font-size: 0.95rem; }
.emp-cert-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }

/* Certification search: the fast path. A box that adds chips; the browse list is behind a toggle. */
.emp-cert-find { position: relative; }
.emp-cert-find input[type="text"] { width: 100%; max-width: 100%; }
.emp-cert-matches {
    list-style: none;
    margin: 0.25rem 0 0;
    padding: 0.25rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    background: var(--color-surface);
    box-shadow: var(--shadow-card);
    max-height: 16rem;
    overflow-y: auto;
}
.emp-cert-match { padding: 0.4rem 0.55rem; border-radius: var(--radius); font-size: 0.9rem; cursor: pointer; }
.emp-cert-match:hover, .emp-cert-match.is-active { background: var(--color-selected-bg); color: var(--color-link); }
.emp-cert-match--new { font-style: italic; }

.emp-cert-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.75rem 0 0; padding: 0; }
.emp-cert-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.3rem 0.2rem 0.55rem;
    border-radius: var(--radius);
    background: var(--color-selected-bg);
    color: var(--color-link);
    font-size: 0.85rem;
}
.emp-cert-chip__remove {
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 1rem;
    line-height: 1;
    padding: 0 0.2rem;
    cursor: pointer;
}
.emp-cert-chip__remove:hover { color: var(--color-danger); }

.emp-cert-browse { margin-top: 1.25rem; }
.emp-cert-browse > summary { cursor: pointer; font-size: 0.9rem; font-weight: 700; color: var(--color-link); }

/* Certification picker: three columns, one per provider (Azure | AWS | Other), each its own
   vertical list. Two columns on a tablet, one on a phone — three side by side are unusable narrow.
   A long label wraps under its own tick box, never under its neighbour. */
.emp-cert-picker { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem 1.5rem; }
.emp-cert-picker__column { margin: 0.75rem 0 0; min-width: 0; }
.emp-cert-picker .emp-cert-option {
    display: grid;
    grid-template-columns: 1.05rem 1fr;
    align-items: start;
    gap: 0.5rem;
    margin: 0 0 0.45rem;
    font-size: 0.9rem;
    line-height: 1.35;
    overflow-wrap: anywhere;
}
.emp-cert-picker .emp-cert-option input { margin-top: 0.15rem; }
.emp-cert-other__label { display: block; margin-top: 0.9rem; font-size: 0.875rem; font-weight: 700; }
@media (max-width: 900px) {
    .emp-cert-picker { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
    .emp-cert-picker { grid-template-columns: 1fr; }
}

.emp-cert--current { background: var(--color-success-bg); color: var(--color-success-text); }
.emp-cert--expiring { background: var(--color-warning-bg); color: var(--color-warning-text); }
.emp-cert--expired { background: var(--color-danger-bg); color: var(--color-danger); }
.emp-cert--retired { background: var(--color-panel); color: var(--color-text-muted); }

.emp-summary .card.emp-card--attention { border-top-color: var(--color-warning-text); }
.emp-summary .card.emp-card--attention .value { color: var(--color-warning-text); }
.emp-summary .card.emp-card--lapsed { border-top-color: var(--color-danger); }
.emp-summary .card.emp-card--lapsed .value { color: var(--color-danger); }

.table tbody tr.emp-row--expiring > td { background: var(--color-warning-bg); }
.table tbody tr.emp-row--expired > td { background: var(--color-danger-bg); }

.emp-total__note { display: block; font-size: 0.75rem; font-weight: 400; color: var(--color-text-muted); }
.table tfoot .emp-total > .num { text-align: right; }

.emp-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 0 1rem; max-width: 560px; }
.emp-form .fieldset { display: flex; flex-direction: column; gap: 0.35rem; }
.emp-form input[type="date"],
.emp-form input[type="number"] {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    width: 100%;
    max-width: 100%;
}

.emp-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: 0 1.5rem; }
.emp-details { display: grid; grid-template-columns: minmax(8rem, max-content) 1fr; gap: 0.5rem 1.25rem; margin: 0.75rem 0 0; }
.emp-details dt { font-size: 0.85rem; font-weight: 700; color: var(--color-text-muted); }
.emp-details dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.emp-notes { white-space: pre-line; }

.emp-section { margin: 2rem 0; }
.emp-section__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; }
.emp-section__header h2 { margin: 0; font-size: 1.2rem; }
.emp-section__note { margin: 0; font-size: 0.875rem; color: var(--color-text-muted); }
.emp-section__note strong { color: var(--color-heading); }

/* Module: Expenses */
.exp-summary { grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); margin-bottom: 1.5rem; }
.exp-summary .card { border-top-color: var(--brand-orange); }
.exp-summary .value { font-size: 1.6rem; }
.exp-hidden-note { margin: -0.75rem 0 1.25rem; }

.exp-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1rem; margin: 0 0 1.25rem; }
.exp-filters__field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.8rem; font-weight: 700; color: var(--color-text-muted); }
.exp-filters__field .input { min-width: 11rem; }
.exp-filters__actions { display: flex; gap: 0.5rem; padding-bottom: 0.2rem; }

.exp-badge--category { background: var(--color-selected-bg); color: var(--color-link); }
.exp-badge--current { background: var(--color-success-bg); color: var(--color-success-text); }
.exp-badge--upcoming { background: var(--color-warning-bg); color: var(--color-warning-text); }
.exp-badge--ended { background: var(--color-panel); color: var(--color-text-muted); }

.table tfoot .exp-total > * { border-top: 2px solid var(--color-line); font-weight: 700; text-align: left; }
.table tfoot .exp-total > .num { text-align: right; }

.exp-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 0 1rem; max-width: 560px; }
.exp-form .fieldset { display: flex; flex-direction: column; gap: 0.35rem; }
.exp-form input[type="date"],
.exp-form input[type="number"] {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    width: 100%;
    max-width: 100%;
}
.exp-needs-amount { color: var(--color-warning-text); font-weight: 700; }
.exp-pnl { margin-bottom: 1.5rem; }
.exp-pnl .table-wrap { margin-top: 0.75rem; }
.exp-pnl__subtitle { margin: 1.5rem 0 0.25rem; font-size: 1rem; }
.exp-positive { color: var(--color-success); }
.exp-negative { color: var(--color-danger); }
.exp-delete { margin-top: 1.5rem; }

.exp-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: 0 1.5rem; }
.exp-details { display: grid; grid-template-columns: minmax(8rem, max-content) 1fr; gap: 0.5rem 1.25rem; margin: 0.75rem 0 0; }
.exp-details dt { font-size: 0.85rem; font-weight: 700; color: var(--color-text-muted); }
.exp-details dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.exp-notes { white-space: pre-line; }
.exp-split { margin-top: 1rem; }

.exp-section { margin: 2rem 0; }
.exp-section__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; }
.exp-section__header h2 { margin: 0; font-size: 1.2rem; }

/* Module: Capacity */
.cap-summary { grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); margin-bottom: 1.5rem; }
.cap-summary .card { border-top-color: var(--brand-orange); }
.cap-summary .value { font-size: 1.6rem; }
/* The good state was the only one with no rule, so it fell through to the house brand orange and
   read like the others (the user agreed, 2026-10-07, after looking at /preview). */
.cap-summary .card.cap-card--within_target { border-top-color: var(--color-success); }
.cap-summary .card.cap-card--near_capacity { border-top-color: var(--color-warning-text); }
.cap-summary .card.cap-card--over_capacity,
.cap-summary .card.cap-card--no_capacity { border-top-color: var(--color-danger); }
.cap-summary .card.cap-card--unknown { border-top-color: var(--color-line); }
/* Forecast demand is the figure capacity is judged against, so it leads. */
.cap-summary .card.cap-card--demand { border-top-color: var(--brand-blue); }
.cap-unit { font-size: 0.9rem; font-weight: 400; color: var(--color-text-muted); }
.cap-hidden-note { margin: -0.75rem 0 1.25rem; }


.cap-badge--ok { background: var(--color-success-bg); color: var(--color-success-text); }
.cap-badge--muted { background: var(--color-panel); color: var(--color-text-muted); }

.cap-section { margin: 2rem 0; }
.cap-year { display: flex; align-items: center; gap: 0.5rem; }

.cap-forecast th[scope="row"] { white-space: nowrap; }
.cap-forecast .cap-row--near_capacity .cap-headroom { color: var(--color-warning-text); font-weight: 700; }
.cap-forecast .cap-row--over_capacity .cap-headroom { color: var(--color-danger); font-weight: 700; }
.cap-row--inactive > * { color: var(--color-text-muted); }

.cap-meter { position: relative; display: inline-block; vertical-align: middle; width: 6rem; height: 0.5rem; border-radius: var(--radius); background: var(--color-panel); overflow: visible; }
.cap-meter__fill { position: absolute; inset: 0 auto 0 0; border-radius: var(--radius); background: var(--color-success); }
.cap-row--near_capacity .cap-meter__fill { background: var(--color-warning-text); }
.cap-row--over_capacity .cap-meter__fill { background: var(--color-danger); }
.cap-meter__target { position: absolute; top: -0.2rem; bottom: -0.2rem; width: 2px; margin-left: -1px; background: var(--color-heading); }
.cap-meter__label { margin-left: 0.4rem; font-variant-numeric: tabular-nums; }

.cap-note { display: inline-block; margin-right: 0.5rem; }
/* Table cells keep display: table-cell; .cell-primary / .cell-secondary are for content inside a cell. */
.table .cap-cell-strong { font-weight: 700; }
.table .cap-cell-muted { font-size: 0.85rem; color: var(--color-text-muted); }

.cap-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); gap: 0 1rem; max-width: 600px; }
.cap-form .fieldset { display: flex; flex-direction: column; gap: 0.35rem; }
.cap-form input[type="date"],
.cap-form input[type="number"] {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    width: 100%;
    max-width: 100%;
}
.cap-inline-form { margin-top: 1rem; }
.cap-delete { margin-top: 1.5rem; }

.cap-method { margin-top: 2rem; }
.cap-method summary { cursor: pointer; font-weight: 700; }
.cap-method ul { margin: 0.75rem 0 0; padding-left: 1.25rem; }
.cap-method li + li { margin-top: 0.4rem; }

/* Module: Overview */
.ov-section { margin: 0 0 2rem; }
.ov-section__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; }
.ov-section__header h2 { margin: 0; font-size: 1.2rem; }
.ov-section__meta { font-size: 0.85rem; color: var(--color-text-muted); }
.ovw-hidden-note { margin: 0.75rem 0 0; }

.ovw-headline { grid-template-columns: repeat(auto-fit, minmax(min(100%, 165px), 1fr)); margin-bottom: 1.5rem; }
.ovw-headline .card { border-top-color: var(--brand-orange); }
.ovw-headline .value { font-size: 1.6rem; }
.ovw-headline .card.ov-card--ok { border-top-color: var(--color-success); }
.ovw-headline .card.ov-card--warning,
.ovw-headline .card.ov-card--over_target { border-top-color: var(--color-warning-text); }
.ovw-headline .card.ov-card--danger,
.ovw-headline .card.ov-card--over_supply { border-top-color: var(--color-danger); }
.ovw-headline .card.ov-card--fake { border-top-style: dashed; border-top-color: var(--color-danger); }
.ovw-headline .card h2 .badge { margin-left: 0.35rem; vertical-align: middle; }
.ov-unit { font-size: 0.9rem; font-weight: 400; color: var(--color-text-muted); }
/* A loss is red wherever it appears. The headline tiles need the extra weight: the shared
   `.card .value` colour (two classes) otherwise beats a lone `.ov-negative`, so a negative margin
   rendered in heading navy — found on /preview 2026-10-07, invisible to every assertion. */
.ov-negative { color: var(--color-danger); }
.ovw-headline .card .value.ov-negative { color: var(--color-danger); }

.ov-all-clear { margin: 0; padding: 0.75rem 1rem; border-radius: var(--radius); background: var(--color-success-bg); color: var(--color-success-text); }
.ov-risks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.ov-risk { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem; padding: 0.65rem 1rem; border: 1px solid var(--color-line); border-left: 4px solid var(--color-warning-text); border-radius: var(--radius); background: var(--color-surface); }
.ov-risk--danger { border-left-color: var(--color-danger); }
.ov-risk__text { flex: 1 1 16rem; min-width: 0; }
.ov-risk__link { font-weight: 700; white-space: nowrap; }
.ov-badge--danger { background: var(--color-danger-bg); color: var(--color-danger); }
.ov-badge--warning { background: var(--color-warning-bg); color: var(--color-warning-text); }

/* Everything else this used to set (padding, font, letter-spacing, background, vertical-align) now
   comes from the shared .table tbody th. Only the heading colour differs: the shared rule uses
   --color-text, and the month label reads as a label rather than a value. */
.ov-outlook tbody th[scope="row"] { color: var(--color-heading); }
.table .ov-outlook-notes { min-width: 14rem; }
.table .ov-cell-strong { font-weight: 700; }
.table .ov-cell-muted { font-size: 0.85rem; color: var(--color-text-muted); }
.ov-outlook .ov-row--over_target .ov-utilization { color: var(--color-warning-text); font-weight: 700; }
.ov-outlook .ov-row--over_supply .ov-utilization { color: var(--color-danger); font-weight: 700; }

.ov-method { margin-top: 2rem; }
.ov-method summary { cursor: pointer; font-weight: 700; }
.ov-method ul { margin: 0.75rem 0 0; padding-left: 1.25rem; }
.ov-method li + li { margin-top: 0.4rem; }

/* Module: Services */
.svc-summary { grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); margin-bottom: 1.5rem; }
.svc-summary .card { border-top-color: var(--brand-blue); }
.svc-summary .value { font-size: 1.6rem; }

.svc-tabs { display: flex; flex-wrap: wrap; gap: 0.25rem; margin: 0 0 1rem; border-bottom: 1px solid var(--color-line); }
.svc-tab { padding: 0.45rem 0.9rem; border-bottom: 3px solid transparent; color: var(--color-text-muted); font-weight: 700; text-decoration: none; }
.svc-tab:hover { color: var(--color-text); }
.svc-tab[aria-current="page"] { color: var(--color-link); border-bottom-color: var(--color-primary); }

.svc-ref { font-variant-numeric: tabular-nums; color: var(--color-text-muted); font-weight: 400; margin-right: 0.35rem; }
.svc-clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; max-width: 60rem; }
.svc-text { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
.svc-error { margin: 0.25rem 0 0; color: var(--color-danger); font-size: 0.875rem; }
.svc-sensitive { margin: 0 0 1.25rem; padding: 0.6rem 0.9rem; border-left: 4px solid var(--color-warning-text); border-radius: var(--radius); background: var(--color-warning-bg); color: var(--color-text); }

.svc-badge--active,
.svc-badge--current { background: var(--color-success-bg); color: var(--color-success-text); }
.svc-badge--upcoming { background: var(--color-warning-bg); color: var(--color-warning-text); }
.svc-badge--retired,
.svc-badge--superseded { background: var(--color-panel); color: var(--color-text-muted); }

.svc-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr)); gap: 0 1rem; max-width: 560px; }
.svc-form .fieldset { display: flex; flex-direction: column; gap: 0.35rem; }
.svc-form input[type="date"],
.svc-form input[type="number"] {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    width: 100%;
    max-width: 100%;
}
.svc-form [aria-invalid="true"] { border-color: var(--color-danger); }
.svc-add-form { margin-top: 1.25rem; }
.svc-delete { margin-top: 1.5rem; }

.svc-details { display: grid; grid-template-columns: minmax(8rem, max-content) 1fr; gap: 0.5rem 1.25rem; margin: 0.75rem 0 0; }
.svc-details dt { font-size: 0.85rem; font-weight: 700; color: var(--color-text-muted); }
.svc-details dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

.svc-section { margin: 2rem 0; }
.svc-section__header { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.5rem 0.75rem; margin-bottom: 0.75rem; }
.svc-section__header h2 { margin: 0; font-size: 1.2rem; }
.svc-section__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem; }

.svc-capabilities,
.svc-exclusions { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.svc-capability,
.svc-exclusions li { padding: 0.9rem 1rem; border: 1px solid var(--color-line); border-left: 4px solid var(--brand-blue); border-radius: var(--radius); background: var(--color-surface); }
.svc-exclusions li { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 0.5rem 1rem; border-left-color: var(--color-line); }
.svc-exclusions li .svc-text { flex: 1 1 24rem; }
.svc-capability--retired { border-left-color: var(--color-line); opacity: 0.8; }
.svc-capability__header { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.5rem 1rem; margin-bottom: 0.4rem; }
.svc-capability__header h3 { margin: 0; font-size: 1rem; }
.svc-capability__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.svc-toc { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; margin: 0 0 1rem; font-size: 0.9rem; }

.svc-price { margin: 1.5rem 0; }
.svc-price__row { display: flex; flex-wrap: wrap; gap: 0.5rem; max-width: 560px; }
.svc-price__row input { flex: 1 1 12rem; }
.svc-price__result { margin-top: 1rem; }

.svc-band-grid input[type="number"] { min-width: 8rem; padding: 0.4rem 0.55rem; }
.svc-band-grid__remove { text-align: center; }
.svc-band-grid__remove input { width: 1.05rem; height: 1.05rem; accent-color: var(--color-danger); }

/* Module: Clients Overview (clients/client_overview, clients/client_onboarding) */

/* Layout */
.co-section { margin: 0 0 2rem; }
/* **Direct children only: a descendant selector here reaches into shared components.** It was
   `.co-section h2`, which matched `.card h2` and `.empty-state__title` inside any of my sections and
   beat them on source order — but only on font-size and margin, leaving the component's own
   uppercase, letter-spacing, weight and colour in place. The result was a hybrid neither rule
   describes: **card labels at 17.6px wearing a 12px label's uppercase and 1.4px tracking** (9 on the
   Azure Savings gallery alone), and empty-state titles at 17.6px against the component's 18.4px.
   Found by Web's container-vs-component sweep and measured in the DOM, 2026-10-13. `.card` is Web's;
   restyling its internals from module CSS is the defect, not the 5px. */
.co-section > h2,
.co-section__header > h2 { font-size: 1.1rem; margin: 0 0 0.75rem; }
.co-section__header { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.5rem 1rem; margin-bottom: 0.75rem; }
.co-section__header h2 { margin: 0; }
.co-eyebrow { margin: 0; font-family: var(--font-heading); font-size: 0.8rem !important; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); }
.co-muted { color: var(--color-text-muted); }
.co-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); gap: 0 1.5rem; }
.co-breakdown { align-items: stretch; gap: 1.25rem; }
.co-kpis { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); margin-bottom: 2rem; }
.co-kpis .card .value { font-size: 1.35rem; }

/* Cards that hold a chart or a table */
.co-card { display: flex; flex-direction: column; min-width: 0; padding: 1.25rem 1.4rem 1.1rem; background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); }
.co-card__title { margin: 0 0 1rem; font-size: 1.05rem; color: var(--color-heading); }
.co-card__sub { font-weight: 500; color: var(--color-text-muted); }
.co-card__empty { margin: 2rem 0; text-align: center; }
.co-card__scroll { flex: 1; max-height: 24rem; overflow-y: auto; margin: 0 -0.4rem; padding: 0 0.4rem; }

/* Tabs inside a tab (Cost | Resources | Security) */
.co-subtabs { display: inline-flex; flex-wrap: wrap; gap: 0.25rem; padding: 0.25rem; margin: 0 0 1.25rem; background: var(--color-panel); border-radius: 999px; }
.co-subtab { padding: 0.4rem 1rem; border-radius: 999px; color: var(--color-text-muted); font-family: var(--font-heading); font-size: 0.9rem; font-weight: 600; text-decoration: none; white-space: nowrap; }
.co-subtab:hover { color: var(--color-heading); text-decoration: none; }
.co-subtab[aria-current="page"] { background: var(--color-surface); color: var(--color-heading); box-shadow: var(--shadow-card); }

/* Period picker */
.co-range { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.25rem; margin: 0 0 1rem; }
.co-range__label { font-family: var(--font-heading); font-weight: 700; color: var(--color-heading); }
.co-range__presets { display: flex; gap: 0.4rem; }
.co-range__custom { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin: 0; }
.co-range__custom label { font-size: 0.85rem; font-weight: 700; color: var(--color-text-muted); }
.co-range__custom input[type="date"] { padding: 0.3rem 0.45rem; border: 1px solid var(--color-line); border-radius: var(--radius); background: var(--color-input-bg); color: var(--color-text); font: inherit; font-size: 0.9rem; }
.co-range__error { margin: 0 0 1rem; }

/* How current the data is */
.co-sync { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; margin: 0 0 1.25rem; font-size: 0.9rem; }
.co-sync__dot { width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--color-text-muted); }
.co-sync--ok .co-sync__dot { background: var(--color-success); }
.co-sync--warning .co-sync__dot { background: var(--color-warning-text); }
.co-sync--danger .co-sync__dot { background: var(--color-danger); }
.co-sync__note { flex-basis: 100%; padding: 0.5rem 0.75rem; border-radius: var(--radius); background: var(--color-warning-bg); color: var(--color-warning-text); }
.co-sync__pending { margin: -0.75rem 0 1.25rem; font-size: 0.9rem; }

/* Month-on-month change */
.co-change { font-variant-numeric: tabular-nums; white-space: nowrap; }
.co-change--up { color: var(--color-danger); }
.co-change--down { color: var(--color-success); }
.co-change--flat { color: var(--color-text-muted); }

/* Service colours, the same order everywhere (the old portal's palette) */
:root {
    --co-c0: #2563eb; --co-c1: #16a34a; --co-c2: #d97706; --co-c3: #7c3aed;
    --co-c4: #dc2626; --co-c5: #0891b2; --co-c6: #db2777; --co-c7: #65a30d;
    --co-others: #94a3b8;
}
:root[data-theme="dark"] {
    --co-c0: #60a5fa; --co-c1: #4ade80; --co-c2: #fbbf24; --co-c3: #a78bfa;
    --co-c4: #f87171; --co-c5: #22d3ee; --co-c6: #f472b6; --co-c7: #a3e635;
    --co-others: #64748b;
}
.co-seg--0 { background: var(--co-c0); }
.co-seg--1 { background: var(--co-c1); }
.co-seg--2 { background: var(--co-c2); }
.co-seg--3 { background: var(--co-c3); }
.co-seg--4 { background: var(--co-c4); }
.co-seg--5 { background: var(--co-c5); }
.co-seg--6 { background: var(--co-c6); }
.co-seg--7 { background: var(--co-c7); }
.co-seg--others { background: var(--co-others); }

/* Stacked column chart: value axis on the left, grid lines, one label under each bar */
.co-vchart { display: grid; grid-template-columns: auto 1fr; grid-template-rows: 240px auto; column-gap: 0.6rem; }
.co-vchart__yaxis { position: relative; min-width: 3.2rem; font-size: 0.8rem; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.co-vchart__yaxis span { position: absolute; right: 0; transform: translateY(50%); line-height: 1; }
.co-vchart__plot { position: relative; border-bottom: 1px solid var(--color-line); }
.co-vchart__grid { position: absolute; left: 0; right: 0; height: 1px; background: var(--color-line); opacity: 0.7; }
.co-vchart__bars { position: absolute; inset: 0; display: flex; align-items: flex-end; gap: 0; margin: 0; padding: 0 0.25rem; list-style: none; }
.co-vchart__xaxis { display: flex; margin: 0.5rem 0 0; padding: 0 0.25rem; list-style: none; font-size: 0.78rem; color: var(--color-text-muted); }
.co-vchart__xaxis li { flex: 1 1 0; min-width: 0; text-align: center; white-space: nowrap; overflow: visible; }

.co-bar { position: relative; flex: 1 1 0; min-width: 0; height: 100%; display: flex; align-items: flex-end; justify-content: center; outline: none; }
.co-bar__stack { display: flex; flex-direction: column; width: 72%; min-height: 1px; }
.co-bar__stack .co-seg { display: block; flex-basis: 0; min-height: 1px; }
.co-bar:hover .co-bar__stack,
.co-bar:focus-visible .co-bar__stack { filter: brightness(1.08); }
.co-bar:focus-visible .co-bar__stack { outline: 3px solid var(--brand-orange); outline-offset: 2px; }

/* Bar tooltip card: every service in the bar, then the total */
.co-tip {
    position: absolute;
    bottom: calc(100% + 0.5rem);
    z-index: 20;
    display: none;
    min-width: 15rem;
    max-width: 24rem;
    padding: 0.75rem 0.9rem;
    border-radius: var(--radius-lg);
    background: rgba(24, 27, 31, 0.95);
    color: #fff;
    font-size: 0.85rem;
    line-height: 1.4;
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
    pointer-events: none;
    white-space: nowrap;
}
.co-tip--middle { left: 50%; transform: translateX(-50%); }
.co-tip--start { left: 0; }
.co-tip--end { right: 0; }
.co-bar:hover .co-tip,
.co-bar:focus-visible .co-tip { display: block; }
.co-tip__title { display: block; margin-bottom: 0.4rem; font-family: var(--font-heading); font-weight: 700; font-size: 0.95rem; }
.co-tip__row { display: flex; align-items: center; gap: 0.5rem; padding: 0.1rem 0; }
.co-tip__swatch { flex: none; width: 0.8rem; height: 0.8rem; border-radius: 2px; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.75); }
.co-tip__name { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.co-tip__amount { padding-left: 0.75rem; font-variant-numeric: tabular-nums; }
.co-tip__total { display: block; margin-top: 0.45rem; padding-top: 0.4rem; border-top: 1px solid rgba(255, 255, 255, 0.2); font-weight: 700; }

/* Chart legends */
.co-legend-list { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.35rem 1.1rem; margin: 1rem 0 0; padding: 0; font-size: 0.82rem; color: var(--color-text-muted); }
.co-legend-list li { display: inline-flex; align-items: center; gap: 0.4rem; }
.co-legend { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.85rem; color: var(--color-text-muted); }
.co-legend__swatch { flex: none; width: 0.8rem; height: 0.8rem; border-radius: 2px; }
.co-legend .co-legend__swatch { margin-left: 0.5rem; }
.co-legend__swatch--a { background: var(--brand-blue); }
.co-legend__swatch--b { background: var(--brand-orange); }

/* Horizontal bar chart (top services, top subscriptions) */
.co-hbars { display: flex; flex-direction: column; gap: 0.7rem; padding: 0.25rem 1.5rem 0 0; }
.co-hbars__row { display: grid; grid-template-columns: minmax(6rem, 13rem) 1fr; align-items: center; gap: 0.9rem; }
.co-hbars__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; font-size: 0.85rem; color: var(--color-text-muted); }
.co-hbars__track { position: relative; height: 1.5rem; }
.co-hbars__grid { position: absolute; top: -0.35rem; bottom: -0.35rem; width: 1px; background: var(--color-line); opacity: 0.7; }
.co-hbars__bar { position: relative; z-index: 1; display: block; height: 100%; min-width: 3px; border-radius: 4px; }
.co-hbars__axis .co-hbars__track { height: 1.2rem; }
.co-hbars__tick { position: absolute; top: 0.25rem; transform: translateX(-50%); font-size: 0.78rem; color: var(--color-text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.co-hbars__tick:first-child { transform: none; }

/* Clean tables inside cards (all services, all subscriptions) */
.co-plain-table { font-size: 0.95rem; }
.co-plain-table th { position: sticky; top: 0; z-index: 1; padding: 0.6rem 0.75rem; background: var(--color-surface); border-bottom: 1px solid var(--color-line); font-size: 0.75rem; letter-spacing: 0.08em; color: var(--color-text-muted); }
.co-plain-table td { padding: 0.7rem 0.75rem; border-bottom: 1px solid var(--color-line); }
.co-plain-table tbody tr:hover { background: var(--color-selected-bg); }

/* Help desk: SLA and status colours */
:root { --co-alert: #e06666; --co-late: #ef6c00; }
.co-seg--alert { background: var(--co-alert); }
.co-fill--good { background: var(--color-success); }
.co-fill--warn { background: #e0a100; }
.co-fill--late { background: var(--co-late); }
.co-fill--bad { background: var(--color-danger); }
.co-fill--none { background: var(--co-others); }
.co-kpi--good { border-top-color: var(--color-success); }
.co-kpi--warn { border-top-color: #e0a100; }
.co-kpi--bad { border-top-color: var(--color-danger); }
.co-kpi--good .value { color: var(--color-success); }
.co-kpi--warn .value { color: var(--color-warning-text); }
.co-kpi--bad .value { color: var(--color-danger); }
.co-band { display: inline-block; padding: 0 0.4rem; border-radius: 999px; font-size: 0.75rem; font-weight: 700; }
.co-band--good { background: var(--color-success-bg); color: var(--color-success-text); }
.co-band--warn { background: var(--color-warning-bg); color: var(--color-warning-text); }
.co-band--bad { background: var(--color-danger-bg); color: var(--color-danger); }

/* Help desk: "Needs attention" alerts */
.co-alerts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); gap: 0.75rem; }
.co-alert { display: flex; align-items: center; gap: 0.85rem; padding: 0.9rem 1rem; border: 1px solid var(--color-line); border-left-width: 5px; border-radius: var(--radius-lg); background: var(--color-surface); box-shadow: var(--shadow-card); color: var(--color-text); text-decoration: none; }
.co-alert:hover { text-decoration: none; background: var(--color-selected-bg); }
.co-alert--bad { border-left-color: var(--color-danger); }
.co-alert--warn { border-left-color: #e0a100; }
.co-alert__count { font-family: var(--font-heading); font-size: 1.6rem; font-weight: 800; line-height: 1; }
.co-alert--bad .co-alert__count { color: var(--color-danger); }
.co-alert--warn .co-alert__count { color: var(--color-warning-text); }
.co-alert__text { flex: 1; font-size: 0.9rem; }
.co-alert__go { color: var(--color-text-muted); }
.co-allclear { display: flex; align-items: center; gap: 0.6rem; margin: 0; padding: 0.9rem 1rem; border-radius: var(--radius-lg); background: var(--color-success-bg); color: var(--color-success-text); }
.co-allclear__dot { width: 0.65rem; height: 0.65rem; border-radius: 50%; background: var(--color-success); }

/* Help desk: layouts */
.co-grid--three { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.co-grid--wide-right { grid-template-columns: minmax(min(100%, 300px), 1fr) minmax(min(100%, 420px), 2fr); }
@media (max-width: 900px) { .co-grid--wide-right { grid-template-columns: 1fr; } }
.co-card--bad { border-top: 3px solid var(--color-danger); }
.co-card__note { margin: auto 0 0; padding-top: 0.9rem; font-size: 0.85rem; color: var(--color-text-muted); }

/* Bars with the value at the end (SLA %, counts) */
.co-hlist { display: flex; flex-direction: column; gap: 0.8rem; }
.co-hlist__row { display: grid; grid-template-columns: minmax(6rem, 9rem) 1fr 3.25rem; align-items: center; gap: 0.75rem; font-size: 0.9rem; }
.co-hlist__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-muted); }
.co-hlist__track { height: 1.25rem; border-radius: 4px; background: var(--color-panel); overflow: hidden; }
.co-hlist__bar { display: block; height: 100%; border-radius: 4px; min-width: 2px; }
.co-hlist__value { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }

/* SLA gauge: a ring filled to the percentage */
.co-gauge-card { align-items: center; text-align: center; }
.co-gauge-card .co-card__title { align-self: flex-start; }
.co-gauge {
    --ring: var(--co-others);
    position: relative;
    width: 168px;
    aspect-ratio: 1;
    margin: 0.25rem auto 0;
    border-radius: 50%;
    background: conic-gradient(var(--ring) calc(var(--pct) * 1%), var(--color-panel) 0);
    display: grid;
    place-items: center;
}
.co-gauge::before { content: ""; position: absolute; inset: 16px; border-radius: 50%; background: var(--color-surface); }
.co-gauge--good { --ring: var(--color-success); }
.co-gauge--warn { --ring: #e0a100; }
.co-gauge--bad { --ring: var(--color-danger); }
.co-gauge__value { position: relative; display: flex; flex-direction: column; font-family: var(--font-heading); font-size: 2rem; font-weight: 800; line-height: 1; color: var(--color-heading); }
.co-gauge__value small { margin-top: 0.3rem; font-size: 0.8rem; font-weight: 600; color: var(--color-text-muted); }

/* Ticket lists */
.table .co-summary-col { width: 40%; min-width: 14rem; }
.co-summary { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.co-ticket { font-weight: 700; white-space: nowrap; }
.co-pill { display: inline-block; padding: 0.1rem 0.55rem; border-radius: 999px; background: var(--color-panel); font-size: 0.8rem; white-space: nowrap; }
.co-days { display: inline-block; min-width: 2rem; padding: 0.05rem 0.45rem; border-radius: 999px; font-weight: 700; text-align: center; }
.co-days--warn { background: var(--color-warning-bg); color: var(--color-warning-text); }
.co-days--bad { background: var(--color-danger-bg); color: var(--color-danger); }

/* Security tables: the name column takes the slack; badge and count hug the right edge */
.co-sec-table { table-layout: auto; }
.co-sec-table th:first-child,
.co-sec-table td:first-child { width: 100%; }
.co-sec-table th:not(:first-child),
.co-sec-table td:not(:first-child) { width: 1%; white-space: nowrap; text-align: right; }
.co-sec-table th:not(:first-child) { padding-left: 1.25rem; }

/* Security severity labels */
.co-severity--critical,
.co-severity--high { background: var(--color-danger-bg); color: var(--color-danger); }
.co-severity--medium { background: var(--color-warning-bg); color: var(--color-warning-text); }
.co-severity--low { background: var(--color-panel); color: var(--color-text-muted); }

/* Onboarding guides (markdown) */
.co-guide { margin: 0 0 1.75rem; scroll-margin-top: 1rem; }
.co-guide h2 { font-size: 1.25rem; margin: 0; }
.co-prose { max-width: 60rem; }
.co-prose h2 { font-size: 1.1rem; margin: 1.75rem 0 0.5rem; }
.co-prose h3 { font-size: 1rem; margin: 1.25rem 0 0.4rem; }
.co-prose table { width: 100%; border-collapse: collapse; margin: 0.75rem 0; font-size: 0.9rem; }
.co-prose th, .co-prose td { padding: 0.45rem 0.75rem; border: 1px solid var(--color-line); text-align: left; vertical-align: top; }
.co-prose th { background: var(--color-panel); }
.co-prose code { font-size: 0.85em; overflow-wrap: anywhere; }
.co-prose pre { overflow-x: auto; padding: 0.75rem 1rem; border-radius: var(--radius); background: var(--color-panel); font-size: 0.85rem; }
.co-prose pre code { overflow-wrap: normal; }
.co-prose blockquote { margin: 0.75rem 0; padding: 0.5rem 1rem; border-left: 4px solid var(--brand-blue); background: var(--color-selected-bg); }
.emp-inline-hint { display: inline; margin-left: 0.35rem; }

/* Client contract page: services list and the fee calculator */
.co-services { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.co-services li { padding: 0.55rem 0.75rem; border-left: 3px solid var(--brand-blue); border-radius: var(--radius); background: var(--color-selected-bg); font-size: 0.95rem; }
.co-fee__control { margin: 1.25rem 0 0; }
.co-fee__control label { display: block; margin-bottom: 0.6rem; font-size: 0.9rem; font-weight: 700; }
.co-fee__control input[type="range"] { width: 100%; accent-color: var(--brand-blue); }
.co-fee__scale { display: flex; justify-content: space-between; gap: 1rem; margin: 0.35rem 0 0.9rem; font-size: 0.8rem; color: var(--color-text-muted); }
.co-fee__marker { font-weight: 700; color: var(--color-link); }
.co-fee--moved .co-fee__marker { opacity: 0.6; font-weight: 500; }
.co-fee--moved [data-fee-spend], .co-fee--moved [data-fee-monthly], .co-fee--moved [data-fee-annual] { color: var(--brand-orange-text); }

/* Client dashboard: one card per area, each a link to its detail page */
.co-dash { align-items: stretch; }
.co-dash__card { text-decoration: none; color: inherit; transition: border-color 0.15s ease; }
.co-dash__card:hover { text-decoration: none; border-color: var(--brand-blue); }
.co-dash__card .co-card__title { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.co-dash__go { color: var(--color-link); font-weight: 400; }
.co-dash__value { margin: 0 0 0.9rem; font-family: var(--font-heading); font-size: 1.5rem; font-weight: 700; color: var(--color-heading); }
.co-dash__facts { margin: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.co-dash__facts div { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.25rem 1rem; }
.co-dash__facts dt { font-size: 0.85rem; color: var(--color-text-muted); }
.co-dash__facts dd { margin: 0; font-size: 0.9rem; font-weight: 600; text-align: right; }

/* Client dashboard: headline tiles, panels, and the trend line chart */
.co-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); gap: 1rem; margin: 0 0 1.5rem; }
.co-tile { display: flex; flex-direction: column; gap: 0.3rem; padding: 1rem 1.15rem; border: 1px solid var(--color-line); border-top: 3px solid var(--brand-blue); border-radius: var(--radius-lg); background: var(--color-surface); box-shadow: var(--shadow-card); color: inherit; text-decoration: none; }
.co-tile:hover { text-decoration: none; border-color: var(--brand-blue); }
.co-tile--good { border-top-color: var(--color-success); }
.co-tile--warn { border-top-color: #e0a100; }
.co-tile--bad { border-top-color: var(--color-danger); }
.co-tile__label { font-family: var(--font-heading); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--color-text-muted); }
.co-tile__value { font-family: var(--font-heading); font-size: 1.65rem; font-weight: 800; line-height: 1.1; color: var(--color-heading); }
.co-tile__meta { font-size: 0.82rem; color: var(--color-text-muted); }

.co-dash-main { align-items: stretch; gap: 1.25rem; margin-bottom: 1.25rem; }
.co-dash-main > .co-dash-panel:first-child:not(:only-child) { grid-column: span 1; }
@media (min-width: 1100px) { .co-dash-main { grid-template-columns: 3fr 2fr; } }
.co-dash-panel { min-width: 0; }
.co-card__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.5rem 1rem; margin-bottom: 1rem; }
.co-card__head .co-card__title { margin: 0; }
.co-dash__go { font-size: 0.85rem; font-weight: 600; white-space: nowrap; }

.co-seg--projected { background: repeating-linear-gradient(135deg, var(--co-c0) 0 4px, transparent 4px 8px); opacity: 0.55; }
.co-dash-security { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); gap: 1rem; }
.co-dash-security__item { display: flex; flex-direction: column; gap: 0.35rem; padding: 0.9rem 1rem; border: 1px solid var(--color-line); border-radius: var(--radius); color: inherit; text-decoration: none; }
.co-dash-security__item:hover { text-decoration: none; border-color: var(--brand-blue); }
.co-dash-security__bar { display: block; }

.co-term { padding: 0.9rem 0; border-top: 1px solid var(--color-line); }
.co-term:first-of-type { border-top: 0; padding-top: 0; }
.co-term__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.25rem 1rem; margin-bottom: 0.5rem; }
.co-term__name { font-weight: 700; }
.co-term__fee { font-size: 0.88rem; color: var(--color-text-muted); }
.co-term__foot { display: flex; justify-content: space-between; gap: 0.5rem; margin-top: 0.35rem; font-size: 0.78rem; }

.co-linechart { display: grid; grid-template-columns: auto 1fr; grid-template-rows: 190px auto; column-gap: 0.6rem; }
.co-linechart__yaxis { position: relative; min-width: 1.75rem; font-size: 0.78rem; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.co-linechart__yaxis span { position: absolute; right: 0; transform: translateY(50%); line-height: 1; }
.co-linechart__plot { position: relative; border-bottom: 1px solid var(--color-line); }
.co-linechart__plot svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.co-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.co-line--a { stroke: var(--co-c0); background: var(--co-c0); }
.co-line--b { stroke: var(--color-success); background: var(--color-success); }
.co-term .co-hlist__track { display: block; margin: 0.15rem 0; }
.co-term--ended .co-term__name { color: var(--color-text-muted); }
.co-badge--ended { background: var(--color-danger-bg); color: var(--color-danger); }

/* Contract page: an ended or cancelled contract, and what it used to cover */

/* "6 services · 5 no longer covered", with the list a hover or focus away */
.co-chip-wrap { position: relative; display: inline-block; }
.co-chip { padding: 0.15rem 0.65rem; border: 1px solid var(--color-line); border-radius: 999px; background: var(--color-panel); color: var(--color-text); font: inherit; font-size: 0.85rem; cursor: help; }
.co-chip--bad { border-color: var(--color-danger); background: var(--color-danger-bg); color: var(--color-danger); font-weight: 700; }
.co-tip--chip { bottom: auto; top: calc(100% + 0.4rem); min-width: 17rem; }
.co-chip-wrap:hover .co-tip--chip,
.co-chip:focus-visible ~ .co-tip--chip { display: block; }
.co-tip--chip .co-tip__swatch { box-shadow: none; }
.co-tip--chip .co-tip__amount { padding-left: 1rem; font-size: 0.8rem; opacity: 0.85; }

/* Earlier contracts: one line each, no repeated dates or document names */
.co-past { list-style: none; margin: 0; padding: 0; }
.co-past__row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.9rem; padding: 0.8rem 0; border-top: 1px solid var(--color-line); }
.co-past__row:first-child { border-top: 0; padding-top: 0; }
.co-past__row:last-child { padding-bottom: 0; }
.co-past__name { flex: 1 1 16rem; min-width: 0; font-weight: 700; }
.co-past__dates { display: block; font-size: 0.8rem; font-weight: 400; color: var(--color-text-muted); }
.co-past__docs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-left: auto; }

/* Export PPTX: the button's own progress line, beside it in the page header */
.co-export__status { align-self: center; font-size: 0.85rem; color: var(--color-text-muted); }
.co-export__status:empty { display: none; }

/* My hours against the client's revenue equivalent (the user, 2026-10-07): the pair is separated
   from the cloud columns by a vertical rule. No colour band — the figure is one person's hours, and
   a share of a whole team's benchmark would be green for everyone for ever. */
.co-col--sep { border-left: 2px solid var(--color-line); }
.co-use { font-variant-numeric: tabular-nums; }

/* The clients list runs to twelve columns, so each group (AWS, Azure, hours) opens with a rule and
   the headings wrap to two lines rather than widening the table (the user, 2026-10-07). */
/* The period, at the right of the page title row: larger than a caption because it governs every
   figure on the page, and aligned with the heading it sits beside rather than with a button. */
.co-period { margin: 0; align-self: center; font-size: 1.35rem; font-weight: 700; color: var(--color-text); font-variant-numeric: tabular-nums; }
/* The Savings tab: a hand-drawn donut (nothing vendored — the module already draws its charts as
   inline SVG, and six slices inherit the theme for free). The slices carry shares and counts and
   never dollars: the page's one money figure is AWS's own, printed above the chart. */
.co-donut { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }
.co-donut__svg { width: 9rem; height: 9rem; flex: none; transform: rotate(0deg); }
.co-donut__track { stroke: var(--color-line); }
.co-donut__slice { stroke-linecap: butt; }
/* The shared segment palette paints backgrounds, which an SVG stroke ignores — the legend swatch
   uses `background` and the slice needs `stroke`, from the same variables so the two can't drift. */
.co-donut__slice.co-seg--0 { stroke: var(--co-c0); }
.co-donut__slice.co-seg--1 { stroke: var(--co-c1); }
.co-donut__slice.co-seg--2 { stroke: var(--co-c2); }
.co-donut__slice.co-seg--3 { stroke: var(--co-c3); }
.co-donut__slice.co-seg--4 { stroke: var(--co-c4); }
.co-donut__slice.co-seg--5 { stroke: var(--co-c5); }
.co-donut__slice.co-seg--6 { stroke: var(--co-c6); }
.co-donut__slice.co-seg--7 { stroke: var(--co-c7); }
.co-donut__key { flex: 1 1 14rem; list-style: none; margin: 0; padding: 0; font-size: 0.9rem; }
.co-donut__key li { display: flex; align-items: center; gap: 0.5rem; padding: 0.2rem 0; }
.co-donut__swatch { width: 0.7rem; height: 0.7rem; border-radius: 2px; flex: none; }
.co-donut__label { flex: 1 1 auto; min-width: 0; }
.co-donut__share { font-variant-numeric: tabular-nums; font-weight: 700; }
.co-donut__count { color: var(--color-text-muted); font-variant-numeric: tabular-nums; min-width: 5.5rem; text-align: right; }
.co-savings__lead { margin: 0.25rem 0 0; font-size: 1.75rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* The grouped header (the user, 2026-10-08). Two things the browser gets wrong for it by default:
   a `th` spanning both rows is centred vertically, so CLIENT/OPEN/NEW/SLA float between the lines
   instead of sitting level with SPEND/SECURE beneath them; and a group label inherits the `.num`
   right-alignment the figures use, so "AWS" sits at the right edge of its three columns rather than
   over them. Centred is what makes the grouping readable at a glance, which is the only reason the
   row exists. */
.co-grouped thead th[rowspan] { vertical-align: bottom; }
.co-grouped thead th[scope="colgroup"] { text-align: center; }

/* Percentages carry a verdict, and the two kinds run in OPPOSITE directions: a high "secured" is
   good, a high "cost opportunity" is money being left on the table. ClientPercent decides which;
   this only paints what it decided, so the direction can never be set twice. */
.co-pct { font-variant-numeric: tabular-nums; }
.co-pct--good { color: var(--color-success-text); }
.co-pct--warn { color: var(--color-warning-text); }
.co-pct--bad { color: var(--color-danger); }
a.co-pct { text-decoration: none; }
a.co-pct:hover, a.co-pct:focus-visible { text-decoration: underline; }

/* Module: Overview — charts (Web's conventions, 2026-09-23; a shared <x-chart> replaces them later) */
.ovw-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); gap: 1rem; margin: 0 0 2rem; }
.ovw-panel { margin: 0; }
.ovw-panel__title { margin: 0 0 0.75rem; font-size: 1rem; }

.ovw-chart { margin: 0; }
.ovw-chart__body { display: grid; grid-template-columns: auto 1fr; grid-template-rows: 180px auto; column-gap: 0.6rem; }
.ovw-chart__yaxis { position: relative; min-width: 3.4rem; font-size: 0.75rem; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.ovw-chart__yaxis span { position: absolute; right: 0; transform: translateY(50%); line-height: 1; }
.ovw-chart__plot { position: relative; border-bottom: 1px solid var(--color-line); }
.ovw-chart__grid { position: absolute; left: 0; right: 0; height: 1px; background: var(--color-line); opacity: 0.7; }
.ovw-chart__bars { position: absolute; inset: 0; display: flex; align-items: flex-end; gap: 0; margin: 0; padding: 0; list-style: none; }
.ovw-chart__bars li { flex: 1 1 0; display: flex; justify-content: center; align-items: flex-end; height: 100%; }
.ovw-chart__bar { display: block; width: 62%; min-height: 1px; border-radius: var(--radius) var(--radius) 0 0; background: var(--color-primary); opacity: 0.85; }
.ovw-chart__plot svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.ovw-chart__line { fill: none; stroke: var(--brand-orange); stroke-width: 2; stroke-linejoin: round; }
.ovw-chart__line--target { stroke: var(--color-text-muted); stroke-dasharray: 4 3; stroke-width: 1.5; }
.ovw-chart__line--second { stroke: var(--color-success); }
.ovw-chart__bar--past { opacity: 0.45; }
.ovw-chart-note { margin: 0.75rem 0 0; }
.ovw-chart__xaxis { display: flex; margin: 0.35rem 0 0; padding: 0; list-style: none; font-size: 0.75rem; color: var(--color-text-muted); }
.ovw-chart__xaxis li { flex: 1 1 0; text-align: center; }

.ovw-chart__caption { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.35rem 1rem; margin-top: 0.75rem; font-size: 0.85rem; color: var(--color-text-muted); }
.ovw-chart__keys { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.ovw-chart__key { display: inline-flex; align-items: center; gap: 0.35rem; }
.ovw-chart__swatch { width: 0.75rem; height: 0.75rem; border-radius: 2px; background: var(--color-primary); }
.ovw-chart__swatch--line { height: 0; border-top: 2px solid var(--brand-orange); border-radius: 0; }
.ovw-chart__swatch--target { height: 0; border-top: 2px dashed var(--color-text-muted); border-radius: 0; }
.ovw-chart__swatch--second { height: 0; border-top: 2px solid var(--color-success); border-radius: 0; }
.ovw-chart__summary { font-weight: 700; color: var(--color-text); }

.ovw-links { display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; margin: 2rem 0 0; padding-top: 1rem; border-top: 1px solid var(--color-line); font-size: 0.9rem; }

/* Module: Time */
.time-status { margin: 0 0 1.25rem; }
.time-months { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; margin-bottom: 1.25rem; }
.time-months__label { margin: 0; font-size: 1.15rem; min-width: 10rem; text-align: center; }
.time-summary { grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); margin-bottom: 1.5rem; }
.time-summary .card { border-top-color: var(--brand-orange); }
.time-summary .value { font-size: 1.6rem; }
.time-summary .card.time-card--warning { border-top-color: var(--color-warning-text); }
/* Wider screens keep a client name on one line; on a phone the shared .table--pin rule wraps it. */
@media (min-width: 641px) { .time-grid th[scope="row"] { white-space: nowrap; } }
.time-grid .time-grid__selected { background: var(--color-panel); font-weight: 700; }
.time-grid .time-grid__total { font-weight: 700; }
.time-grid tfoot th, .time-grid tfoot td { border-top: 2px solid var(--color-line); font-weight: 700; }
.time-note { margin: 1rem 0 0.5rem; }
.time-partial { display: block; margin-top: 0.1rem; font-size: 0.7rem; font-weight: 400; letter-spacing: normal; text-transform: none; color: var(--color-warning-text); }
.time-months__status { margin: -0.5rem 0 1.25rem; }
/* A filter that lives in a section heading's actions slot: no margin of its own, so the house
   heading component controls the spacing. */
.cap-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0; }
.table tfoot .cap-total > * { border-top: 2px solid var(--color-line); font-weight: 700; text-align: left; }
.table tfoot .cap-total > .num { text-align: right; }
.time-grid__contract { border-right: 2px solid var(--color-line); white-space: nowrap; }
.time-cell__pct { display: block; font-weight: 700; font-variant-numeric: tabular-nums; }
.time-cell__hrs { display: block; font-size: 0.75rem; color: var(--color-text-muted); }
.time-use--under .time-cell__pct, td.time-use--under > .time-cell { color: var(--color-success-text); }
.time-use--near .time-cell__pct, td.time-use--near > .time-cell { color: var(--color-warning-text); }
.time-use--over .time-cell__pct, td.time-use--over > .time-cell { color: var(--color-danger); }
.time-grid th, .time-grid td { vertical-align: middle; }
.time-grid thead .time-grid__contract { white-space: normal; min-width: 6rem; max-width: 7rem; }
.time-cell__hrs { white-space: nowrap; }
.time-cell--no-contract { color: var(--color-text-muted); }
.time-cell { display: inline-block; cursor: default; border-radius: 2px; }
.time-cell:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.time-pop { position: fixed; z-index: 40; width: max-content; min-width: 14rem; max-width: min(20rem, calc(100vw - 16px)); padding: 0.6rem 0.75rem; border: 1px solid var(--color-line); border-radius: var(--radius); background: var(--color-surface); box-shadow: var(--shadow-card); color: var(--color-text); font-size: 0.8rem; line-height: 1.35; pointer-events: none; }
.time-pop[hidden] { display: none; }
.time-pop__head { display: grid; gap: 0.1rem; margin-bottom: 0.45rem; }
.time-pop__head strong { font-weight: 700; }
.time-pop__head span { color: var(--color-text-muted); }
.time-pop__table { width: 100%; border-collapse: collapse; }
.time-pop__table th, .time-pop__table td { padding: 0.15rem 0; text-align: left; font-weight: 400; white-space: nowrap; }
.time-pop__table thead th { font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted); border-bottom: 1px solid var(--color-line); }
.time-pop__table .num { text-align: right; padding-left: 1.25rem; font-variant-numeric: tabular-nums; }
.time-pop__table tfoot th, .time-pop__table tfoot td { border-top: 1px solid var(--color-line); font-weight: 700; }
/* Time: At Risk. Over contract reads as an alarm; barely used is a different, quieter question. */
.time-risk__group { margin: 1rem 0 0.4rem; font-size: 0.8rem; letter-spacing: 0.05em; text-transform: uppercase; }
.time-risk__group--over { color: var(--color-danger); }
.time-risk__group--under { color: var(--color-primary); }
.time-risk__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.4rem; }
.time-risk__list li { padding: 0.55rem 0.8rem; border-left: 4px solid; border-radius: var(--radius); line-height: 1.45; }
.time-risk__list--over li { border-left-color: var(--color-danger); background: var(--color-danger-bg); }
.time-risk__list--under li { border-left-color: var(--color-primary); background: var(--color-selected-bg); }
.time-risk__list a { color: inherit; }
.time-grid__recent { border-right: 2px solid var(--color-line); }
.time-row--over th[scope="row"] { --pin-flag: inset 4px 0 0 var(--color-danger); }
.time-row--under th[scope="row"] { --pin-flag: inset 4px 0 0 var(--color-primary); }
.time-team { width: 100%; }
.time-team td:last-child { width: 100%; }
.time-split { display: flex; gap: 2px; height: 0.6rem; width: 100%; border-radius: 999px; overflow: hidden; background: var(--color-panel); }
.time-split__part { flex-basis: 0; min-width: 2px; cursor: default; }
.time-split__legend { display: flex; flex-wrap: wrap; gap: 0.15rem 0.9rem; margin: 0.4rem 0 0; font-size: 0.8rem; color: var(--color-text-muted); }
.time-split__legend > span { white-space: nowrap; }
.time-split__item::before, .time-split__more::before { content: ""; display: inline-block; width: 0.55rem; height: 0.55rem; margin-right: 0.3rem; border-radius: 2px; background: var(--color-text-muted); }
.time-split__more { font-weight: 700; }
/* Segment colours, largest client first; the ninth and later share the muted grey. */
.time-c1 { --time-c: var(--brand-orange); }
.time-c2 { --time-c: var(--color-primary); }
.time-c3 { --time-c: var(--color-success-text); }
.time-c4 { --time-c: var(--color-warning-text); }
.time-c5 { --time-c: var(--color-danger); }
.time-c6 { --time-c: var(--color-link); }
.time-c7 { --time-c: var(--color-heading); }
.time-c8 { --time-c: color-mix(in srgb, var(--brand-orange) 45%, var(--color-panel)); }
.time-c9 { --time-c: var(--color-text-muted); }
.time-split__part[class*="time-c"] { background: var(--time-c); }
.time-split__item[class*="time-c"]::before { background: var(--time-c); }
.time-foot { margin-top: 1rem; }
.time-split__more[hidden], .time-split__item[hidden] { display: none; }
/* Past months are fact and sit back; this month is the reader's anchor, marked by the rules above
   and below it. Never colour alone: a past row is also the one with no forecast figure. */
.cap-forecast .cap-row--history > * { color: var(--color-text-muted); background: var(--color-panel); }
.cap-forecast .cap-row--now > * { border-top: 2px solid var(--color-line); border-bottom: 2px solid var(--color-line); }
.cap-forecast .cap-row--now .cap-cell-strong { font-weight: 700; }
/* Coverage tiers in the user's own notation (8x5, 8x8x7, 24x7x365): the text carries the meaning,
   so the badge is neutral and never the only signal. */
.cap-badge--tier { background: var(--color-selected-bg); color: var(--color-link); font-variant-numeric: tabular-nums; }

/* Module: Quotes */
.qt-muted { color: var(--color-text-muted); font-weight: 400; }
.qt-strong { font-weight: 700; }
.qt-filter { margin-top: 0.5rem; }

/* A muted fill is 14/255 from the panel behind it in dark mode — the pill dissolves and the word
   reads as plain text (measured on /preview, 2026-10-09). The ring gives it an edge in both themes
   without changing a shared token. */
.qt-badge--draft,
.qt-badge--lost { background: var(--color-panel); color: var(--color-text-muted); box-shadow: inset 0 0 0 1px var(--color-line); }
.qt-badge--sent { background: var(--color-selected-bg); color: var(--color-link); }
.qt-badge--won { background: var(--color-success-bg); color: var(--color-success-text); }
.qt-badge--expired { background: var(--color-warning-bg); color: var(--color-warning-text); }
.qt-badge--prospect { background: var(--color-panel); color: var(--color-text-muted); border: 1px solid var(--color-line); }
.qt-badge--tier-continuous { background: var(--color-selected-bg); color: var(--color-link); }
.qt-badge--tier-extended { background: var(--color-warning-bg); color: var(--color-warning-text); }
.qt-badge--tier-standard,
.qt-badge--tier-none { background: var(--color-panel); color: var(--color-text-muted); }

.qt-form { max-width: 960px; }
.qt-form input[type="date"],
.qt-form input[type="number"] {
    font: inherit;
    color: var(--color-text);
    background: var(--color-input-bg);
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    width: 100%;
    max-width: 100%;
}
.qt-form [aria-invalid="true"] { border-color: var(--color-danger); }
.qt-form [data-client-block],
.qt-form [data-pricing-block],
.qt-form-row > div,
.qt-form-grid > div { display: flex; flex-direction: column; gap: 0.35rem; }
.qt-form [data-client-block][hidden],
.qt-form [data-pricing-block][hidden] { display: none; }
.qt-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 0 1rem; }
.qt-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); gap: 0 1.25rem; }

.qt-services { display: flex; flex-direction: column; gap: 1rem; margin-top: 0.75rem; }
.qt-service { padding: 0.9rem 1rem; border: 1px solid var(--color-line); border-left: 4px solid var(--brand-blue); border-radius: var(--radius); }
.qt-service__tools { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.qt-preview { margin: 0.75rem 0 0.5rem; max-width: 560px; }
.qt-preview p { margin: 0; }
.qt-preview .svc-details { margin: 0; }

.qt-status { margin-bottom: 1.5rem; }
.qt-status h2 { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0; font-size: 1.1rem; }
.qt-status p { margin: 0.25rem 0 0; }
.qt-status__actions { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem; margin-top: 1rem; }

.qt-service-title { margin: 1.25rem 0 0.6rem; font-size: 1.05rem; }
.qt-capability-title { margin: 0; font-size: 1rem; }
.qt-exclusions summary { cursor: pointer; }
.qt-exclusions summary h2 { display: inline; margin: 0; font-size: 1.2rem; }
.qt-list { margin: 0; padding-left: 1.25rem; display: flex; flex-direction: column; gap: 0.35rem; }

.qt-breakdown th[scope="row"] { font-weight: 700; white-space: nowrap; }
.qt-total th,
.qt-total td { border-top: 2px solid var(--color-line); font-weight: 700; }
.qt-note-row td { padding-top: 0; font-size: 0.9rem; }

/* Module: Quotes — the quote form's compact controls (the user's declutter, 2026-09-29) */
/* A fieldset carries 1.25rem of top margin for its legend. Where the legend is hidden (Client,
   Price), that margin plus the heading's own leaves a hole under the heading, so close it once
   here rather than per section. */
.qt-form .form-section-title + .fieldset { margin-top: 0.35rem; }
.qt-form .fieldset > .visually-hidden:first-child + .qt-chips { margin-top: 0; }
.qt-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.4rem; }
.qt-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.85rem;
    border: 1px solid var(--color-line);
    border-radius: 2rem;
    background: var(--color-surface);
    cursor: pointer;
    font-size: 0.9rem;
}
.qt-chip:hover { background: var(--color-panel); }
.qt-chip:has(input:checked) { border-color: var(--color-primary); background: var(--color-selected-bg); font-weight: 700; }
.qt-chip:has(input:focus-visible) { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.qt-chip input { width: 1rem; height: 1rem; margin: 0; accent-color: var(--color-primary); }

/* Coverage and term: two columns with a divider (the user's revised mockup, 2026-09-29), drawn in
   HUB's own tokens. One column on a narrow screen, where the divider becomes a rule above. */
.qt-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); gap: 1.5rem; align-items: start; margin-top: 0.35rem; }
.qt-column { display: flex; flex-direction: column; gap: 0.35rem; margin: 0; padding: 0 0 0 1.5rem; border-left: 1px solid var(--color-line); }
.qt-column:first-child { padding-left: 0; border-left: 0; }
.qt-column > legend { margin: 0; }
.qt-column .field-hint { margin: 0 0 0.35rem; }
@media (max-width: 47.99em) {
    .qt-column { padding: 1rem 0 0; border-left: 0; border-top: 1px solid var(--color-line); }
    .qt-column:first-child { padding-top: 0; border-top: 0; }
}
.qt-rule { margin: 1.75rem 0 1.25rem; border: 0; border-top: 1px solid var(--color-line); }

/* A money field: the $ sits inside the box and can't be typed over or deleted. */
.qt-money { display: flex; align-items: stretch; max-width: 560px; border: 1px solid var(--color-line); border-radius: var(--radius); background: var(--color-input-bg); }
.qt-money:focus-within { border-color: var(--color-primary); }
.qt-money:has([aria-invalid="true"]) { border-color: var(--color-danger); }
.qt-money__mark { display: flex; align-items: center; padding: 0 0.15rem 0 0.75rem; color: var(--color-text-muted); }
.qt-form .qt-money input { border: 0; background: none; border-radius: 0; padding-left: 0.35rem; }
.qt-form .qt-money input:focus { outline: none; }

.qt-cards { display: flex; flex-direction: column; gap: 0.5rem; }
/* Two across, with the last card spanning the row; and three across. Both fall to one column. */
.qt-cards--pairs,
.qt-cards--threes { display: grid; gap: 0.5rem; }
.qt-cards--pairs { grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); }
.qt-cards--threes { grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr)); }
.qt-card--wide { grid-column: 1 / -1; }

.qt-card {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--color-line);
    border-radius: var(--radius);
    background: var(--color-surface);
    cursor: pointer;
}
.qt-card:hover { border-color: var(--color-primary); }
.qt-card:has(input:checked) { border-color: var(--color-primary); background: var(--color-selected-bg); }
.qt-card:has(input:focus-visible) { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.qt-card input { flex: none; width: 1.05rem; height: 1.05rem; margin: 0.15rem 0 0; accent-color: var(--color-primary); }
.qt-card__icon { flex: none; margin-top: 0.15rem; color: var(--color-text-muted); }
.qt-card:has(input:checked) .qt-card__icon { color: var(--color-link); }
.qt-card__logo { flex: none; width: 1.75rem; height: 1.75rem; object-fit: contain; color: var(--color-text-muted); }
.qt-card__text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; overflow-wrap: anywhere; font-size: 0.9rem; }
.qt-card__text .qt-muted { font-size: 0.82rem; }
.qt-card--term .qt-card__text { gap: 0.05rem; }

.qt-service { padding: 0.9rem 1rem 1rem; }
.qt-service__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 1rem; margin-bottom: 0.6rem; }
.qt-service__name { margin: 0; font-size: 1rem; }

.qt-capabilities { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr)); gap: 0.35rem 1.25rem; align-items: start; }
.qt-capability { padding: 0.15rem 0; }
.qt-capability__pick { display: flex; align-items: flex-start; gap: 0.5rem; padding: 0.3rem 0; cursor: pointer; font-size: 0.92rem; }
.qt-capability__pick input { flex: none; width: 1.05rem; height: 1.05rem; margin: 0.15rem 0 0; accent-color: var(--color-primary); }
.qt-capability__pick:hover { color: var(--color-link); }
.qt-capability__pick > span { min-width: 0; overflow-wrap: anywhere; }
.qt-covers .svc-text { overflow-wrap: anywhere; }

.qt-covers { margin: 0 0 0 1.55rem; }
.qt-covers > summary { display: inline-block; font-size: 0.8rem; color: var(--color-link); cursor: pointer; }
.qt-covers > summary:hover { text-decoration: underline; }
.qt-covers[open] > .svc-text {
    /* No cap and no scroll of its own (2026-09-29): an 8rem box clipped every description
       mid-sentence, which is worse than the list moving — you opened it to read it. The content
       below moving down is what a disclosure does; what mustn't move is the checkbox you clicked,
       and that's held by the layout, not by capping this. */
    margin: 0.35rem 0 0.5rem;
    padding: 0.5rem 0.65rem;
    /* The fill alone is 14/255 from the page in dark mode, so the rule carries the separation. */
    border-left: 3px solid var(--color-primary);
    background: var(--color-panel);
    border-radius: var(--radius);
    font-size: 0.85rem;
    color: var(--color-text-muted);
}
