/* ============================================================================
   app-ui.css — shared design system (loaded globally from header.html)
   Built on the existing theme tokens (--bs-*, primary #574fec, Inter, dark mode).
   Page-specific styles still live in common.css / per-page CSS.
   ========================================================================== */

:root {
    --app-primary-rgb: 87, 79, 236;            /* #574fec */
    --app-accent: #574fec;                     /* accent used as text/icon/border (brand in light) */
    --app-radius: 1rem;
    --app-radius-lg: 1.5rem;
    --app-radius-md: .6rem;   /* inputs, secondary panels, nested cards */
    --app-radius-sm: .4rem;   /* small chips, time inputs */
    --app-shadow: 0 .5rem 1.5rem rgba(13, 18, 41, .06);
    --app-shadow-lg: 0 1rem 2.5rem rgba(13, 18, 41, .10);
    --app-hero: linear-gradient(135deg, #574fec 0%, #463fbd 100%);
}

/* ============================================================================
   Light theme refinements — pull the indigo brand through the neutrals so the
   theme reads as one cohesive "white + indigo" system. Cards stay white and pop
   on a faintly-tinted canvas. Scoped to [data-bs-theme="light"] (the head FOUC
   script always sets an explicit theme). Dark is overridden separately below.
   ========================================================================== */
[data-bs-theme="light"] {
    --bs-secondary-bg: #eeedf8;            /* faint indigo (was cool #f1f4f8) */
    --bs-tertiary-bg: #f4f3fb;             /* faint indigo (was cool #f9fbfd) */
    --bs-border-color: #e7e5f5;            /* faint indigo (was cool #dde4ea) */
    --bs-emphasis-color: #1c0950;          /* indigo-ink headings, not pure #000 */
    --bs-emphasis-color-rgb: 28, 9, 80;
    --bs-heading-color: var(--bs-emphasis-color);   /* realise the indigo-ink heading intent (Bootstrap default = inherit body colour) */
    --app-shadow: 0 .5rem 1.5rem rgba(87, 79, 236, .10);     /* soft indigo lift (was navy) */
    --app-shadow-lg: 0 1rem 2.5rem rgba(87, 79, 236, .14);
    --app-hero: linear-gradient(135deg, #5b53f0 0%, #3a31ad 100%);   /* richer indigo, tied to the footer */
    /* --bs-body-bg stays #ffffff so cards/surfaces pop against the tinted canvas */
}
/* Faintly-indigo page canvas; the white cards (which use --bs-body-bg) pop on it.
   Studios keep crisp white — their shell paints var(--ss-canvas)=var(--bs-body-bg) over body. */
[data-bs-theme="light"] body { background-color: #f7f6fd; }

/* ============================================================================
   Dark theme — "Warm Charcoal & Indigo". Overrides Bootstrap's dark token
   ladder in this late-loading layer (wins the cascade vs core.min.css at equal
   specificity — no core edits). Warm near-black base, a perceptible elevation
   ladder, one accessible border, and a brighter on-dark indigo for links/icons.
   Brand #574fec stays a FILL colour (white text = 5.62:1); it fails as text on
   the dark base, so accent-as-text/icon routes through #9a90f7. Each hex is
   paired with its -rgb companion so components using rgba(var(--…-rgb)) don't
   ghost back to the old navy.
   ========================================================================== */
[data-bs-theme="dark"] {
    /* base */
    --bs-body-bg: #17171b;            --bs-body-bg-rgb: 23, 23, 27;
    --bs-body-color: #ece9e3;         --bs-body-color-rgb: 236, 233, 227;
    --bs-emphasis-color: #fbfaf8;     --bs-emphasis-color-rgb: 251, 250, 248;
    --bs-heading-color: var(--bs-emphasis-color);     /* crisp near-white headings (was inheriting the dimmer body off-white) */
    --bs-secondary-color: rgba(236, 233, 227, .66);   --bs-secondary-color-rgb: 236, 233, 227;

    /* surfaces — tertiary = raised card (mid), secondary = highest (lightest) */
    --bs-tertiary-bg: #202024;        --bs-tertiary-bg-rgb: 32, 32, 36;
    --bs-secondary-bg: #2a2a30;       --bs-secondary-bg-rgb: 42, 42, 48;

    /* one accessible border (3.06:1) — single token used for cards AND inputs/tables */
    --bs-border-color: #646470;

    /* accent: brand fill stays #574fec; links / icons / focus use the bright sibling */
    --bs-primary: #574fec;
    --bs-link-color: #9a90f7;         --bs-link-color-rgb: 154, 144, 247;
    --bs-link-hover-color: #b3acf9;   --bs-link-hover-color-rgb: 179, 172, 249;
    --bs-primary-text-emphasis: #9a90f7;

    /* app layer */
    --app-accent: #9a90f7;
    --app-primary-rgb: 154, 144, 247;        /* re-lights every rgba(var(--app-primary-rgb), …) soft fill + --ss-accent-soft */
    --app-hero: linear-gradient(135deg, #5a4fe0 0%, #3a31ad 100%);
    --app-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .5);
    --app-shadow-lg: 0 1rem 2.5rem rgba(0, 0, 0, .6);
}

/* Headings inside explicitly inverted/coloured surfaces (the hero gradient, the
   dark footer, any .text-white card) must keep white text. Without this they'd
   pick up the indigo-ink heading colour above and vanish on the dark background. */
.text-white, .app-hero { --bs-heading-color: #fff; }

/* The vendored Bootstrap-3 theme hardcodes .modal-content to a white background,
   so every Bootstrap modal (Terms, SignupTerms, the studio dialogs) renders white
   with light dark-theme text — invisible headings. Re-theme the surface + chrome
   borders for dark mode. (Custom .ws-modal/.ms-rail overlays handle their own.) */
[data-bs-theme="dark"] .modal-content { background-color: var(--bs-tertiary-bg); border-color: var(--bs-border-color); color: var(--bs-body-color); }
[data-bs-theme="dark"] .modal-header, [data-bs-theme="dark"] .modal-footer { border-color: var(--bs-border-color); }

/* ---- Sticky header chrome ---- */
.app-header {
    position: sticky;
    top: 0;
    z-index: 1030;
    background: color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
    backdrop-filter: saturate(1.1) blur(8px);
    border-bottom: 1px solid var(--bs-border-color);
}
@supports not (backdrop-filter: blur(1px)) {
    .app-header { background: var(--bs-body-bg); }
}
/* The theme sets #header{background:#fff; z-index:10} via ID selectors that beat
   the .app-header class — re-assert both via #header.app-header so the bar follows
   the theme (translucent + blurred, not permanently white) AND clears page overlays
   like the Minutes deck (z-index:1020). Panels/backdrops (1035+) still sit above. */
#header.app-header {
    z-index: 1031;
    background: color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
}
@supports not (backdrop-filter: blur(1px)) {
    #header.app-header { background: var(--bs-body-bg); }
}

/* ---- Header layout: brand (left) + actions (right). No navbar/hamburger:
   the logo links home and one settings menu holds language + theme. ---- */
.app-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: 62px;
}

/* Brand lockup → home. Light: square mark + wordmark text. Dark: white wordmark. */
.app-brand {
    display: inline-flex;
    align-items: center;
    gap: .6rem;
    text-decoration: none;
    color: var(--bs-body-color);
    border-radius: var(--app-radius);
    padding: .2rem .3rem;
    transition: opacity .15s ease;
}
.app-brand:hover { opacity: .85; }
.app-brand-mark { display: block; width: 36px; height: 36px; flex: 0 0 auto; }
.app-brand-text { display: flex; flex-direction: column; line-height: 1.04; }
.app-brand-text strong { font-weight: 700; font-size: 1.02rem; letter-spacing: -.01em; color: var(--bs-primary-text-emphasis); }
.app-brand-text span { font-size: .82rem; font-weight: 500; color: var(--bs-primary-text-emphasis); }   /* same crisp colour as the bold word — hierarchy by weight only */
/* Dark: the dark-navy app mark would vanish on the dark bar — seat it on a subtle
   light "chip" so it stays crisp. The wordmark text already adapts via tokens
   (emphasis/secondary colours), so the full lockup stays consistent across themes. */
[data-bs-theme="dark"] .app-brand-mark {
    box-sizing: border-box;
    width: 38px; height: 38px;
    padding: 4px;
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .1);
}

.app-nav-actions { display: inline-flex; align-items: center; gap: .25rem; }

/* Round icon-buttons (settings gear, dev) */
.app-iconbtn {
    width: 40px; height: 40px; flex: 0 0 auto;
    display: inline-grid; place-items: center;
    border: 0; background: transparent; cursor: pointer;
    border-radius: 50%; font-size: 1.15rem; line-height: 1;
    color: var(--bs-body-color);
    transition: background-color .15s ease, color .15s ease;
}
.app-iconbtn:hover, .app-iconbtn:focus-visible,
.app-iconbtn[aria-expanded="true"] {
    background: var(--bs-tertiary-bg);
    color: var(--app-accent);
    outline: none;
}
.app-iconbtn > svg { width: 1.1rem; height: 1.1rem; }

/* Direct header toggles — language (globe + code) and appearance (light/dark/auto) */
.app-lang-btn { width: auto; gap: .3rem; padding: 0 .6rem; border-radius: 999px; }
.app-lang-code { font-size: .72rem; font-weight: 700; letter-spacing: .04em; }
.app-theme-btn .bi { display: none; }
.app-theme-btn:not([data-choice]) .app-theme-ico-auto,
.app-theme-btn[data-choice="light"] .app-theme-ico-light,
.app-theme-btn[data-choice="dark"] .app-theme-ico-dark,
.app-theme-btn[data-choice="system"] .app-theme-ico-auto { display: inline-block; }
/* A hairline that fences the developer tool off from the user controls */
.app-nav-div { width: 1px; height: 1.4rem; margin: 0 .3rem; background: var(--bs-border-color); flex: 0 0 auto; }
.app-dev-btn { color: var(--bs-secondary-color); font-size: 1.05rem; }

/* Settings dropdown (language + theme) */
.app-settings-menu { min-width: 13rem; padding: .35rem; box-shadow: var(--app-shadow-lg); }
.app-settings-menu .dropdown-header {
    font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
    padding: .35rem .6rem .2rem;
}
/* ANCHOR items (header menu, Minutes speaker menus) used to lose these metrics
   to the vendored theme and fall back to block layout + 8px 40px 8px 25px, while
   BUTTON items (workspace row menus) kept them — so the menus never matched each
   other. The culprit is the theme's `.dropdown-menu li:not(.dropdown-item) > a`:
   :not() contributes its argument's specificity, making it (0,2,2) — above the
   plain (0,2,0) selector here, and above a naive `a.app-set-item` (0,2,1) too.
   The `li >` selector below matches that (0,2,2) and, loading later, wins on
   source order — no !important needed. Now every menu item is flex with the
   intended padding, which also makes order/margin-auto on .app-set-ico and
   .app-set-check behave as designed. */
.app-settings-menu .app-set-item,
.app-settings-menu li > a.app-set-item {
    display: flex; align-items: center; gap: .55rem;
    border-radius: .5rem; padding: .45rem .6rem; font-size: .9rem;
}
/* The second selector (0,3,1) exists to beat the theme's
   `.dropdown-menu a.dropdown-item > i { margin-right: 15px }` at (0,2,2), which
   applied to anchor items only and pushed their labels 15px further right than
   button items' — the flex `gap` already handles that spacing. */
.app-settings-menu .app-set-ico,
.app-settings-menu a.app-set-item > .app-set-ico {
    order: 0; font-size: 1rem; width: 1.15rem; text-align: center;
    color: var(--bs-secondary-color); margin-right: 0;
}
.app-settings-menu .app-set-check { order: 2; margin-left: auto; font-size: 1rem; color: var(--app-accent); visibility: hidden; }
.app-settings-menu .app-set-item.is-active .app-set-check { visibility: visible; }
.app-settings-menu .app-set-item.is-active { color: var(--app-accent); font-weight: 600; }
.app-settings-menu .app-set-item.is-active .app-set-ico { color: var(--app-accent); }

@media (max-width: 575.98px) {
    .app-brand-text strong { font-size: .95rem; }
    .app-brand-text span { font-size: .78rem; }
}

/* ---- Premium primary button — indigo gradient + soft glow so it reads as
   designed depth, not a flat bright slab. Both themes. Keep the gradient on
   hover/active (Bootstrap's hover sets background-color via --bs-btn-hover-bg). ---- */
.btn-primary {
    background: linear-gradient(180deg, #6a62f0 0%, #574fec 100%);
    border-color: transparent;
    box-shadow: 0 .35rem .9rem rgba(87, 79, 236, .30);
    transition: transform .15s ease, box-shadow .2s ease, filter .15s ease;
}
/* The vendored scroll-to-top widget renders as `.btn .btn-primary .bg-gradient`.
   `.bg-gradient { background-image: …!important }` overrides the gradient above —
   and since that's a `background` shorthand it also zeroed background-color, leaving
   a transparent button with a white glyph (only its shadow showed). Pin the fill. */
#btnScrollTo.btn-primary { background-color: #574fec !important; }
.btn-primary:hover, .btn-primary:focus-visible {
    background: linear-gradient(180deg, #6a62f0 0%, #574fec 100%);
    border-color: transparent;
    filter: brightness(1.06);
    box-shadow: 0 .5rem 1.1rem rgba(87, 79, 236, .40);
    transform: translateY(-1px);
}
.btn-primary:active, .btn-primary:first-child:active {
    background: linear-gradient(180deg, #574fec 0%, #4a43d6 100%);
    border-color: transparent;
    transform: translateY(0);
    box-shadow: 0 .25rem .6rem rgba(87, 79, 236, .35);
}
@media (prefers-reduced-motion: reduce) {
    .btn-primary, .btn-primary:hover { transform: none; }
}

/* ---- Shared overlay components in dark mode. The vendored theme hardcodes light
   dropdown dividers (#f1f6fa) / active bg (#f9fbfd) and white popovers; re-point
   them at theme tokens so the settings menu AND any other .dropdown-menu/.popover
   (e.g. EditorHeader) read correctly on the dark base. ---- */
[data-bs-theme="dark"] .dropdown-menu {
    --bs-dropdown-bg: var(--bs-secondary-bg);
    --bs-dropdown-color: var(--bs-body-color);
    --bs-dropdown-border-color: var(--bs-border-color);
    --bs-dropdown-link-color: var(--bs-body-color);
    --bs-dropdown-link-hover-color: var(--bs-body-color);
    --bs-dropdown-link-hover-bg: rgba(var(--app-primary-rgb), .16);
    --bs-dropdown-link-active-color: #fff;
    --bs-dropdown-link-active-bg: var(--bs-primary);
    --bs-dropdown-divider-bg: var(--bs-border-color);
    --bs-dropdown-header-color: var(--bs-secondary-color);
}
[data-bs-theme="dark"] .popover {
    --bs-popover-bg: var(--bs-secondary-bg);
    --bs-popover-border-color: var(--bs-border-color);
    --bs-popover-header-bg: var(--bs-secondary-bg);
    --bs-popover-header-color: var(--bs-emphasis-color);
    --bs-popover-body-color: var(--bs-body-color);
}

/* Language selector in the navbar — a clean nav link, not a pill */
.app-lang-btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    line-height: 1.2;
}
.app-lang-btn:hover { color: var(--bs-primary); }

/* Collapsed mobile nav (<992px). The theme renders it as a broken overlay: the
   collapse is a full-screen fixed layer and the list itself is an absolute box
   positioned top:85px relative to the 71px navbar (so it collapses to a clipped
   sliver) with a hardcoded white bg (invisible icons in dark mode). Replace all
   that with a clean dropdown card, using theme variables so it works in light
   and dark. Scoped to <992px, so the desktop navbar is untouched. */
@media (max-width: 991.98px) {
    .navbar-collapse.show {
        position: absolute;
        top: 100%; right: 0; left: auto; bottom: auto;
        height: auto; max-height: 80vh; overflow-y: auto;
        min-width: 13rem;
        margin-top: .25rem;
        background: var(--bs-body-bg);
        border: 1px solid var(--bs-border-color);
        border-radius: var(--app-radius);
        box-shadow: var(--app-shadow-lg, 0 .6rem 1.4rem rgba(13, 18, 41, .18));
        padding: .4rem;
        z-index: 1050;
    }
    /* Reset the list from the theme's absolute clipped scroll-box so it flows
       inside the card and shows every item. */
    .navbar-collapse.show .navbar-nav {
        position: static;
        top: auto; right: auto; bottom: auto; left: auto;
        height: auto; max-height: none; overflow: visible;
        background: transparent; box-shadow: none; padding: 0;
        flex-direction: column; gap: .1rem; width: 100%;
    }
    .navbar-collapse.show .nav-link {
        color: var(--bs-body-color);          /* legible in light AND dark */
        padding: .5rem .65rem; border-radius: .5rem;
    }
    .navbar-collapse.show .nav-link:hover { background: var(--bs-tertiary-bg); color: var(--bs-primary); }
    .navbar-collapse.show .app-lang-btn { color: var(--bs-body-color); background: transparent; }
    /* Hide the theme's in-drawer duplicate logo + close button. */
    .navbar-collapse.show .navbar-xs { display: none !important; }
}

/* ---- Branded hero header (dashboards, admin, interns, etc.) ---- */
.app-hero {
    position: relative;
    background: var(--app-hero);
    color: #fff;
    border-radius: 0 0 var(--app-radius-lg) var(--app-radius-lg);
    padding: 2.25rem 0 2rem;
    margin-bottom: 1.75rem;
    box-shadow: var(--app-shadow);
}
.app-hero a, .app-hero .breadcrumb-item, .app-hero .breadcrumb-item a { color: #fff; }
.app-hero .app-hero-icon {
    display: inline-grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--app-radius);
    background: rgba(255, 255, 255, .18);
    font-size: 1.5rem;
    margin-bottom: .5rem;
}
.app-hero .lead { color: rgba(255, 255, 255, .85); }

/* ---- Surface card ---- */
.app-surface {
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--app-radius);
    box-shadow: var(--app-shadow);
}
.app-surface-hover { transition: transform .2s ease, box-shadow .2s ease; }
.app-surface-hover:hover { transform: translateY(-2px); box-shadow: var(--app-shadow-lg); }

/* ---- Stat card (dashboards / admin / interns) ---- */
.stat-card {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.25rem 1.35rem;
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--app-radius);
    box-shadow: var(--app-shadow);
}
.stat-card .stat-icon {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--app-radius);
    font-size: 1.4rem;
    background: rgba(var(--app-primary-rgb), .12);
    color: var(--bs-primary);
}
.stat-card .stat-value {
    font-size: 1.9rem;
    font-weight: 700;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
    color: var(--bs-body-color);
}
.stat-card .stat-label {
    font-size: .8rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}

/* Accent variants for the stat icon */
.stat-card.is-success .stat-icon { background: rgba(109, 187, 48, .15); color: var(--bs-success); }
.stat-card.is-danger  .stat-icon { background: rgba(246, 78, 96, .15);  color: var(--bs-danger); }
.stat-card.is-info    .stat-icon { background: rgba(115, 231, 247, .18); color: var(--bs-info); }
.stat-card.is-warning .stat-icon { background: rgba(250, 215, 118, .25); color: #b9892b; }

/* ---- Segmented toggle (shared: home console, editor, presets) ---- */
.mode-toggle {
    display: inline-flex;
    gap: .15rem;
    padding: .25rem;
    border-radius: 999px;
    background: var(--bs-tertiary-bg, #f1f4f8);
    transition: opacity .2s ease;
}
.mode-toggle input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}
.mode-toggle label {
    margin: 0;
    padding: .45rem 1.3rem;
    border-radius: 999px;
    font-size: .9rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--bs-secondary-color, #6c757d);
    cursor: pointer;
    user-select: none;
    transition: color .2s ease, background-color .2s ease, box-shadow .2s ease;
}
.mode-toggle input:checked + label {
    background: var(--bs-body-bg, #fff);
    color: var(--bs-primary, #574fec);
    box-shadow: 0 .25rem .7rem rgba(13, 18, 41, .14);
}
.mode-toggle input:focus-visible + label {
    outline: 2px solid var(--bs-primary, #574fec);
    outline-offset: 2px;
}

/* ---- Illustrated empty state ---- */
.app-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .6rem;
    padding: 3rem 1.5rem;
    color: var(--bs-secondary-color);
}
.app-empty .app-empty-icon {
    display: grid;
    place-items: center;
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    background: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
    font-size: 1.8rem;
}
.app-empty h3, .app-empty .h3 { color: var(--bs-body-color); margin: 0; }

/* ---- Table polish ---- */
.app-table { width: 100%; }
.app-table thead th {
    font-size: .78rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
    border-bottom: 1px solid var(--bs-border-color);
    font-weight: 600;
}
.app-table tbody tr { transition: background-color .15s ease; }
.app-table tbody tr:hover { background: var(--bs-tertiary-bg); }
.app-table td, .app-table th { padding: .65rem .75rem; vertical-align: middle; }

/* ---- Footer — theme-aware: deep indigo in light (Refined Midnight Indigo),
   warm near-black in dark (sits naturally on the charcoal body). Stays dark in
   both modes (partner logos are white); accents are translucent-white so they
   read on either background. ---- */
#footer.bg-gray-900 { background-color: #1a1a1f !important; }                                    /* dark mode + no-JS fallback */
[data-bs-theme="light"] #footer.bg-gray-900 { background: linear-gradient(180deg, #171f48 0%, #0c1330 100%) !important; }
#footer { border-top: 1px solid rgba(255, 255, 255, .08); }
#footer hr.bg-gray-500 { background-color: rgba(255, 255, 255, .14) !important; border: 0; }
#footer p { color: rgba(255, 255, 255, .6); }
#footer a.text-gray-400 { color: rgba(255, 255, 255, .72) !important; transition: color .15s ease; }
#footer a.text-gray-400:hover { color: #fff !important; }
#footer .btn.bg-gray-700 { background-color: rgba(255, 255, 255, .1) !important; transition: transform .15s ease, background-color .2s ease; }
#footer .btn.bg-gray-700:hover { background-color: var(--bs-primary) !important; transform: translateY(-2px); }

/* App-shell pages (the studios) set .appShell → the footer becomes a right-hand
   off-canvas "info / about" panel instead of a bottom bar, so the editor fills the
   viewport with no page scroll. Keeps the footer's own dark styling + white logos. */
.app-footer-offcanvas {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 1046;
    width: min(380px, 92vw); overflow-y: auto;
    border-left: 1px solid rgba(255, 255, 255, .1);
    /* Shadow is transparent when closed: the panel only sits at translateX(101%), so a
       visible shadow would bleed ~50px back onto the right edge of every page. Fades in on open. */
    box-shadow: -1rem 0 2.5rem rgba(0, 0, 0, 0);
    transform: translateX(101%);
    transition: transform .24s cubic-bezier(.4, 0, .2, 1), box-shadow .24s cubic-bezier(.4, 0, .2, 1);
}
.app-footer-offcanvas.is-open { transform: none; box-shadow: -1rem 0 2.5rem rgba(0, 0, 0, .5); }
/* Reflow the marketing-grid containers to the narrow panel width */
.app-footer-offcanvas .container { width: auto; max-width: none; padding-left: 1.25rem; padding-right: 1.25rem; }
.app-footer-offcanvas .py-5 { padding-top: 1.4rem !important; padding-bottom: 1.4rem !important; }
.app-footer-offcanvas img { max-width: 100%; height: auto; }
.app-footer-close {
    position: absolute; top: .6rem; right: .6rem; z-index: 1;
    width: 2rem; height: 2rem; border: 0; border-radius: 50%;
    background: rgba(255, 255, 255, .12); color: #fff; cursor: pointer;
    display: grid; place-items: center;
}
.app-footer-close:hover { background: rgba(255, 255, 255, .22); }
.app-footer-backdrop { position: fixed; inset: 0; z-index: 1045; background: rgba(8, 10, 14, .5); }
.app-footer-backdrop[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .app-footer-offcanvas { transition: none; } }

/* Off-canvas "menu / about" panel — understated, research-dept tone, readable on the dark panel.
   Colours are scoped to #footer + !important: the vendored marketing theme forces link/icon text
   to near-black (#121212) via higher-specificity rules, so we must out-rank it to stay legible. */
.app-info { padding: 1.35rem 1.35rem 1.6rem; display: flex; flex-direction: column; gap: 1.15rem; }
.app-info-brand { display: flex; align-items: center; gap: .7rem; }
/* Brand mark = the app glyph on a clean white "app-icon" tile so the indigo logo reads
   crisply on the dark panel — a deliberate, slightly larger sibling of the header white chip
   (calmed to 48px / soft shadow so it introduces the wordmark rather than out-shouting it). */
.app-info-mark { width: 48px; height: 48px; flex: 0 0 auto; display: grid; place-items: center; box-sizing: border-box; padding: 9px; border-radius: 14px; background: linear-gradient(160deg, #fff 0%, #f1f0fb 100%); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65), 0 0 0 1px rgba(255, 255, 255, .14), 0 5px 14px -4px rgba(8, 12, 38, .5); }
/* Reset the global dark-mode `.app-brand-mark` white-box rule on the inner <img>, or it
   paints a second chip (white box + padding + radius) INSIDE this one. */
#footer .app-info-mark .app-brand-mark { width: 30px; height: 30px; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; }
.app-info-name { display: flex; flex-direction: column; line-height: 1.05; }
#footer .app-info-name strong { font-weight: 700; font-size: 1.08rem; color: #fff !important; }
#footer .app-info-name span { font-size: .8rem; color: rgba(255, 255, 255, .62) !important; }
#footer .app-info-about { margin: -.25rem 0 .1rem; font-size: .86rem; line-height: 1.55; color: rgba(255, 255, 255, .72) !important; }
.app-info-sec { display: flex; flex-direction: column; gap: .1rem; }
/* Quiet section label — sentence case, dim. Deliberately NOT an uppercase "marketing" header. */
#footer .app-info-h, #footer .app-info-funded { display: block; margin: 0 0 .4rem; font-size: .74rem; font-weight: 600; letter-spacing: 0; text-transform: none; color: rgba(255, 255, 255, .45) !important; }
.app-info-link { display: flex; align-items: center; gap: .7rem; padding: .5rem .55rem; border-radius: .55rem; font-size: .92rem; text-decoration: none; transition: background-color .15s ease, color .15s ease; }
#footer .app-info-link { color: rgba(255, 255, 255, .9) !important; }
#footer .app-info-link:hover { background: rgba(255, 255, 255, .09); color: #fff !important; }
#footer .app-info-link > .bi { color: var(--app-accent) !important; font-size: 1.02rem; width: 1.1rem; text-align: center; flex: 0 0 auto; }
.app-info-social { display: flex; gap: .6rem; flex-wrap: wrap; }
.app-info-soc { width: 2.6rem; height: 2.6rem; display: grid; place-items: center; border-radius: 50%; font-size: 1.05rem; text-decoration: none; border: 1px solid rgba(255, 255, 255, .14); transition: background-color .15s ease, border-color .15s ease, transform .15s ease; }
#footer .app-info-soc { background: rgba(255, 255, 255, .18); color: #fff !important; }
#footer .app-info-soc:hover { background: var(--app-accent); border-color: var(--app-accent); color: #fff !important; transform: translateY(-2px); }
.app-info-funders { display: flex; flex-direction: column; gap: .55rem; }
.app-info-partners { display: flex; flex-direction: column; align-items: center; gap: 1rem; padding: 1.1rem; background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .08); border-radius: .8rem; }
.app-info-partners img { max-width: 78%; height: auto; opacity: .95; }
#footer .app-info-copy { margin: .15rem 0 0; font-size: .75rem; color: rgba(255, 255, 255, .5) !important; text-align: center; line-height: 1.5; }
@media (prefers-reduced-motion: reduce) { .app-info-soc:hover { transform: none; } }

/* ---- Cookie-consent card (cookies.html) ------------------------------------
   A fixed 350px-wide panel. Its padding made it ~517px tall regardless of
   viewport, so on anything shorter than ~560px it overflowed the top of the
   screen and sat over page controls — on a studio that included the toolbar and
   the Save button, which had to be dismissed before the page was usable.
   Capping the height (and scrolling the overflow) keeps it on-screen; the short-
   viewport padding step keeps the content readable once space is tight.
   `gdpr-pad`/`gdpr-title`/`gdpr-rule` replace `p-5`/`mb-4`/`my-4` utilities —
   Bootstrap declares those !important, so overriding them in place would have
   needed !important right back. Owning the properties is cleaner. */
.gdpr-pad { padding: 3rem; }
.gdpr-title { margin-bottom: 1.5rem; }
.gdpr-rule { margin-top: 1.5rem; margin-bottom: 1.5rem; }
#gdpr { max-height: calc(100vh - 2rem); overflow-y: auto; }
@media (max-height: 620px) {
    .gdpr-pad { padding: 1.25rem; }
    .gdpr-title { margin-bottom: .75rem; }
    .gdpr-rule { margin-top: .75rem; margin-bottom: .75rem; }
    /* Keep the card to the lower part of a short screen so the page's own top
       toolbar stays clickable while consent is still pending; the card scrolls
       internally rather than growing. */
    #gdpr { max-height: 65vh; }
}

/* Respect reduced motion across the system */
@media (prefers-reduced-motion: reduce) {
    .app-surface-hover, #footer .btn.bg-gray-700, .app-table tbody tr { transition: none; }
    .app-surface-hover:hover, #footer .btn.bg-gray-700:hover { transform: none; }
}
