/*
 * iClient portal styles — mobile-first, built on --ideal-* tokens from
 * brand-colors.css (shared IDEAL design system), refined to match (and gently
 * exceed) iCRM's visual refresh: Inter type, light/dark themes, soft rounded
 * surfaces, teal gradient nav, smooth micro-interactions.
 * Bottom tab bar on phones, fixed sidebar from 992px up. Touch >= 44px.
 */

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../vendor/inter/Inter-Variable.260c81a4759b.woff2") format('woff2');
}

:root {
    --bs-body-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --icl-radius: 1rem;
    --icl-radius-sm: 0.65rem;
    --icl-shadow-soft: 0 1px 2px rgba(16, 24, 40, .04), 0 4px 16px rgba(16, 24, 40, .06);
    --icl-shadow-hover: 0 2px 4px rgba(16, 24, 40, .06), 0 12px 28px rgba(16, 24, 40, .10);
    --icl-teal-tint: rgba(92, 189, 189, .12);
    --icl-hairline: #eef1f3;
    --icl-surface: #ffffff;
    --icl-surface-2: #fbfcfc;
    --icl-body-bg: #f6f8f9;
    --icl-label: #8a95a1;
    --icl-nav-grad: linear-gradient(180deg, #3f8f8f 0%, #5CBDBD 55%, #6dcaca 100%);
    --icl-tab-grad: linear-gradient(0deg, #35807f 0%, #418f8e 100%);
    --donut-track: #e9ecef;
}

[data-bs-theme="dark"] {
    --icl-hairline: #2b3138;
    --icl-teal-tint: rgba(92, 189, 189, .16);
    --icl-shadow-soft: 0 1px 2px rgba(0, 0, 0, .35), 0 6px 20px rgba(0, 0, 0, .45);
    --icl-shadow-hover: 0 2px 6px rgba(0, 0, 0, .4), 0 16px 36px rgba(0, 0, 0, .55);
    --icl-surface: #1b1f24;
    --icl-surface-2: #171b1f;
    --icl-body-bg: #14171a;
    --icl-label: #7c8794;
    --icl-nav-grad: linear-gradient(180deg, #1c3b3b 0%, #23514f 55%, #2c625f 100%);
    --icl-tab-grad: linear-gradient(0deg, #16302f 0%, #1d403e 100%);
    --donut-track: #2b3138;
}

html, body { height: 100%; }
body {
    font-family: var(--bs-body-font-family);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    color: var(--bs-body-color);
    background: var(--icl-body-bg);
    margin: 0;
}
/* room for the bottom tab bar on phones (only when it's rendered) */
/* Room for the fixed tab bar, on .page rather than on body.
   `html, body { height: 100% }` just above means the body BOX is exactly the
   viewport, however long the page is — so padding-bottom on body lands at the
   top of a long list, thousands of pixels above where the content ends, and
   reserves nothing. .page is the element that actually grows. That is why the
   pager on Invoices, Payments and Clients sat under the bar.
   --tabbar-h is measured by base.html: the bar's height moves with text size
   and with env(safe-area-inset-bottom) on a phone with a home indicator, and
   offsetHeight already counts both. The fallback is deliberately generous —
   too much space costs a little scrolling, too little costs a button nobody
   can press. */
@media (max-width: 991.98px) {
    body.with-tabbar .page { padding-bottom: calc(var(--tabbar-h, 100px) + 1.75rem); }
}

h1, h2, h3, .h3, .h4, .h5 { letter-spacing: -0.01em; }

/* Page titles: bold teal, consistent with iCRM */
.page > h1, .page h1 {
    color: var(--ideal-teal-dark);
    font-weight: 700;
}
[data-bs-theme="dark"] .page > h1, [data-bs-theme="dark"] .page h1 { color: var(--ideal-teal-light); }

/* Smooth theme + surface transitions */
body, .pcard, .topbar, .sidenav, .tabbar, .modal-content,
.form-control, .form-select, .kv, .countdown-chip {
    transition: background-color .28s ease, border-color .28s ease, color .2s ease,
                box-shadow .2s ease, transform .18s ease;
}

/* === Staff act-as banner === */
.actas-banner {
    position: sticky;
    top: 0;
    z-index: 1040;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    flex-wrap: wrap;
    background: linear-gradient(90deg, #6d28d9 0%, #7c3aed 60%, #8b5cf6 100%);
    color: #fff;
    padding: .45rem .75rem;
    font-size: .9rem;
    text-align: center;
}
.actas-banner a { min-height: 32px; border-radius: 999px; }

/* Icon-only ghost button (theme toggle) */
.btn-ghost {
    border: none;
    background: transparent;
    color: var(--ideal-text-muted);
    min-width: 44px;
    justify-content: center;
}
.btn-ghost:hover { background: var(--icl-teal-tint); color: var(--ideal-teal-dark); }
[data-bs-theme="dark"] .btn-ghost:hover { color: var(--ideal-teal-light); }
.theme-toggle i { transition: transform .25s ease; }
.theme-toggle:hover i { transform: rotate(-15deg) scale(1.15); }

/* === Account card (mobile header on the Profile tab) === */
.account-card { padding: 1rem 1.15rem; }
.account-card .avatar {
    width: 52px; height: 52px; border-radius: 50%;
    background: var(--ideal-gradient-primary); color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1.1rem; font-weight: 700;
    flex-shrink: 0;
}
.account-card .account-card-main { min-width: 0; }
.account-card .name { font-weight: 700; letter-spacing: -.01em; overflow-wrap: anywhere; }
.account-card .switch-link {
    display: inline-flex; align-items: center; gap: .3rem;
    color: var(--ideal-teal-dark);
    font-weight: 600; font-size: .85rem;
    text-decoration: none;
}
.account-card .switch-link:hover { text-decoration: underline; }
[data-bs-theme="dark"] .account-card .switch-link { color: var(--ideal-teal-light); }

/* === Bottom tab bar (phones): teal gradient, springy active pill === */
.tabbar {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    z-index: 1030;
    display: flex;
    background: var(--icl-tab-grad);
    padding: .3rem .35rem calc(.3rem + env(safe-area-inset-bottom));
    box-shadow: 0 -4px 20px rgba(0, 0, 0, .18);
}
.tabbar a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: #cfe8e8;
    text-decoration: none;
    font-size: .65rem;
    font-weight: 500;
    padding: .45rem 0 .4rem;
    min-height: 56px;
    border-radius: .8rem;
    transition: background-color .2s ease, color .2s ease, transform .18s ease;
}
.tabbar a i { font-size: 1.3rem; line-height: 1; transition: transform .22s cubic-bezier(.34, 1.56, .64, 1); }
.tabbar a:active i { transform: scale(.9); }
.tabbar a.active {
    color: #fff;
    background: rgba(255, 255, 255, .16);
    font-weight: 700;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14);
}
.tabbar a.active i { transform: translateY(-1px) scale(1.08); }

/* === Sidebar (desktop) === */
.sidenav { display: none; }

@media (min-width: 992px) {
    .tabbar { display: none; }
    .layout { display: flex; min-height: 100vh; }
    /* Floating rounded panel, inset from the viewport edge */
    .sidenav {
        display: flex;
        flex-direction: column;
        width: 264px;
        flex-shrink: 0;
        position: sticky;
        top: .75rem;
        height: calc(100vh - 1.5rem);
        margin: .75rem 0 .75rem .75rem;
        border-radius: 1.25rem;
        overflow-y: auto;
        background: var(--icl-nav-grad);
        color: #e4f2f2;
        padding: 1.25rem .6rem 1rem;
        box-shadow: 0 10px 30px rgba(16, 24, 40, .18), 0 2px 8px rgba(16, 24, 40, .08);
        transition: width .3s ease, padding .3s ease, background-color .28s ease;
    }
    [data-bs-theme="dark"] .sidenav { box-shadow: 0 10px 30px rgba(0, 0, 0, .5), 0 2px 8px rgba(0, 0, 0, .3); }
    .sidenav-top {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: .5rem;
        padding: 0 .5rem 1.2rem;
    }
    .sidenav .brand {
        display: flex;
        align-items: baseline;
        gap: .45rem;
        text-decoration: none;
        min-width: 0;
    }
    .sidenav .brand .logo { color: #fff; font-weight: 800; font-size: 1.3rem; letter-spacing: -.5px; }
    .sidenav .brand .app { color: rgba(255, 255, 255, .8); font-weight: 500; font-size: .85rem; white-space: nowrap; }
    .sidenav .brand .logo-mini { display: none; color: #fff; font-weight: 800; font-size: 1.25rem; }
    .sidenav-collapse-btn {
        background: rgba(255, 255, 255, .15);
        border: none;
        color: #fff;
        width: 30px;
        height: 30px;
        border-radius: .55rem;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        transition: background-color .2s ease;
    }
    .sidenav-collapse-btn:hover { background: rgba(255, 255, 255, .28); }
    .sidenav-collapse-btn i { font-size: .85rem; transition: transform .3s ease; }
    html.sidenav-collapsed .sidenav-collapse-btn i { transform: rotate(180deg); }
    .sidenav .user-block { text-align: center; padding: 0 1rem 1.25rem; }
    .sidenav .user-block .avatar {
        width: 68px; height: 68px; border-radius: 50%;
        background: rgba(255, 255, 255, .18);
        color: #fff;
        box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .35);
        display: inline-flex; align-items: center; justify-content: center;
        font-size: 1.45rem; font-weight: 700; margin-bottom: .6rem;
    }
    .sidenav .user-block .name {
        font-weight: 700; color: #fff; letter-spacing: -.01em;
        /* Most providers sign in as an address rather than a name, and an
           address has no spaces to wrap at — so the default leaves a long one
           running off the side of the sidebar and cut in half. `anywhere`
           breaks mid-token; `break-word` would not, because there is no
           opportunity to prefer. */
        overflow-wrap: anywhere;
        /* Two lines covers the addresses people actually have. Past that the
           nav below starts getting pushed down the page, so clamp and let the
           title attribute carry the rest. */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        line-height: 1.25;
    }
    .sidenav .user-block a {
        display: inline-block;
        color: #eafafa;
        text-decoration: none;
        font-weight: 600;
        font-size: .82rem;
        margin-top: .35rem;
        padding: .25rem .8rem;
        border-radius: 999px;
        background: rgba(255, 255, 255, .14);
        transition: background-color .2s ease;
    }
    .sidenav .user-block a:hover { background: rgba(255, 255, 255, .24); }
    .sidenav .nav-link {
        display: flex; align-items: center; gap: .75rem;
        color: #e9f7f7; text-decoration: none;
        padding: .65rem .85rem; min-height: 44px;
        border-radius: var(--icl-radius-sm);
        margin: 2px .2rem;
        font-weight: 500;
        transition: background-color .2s ease, transform .18s ease, box-shadow .2s ease;
    }
    .sidenav .nav-link i:first-child { transition: transform .2s ease; }
    .sidenav .nav-link:hover { background: rgba(255, 255, 255, .12); color: #fff; transform: translateX(2px); }
    .sidenav .nav-link:hover i:first-child { transform: scale(1.12); }
    .sidenav .nav-link.active {
        background: linear-gradient(90deg, rgba(255, 255, 255, .30) 0%, rgba(255, 255, 255, .14) 100%);
        color: #fff;
        font-weight: 700;
        box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18), 0 2px 10px rgba(0, 0, 0, .12);
    }
    .sidenav-footer {
        margin-top: auto;
        display: flex;
        align-items: center;
        gap: .4rem;
        padding: .85rem .35rem 0;
        border-top: 1px solid rgba(255, 255, 255, .16);
    }
    .sidenav-footer .btn {
        color: #e9f7f7;
        border: none;
        background: transparent;
        border-radius: var(--icl-radius-sm);
        display: inline-flex;
        align-items: center;
        gap: .45rem;
        font-weight: 500;
    }
    .sidenav-footer .btn:hover { background: rgba(255, 255, 255, .14); color: #fff; }
    .sidenav-footer .theme-toggle { min-width: 44px; justify-content: center; }
    .sidenav-footer a.btn { flex: 1; justify-content: center; }
    .content { flex: 1; min-width: 0; }

    /* --- Collapsed icon rail --- */
    html.sidenav-collapsed .sidenav {
        width: 84px;
        padding-left: .45rem;
        padding-right: .45rem;
        overflow: visible;   /* icon tooltips must escape the panel */
    }
    html.sidenav-collapsed .sidenav-top {
        flex-direction: column;
        gap: .65rem;
        padding: 0 0 1rem;
    }
    html.sidenav-collapsed .sidenav .brand .logo,
    html.sidenav-collapsed .sidenav .brand .app { display: none; }
    html.sidenav-collapsed .sidenav .brand .logo-mini { display: block; }
    html.sidenav-collapsed .sidenav .user-block { padding: 0 0 1rem; }
    html.sidenav-collapsed .sidenav .user-block .avatar {
        width: 44px; height: 44px; font-size: 1rem; margin-bottom: 0;
    }
    html.sidenav-collapsed .sidenav .user-block .name,
    html.sidenav-collapsed .sidenav .user-block a { display: none; }
    html.sidenav-collapsed .sidenav .nav-link {
        justify-content: center;
        padding: .65rem 0;
        position: relative;
    }
    html.sidenav-collapsed .sidenav .nav-link span { display: none; }
    html.sidenav-collapsed .sidenav .nav-link i:first-child { font-size: 1.25rem; }
    html.sidenav-collapsed .sidenav .nav-link:hover { transform: none; }
    /* Tooltip on the icon rail */
    html.sidenav-collapsed .sidenav .nav-link::after {
        content: attr(data-title);
        position: absolute;
        left: 100%;
        top: 50%;
        transform: translateY(-50%);
        margin-left: .85rem;
        background: #1f2933;
        color: #fff;
        padding: .45rem .75rem;
        border-radius: .5rem;
        font-size: .85rem;
        font-weight: 500;
        white-space: nowrap;
        box-shadow: 0 6px 18px rgba(0, 0, 0, .25);
        opacity: 0;
        visibility: hidden;
        transition: opacity .15s ease, visibility .15s ease;
        pointer-events: none;
        z-index: 1060;
    }
    html.sidenav-collapsed .sidenav .nav-link:hover::after,
    html.sidenav-collapsed .sidenav .nav-link:focus-visible::after {
        opacity: 1;
        visibility: visible;
    }
    html.sidenav-collapsed .sidenav-footer {
        flex-direction: column;
        gap: .35rem;
        padding-left: 0;
        padding-right: 0;
    }
    html.sidenav-collapsed .sidenav-footer .btn span { display: none; }
    html.sidenav-collapsed .sidenav-footer a.btn { flex: 0 0 auto; width: 100%; }
}

.page { padding: 1.25rem 1rem; max-width: 1100px; margin: 0 auto; }
@media (min-width: 992px) { .page { padding: 1.75rem 2rem; } }

/* Gentle page entrance */
@keyframes icl-rise {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.page > * { animation: icl-rise .32s ease both; }

/* === Cards === */
.pcard {
    background: var(--icl-surface);
    border: 1px solid var(--icl-hairline);
    border-radius: var(--icl-radius);
    box-shadow: var(--icl-shadow-soft);
    padding: 1.1rem 1.3rem;
    margin-bottom: 1rem;
    transition: box-shadow .22s ease, transform .22s ease, background-color .28s ease, border-color .28s ease;
}
.pcard:hover { box-shadow: var(--icl-shadow-hover); }
.pcard h2 {
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .01em;
    color: var(--ideal-teal-dark);
    margin: 0 0 .75rem;
    padding-bottom: .45rem;
    border-bottom: 2px solid var(--icl-teal-tint);
}
[data-bs-theme="dark"] .pcard h2 { color: var(--ideal-teal-light); }

/* flex-wrap: a value that doesn't fit beside its label drops to its own
   right-aligned line instead of breaking mid-word (e.g. "$17,340.5|0") */
.kv { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .25rem 1rem; padding: .55rem 0; border-bottom: 1px solid var(--icl-hairline); }
.kv:last-child { border-bottom: none; }
.kv .k {
    color: var(--icl-label);
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    align-self: center;
}
.kv .v { text-align: right; font-weight: 500; margin-left: auto; overflow-wrap: anywhere; }

/* === Support-coordinator accordion (shown when a participant has 2+) === */
.coord-accordion {
    --bs-accordion-bg: transparent;
    --bs-accordion-color: inherit;
    --bs-accordion-border-color: var(--icl-hairline);
    --bs-accordion-border-radius: 10px;
    --bs-accordion-inner-border-radius: 10px;
    --bs-accordion-btn-padding-y: .65rem;
    --bs-accordion-btn-padding-x: .85rem;
    --bs-accordion-btn-bg: transparent;
    --bs-accordion-btn-color: inherit;
    --bs-accordion-active-bg: var(--icl-teal-tint);
    --bs-accordion-active-color: var(--ideal-teal-dark);
    --bs-accordion-btn-focus-border-color: var(--ideal-teal);
    --bs-accordion-btn-focus-box-shadow: 0 0 0 .2rem var(--icl-teal-tint);
}
[data-bs-theme="dark"] .coord-accordion { --bs-accordion-active-color: var(--ideal-teal-light); }
.coord-accordion .accordion-item { margin-bottom: .5rem; overflow: hidden; }
.coord-accordion .accordion-item:last-child { margin-bottom: 0; }
.coord-accordion .accordion-button:not(.collapsed) { box-shadow: none; }
.coord-accordion .coord-head { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.coord-accordion .coord-name { font-weight: 600; }
.coord-accordion .coord-org { font-size: .82em; font-weight: 400; color: var(--icl-label); }
.coord-accordion .accordion-body { padding: .15rem .85rem .5rem; }

/* === Overview dashboard (reps/coordinators) === */
.ov-card { position: relative; }
.ov-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .25rem 1rem; margin-bottom: .6rem; }
.ov-name { font-weight: 700; font-size: 1.02rem; color: var(--ideal-teal-dark); }
[data-bs-theme="dark"] .ov-name { color: var(--ideal-teal-light); }
.ov-period { font-size: .82rem; }
.ov-metric { margin-top: .55rem; }
.ov-metric-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .1rem 1rem; font-size: .82rem; margin-bottom: .2rem; }
.ov-metric-head > span:first-child { color: var(--icl-label); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; font-size: .72rem; align-self: center; }
.ov-bar { height: 10px; border-radius: 6px; background: var(--icl-teal-tint); }
.ov-bar .progress-bar { background: var(--ideal-teal); border-radius: 6px; }
.ov-bar-time { background: rgba(120, 130, 140, .18); }
.ov-bar-time .progress-bar { background: #8a97a3; border-radius: 6px; }
.ov-used { font-weight: 600; }
.ov-flags { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .7rem; }
.ov-flags .badge { font-weight: 600; }
.ov-cta { margin-top: .9rem; }

/* === Support Planner (budgeting workspace) === */
.cat-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; margin-bottom: .5rem; }
.cat-name { font-size: 1.05rem; font-weight: 700; color: var(--ideal-teal-dark); line-height: 1.25; }
[data-bs-theme="dark"] .cat-name { color: var(--ideal-teal-light); }
.cat-avail { color: var(--icl-label); font-size: .8rem; margin-top: .15rem; }
.cat-head-right { display: flex; align-items: center; gap: .9rem; }
.cat-left { text-align: right; white-space: nowrap; }
.cat-left .amt { font-size: 1.5rem; font-weight: 700; }
.cat-left .lbl { display: block; color: var(--icl-label); font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; }
.cat-compact .cat-head { margin: 0; align-items: center; }
.cat-spend-link { font-size: .8rem; text-decoration: none; margin-top: .15rem; }
.cat-spend-link:hover { text-decoration: underline; }

.sup { border-bottom: 1px solid var(--icl-hairline); }
.sup:first-of-type { border-top: 1px solid var(--icl-hairline); }
.sup-ended .sup-name, .sup-ended .sup-sub, .sup-ended .sup-cost { opacity: .55; }
.sup-read { display: flex; align-items: center; gap: 1rem; padding: .7rem 0; }
.sup-main { flex: 1 1 auto; min-width: 0; }
.sup-name { font-weight: 600; }
.sup-sub { color: var(--icl-label); font-size: .82rem; margin-top: .1rem; }
.sup-cost { font-weight: 700; white-space: nowrap; text-align: right; }
.sup-cost span { color: var(--icl-label); font-weight: 400; font-size: .8rem; }
.sup-total { display: block; margin-top: .1rem; }
.sup-actions { display: flex; gap: .25rem; }
.sup-edit { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .6rem; padding: .7rem 0; }

.pl-field { display: flex; flex-direction: column; gap: .15rem; font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--icl-label); margin: 0; }
.pl-field input { width: 6rem; }
.pl-field input[type="date"] { width: 9.5rem; }
.pl-hint { font-size: .68rem; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--icl-label); margin-top: .12rem; }
/* Stretch to the row height so the "Ends" label pins to the top (aligned with
   the other field labels); the switch fills the space below and centres itself
   vertically — the field is shorter than the others without this. */
.pl-end { gap: .3rem; align-self: stretch; }
.pl-end .pl-switch { flex: 1 1 auto; }
.pl-switch { margin: 0; padding-left: 2.2em; min-height: auto; }
.pl-switch .form-check-label { font-size: .78rem; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--icl-text); }
.pl-end .js-end-date { width: 9.5rem; }
.pl-grow { flex: 1 1 10rem; }
.pl-grow input { width: 100%; }
.pl-in { display: inline-flex; align-items: center; gap: .2rem; }
.pl-btns { display: inline-flex; gap: .4rem; }
.planner-add { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .6rem; margin-top: .7rem; }

.add-support { margin-top: .7rem; }
.cat-outcome { display: flex; gap: .5rem; align-items: flex-start; margin-top: .9rem; padding: .6rem .8rem; border-radius: 10px; font-size: .92rem; }
.cat-outcome.ok { background: rgba(40, 167, 69, .12); }
.cat-outcome.warn { background: rgba(220, 53, 69, .12); }
.cat-actual { color: var(--icl-label); font-size: .86rem; margin-top: .5rem; }
.planner-total { font-size: 1rem; }

/* === Claim cards === */
.claim-card { border-left: 4px solid var(--ideal-teal); }
.claim-card.expired { border-left-color: #b3bcc5; }
.claim-card.rejected { border-left-color: var(--ideal-danger); }
.claim-card .amount, .pcard .amount {
    font-size: 1.45rem;
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--ideal-teal-dark);
    font-variant-numeric: tabular-nums;
}
.pay-card .amount { font-size: 1.2rem; }
[data-bs-theme="dark"] .claim-card .amount, [data-bs-theme="dark"] .pcard .amount { color: var(--ideal-teal-light); }
.claim-footer {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex-wrap: wrap;
    margin-top: .85rem;
}
.claim-file-btn { min-height: 38px; display: inline-flex; align-items: center; gap: .35rem; }
.claim-card .claimed-note, .pcard .claimed-note { color: var(--ideal-text-muted); font-size: .82rem; font-weight: 600; }
/* Visible but secondary: cancellation is the exception, auto-approval the norm.
   A soft red-tinted pill — reads as an action without competing for attention. */
.claim-cancel-btn {
    background: rgba(220, 53, 69, .08);
    border: 1px solid rgba(220, 53, 69, .3);
    color: #c82333;
    border-radius: 999px;
    font-size: .82rem;
    font-weight: 600;
    min-height: 44px;
    padding: .4rem .95rem;
}
.claim-cancel-btn:hover {
    background: var(--ideal-danger);
    border-color: var(--ideal-danger);
    color: #fff;
}
.claim-cancel-btn:disabled { opacity: .5; }
[data-bs-theme="dark"] .claim-cancel-btn {
    background: rgba(220, 53, 69, .16);
    border-color: rgba(248, 113, 113, .4);
    color: #f87171;
}
[data-bs-theme="dark"] .claim-cancel-btn:hover { background: var(--ideal-danger); color: #fff; }
.countdown-chip {
    display: inline-flex; align-items: center; gap: .35rem;
    border-radius: 999px; padding: .3rem .8rem;
    font-size: .8rem; font-weight: 600;
    background: rgba(255, 193, 7, .18); color: #a9791c;
}
.countdown-chip.locked { background: rgba(108, 117, 125, .14); color: var(--ideal-text-muted); }
.countdown-chip.rejected { background: rgba(220, 53, 69, .14); color: #c82333; }
[data-bs-theme="dark"] .countdown-chip { background: rgba(255, 193, 7, .2); color: #fbbf24; }
[data-bs-theme="dark"] .countdown-chip.locked { background: rgba(148, 163, 184, .18); color: #cbd5e1; }
[data-bs-theme="dark"] .countdown-chip.rejected { background: rgba(220, 53, 69, .22); color: #f87171; }

/* Line-items disclosure: pill summary, no marker */
.pcard details > summary {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    font-size: .82rem;
    font-weight: 600;
    color: var(--ideal-teal-dark);
    background: var(--icl-teal-tint);
    border: 1px solid rgba(92, 189, 189, .4);
    border-radius: 999px;
    padding: .35rem .9rem;
    min-height: 36px;
    list-style: none;
    transition: background-color .15s ease;
}
.pcard details > summary:hover { background: rgba(92, 189, 189, .22); }
.pcard details > summary::-webkit-details-marker { display: none; }
.pcard details > summary::before { content: "\25B8"; margin-right: .4rem; }
.pcard details[open] > summary::before { content: "\25BE"; }
.pcard details[open] > summary { margin-bottom: .5rem; }
[data-bs-theme="dark"] .pcard details > summary { color: var(--ideal-teal-light); }

/* === Tables (inside cards): iCRM-style micro headers + hover accent === */
.pcard .table th {
    background: var(--icl-surface-2);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .72rem;
    font-weight: 600;
    color: var(--icl-label);
    border-bottom: 1px solid var(--icl-hairline);
    padding: .6rem 1rem;
    white-space: nowrap;
}
.pcard .table td { border-bottom: 1px solid var(--icl-hairline); padding: .7rem 1rem; }
.pcard .table tbody tr:last-child td { border-bottom: none; }
.pcard .table tbody tr {
    transition: background-color .18s ease, box-shadow .18s ease;
    box-shadow: inset 3px 0 0 transparent;
}
.pcard .table tbody tr:hover {
    background: var(--icl-teal-tint);
    box-shadow: inset 3px 0 0 var(--ideal-teal);
}
.pcard.p-0 { overflow: hidden; }  /* keep rounded corners on full-bleed tables */
.pcard .table { --bs-table-bg: transparent; margin-bottom: 0; }

/* Expandable line-item detail rows (payments) — no hover accent on these */
.pcard .table tbody tr.pay-lines-row,
.pcard .table tbody tr.pay-lines-row:hover { background: transparent; box-shadow: none; }
.pay-lines {
    background: var(--icl-surface-2);
    border-bottom: 1px solid var(--icl-hairline);
    padding: .35rem .75rem .75rem;
}
.pay-lines .table th { background: transparent; }

/* === Donuts (SVG) === */
.donut-wrap { text-align: center; }
.donut-wrap .pct { font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.donut-wrap .lbl { color: var(--ideal-text-muted); font-size: .8rem; }
.donut-track { stroke: var(--donut-track); }
@keyframes icl-donut { from { stroke-dasharray: 0 100; } }
.donut-value { animation: icl-donut .8s cubic-bezier(.22, .8, .36, 1) both; }

/* === Budget progress bars (plan page) === */
.budget-bar {
    height: 8px;
    border-radius: 999px;
    background: var(--donut-track);
    overflow: hidden;
    margin: .25rem 0 .75rem;
}
.budget-bar .fill {
    height: 100%;
    border-radius: 999px;
    background: var(--ideal-gradient-primary);
    transform-origin: left;
    animation: icl-grow .7s cubic-bezier(.22, .8, .36, 1) both;
}
@keyframes icl-grow { from { transform: scaleX(0); } }
.budget-bar .fill.low { background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%); }

/* === Buttons: soft radius, gradient primary, press feedback === */
.btn {
    min-height: 44px;
    /* Flex-centre the label: with only min-height, icon + text sit high */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    border-radius: var(--icl-radius-sm);
    font-weight: 500;
    transition: transform .15s ease, box-shadow .2s ease, background-color .2s ease, background-image .2s ease;
}
.btn-sm { min-height: 0; border-radius: .5rem; }
.btn-primary {
    background-image: linear-gradient(135deg, #66c8c8 0%, #4faaaa 100%);
    border: none;
    box-shadow: 0 1px 2px rgba(74, 153, 153, .25);
}
.btn-primary:hover, .btn-primary:focus {
    background-image: linear-gradient(135deg, #4faaaa 0%, #3f9494 100%);
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(74, 153, 153, .35);
}
.btn-primary:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(74, 153, 153, .3); }
.btn:not(.btn-link):active { transform: translateY(0) scale(.985); }
.btn-outline-primary { color: var(--ideal-teal-dark); border-color: var(--ideal-teal); }
.btn-outline-primary:hover {
    background: var(--ideal-teal);
    border-color: var(--ideal-teal);
    color: #fff;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(74, 153, 153, .3);
}
[data-bs-theme="dark"] .btn-outline-primary { color: var(--ideal-teal-light); }
[data-bs-theme="dark"] .btn-outline-primary:hover { color: #10312f; }

/* === Forms === */
.form-control, .form-select { min-height: 44px; border-radius: var(--icl-radius-sm); border-color: #e3e8ea; }
[data-bs-theme="dark"] .form-control, [data-bs-theme="dark"] .form-select { border-color: #2b3138; }
.form-control:focus, .form-select:focus {
    border-color: var(--ideal-teal);
    box-shadow: 0 0 0 .2rem rgba(92, 189, 189, .25);
}
input[type="search"].form-control { border-radius: 999px; padding-left: 1.1rem; }
textarea.form-control { min-height: 7rem; }

/* Teal checkboxes / radios / switches */
.form-check-input:checked {
    background-color: var(--ideal-teal);
    border-color: var(--ideal-teal);
}
.form-check-input:focus {
    border-color: var(--ideal-teal);
    box-shadow: 0 0 0 .25rem rgba(92, 189, 189, .25);
}
.form-switch .form-check-input { height: 1.4em; width: 2.6em; }
.form-check.form-switch { display: flex; align-items: center; gap: .65rem; }
.form-check.form-switch .form-check-label { padding-top: .1rem; }

/* Focus visibility for keyboard + switch users */
a:focus-visible, button:focus-visible, .btn:focus-visible {
    outline: 3px solid var(--ideal-teal-dark);
    outline-offset: 2px;
    box-shadow: none;
}

/* === Badges → soft pills === */
.badge { border-radius: 999px; font-weight: 600; padding: .35em .75em; }
.badge.text-bg-success { background: rgba(40, 167, 69, .14) !important; color: #1e7e34 !important; }
.badge.text-bg-danger  { background: rgba(220, 53, 69, .14) !important; color: #c82333 !important; }
.badge.text-bg-warning { background: rgba(255, 193, 7, .20) !important; color: #a9791c !important; }
.badge.text-bg-secondary { background: rgba(108, 117, 125, .15) !important; color: #5c636a !important; }
.badge.text-bg-info    { background: rgba(23, 162, 184, .15) !important; color: #117a8b !important; }
[data-bs-theme="dark"] .badge.text-bg-success { background: rgba(40, 167, 69, .22) !important; color: #4ade80 !important; }
[data-bs-theme="dark"] .badge.text-bg-danger  { background: rgba(220, 53, 69, .22) !important; color: #f87171 !important; }
[data-bs-theme="dark"] .badge.text-bg-warning { background: rgba(255, 193, 7, .22) !important; color: #fbbf24 !important; }
[data-bs-theme="dark"] .badge.text-bg-secondary { background: rgba(148, 163, 184, .20) !important; color: #cbd5e1 !important; }
[data-bs-theme="dark"] .badge.text-bg-info    { background: rgba(23, 162, 184, .22) !important; color: #22d3ee !important; }

/* === Alerts: soft, borderless, rounded === */
.alert {
    border: none;
    border-radius: var(--icl-radius);
    box-shadow: var(--icl-shadow-soft);
}
.alert-info { background: rgba(23, 162, 184, .1); color: #0f6674; }
[data-bs-theme="dark"] .alert-info { background: rgba(23, 162, 184, .16); color: #7dd3e0; }
.alert-info .bi { color: var(--ideal-info); }

/* === Modals: iCRM chrome (clean header, deep shadow, scale-in) === */
.modal-content {
    border: none;
    border-radius: var(--icl-radius);
    box-shadow: 0 24px 64px rgba(16, 24, 40, .24);
    overflow: hidden;
    background: var(--icl-surface);
}
.modal .modal-header { background: var(--icl-surface); border-bottom: 1px solid var(--icl-hairline); padding: 1.1rem 1.5rem; }
.modal .modal-title { display: flex; align-items: center; gap: .5rem; color: var(--ideal-teal-dark); font-weight: 700; }
[data-bs-theme="dark"] .modal .modal-title { color: var(--ideal-teal-light); }
.modal .modal-body { padding: 1.4rem 1.5rem; }
.modal .modal-footer { background: var(--icl-surface-2); border-top: 1px solid var(--icl-hairline); padding: 1rem 1.5rem; }
.modal.fade .modal-dialog { transform: scale(.96) translateY(8px); opacity: 0; transition: transform .2s ease-out, opacity .2s ease-out; }
.modal.show .modal-dialog { transform: scale(1) translateY(0); opacity: 1; }
/* A <form class="modal-content"> must still lay out header/body/footer correctly
   with .modal-dialog-scrollable (flex children). */
.modal-content > form { display: contents; }

/* Modal field labels: small muted captions; the value is the prominent element */
.modal-body .form-label {
    font-size: .7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--icl-label);
    margin-bottom: .1rem;
}
/* Material-style underline inputs inside modal forms (cleaner than boxed) */
.modal-body .form-control:not(textarea):not([type="file"]),
.modal-body .form-select {
    border-width: 0 0 1px;
    border-radius: 0;
    background-color: transparent;
    padding-left: .25rem;
    font-size: .95rem;
}
.modal-body .form-control:not(textarea):not([type="file"]):focus,
.modal-body .form-select:focus {
    border-bottom-color: var(--ideal-teal);
    border-bottom-width: 2px;
    box-shadow: none;
    background-color: transparent;
}
/* Textareas + file inputs keep a real box */
.modal-body textarea.form-control {
    border-width: 1px;
    border-radius: var(--icl-radius-sm);
    background-color: rgba(0, 0, 0, .02);
    padding: .5rem .75rem;
}
[data-bs-theme="dark"] .modal-body textarea.form-control { background-color: rgba(255, 255, 255, .04); }
.modal-body textarea.form-control:focus {
    border-color: var(--ideal-teal);
    box-shadow: 0 0 0 .2rem rgba(92, 189, 189, .15);
    background-color: transparent;
}

/* === Segmented view tabs (plan page: Budgets | Spending by supplier) === */
.seg-tabs {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    background: var(--icl-surface);
    border: 1px solid var(--icl-hairline);
    border-radius: 999px;
    box-shadow: var(--icl-shadow-soft);
}
.seg-tabs button {
    border: none;
    background: transparent;
    border-radius: 999px;
    padding: .45rem 1.05rem;
    min-height: 40px;
    font-size: .88rem;
    font-weight: 600;
    color: var(--ideal-text-muted);
    cursor: pointer;
    transition: background-color .2s ease, color .2s ease, box-shadow .2s ease;
}
.seg-tabs button:hover { color: var(--ideal-teal-dark); }
.seg-tabs button.active {
    background-image: linear-gradient(135deg, #66c8c8 0%, #4faaaa 100%);
    color: #fff;
    box-shadow: 0 2px 8px rgba(74, 153, 153, .35);
}
[data-bs-theme="dark"] .seg-tabs button:hover { color: var(--ideal-teal-light); }
[data-bs-theme="dark"] .seg-tabs button.active { color: #fff; }

/* === Spending by supplier (plan page) === */
.spend-row { padding: .45rem 0; }
.spend-row + .spend-row { border-top: 1px solid var(--icl-hairline); }
.spend-row .spend-supplier { font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.spend-row .spend-amount { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.spend-bar { height: 6px; margin: .35rem 0 0; }
.spend-bar .fill { background: var(--ideal-gradient-primary); }

/* === Funding periods (plan category modal) === */
.fp-table {
    border: 1px solid var(--icl-hairline);
    border-radius: var(--icl-radius-sm);
    overflow: hidden;
}
.fp-table .table { --bs-table-bg: transparent; }
.fp-table .table th {
    background: var(--icl-surface-2);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .7rem;
    font-weight: 600;
    color: var(--icl-label);
    padding: .55rem .85rem;
    border-bottom: 1px solid var(--icl-hairline);
    white-space: nowrap;
}
.fp-table .table td {
    padding: .6rem .85rem;
    border-bottom: 1px solid var(--icl-hairline);
    font-variant-numeric: tabular-nums;
}
.fp-table .table tbody tr:last-child td { border-bottom: 0; }
.fp-table .table tbody tr:hover { background: var(--icl-teal-tint); }
.fp-table .table tbody tr.fp-current td { background: var(--icl-teal-tint); font-weight: 600; }

/* Phone list variant: one compact card per period, status via left accent */
.fp-list { display: flex; flex-direction: column; gap: .5rem; }
.fp-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .75rem;
    border: 1px solid var(--icl-hairline);
    border-left: 3px solid var(--ideal-warning);
    border-radius: var(--icl-radius-sm);
    padding: .55rem .75rem;
    background: var(--icl-surface-2);
}
.fp-item.released { border-left-color: var(--ideal-success); }
.fp-item.current { background: var(--icl-teal-tint); }
.fp-item .fp-dates { font-weight: 600; font-size: .9rem; font-variant-numeric: tabular-nums; }
.fp-item .fp-meta { color: var(--ideal-text-muted); font-size: .78rem; }
.fp-item .fp-amount { font-weight: 700; font-variant-numeric: tabular-nums; }

/* Mobile enquiry cards: the whole card is the link */
.enquiry-card { color: inherit; text-decoration: none; }
.enquiry-card:hover { color: inherit; }

/* === Empty states === */
/* Invoices that have arrived but are not bills yet.
   Deliberately quieter than a real invoice row: there is no amount to show and
   nothing to click, so it must not look like a row that has been disabled.
   Own list rather than .list-group-flush, whose borders and background are
   Bootstrap's card, not .pcard's. */
.pending-list { list-style: none; margin: 0; padding: 0; }
.pending-list li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .65rem 0;
    border-top: 1px solid var(--icl-hairline);
}
.pending-list li:first-child { border-top: none; }
.pending-date { font-weight: 600; }
.pending-ref {
    color: var(--ideal-text-muted);
    font-size: .82rem;
    overflow-wrap: anywhere;
}
/* Teal rather than one of the status colours. This is not a billing status and
   must not be mistaken for one: green reads as paid, amber as outstanding. */
.badge-received {
    background: var(--icl-teal-tint);
    color: var(--ideal-teal-dark);
    border: 1px solid rgba(92, 189, 189, .35);
    border-radius: 999px;
    font-weight: 600;
    white-space: nowrap;
    flex-shrink: 0;
}
[data-bs-theme="dark"] .badge-received { color: var(--ideal-teal-light); }

.empty-state {
    text-align: center;
    padding: 2.25rem 1rem;
    color: var(--ideal-text-muted);
}
.empty-state .bi {
    display: block;
    font-size: 2.2rem;
    margin-bottom: .5rem;
    color: var(--ideal-teal);
    opacity: .55;
}

/* === Pagination === */
.pagination .page-link { border-radius: .5rem; margin: 0 2px; border-color: var(--icl-hairline); }

/* === Auth pages === */
.auth-shell { min-height: 100vh; display: flex; align-items: stretch; }
.auth-side {
    display: none;
    background: var(--icl-nav-grad);
    color: #fff;
    width: 300px;
    padding: 2.5rem 2rem;
    position: relative;
    overflow: hidden;
}
.auth-side::after {
    content: "";
    position: absolute;
    right: -70px; bottom: -70px;
    width: 240px; height: 240px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .08);
}
.auth-side::before {
    content: "";
    position: absolute;
    right: -20px; bottom: 60px;
    width: 120px; height: 120px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .07);
}
.auth-side .auth-logo { font-size: 1.6rem; font-weight: 800; letter-spacing: -.5px; margin-bottom: 2.5rem; }
.auth-side .auth-tagline { font-size: 1.9rem; font-weight: 700; line-height: 1.25; letter-spacing: -.02em; }
.auth-side .auth-sub { margin-top: 1rem; font-size: .95rem; color: rgba(255, 255, 255, .85); font-weight: 400; }
@media (min-width: 768px) { .auth-side { display: block; } }
.auth-main { flex: 1; display: flex; flex-direction: column; padding: 1.5rem; max-width: 640px; margin: 0 auto; }
.auth-main > * { animation: icl-rise .32s ease both; }
.auth-topline { display: flex; justify-content: flex-end; align-items: center; gap: .5rem; margin-bottom: 1.5rem; }
.auth-topline .btn-group .btn { min-width: 100px; }
.auth-main h1 { color: var(--ideal-teal-dark); font-weight: 700; }
[data-bs-theme="dark"] .auth-main h1 { color: var(--ideal-teal-light); }
.auth-main fieldset.pcard legend { font-weight: 700; color: var(--ideal-teal-dark); }
[data-bs-theme="dark"] .auth-main fieldset.pcard legend { color: var(--ideal-teal-light); }

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

/* Expander chevrons: point down when closed, up when open. Bootstrap's
   collapse plugin owns aria-expanded, so the CSS follows it rather than
   needing any JS of its own. */
[data-bs-toggle="collapse"] .bi-chevron-down {
  transition: transform 0.15s ease-in-out;
}
[data-bs-toggle="collapse"][aria-expanded="true"] .bi-chevron-down {
  transform: rotate(180deg);
}

/* Row expanders load their content over the network, so their final height is
   not known when the click happens. Bootstrap would animate 0.35s toward
   whatever is in the box at that moment — nothing, or a spinner — and then
   snap to the real height once htmx swaps the content in. Both read as lag.
   Opening instantly is honest: the height is simply not animatable here. */
.row-expand.collapsing {
  transition: none;
}

/* Supplier switcher in the sidebar. Only rendered above one linked account.
   A ghost button rather than a form control: a white <select> slab fought the
   sidebar, and a native select cannot wrap, so long provider names clipped. */
.sidenav-switcher {
  padding: 0.25rem 1rem 0.75rem;
}
.sidenav-switcher .switcher-label {
  display: block;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-bottom: 0.1rem;
}
.sidenav-switcher .switcher-toggle {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
  width: 100%;
  padding: 0.15rem 0 0.4rem;
  background: none;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.28);
  color: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.25;
  text-align: left;
}
.sidenav-switcher .switcher-toggle:hover,
.sidenav-switcher .switcher-toggle:focus-visible {
  border-bottom-color: rgba(255, 255, 255, 0.7);
}
/* The name wraps; the chevron stays put on the first line. */
.sidenav-switcher .switcher-name {
  flex: 1;
}
.sidenav-switcher .switcher-toggle .bi-chevron-down {
  font-size: 0.75rem;
  margin-top: 0.2rem;
  transition: transform 0.15s ease-in-out;
}
.sidenav-switcher .switcher-toggle[aria-expanded="true"] .bi-chevron-down {
  transform: rotate(180deg);
}
.switcher-menu {
  min-width: 15rem;
  max-width: 20rem;
}
.switcher-menu .dropdown-item {
  white-space: normal;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}
/* Bootstrap's .active is its own blue, which fights the brand teal. */
.switcher-menu .dropdown-item.active,
.switcher-menu .dropdown-item:active {
  background-color: var(--bs-tertiary-bg);
  color: inherit;
  font-weight: 600;
}
.switcher-menu .dropdown-item.active .bi-check2 {
  color: var(--ip-teal, #4aa8a3);
}
.sidenav-collapsed .sidenav-switcher {
  display: none;
}

/* Account page: each account is a collapsible header when there is more than
   one. Content is already in the DOM, so the collapse animation is honest
   here — unlike the network-loaded row expanders, whose height is unknown. */
.account-toggle {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  text-align: left;
}
.account-toggle .bi-chevron-down {
  font-size: 0.8rem;
  opacity: 0.6;
  transition: transform 0.15s ease-in-out;
}
.account-toggle[aria-expanded="true"] .bi-chevron-down {
  transform: rotate(180deg);
}

/* === Data tables as cards on a phone === */
/* A .table-responsive stops a wide table breaking the page, but it does not
   make it readable: eight columns squeezed into 390px wraps "31 Aug 2026" onto
   three lines and hides Status and Amount behind a sideways scroll nobody
   notices. Below the tablet breakpoint each row becomes a card instead, with
   the column heading carried in data-label on the cell.
   One source of markup, two layouts, and no duplicate mobile table to keep in
   step with the real one.

   The breakpoint is lg, not md, and matches the hand-written d-lg-none card
   lists on Invoices, Payments and Clients. Those used to switch at md, but a
   seven-column table is still unreadable at 900px — squeezed columns, dates
   broken across three lines, and the last two columns hidden behind a
   sideways scroll nobody notices. */
@media (max-width: 991.98px) {
    .table-cards,
    .table-cards tbody,
    .table-cards tr,
    .table-cards td { display: block; width: 100%; }
    .table-cards thead { display: none; }
    .table-cards tbody tr {
        border: 1px solid var(--icl-hairline);
        border-radius: var(--icl-radius-sm);
        padding: .8rem .9rem;
        margin-bottom: .6rem;
        background-color: var(--bs-body-bg);
    }
    .table-cards tbody tr:last-child { margin-bottom: 0; }
    .table-cards td {
        border: 0 !important;
        padding: .22rem 0 !important;
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: .35rem 1rem;
        text-align: right;
        /* A value longer than the room left beside its label drops to the next
           line rather than pushing out of the card: supplier names and invoice
           numbers are both long enough to do it. `anywhere` covers the ones
           with no space to break at. */
        flex-wrap: wrap;
        overflow-wrap: anywhere;
    }
    /* A flex item will not shrink below its own content unless told to. */
    .table-cards td > * { min-width: 0; }
    .table-cards td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        text-align: left;
        color: var(--ideal-text-muted);
        font-size: .74rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .02em;
    }
    /* The identifying cell reads as the card's heading, not a labelled row. */
    .table-cards td[data-primary] {
        display: block;
        text-align: left;
        font-size: 1.05rem;
        font-weight: 600;
        padding-bottom: .45rem !important;
    }
    .table-cards td[data-primary]::before { content: none; }
    /* Dates and money are short and must never wrap mid-value. */
    .table-cards td[data-nowrap] { white-space: nowrap; }
    /* Its own row, so an action button is not squashed against a label. */
    .table-cards td[data-actions] { justify-content: flex-end; padding-top: .5rem !important; }
    .table-cards td[data-actions]::before { content: none; }
    /* The wrapper has nothing left to scroll once the rows are blocks. */
    .table-responsive:has(.table-cards) { overflow-x: visible; }
}

/* A flex item's default min-width is auto, so it refuses to shrink below its
   own content and pushes its siblings out of the row. Bootstrap 5.3 ships
   .min-w-0 for this; this project is on an earlier build, so it is defined
   here rather than upgrading Bootstrap for one utility. */
.min-w-0 { min-width: 0; }

/* === Segmented passcode input === */
/* Cells drawn over one real <input> — see static/js/pincode.js. Sized and
   coloured from the same tokens as .form-control, so the row reads as a field
   of this product rather than a widget that wandered in from another one. */
/* Block-level, not inline-flex: it replaces a .form-control, and Bootstrap's
   .form-label is inline-block — an inline row would sit alongside the label
   instead of under it. */
.pincode { position: relative; display: flex; flex-wrap: wrap; gap: .5rem; }
.pincode__input {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    opacity: 0; border: 0; padding: 0; margin: 0;
    /* 16px, or iOS zooms the whole page on focus. */
    font-size: 16px;
    cursor: pointer;
}
.pincode__cell {
    width: 3.25rem; height: 3.5rem;
    display: grid; place-items: center;
    border: 1px solid #e3e8ea;
    border-radius: var(--icl-radius-sm);
    background-color: var(--bs-body-bg);
    font-size: 1.4rem; font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--bs-body-color);
    transition: border-color .15s ease, box-shadow .15s ease;
}
[data-bs-theme="dark"] .pincode__cell { border-color: #2b3138; }
.pincode__cell--filled { border-color: var(--ideal-teal); }
/* The one flourish: a filled cell settles rather than snapping in.
   Everything else here is deliberately quiet. */
.pincode--masked .pincode__cell--filled::after {
    content: "";
    width: .7rem; height: .7rem;
    border-radius: 50%;
    background-color: var(--ideal-teal);
    animation: pincode-settle .16s ease-out;
}
@keyframes pincode-settle {
    from { transform: scale(.4); opacity: 0; }
    to   { transform: scale(1); opacity: 1; }
}
/* Deliberately identical to .form-control:focus — same border, same ring. */
.pincode__cell--active {
    border-color: var(--ideal-teal);
    box-shadow: 0 0 0 .2rem rgba(92, 189, 189, .25);
}
@media (prefers-reduced-motion: reduce) {
    .pincode__cell { transition: none; }
    .pincode--masked .pincode__cell--filled::after { animation: none; }
}
@media (max-width: 400px) {
    .pincode { gap: .35rem; }
    .pincode__cell { width: 2.6rem; height: 3.1rem; font-size: 1.2rem; }
}
/* === Overview (provider landing) ===
   Built on the .ov-* vocabulary above. The one new idea here is .ov-split:
   outstanding money is two different things to a provider — approved and
   waiting, versus already in a payment run — and the bar is what makes the
   second half visible at all, since the ledger has already netted it out of
   the balance. Neutral slate advances to brand teal as the money gets closer
   to the bank. */
.ov-hero-amount { font-size: 2.1rem; line-height: 1.15; }
.ov-card .amount { display: block; }
.ov-foot { color: var(--icl-label); font-size: .82rem; margin: .6rem 0 0; }
.ov-hero:hover .ov-hero-amount { color: var(--ideal-teal-dark); }
[data-bs-theme="dark"] .ov-hero:hover .ov-hero-amount { color: var(--ideal-teal-light); }

.ov-split {
    display: flex;
    height: 10px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--icl-teal-tint);
    margin: .9rem 0 .1rem;
}
.ov-split > span { display: block; transition: width .3s ease; }
.ov-split-approved { background: #8a97a3; }
.ov-split-scheduled { background: var(--ideal-teal); }

.ov-legend { display: flex; flex-wrap: wrap; gap: .35rem 1.75rem; margin: .7rem 0 0; }
.ov-legend > div { display: flex; flex-direction: column; gap: .1rem; }
.ov-legend dt {
    display: flex;
    align-items: center;
    gap: .4rem;
    color: var(--icl-label);
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
}
.ov-legend dd { margin: 0; font-weight: 600; }
.ov-dot { width: .55rem; height: .55rem; border-radius: 50%; flex: none; }
.ov-dot-approved { background: #8a97a3; }
.ov-dot-scheduled { background: var(--ideal-teal); }

/* Twelve months always occupy the full width, so the shape of a year is
   comparable between accounts rather than depending on how many months
   happen to carry a payment. */
.ov-spark { display: flex; align-items: flex-end; gap: .35rem; margin-top: .9rem; }
.ov-spark-col { flex: 1 1 0; display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
/* A baseline rather than a filled track: a boxed track gives every month the
   same visual weight, so a year with three payments in it looked like a year
   with twelve. min-height keeps a paid-nothing month as a visible zero instead
   of a gap the eye reads as missing data. */
.ov-spark-track {
    display: flex;
    align-items: flex-end;
    height: 56px;
    border-bottom: 1px solid var(--icl-hairline);
}
.ov-spark-bar {
    width: 100%;
    background: var(--ideal-teal);
    border-radius: var(--icl-radius-sm) var(--icl-radius-sm) 0 0;
    min-height: 2px;
}
/* min-height, not a placeholder character: a blank month must still reserve
   the line, or its label would ride up out of step with the others. */
.ov-spark-value {
    min-height: 1.1em;
    text-align: center;
    font-size: .68rem;
    font-weight: 700;
    color: var(--ideal-teal-dark);
    overflow: hidden;
    white-space: nowrap;
}
[data-bs-theme="dark"] .ov-spark-value { color: var(--ideal-teal-light); }
/* Twelve columns share a phone's width at ~22px each, which cannot hold
   "$461k". Clipping it would show "$46" — a different, smaller number, in a
   place a provider reads money. Drop the row instead; the bars still compare,
   and the exact figure stays on each bar's title. */
@media (max-width: 767.98px) {
    .ov-spark-value { display: none; }
}
.ov-spark-label { text-align: center; color: var(--icl-label); font-size: .68rem; font-weight: 600; }

.ov-section-head { padding: 1.1rem 1.3rem 0; margin-bottom: .6rem; }

/* Budget-check picker (Overview card). Rows are buttons, not links: choosing a
   client opens the check in place rather than navigating away from the page
   the provider is using to decide. */
.picker-wrap { position: relative; }
/* Floating, not in flow: an inline list grew this card, and the financial-year
   card beside it grew too (h-100), so typing a name resized the chart. */
.picker-menu {
    position: absolute;
    top: calc(100% + .3rem);
    left: 0;
    right: 0;
    z-index: 5;
    max-height: 15rem;
    overflow-y: auto;
    padding: .3rem;
    background: var(--icl-surface);
    border: 1px solid var(--icl-hairline);
    border-radius: var(--icl-radius-sm);
    box-shadow: var(--icl-shadow-hover);
}
.picker { display: flex; flex-direction: column; gap: .25rem; }
.picker-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .05rem;
    width: 100%;
    padding: .45rem .6rem;
    text-align: left;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--icl-radius-sm);
    transition: background-color .18s ease, border-color .18s ease;
}
.picker-row:hover,
.picker-row:focus-visible {
    background: var(--icl-teal-tint);
    border-color: var(--ideal-teal);
}
.picker-name { font-weight: 600; }
.picker-ndis { color: var(--icl-label); font-size: .78rem; }

/* The chosen client, shown back as a chip. Replaces the input rather than
   sitting beside it: the input still holds the value that posts, so two
   visible controls for one value would be a lie about which one is real. */
.picker-chip {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .4rem .5rem .4rem .75rem;
    background: var(--icl-teal-tint);
    border: 1px solid var(--ideal-teal);
    border-radius: var(--icl-radius-sm);
}
.picker-chip-text { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.picker-chip-clear {
    margin-left: auto;
    display: flex;
    padding: .25rem;
    line-height: 1;
    color: var(--icl-label);
    background: transparent;
    border: none;
    border-radius: 50%;
}
.picker-chip-clear:hover, .picker-chip-clear:focus-visible {
    color: var(--ideal-teal-dark);
    background: rgba(92, 189, 189, .25);
}
[data-bs-theme="dark"] .picker-chip-clear:hover,
[data-bs-theme="dark"] .picker-chip-clear:focus-visible { color: var(--ideal-teal-light); }

/* Financial-year navigator on the payments card. Chevrons are inert when the
   data does not reach that far, rather than absent — a control that changes
   shape between providers is harder to learn than one that greys out. */
.ov-fy-nav { display: flex; align-items: center; gap: .35rem; font-size: .82rem; }
.ov-fy-label { color: var(--icl-label); font-weight: 600; min-width: 6.5rem; text-align: center; }
.ov-fy-nav a {
    display: flex;
    padding: .15rem .3rem;
    border-radius: var(--icl-radius-sm);
    color: var(--ideal-teal-dark);
}
.ov-fy-nav a:hover, .ov-fy-nav a:focus-visible { background: var(--icl-teal-tint); }
[data-bs-theme="dark"] .ov-fy-nav a { color: var(--ideal-teal-light); }
.ov-fy-stop { padding: .15rem .3rem; color: var(--icl-hairline); }
[data-bs-theme="dark"] .ov-fy-stop { color: #39414a; }

/* Invoice header fields, two-up on anything wider than a phone. Four short
   inputs stacked down a laptop's full width is mostly whitespace, and it pushed
   the line items below the fold. Scoped to a wrapper rather than restyling
   _field.html, which every other form in the app renders through. */
.form-grid {
    display: grid;
    grid-template-columns: 1fr;
    column-gap: 1rem;
}
/* Exactly two, not auto-fit: three columns fitted on a wide screen and put
   Invoice date up beside Participant, which pairs fields that have nothing to
   do with each other. Account | Participant, then the paperwork. */
@media (min-width: 768px) {
    .form-grid { grid-template-columns: 1fr 1fr; }
}
/* Every cell's label row is the same height, so the inputs line up across the
   row whether the cell's heading is a bare label or a label plus a toggle. */
.form-grid .form-label,
.form-grid .field-head { min-height: 1.7rem; }
.form-grid .form-label { display: flex; align-items: center; }
.field-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .2rem;
}
.field-head .form-label { margin-bottom: 0; }
/* Opt one cell out of the two-column grid — a textarea or a lone checkbox
   reads badly in half a row. */
.form-grid-wide { grid-column: 1 / -1; }
/* Labels sit tighter here than the app default: with four of them on screen at
   once the default 8px each read as gaps between unrelated fields. */
.form-grid .form-label,
.line-card .form-label { margin-bottom: .2rem; font-size: .82rem; }

/* Segmented control: a small set of mutually exclusive choices, all visible.
   Hand-built rather than Bootstrap's .btn-group, whose btn-outline-primary is
   a blue that appears nowhere else in this app. Small enough to ride on a
   label line without deepening the row. Used by the participant branch toggle
   and the referral form's contact-for choice. */
.segmented {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    background: var(--icl-teal-tint);
    border-radius: 999px;
}
.segmented label {
    margin: 0;
    padding: .1rem .55rem;
    font-size: .72rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--ideal-teal-dark);
    white-space: nowrap;
    border-radius: 999px;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
[data-bs-theme="dark"] .segmented label { color: var(--ideal-teal-light); }
.segmented label:hover { background: rgba(92, 189, 189, .2); }
.segmented .btn-check:checked + label {
    background: var(--ideal-teal);
    color: #fff;
}
.segmented .btn-check:focus-visible + label {
    outline: 2px solid var(--ideal-teal);
    outline-offset: 1px;
}
/* Offered but unusable beats absent: a control that appears and disappears
   between accounts is harder to learn than one that greys out. */
.segmented .btn-check:disabled + label {
    opacity: .45;
    cursor: not-allowed;
}
.segmented .btn-check:disabled + label:hover { background: transparent; }

/* One field under "Existing", two side by side under "New". */
.participant-fields { display: grid; grid-template-columns: 1fr; gap: .5rem; }
#participant-cell[data-mode="new"] .participant-fields {
    grid-template-columns: 1fr 1fr;
}
#participant-cell[data-mode="existing"] .participant-ndis { display: none; }
/* Under "New" the menu and the chip are inert — the same input is now a plain
   text box, and a suggestion list over it would offer the very clients this
   branch exists to get past. */
#participant-cell[data-mode="new"] .picker-menu,
#participant-cell[data-mode="new"] .picker-chip { display: none !important; }

/* Invoice line items. Cards, not table rows: the support-item menu floats
   (absolute, inside .picker-wrap) and a six-column table needs overflow-x on a
   phone, which clips exactly that menu. Cards stack instead of scrolling
   sideways, so there is no overflow for the menu to escape. */
.line-card {
    padding: .7rem .75rem;
    margin-bottom: .6rem;
    border: 1px solid var(--icl-hairline);
    border-radius: var(--icl-radius-sm);
}
.line-card-head { display: flex; align-items: flex-end; gap: .5rem; }
/* auto-fit rather than fixed columns: five money/date fields fit one row on a
   laptop and wrap to two on a phone without a second breakpoint. */
.line-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: .5rem;
    margin-top: .45rem;
}
/* The date and money fields are keyboard targets in a dense row, not the
   primary tap targets the 44px app default is sized for. */
.line-grid .form-control { min-height: 38px; }
.line-total { font-weight: 600; }
.line-total span { margin-left: .35rem; }
/* The picker's results render into this, and .picker-menu positions itself
   against the .picker-wrap above — so this stays an empty, zero-height hook. */
.si-results { position: relative; }

/* Bank details reveal. The numbers are masked server-side and swapped in by
   portal:reveal_bank, so "revealed" is a state of the fragment, not a class
   toggled over a value the page already holds. */
.bank-actions {
    display: flex;
    align-items: center;
    gap: .6rem;
    justify-content: flex-end;
    margin-top: .15rem;
}
.bank-rows.is-revealed .kv .v {
    font-variant-numeric: tabular-nums;
    letter-spacing: .02em;
}
.bank-countdown { font-variant-numeric: tabular-nums; }

/* "What the answers mean" on the budget check. A quiet affordance beside the
   heading — it explains an answer the provider has not seen yet, so it must
   not compete with the control that produces one. */
.btn-outcomes {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    /* Set, not inherited: the button sits inside an <h2>, and inheriting the
       heading's size would make the icon grow with it. */
    font-size: .95rem;
    line-height: 1;
    color: var(--icl-label);
    background: none;
    border: none;
}
/* bootstrap-icons ships `vertical-align: -.125em` on every icon, which is
   right for one sitting in a run of text and wrong here: inside a flex button
   there is no text baseline to sink to, so it only pushes the glyph ~2px below
   the centre of the heading it is meant to sit beside. */
.btn-outcomes .bi {
    display: block;
    vertical-align: 0;
    line-height: 1;
}
/* Optical, not geometric. align-items:center centres the icon against the
   heading's LINE BOX, which reserves room for descenders the heading barely
   uses — so a glyph centred there reads low against a row of capitals. The
   nudge is in em so it tracks the icon size rather than a fixed pixel count.
   transform, not margin, so it moves nothing else in the row. */
.btn-outcomes { transform: translateY(-0.1em); }
.btn-outcomes:hover, .btn-outcomes:focus-visible { color: var(--ideal-teal-dark); }
[data-bs-theme="dark"] .btn-outcomes:hover,
[data-bs-theme="dark"] .btn-outcomes:focus-visible { color: var(--ideal-teal-light); }
/* 24rem is 384px, which does not fit a 390px phone once the arrow and the
   viewport padding are counted — the panel hung off the left edge with its
   first words cut off. Keeps its comfortable width on a desktop and shrinks to
   the screen below that. */
.outcomes-popover { max-width: min(24rem, calc(100vw - 1.5rem)); }
.outcome-list { display: flex; flex-direction: column; gap: .5rem; margin: 0; padding: 0; list-style: none; }
.outcome-list li { display: flex; flex-direction: column; gap: .15rem; }
.outcome-list span:last-child { color: var(--icl-label); font-size: .82rem; }

/* Referral form. Section headings rather than one long run of fields: the
   form asks two separate questions — who is being referred, and who to ring
   about them — and they are often different people. */
.form-section {
    margin: .9rem 0 .5rem;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--icl-label);
}
.form-grid + .form-section { margin-top: .3rem; }
/* The consent tick, set apart from the fields above it — it is an assertion
   about someone else's data, not another detail of the referral. */
.consent-row {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    margin-top: .3rem;
    padding: .7rem .85rem;
    background: var(--icl-teal-tint);
    border-radius: var(--icl-radius-sm);
}
.consent-row input { margin-top: .15rem; flex: none; }
.consent-row label { margin: 0; }

/* Staff act-as. Deliberately loud: a staff member who forgets they are
   impersonating is how a support call ends with the wrong provider's numbers
   being read out. */
.acting-bar {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .5rem 1.3rem;
    color: #fff;
    background: #8a5a00;
    font-size: .85rem;
}
.acting-bar form { margin-left: auto; }
.acting-bar .btn {
    color: #fff;
    border: 1px solid rgba(255, 255, 255, .6);
    padding: .1rem .6rem;
}
.acting-bar .btn:hover { background: rgba(255, 255, 255, .15); color: #fff; }
/* On desktop the sidenav is a floating rounded panel inset from the viewport,
   so a full-bleed bar with square corners butts against it and reads as a
   different surface rather than a sibling. Same margin rhythm (.75rem), and
   the card radius rather than the sidenav's 1.25rem: this bar is one line
   tall, and the larger radius on that height turns the ends into a stadium.
   Left untouched below 992px, where there is no floating panel to sit beside
   and full width serves the warning better. */
@media (min-width: 992px) {
    .acting-bar {
        margin: .75rem .75rem 0;
        border-radius: var(--icl-radius);
        box-shadow: var(--icl-shadow-soft);
    }
}
.staff-bar {
    display: flex;
    align-items: center;
    /* Wraps rather than pushing Sign out off the right: a Microsoft SSO
       address is long, and a flex item does not shrink below its own content
       unless told to. Row gap for when it does wrap. */
    flex-wrap: wrap;
    gap: .4rem .75rem;
    padding: .6rem 1.3rem;
    border-bottom: 1px solid var(--icl-hairline);
}
.staff-bar-label { font-weight: 700; flex: 0 0 auto; }

/* The supplier state panel, rendered both as a page and inside a modal. The
   sections used to be bare h2s over an unpadded list, which on a two-row page
   read as a lot of nothing; these give the two lists the same card surface the
   rest of the portal uses and put the status where the eye lands. */
.staff-section-label {
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--icl-label);
    margin-bottom: .15rem;
}
.staff-row-title { font-weight: 600; word-break: break-word; }
.staff-row-main { min-width: 0; }
.staff-rows .list-group-item { padding: .8rem 1rem; background: transparent; }

/* The address is the part that gives: it can be truncated and still identify
   who is signed in, whereas Sign out cannot be half a button. */
.staff-bar .staff-bar-email {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The two staff view modes, as a segmented control. Anchors rather than
   buttons: each mode is its own URL with its own search, so this is
   navigation, not a form control — which also means it works with no JS and
   survives a back button. */
.staff-modes {
    display: inline-flex;
    gap: .25rem;
    padding: .25rem;
    margin-bottom: 1rem;
    border: 1px solid var(--icl-hairline);
    border-radius: .6rem;
}
.staff-mode {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .35rem .9rem;
    border-radius: .45rem;
    font-size: .9rem;
    font-weight: 600;
    color: var(--bs-secondary-color, #6c757d);
    text-decoration: none;
    white-space: nowrap;
}
.staff-mode:hover { color: var(--bs-body-color); }
.staff-mode.is-active {
    /* The brand gradient the primary buttons use, not --bs-primary — that
       token is still Bootstrap's blue in this theme and looked nothing like
       the rest of the page. */
    background-image: linear-gradient(135deg, #66c8c8 0%, #4faaaa 100%);
    color: #fff;
    box-shadow: 0 1px 2px rgba(74, 153, 153, .25);
}
.staff-mode.is-active:hover { color: #fff; }

