/**
 * Modern CSS Stylesheet - Mobile First Adaptive Navigation
 * Using CSS Layers, Container Queries, and fluid typography
 *
 * IMPORTANT: This file requires tokens.css to be loaded first.
 * Design tokens (CSS variables) are defined in tokens.css.
 *
 * Navigation pattern:
 * - Mobile (< 768px): Drawer sidebar (hamburger menu)
 * - Tablet (768px - 1024px): Mini sidebar (icons only) + header
 * - Desktop (> 1024px): Full sidebar (icons + labels) + header
 *
 * Browser support:
 * - CSS Layers: 90%+ (2025)
 * - Container Queries: 90%+ (2025)
 * - light-dark(): 87%+ (2025) with fallback in tokens.css
 * - clamp(): 95%+ (2025)
 */

/* ==========================================================================
   CSS Layers - Define cascade order
   ========================================================================== */
@layer base, layout, components, utilities;

/* ==========================================================================
   Base Layer - Reset and typography
   Design tokens are defined in tokens.css
   ========================================================================== */
@layer base {
    /* Reset */
    *,
    *::before,
    *::after {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
    }

    /* Enforce [hidden] over author stylesheets that set display:flex/grid/etc.
       Allows using the native HTML hidden attribute instead of inline style="display:none". */
    [hidden] {
        display: none !important;
    }

    /* Base typography with fluid sizing */
    html {
        font-size: var(--font-size-base, 16px);
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-rendering: optimizeLegibility;
    }

    body {
        font-family: var(--font-sans);
        font-size: var(--text-base);
        line-height: var(--leading-normal);
        color: var(--color-text);
        background-color: var(--color-bg);
        font-feature-settings: var(--font-features);
        transition: background-color var(--duration-normal) var(--ease-standard),
                    color var(--duration-normal) var(--ease-standard);
    }

    /* Numerical contexts use tabular figures for column alignment.
       Substring selectors cover module-prefixed value classes (e.g.
       .bc-widget-stat-value, .drawer-kpi-value) without forcing every
       module to opt in manually. They must be `*=`, not `$=`: the attribute
       selector matches the WHOLE class attribute, so `$=` silently drops any
       element carrying a second class (`class="charts-kpi-value charts-kpi-delta"`
       lost its tabular figures that way). */
    .tabular-nums,
    .admin-table td,
    .table td,
    input[type="number"],
    .amount,
    .number,
    .kpi-value, [class*="-kpi-value"],
    .stat-value, [class*="-stat-value"],
    /* Framework-owned value slots. .summary-value is the summary-grid KPI
       (rendered 4-across, where proportional digits are most visible) and is
       numeric everywhere it is used. .meta-value is a generic label/value slot
       whose uses are mixed — badges and names among them — so it is included
       for the numeric majority (rates, ROI, amounts) at no cost to the rest:
       font-variant-numeric only affects digits. */
    .summary-value,
    .meta-value,
    code, kbd, samp, pre {
        font-variant-numeric: tabular-nums;
    }

    code, kbd, samp, pre {
        font-family: var(--font-mono);
    }

    /* Heading scale — negative tracking at larger sizes (modern standard) */
    h1 {
        font-size: var(--text-2xl);
        font-weight: 650;
        line-height: var(--leading-tight);
        letter-spacing: var(--tracking-tight);
    }

    h2 {
        font-size: var(--text-xl);
        font-weight: 600;
        line-height: var(--leading-tight);
        letter-spacing: var(--tracking-tight);
    }

    h3 {
        font-size: var(--text-lg);
        font-weight: 600;
        line-height: var(--leading-snug);
    }

    h4 {
        font-size: var(--text-md);
        font-weight: 600;
        line-height: var(--leading-snug);
    }

    /* Links — inline copy links get a soft underline + slightly stronger
       weight so they remain findable on dense pages. Link-like buttons
       (.btn, .btn-link, .nav-item, etc.) opt out explicitly. */
    a {
        color: var(--color-primary);
        text-decoration: none;
        font-weight: 550;
    }

    a:hover {
        text-decoration: underline;
        text-underline-offset: 2px;
    }

    /* Reset link styling for elements that are structurally links but
       visually something else (buttons, nav items, cards acting as links). */
    a.btn,
    a.nav-item,
    a.sidebar-utility-item,
    a.sidebar-logo,
    a.card,
    a[class*="-btn"],
    a[class*="-card"] {
        font-weight: inherit;
    }

    /* Content lists - proper styling for ul/ol in content areas */
    :is(.card-body, .backup-card-body, .alert, .modal-body) :is(ul, ol):not([class]) {
        padding-left: var(--space-lg);
        margin: var(--space-sm) 0;
    }

    :is(.card-body, .backup-card-body, .alert, .modal-body) ul:not([class]) {
        list-style-type: disc;
    }

    :is(.card-body, .backup-card-body, .alert, .modal-body) ol:not([class]) {
        list-style-type: decimal;
    }

    :is(.card-body, .backup-card-body, .alert, .modal-body) :is(ul, ol):not([class]) li {
        margin-bottom: var(--space-xs);
        line-height: 1.5;
    }

    /* Focus ring — double-layer pattern (readable on any background).
       Box-shadow inherits the element's own border-radius so it hugs
       pills, cards, and default-shaped elements alike.

       ── Why `2px solid transparent` and never `outline: none` ──────────────
       Forced-colors mode (Windows High Contrast) drops author box-shadows and
       forces `outline-color` to a system colour. A rule that says
       `outline: none` therefore survives into that mode while the box-shadow
       that replaced the ring does not — leaving NO focus indicator at all. The
       fallback at the end of this file (`*:focus-visible { outline: … Highlight }`)
       cannot rescue it: it scores 0,1,0 and every component rule that
       suppresses the outline is a class selector, 0,2,0 or higher.

       A transparent outline reserves the ring instead of removing it: invisible
       in normal rendering, no effect on layout, and it reappears automatically
       under forced colours — including on components whose author never thought
       about the mode. No `!important`, and no selector list to keep in sync.

       This is enforced: `make test` runs check-focus-forced-colors.sh, which
       fails on an `outline: none` anywhere in our own stylesheets.

       HONEST LIMIT: the visible result cannot be verified by this project's
       toolchain — Playwright's forced-colors emulation does not satisfy
       `matchMedia('(forced-colors: active)')`. The behaviour is read from the
       CSS Color Adjust spec's forced-properties list; confirming it needs a real
       high-contrast OS. The guard pins the cascade, which is the part that was
       provably wrong. */
    :focus-visible {
        outline: 2px solid transparent;
        box-shadow: var(--focus-ring);
    }

    /* Skip-link keeps the outline pattern for maximum visibility when
       appearing over arbitrary content at the top of the viewport. */
    .skip-link:focus,
    .skip-link:focus-visible {
        outline: 2px solid var(--color-text-inverted);
        outline-offset: 2px;
        box-shadow: none;
    }
}

/* ==========================================================================
   Layout Layer - Page structure and containers (Mobile First)
   ========================================================================== */
@layer layout {
    /* App layout - Mobile first (no sidebar visible).
       Uses 100svh (small viewport height) rather than 100dvh: in a Chrome 135+
       Android edge-to-edge PWA the dynamic value animates with the gesture-bar
       chin, which throttles below 60fps and reflows the inner scroll
       container — leaving the last list item clipped. svh is stable. In
       PWA standalone mode the small/dynamic/large values are equal, so
       there is no wasted space; in browser-tab mode we trade a few pixels
       for layout stability. */
    .app-layout {
        display: flex;
        flex-direction: column;
        height: 100vh;
        height: 100svh;
        overflow: hidden;
    }

    /* ==========================================================================
       App Header
       ========================================================================== */
    /* The header reserves space for the system status bar via padding-top
       (rather than top:env(...)) so the elevated background still paints
       edge-to-edge under the status bar — matching the iOS / Android
       Material 3 expectation. */
    .app-header {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        height: calc(var(--header-height) + env(safe-area-inset-top, 0px));
        padding: env(safe-area-inset-top, 0px) var(--space-md) 0;
        background-color: var(--color-bg-elevated);
        border-bottom: 1px solid var(--color-border);
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        z-index: var(--z-sticky);
        box-shadow: var(--shadow-sm);
    }

    .header-menu-toggle {
        display: flex;
        align-items: center;
        justify-content: center;
        width: var(--touch-target);
        height: var(--touch-target);
        background: none;
        border: none;
        color: var(--color-text);
        cursor: pointer;
        border-radius: var(--radius-md);
        transition: background-color var(--transition-fast);
        flex-shrink: 0;
    }

    .header-menu-toggle:hover {
        background-color: var(--color-bg-subtle);
    }

    .header-logo {
        display: flex;
        align-items: center;
        gap: var(--space-xs);
        text-decoration: none;
        color: var(--color-text);
        font-weight: 600;
        font-size: 1rem;
        flex-shrink: 0;
    }

    .header-logo:hover {
        text-decoration: none;
    }

    .header-logo-image {
        height: 32px;
        width: auto;
    }

    /* ==========================================================================
       Sidebar - Hidden on mobile, drawer behavior
       ========================================================================== */
    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        bottom: 0;
        width: var(--sidebar-width-full);
        background-color: var(--sidebar-bg);
        color: var(--sidebar-text);
        display: flex;
        flex-direction: column;
        z-index: var(--z-sidebar);
        transform: translateX(-100%);
        transition: transform var(--transition-normal), width var(--transition-normal);
        overflow: hidden;
    }

    .sidebar.open {
        transform: translateX(0);
        /* Allow dropdowns to overflow sidebar bounds (user menu) */
        overflow: visible;
    }

    .sidebar-overlay {
        position: fixed;
        inset: 0;
        background-color: rgb(0 0 0 / 0.5);
        z-index: var(--z-sidebar-overlay);
        opacity: 0;
        visibility: hidden;
        transition: opacity var(--transition-normal), visibility var(--transition-normal);
    }

    .sidebar.open ~ .sidebar-overlay {
        opacity: 1;
        visibility: visible;
    }

    /* The drawer container itself stays edge-to-edge so its background paints
       under the system status / gesture bars. Inner regions (header / nav)
       carry the safe-area padding instead, matching iOS Mail / Material 3
       drawers. */
    .sidebar-header {
        padding: calc(var(--space-md) + env(safe-area-inset-top, 0px)) var(--space-lg) var(--space-md);
        border-bottom: 1px solid var(--sidebar-border);
        display: flex;
        align-items: center;
        justify-content: space-between;
        min-height: calc(var(--header-height) + env(safe-area-inset-top, 0px));
        flex-shrink: 0;
    }

    .sidebar-logo {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        text-decoration: none;
        color: var(--sidebar-text-active);
        overflow: hidden;
    }

    .sidebar-logo:hover {
        text-decoration: none;
    }

    .sidebar-logo-text {
        font-size: 1.125rem;
        font-weight: 600;
        white-space: nowrap;
    }

    /* Sidebar toggle (hamburger) - hidden on mobile (header hamburger handles it) */
    .sidebar-toggle {
        display: none;
    }

    .sidebar-close {
        display: flex;
        align-items: center;
        justify-content: center;
        width: var(--touch-target);
        height: var(--touch-target);
        background: none;
        border: none;
        color: var(--sidebar-text);
        cursor: pointer;
        border-radius: var(--radius-md);
        flex-shrink: 0;
    }

    .sidebar-close:hover {
        background-color: var(--sidebar-hover);
        color: var(--sidebar-text-hover);
    }

    /* Admin context visual indicator - sidebar left border */
    .sidebar.admin-context {
        border-left: 3px solid var(--color-warning);
    }

    .sidebar-nav {
        flex: 1;
        padding: var(--space-md) 0;
        overflow-y: auto;
        overflow-x: hidden;
        /* Theme-aware scrollbar — the previous fixed white-rgba was
           invisible on the light-mode white sidebar. */
        scrollbar-width: thin;
        scrollbar-color: var(--color-border) transparent;
        /* Ensure workspace dropdown appears above nav items */
        position: relative;
        z-index: 0;
    }

    /* Custom scrollbar - Webkit (Chrome, Safari, Edge) */
    .sidebar-nav::-webkit-scrollbar {
        width: 6px;
    }

    .sidebar-nav::-webkit-scrollbar-track {
        background: transparent;
    }

    .sidebar-nav::-webkit-scrollbar-thumb {
        background-color: var(--color-border);
        border-radius: 3px;
    }

    .sidebar-nav::-webkit-scrollbar-thumb:hover {
        background-color: var(--color-border-strong);
    }

    /* Hide scrollbar thumb until the user hovers the nav (reveal on intent) */
    .sidebar-nav:not(:hover)::-webkit-scrollbar-thumb {
        background-color: transparent;
    }

    .sidebar-nav:not(:hover) {
        scrollbar-color: transparent transparent;
    }

    .nav-section {
        margin-bottom: var(--space-md);
    }

    /* Section header button (collapsible) */
    .nav-section-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        padding: var(--space-sm) var(--space-lg);
        background: none;
        border: none;
        cursor: pointer;
        transition: background-color var(--transition-fast);
    }

    .nav-section-header:hover {
        background-color: var(--sidebar-hover);
    }

    .nav-section-header:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: -2px;
    }

    .nav-section-title {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        font-size: 0.6875rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.1em;
        color: var(--sidebar-text);
        opacity: 0.6;
        white-space: nowrap;
        overflow: hidden;
        /* Remove padding - now handled by parent button */
        padding: 0;
    }

    .nav-section-chevron {
        flex-shrink: 0;
        color: var(--sidebar-text);
        opacity: 0.5;
        transition: transform var(--transition-fast), opacity var(--transition-fast);
    }

    .nav-section-header:hover .nav-section-chevron {
        opacity: 0.8;
    }

    /* Collapsed state */
    .nav-section.collapsed .nav-section-chevron {
        transform: rotate(-90deg);
    }

    /* Section items container */
    .nav-section-items {
        overflow: hidden;
    }

    .nav-section.collapsed .nav-section-items {
        max-height: 0;
        overflow: hidden;
    }

    .nav-item {
        display: flex;
        align-items: center;
        gap: var(--space-md);
        padding: 0.75rem var(--space-lg);
        color: var(--sidebar-text);
        text-decoration: none;
        font-size: 0.875rem;
        font-weight: 500;
        transition: background-color var(--transition-fast), color var(--transition-fast);
        min-height: var(--touch-target);
        position: relative;
        white-space: nowrap;
        overflow: hidden;
    }

    .nav-item:hover {
        background-color: var(--sidebar-hover);
        color: var(--sidebar-text-hover);
        text-decoration: none;
    }

    .nav-item.active {
        background-color: var(--sidebar-active);
        color: var(--sidebar-text-active);
        font-weight: 600;
    }

    /* Accent bar on the left edge — signature marker for active item */
    .nav-item.active::before {
        content: '';
        position: absolute;
        left: 0;
        top: 0.5rem;
        bottom: 0.5rem;
        width: 3px;
        border-radius: 0 var(--radius-xs) var(--radius-xs) 0;
        background-color: var(--sidebar-accent);
    }

    .nav-icon {
        flex-shrink: 0;
        width: 20px;
        height: 20px;
    }

    .nav-label {
        flex: 1;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .sidebar-footer {
        padding: var(--space-md) var(--space-md) calc(var(--space-md) + env(safe-area-inset-bottom, 0px));
        border-top: 1px solid var(--sidebar-border);
        display: flex;
        flex-direction: column;
        gap: var(--space-sm);
        flex-shrink: 0;
    }

    /* Sidebar utility zone - items above user menu */
    .sidebar-utility {
        display: flex;
        flex-direction: column;
        gap: 2px;
    }

    .sidebar-utility-item {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        padding: var(--space-sm);
        color: var(--sidebar-text);
        text-decoration: none;
        border-radius: var(--radius-md);
        transition: background-color var(--transition-fast), color var(--transition-fast);
        position: relative;
        min-height: var(--touch-target);
    }

    .sidebar-utility-item:hover {
        background-color: var(--sidebar-hover);
        color: var(--sidebar-text-hover);
    }

    .sidebar-utility-item.active {
        background-color: var(--sidebar-active);
        color: var(--sidebar-text-active);
    }

    .sidebar-utility-item svg {
        width: 20px;
        height: 20px;
        flex-shrink: 0;
    }

    .sidebar-utility-label {
        font-size: 0.875rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .sidebar-utility-badge {
        margin-left: auto;
        background-color: var(--color-primary);
        color: var(--color-primary-contrast);
        font-size: 0.6875rem;
        font-weight: 600;
        min-width: 18px;
        height: 18px;
        padding: 0 5px;
        border-radius: var(--radius-full);
        display: flex;
        align-items: center;
        justify-content: center;
        line-height: 1;
    }

    /* User menu in sidebar footer - mobile styles */
    .sidebar-footer .user-menu {
        width: 100%;
        margin-left: 0;
    }

    .sidebar-footer .user-menu-trigger {
        width: 100%;
        justify-content: flex-start;
        color: var(--sidebar-text);
        padding: var(--space-sm);
    }

    .sidebar-footer .user-menu-trigger:hover {
        background-color: var(--sidebar-hover);
    }

    .sidebar-footer .user-name {
        display: block;
        color: var(--sidebar-text);
    }

    .sidebar-footer .user-menu-chevron {
        display: block;
        margin-left: auto;
        color: var(--sidebar-text);
    }

    .sidebar-footer .user-menu-dropdown {
        bottom: 100%;
        top: auto;
        left: 0;
        right: auto;
        margin-bottom: var(--space-xs);
    }

    /* ==========================================================================
       Main Content
       ========================================================================== */
    .main-content {
        flex: 1;
        display: flex;
        flex-direction: column;
        /* Match the .app-header total height so content begins below the
           fixed header AND the system status bar inset on PWA edge-to-edge. */
        margin-top: calc(var(--header-height) + env(safe-area-inset-top, 0px));
        min-width: 0;
        min-height: 0;
    }

    /* The scroll container reserves the system gesture-bar inset upfront via
       env(safe-area-max-inset-bottom): the static maximum value (Chrome 135+,
       falls back to safe-area-inset-bottom on older browsers) avoids the
       layout reflow that the dynamic inset triggers as the chin retracts on
       scroll — which was clipping the last list item.
       scroll-padding-* keeps focused elements clear of the fixed header
       and the gesture bar (WCAG 2.2 SC 2.4.11 "Focus Not Obscured", AA).
       overscroll-behavior-y: contain stops scroll-chaining into parent
       containers (sidebar drawer, modals). */
    .content-body {
        flex: 1;
        padding: var(--space-md);
        padding-bottom: calc(var(--space-md) + env(safe-area-max-inset-bottom, env(safe-area-inset-bottom, 0px)));
        scroll-padding-top: var(--header-height);
        scroll-padding-bottom: calc(var(--space-md) + env(safe-area-max-inset-bottom, env(safe-area-inset-bottom, 0px)));
        overflow-y: auto;
        overscroll-behavior-y: contain;
        min-height: 0;
        container-type: inline-size;
    }

    /* ==========================================================================
       Content Top Bar - Slot for in-flow global widgets (e.g. notification bell)
       Rendered above content-body within main-content flex column.
       ========================================================================== */
    .content-top-bar {
        display: flex;
        justify-content: flex-end;
        align-items: center;
        gap: var(--space-sm);
        /* Mobile: overlay on header (right side where user-menu is hidden).
           Aligns with .app-header which now reserves safe-area-inset-top. */
        position: fixed;
        top: env(safe-area-inset-top, 0px);
        right: var(--space-md);
        height: var(--header-height);
        padding: 0;
        z-index: var(--z-sticky);
        background: none;
        pointer-events: none;
    }

    .content-top-bar > * {
        pointer-events: auto;
    }

    /* Logo in content-top-bar - hidden on mobile (header has its own logo) */
    .content-top-bar-logo {
        display: none;
    }

    /* ==========================================================================
       User Menu (Header)
       ========================================================================== */
    .user-menu {
        position: relative;
        margin-left: auto;
    }

    /* User menu in header - hidden on mobile (use sidebar footer menu instead) */
    .app-header .user-menu {
        display: none;
    }

    .user-menu-trigger {
        display: flex;
        align-items: center;
        gap: var(--space-xs);
        padding: var(--space-xs);
        background: none;
        border: none;
        cursor: pointer;
        border-radius: var(--radius-md);
        transition: background-color var(--transition-fast);
        color: var(--color-text);
        min-height: var(--touch-target);
    }

    .user-menu-trigger:hover {
        background-color: var(--color-bg-subtle);
    }

    .user-menu-avatar-wrapper {
        position: relative;
        flex-shrink: 0;
    }

    .user-name {
        display: none;
        font-size: 0.875rem;
        font-weight: 500;
        max-width: 120px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .user-menu-chevron {
        display: none;
        flex-shrink: 0;
        transition: transform var(--transition-fast);
    }

    .user-menu.open .user-menu-chevron {
        transform: rotate(180deg);
    }

    .user-menu-dropdown {
        position: absolute;
        top: calc(100% + var(--space-xs));
        right: 0;
        min-width: 240px;
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-lg);
        opacity: 0;
        visibility: hidden;
        transform: translateY(-8px);
        transition: opacity var(--transition-fast), visibility var(--transition-fast), transform var(--transition-fast);
        z-index: var(--z-dropdown);
    }

    .user-menu.open .user-menu-dropdown {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
    }

    .user-menu-header {
        padding: var(--space-md);
        border-bottom: 1px solid var(--color-border);
    }

    .user-menu-name {
        display: block;
        font-weight: 600;
        color: var(--color-text);
        margin-bottom: 2px;
    }

    .user-menu-email {
        display: block;
        font-size: 0.75rem;
        color: var(--color-text-muted);
        word-break: break-all;
    }

    .user-menu-role {
        display: block;
        margin-top: var(--space-xs);
    }

    .user-menu-divider {
        height: 1px;
        background-color: var(--color-border);
    }

    .user-menu-item {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        padding: var(--space-sm) var(--space-md);
        color: var(--color-text);
        text-decoration: none;
        font-size: 0.875rem;
        min-height: var(--touch-target);
        transition: background-color var(--transition-fast);
        background: none;
        border: none;
        width: 100%;
        cursor: pointer;
        text-align: left;
    }

    .user-menu-item:hover {
        background-color: var(--color-bg-subtle);
        text-decoration: none;
    }

    .user-menu-logout {
        color: var(--color-danger);
    }

    .user-menu-logout:hover {
        background-color: rgba(239, 68, 68, 0.1);
    }

    .user-menu-logout-form {
        width: 100%;
        margin: 0;
    }

    .user-menu-badge {
        margin-left: auto;
        font-size: 0.7rem;
        font-weight: 600;
        background-color: var(--color-primary);
        color: var(--color-primary-contrast);
        border-radius: var(--radius-full, 9999px);
        padding: 1px 6px;
        min-width: 18px;
        text-align: center;
        line-height: 1.4;
    }

    .user-menu-item .nav-icon {
        width: 18px;
        height: 18px;
        flex-shrink: 0;
    }
    /* ==========================================================================
       Auth pages layout
       ========================================================================== */
    .auth-page {
        min-height: 100vh;
        min-height: 100dvh;
        display: flex;
        flex-direction: column;
        background: light-dark(var(--color-bg), linear-gradient(135deg, #1f2937 0%, #111827 100%));
    }

    .auth-page-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: var(--space-md) var(--space-lg);
        width: 100%;
    }

    .auth-page-header-logo {
        font-size: 1.25rem;
        font-weight: 700;
        color: light-dark(var(--color-text), #ffffff);
        text-decoration: none;
        transition: opacity var(--transition-fast);
    }

    .auth-page-header-logo-img {
        height: 28px;
        width: auto;
        display: block;
    }

    a.auth-page-header-logo:hover {
        opacity: 0.8;
    }

    a.auth-page-header-logo:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: 2px;
        border-radius: var(--radius-sm);
    }

    .auth-page-header-controls {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        margin-left: auto;
    }

    /* Auth header: theme/language menu triggers share a 40 px square pill so
       both controls align as a symmetric pair. */
    .auth-page-header-controls .theme-menu-trigger,
    .auth-page-header-controls .language-menu-trigger {
        width: 40px;
        height: 40px;
        background-color: light-dark(var(--color-bg-subtle), rgba(255, 255, 255, 0.1));
        border-color: light-dark(var(--color-border), rgba(255, 255, 255, 0.2));
        color: light-dark(var(--color-text), rgba(255, 255, 255, 0.9));
    }

    .auth-page-header-controls .theme-menu-trigger:hover,
    .auth-page-header-controls .language-menu-trigger:hover {
        background-color: light-dark(var(--color-bg-muted), rgba(255, 255, 255, 0.2));
    }

    .auth-page-header-controls .theme-menu-trigger:focus-visible,
    .auth-page-header-controls .language-menu-trigger:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: 2px;
    }

    .auth-page-content {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: var(--space-md);
    }

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

    /* ==========================================================================
       Error pages layout
       ========================================================================== */
    .error-page {
        min-height: 100vh;
        min-height: 100dvh;
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: var(--color-bg);
        padding: var(--space-md);
    }

    .error-container {
        text-align: center;
        max-width: 400px;
    }

    /* Fallback for auth pages without light-dark() support */
    @supports not (color: light-dark(#000, #fff)) {
        .auth-page {
            background: var(--color-bg);
        }
        .auth-page-header-logo {
            color: var(--color-text);
        }
        .auth-page-header-controls .theme-menu-trigger,
        .auth-page-header-controls .language-menu-trigger {
            background-color: var(--color-bg-subtle);
            border-color: var(--color-border);
            color: var(--color-text);
        }
        .auth-page-header-controls .theme-menu-trigger:hover,
        .auth-page-header-controls .language-menu-trigger:hover {
            background-color: var(--color-bg-muted);
        }

        [data-theme="dark"] .auth-page {
            background: linear-gradient(135deg, #1f2937 0%, #111827 100%);
        }
        [data-theme="dark"] .auth-page-header-logo {
            color: #ffffff;
        }
        [data-theme="dark"] .auth-page-header-controls .theme-menu-trigger,
        [data-theme="dark"] .auth-page-header-controls .language-menu-trigger {
            background-color: rgba(255, 255, 255, 0.1);
            border-color: rgba(255, 255, 255, 0.2);
            color: rgba(255, 255, 255, 0.9);
        }
        [data-theme="dark"] .auth-page-header-controls .theme-menu-trigger:hover,
        [data-theme="dark"] .auth-page-header-controls .language-menu-trigger:hover {
            background-color: rgba(255, 255, 255, 0.2);
        }
    }
}

/* ==========================================================================
   Components Layer - Reusable UI components
   ========================================================================== */
@layer components {
    /* ==========================================================================
       Buttons
       ========================================================================== */
    .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0.625rem 1.25rem;
        font-size: var(--text-sm);
        font-weight: 550;
        line-height: 1.25rem;
        letter-spacing: var(--tracking-normal);
        border-radius: var(--radius-md);
        border: 1px solid transparent;
        cursor: pointer;
        transition: var(--motion-hover);
        text-decoration: none;
        white-space: nowrap;
        min-height: var(--touch-target);
    }

    .btn:disabled,
    .btn[disabled] {
        background-color: var(--color-bg-muted);
        color: var(--color-text-muted);
        border-color: var(--color-border);
        cursor: not-allowed;
    }

    .btn-primary {
        background-color: var(--color-primary);
        color: var(--color-primary-contrast);
    }

    .btn-primary:hover:not(:disabled) {
        background-color: var(--color-primary-hover);
        text-decoration: none;
    }

    .btn-secondary {
        background-color: var(--color-bg-muted);
        color: var(--color-text);
    }

    .btn-secondary:hover:not(:disabled) {
        background-color: var(--color-border);
        text-decoration: none;
    }

    .btn-danger {
        background-color: var(--color-danger);
        color: #ffffff;
    }

    .btn-danger:hover:not(:disabled) {
        background-color: var(--color-danger-hover);
        text-decoration: none;
    }

    .btn-outline {
        background-color: transparent;
        border: 1px solid var(--color-border);
        color: var(--color-text);
    }

    .btn-outline:hover:not(:disabled) {
        border-color: var(--color-primary);
        color: var(--color-primary);
        text-decoration: none;
    }

    .btn-ghost {
        background-color: transparent;
        color: var(--color-text-secondary);
    }

    .btn-ghost:hover:not(:disabled) {
        background-color: var(--color-bg-muted);
        color: var(--color-text);
        text-decoration: none;
    }

    .btn-link {
        background: none;
        border: none;
        padding: 0;
        color: inherit;
        font: inherit;
        text-decoration: underline;
        cursor: pointer;
    }

    .btn-link:hover:not(:disabled) {
        text-decoration: none;
    }

    .btn-link:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: 2px;
    }

    .btn-link:disabled,
    .btn-link[disabled] {
        color: var(--color-text-muted);
        cursor: not-allowed;
        text-decoration: none;
    }

    .btn-block {
        width: 100%;
    }

    .btn-sm {
        padding: 0.375rem 0.75rem;
        font-size: 0.75rem;
        min-height: 36px;
    }

    .btn-lg {
        padding: 0.625rem 1.25rem;
        font-size: 1rem;
        min-height: 48px;
    }

    /* Alias: use .btn-sm instead */
    .btn-small {
        padding: 0.375rem 0.75rem;
        font-size: 0.75rem;
        min-height: 36px;
    }

    .btn-logout {
        background-color: transparent;
        color: var(--sidebar-text);
        padding: var(--space-sm) var(--space-md);
        font-size: 0.875rem;
    }

    .btn-logout:hover {
        background-color: var(--sidebar-hover);
        color: #ffffff;
    }

    /* ==========================================================================
       Avatar Component
       ========================================================================== */
    .avatar {
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 50%;
        overflow: hidden;
        flex-shrink: 0;
        background-color: var(--color-primary);
        color: var(--color-primary-contrast);
    }

    .avatar-img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

    .avatar-initials {
        font-weight: 600;
        text-transform: uppercase;
        line-height: 1;
    }

    /* Avatar sizes */
    .avatar-sm {
        width: 32px;
        height: 32px;
        font-size: 0.75rem;
    }

    .avatar-md {
        width: 40px;
        height: 40px;
        font-size: 0.875rem;
    }

    .avatar-lg {
        width: 64px;
        height: 64px;
        font-size: 1.25rem;
    }

    .avatar-xl {
        width: 96px;
        height: 96px;
        font-size: 1.75rem;
    }

    .file-input {
        display: none;
    }

    /* ==========================================================================
       Cards — border-first aesthetic, paired with a barely-visible shadow
       so cards lift off a tinted canvas (1px hint, not a glow). For floating
       contexts (popovers, command palette, menus), opt into shadow-sm via
       .card-elevated.
       ========================================================================== */
    .card {
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-lg);
        box-shadow: var(--shadow-xs);
        padding: var(--space-lg);
        margin-bottom: var(--space-lg);
        container-type: inline-size;
    }

    /* Opt-in elevation (floating widgets, popovers) */
    .card-elevated {
        box-shadow: var(--shadow-sm);
    }

    .card-title {
        font-size: var(--text-lg);
        font-weight: 600;
        color: var(--color-text);
        margin-bottom: var(--space-sm);
        letter-spacing: var(--tracking-tight);
    }

    .card-description {
        color: var(--color-text-secondary);
        font-size: var(--text-sm);
        margin-bottom: var(--space-md);
    }

    .card-actions {
        margin-top: var(--space-lg);
        padding-top: var(--space-md);
        border-top: 1px solid var(--color-border-subtle);
    }

    /* ==========================================================================
       Auth card
       ========================================================================== */
    .auth-card {
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-md);
        padding: var(--space-lg);
    }

    .auth-card-header {
        text-align: center;
        margin-bottom: var(--space-lg);
    }

    .auth-card-logo {
        display: block;
        max-width: 100%;
        max-height: 150px;
        width: auto;
        height: auto;
        margin: 0 auto var(--space-lg);
        object-fit: contain;
    }

    /* Framework default brand lockup. A bounded box (not a fixed height) so it
       adapts to any app's lockup shape: a tall/stacked mark (icon over wordmark)
       is height-bounded and reaches a legible focal size, while a wide horizontal
       mark is width-bounded and stays compact — one rule, no per-app tuning.
       Custom uploads keep the generous max-height above. */
    .auth-card-logo--default {
        max-height: 80px;
        max-width: 220px;
    }

    .auth-title {
        font-size: 1.5rem;
        font-weight: 700;
        color: var(--color-text);
        margin-bottom: var(--space-sm);
    }

    .auth-subtitle {
        font-size: 0.875rem;
        font-weight: 400;
        color: var(--color-text-secondary);
    }

    .auth-form {
        margin-top: var(--space-lg);
    }

    .auth-form .form-row .form-group {
        margin-bottom: 0;
    }

    .auth-footer {
        margin-top: var(--space-lg);
        text-align: center;
    }

    .auth-footer .link {
        color: var(--color-primary);
        text-decoration: none;
        font-size: 0.875rem;
    }

    .auth-footer .link:hover {
        text-decoration: underline;
    }

    .form-options {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: var(--space-sm);
    }

    .auth-forgot-link {
        color: var(--color-text-muted);
        text-decoration: none;
        font-size: 0.8125rem;
        white-space: nowrap;
        padding-top: 2px;
    }

    .auth-forgot-link:hover {
        color: var(--color-primary);
        text-decoration: underline;
    }

    .auth-plan-banner {
        background-color: var(--color-bg-subtle);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-sm);
        padding: var(--space-sm) var(--space-md);
        margin-bottom: var(--space-lg);
        text-align: center;
    }

    .auth-plan-banner-name {
        font-weight: 600;
        font-size: 0.9375rem;
        color: var(--color-text);
    }

    .auth-plan-banner-price {
        font-size: 0.875rem;
        color: var(--color-text-muted);
        margin-top: var(--space-xs);
    }

    .auth-plan-banner-trial {
        font-size: 0.8125rem;
        color: var(--color-success);
        margin-top: var(--space-xs);
    }

    .auth-plan-banner-hint {
        font-size: 0.8125rem;
        color: var(--color-text-muted);
        margin-top: var(--space-xs);
    }

    .auth-alt-action {
        margin-top: var(--space-lg);
        padding-top: var(--space-lg);
        border-top: 1px solid var(--color-border);
        text-align: center;
        font-size: 0.875rem;
    }

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

    .auth-alt-action-link {
        color: var(--color-primary);
        text-decoration: none;
        font-weight: 600;
    }

    .auth-alt-action-link:hover {
        text-decoration: underline;
    }

    /* Auth method selection cards */
    .auth-method-card {
        display: flex;
        align-items: flex-start;
        gap: var(--space-sm);
        width: 100%;
        padding: var(--space-md);
        margin-bottom: var(--space-sm);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        background: var(--color-bg-elevated);
        cursor: pointer;
        text-align: left;
        font: inherit;
        color: inherit;
        transition: border-color 0.15s, box-shadow 0.15s;
    }

    .auth-method-card:hover {
        border-color: var(--color-primary);
        box-shadow: 0 0 0 1px var(--color-primary);
    }

    .auth-method-card svg {
        flex-shrink: 0;
        margin-top: 2px;
    }

    .auth-method-card strong {
        display: block;
        margin-bottom: 2px;
    }

    .auth-method-card small {
        color: var(--color-text-muted);
        font-size: 0.8125rem;
        line-height: 1.4;
    }

    /* Recovery phrase grid (BIP39 12-word input) */
    .phrase-grid {
        display: grid;
        grid-template-rows: repeat(6, auto);
        grid-auto-flow: column;
        grid-auto-columns: 1fr;
        gap: var(--space-xs);
        margin-bottom: var(--space-md);
    }

    .phrase-grid-item {
        display: flex;
        align-items: center;
        border: 1px solid var(--color-border);
        border-radius: var(--radius-sm);
        overflow: hidden;
        transition: border-color 0.15s;
    }

    .phrase-grid-item:focus-within {
        border-color: var(--color-primary);
        box-shadow: 0 0 0 1px var(--color-primary);
    }

    .phrase-grid-item.is-valid {
        border-color: var(--color-success);
    }

    .phrase-grid-item.is-invalid {
        border-color: var(--color-danger);
    }

    .phrase-grid-num {
        flex-shrink: 0;
        width: 2rem;
        text-align: center;
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--color-text-muted);
        background: var(--color-bg-muted);
        padding: 0.5rem 0;
        line-height: 1;
        user-select: none;
    }

    .phrase-grid-input {
        flex: 1;
        border: none;
        outline: none;
        padding: 0.5rem 0.5rem;
        font-size: 0.875rem;
        font-family: inherit;
        background: transparent;
        color: inherit;
        min-width: 0;
        /* Sub-control inside .phrase-grid-item — the wrapper provides
           the visual chrome. Opt out of the framework input baseline so
           we don't inherit min-height: 44px (which would inflate every
           cell of the 24-word mnemonic grid). */
        min-height: auto;
    }

    /* ==========================================================================
       Device pairing (smartphone-side + primary-side widget)
       ==========================================================================
       Shared visual language for the two halves of the Signal-style
       E2E device-pair flow:

         - smartphone-side: /auth/device-link page (full-screen card
           inside .auth-layout > .auth-container).
         - primary-side: #device-pair-card embedded in pwa-install
           (rendered in /profile and the onboarding mobile-install
           fragment).

       The fingerprint block is the security-critical element. It MUST
       look identical on both ends so the user compares the codes
       visually without hesitation — same monospace, same letter
       spacing, same enclosure. We deliberately use --color-bg-subtle
       + --color-border-strong (not the primary tint): a high-contrast
       neutral panel reads as "vigilance / verification", not as a
       coloured CTA. Apple, Signal, Element all follow this convention.
       ========================================================================== */

    /* Container the entire pwa-install component (QR/action zone +
       benefits list + already-installed state) into a single centered
       column. Without this, on wide profile sections the action zone
       was centered while the benefits <ul> stayed left-aligned —
       producing two contradictory alignment rules side by side.
       The flex column with gap also gives a regular vertical rhythm
       between the sub-blocks (zone d'action ↔ benefits ↔ installed). */
    .pwa-install {
        display: flex;
        flex-direction: column;
        gap: var(--space-xl);
        max-width: 32rem;
        margin-inline: auto;
    }

    .device-pair-card {
        max-width: 28rem;
        margin: 0 auto;
    }

    .device-link-fingerprint {
        background: var(--color-bg-subtle);
        border: 1px solid var(--color-border-strong);
        border-radius: var(--radius-md);
        padding: var(--space-lg);
        margin: var(--space-lg) 0;
        text-align: center;
    }

    .device-link-fingerprint-label {
        display: block;
        font-size: var(--text-sm);
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: var(--color-text-muted);
        margin-bottom: var(--space-sm);
    }

    .device-link-fingerprint-words {
        display: block;
        font-family: var(--font-mono);
        font-size: 1.5rem;
        font-weight: 600;
        letter-spacing: 0.04em;
        color: var(--color-text);
        word-spacing: 0.5rem;
        line-height: 1.3;
    }

    @media (min-width: 768px) {
        .device-link-fingerprint-words {
            font-size: 1.75rem;
        }
    }

    .qr-frame {
        display: flex;
        align-items: center;
        justify-content: center;
        background: #ffffff;
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        padding: var(--space-md);
        aspect-ratio: 1 / 1;
        max-width: 280px;
        margin: 0 auto var(--space-md);
    }

    .qr-frame img {
        max-width: 100%;
        height: auto;
        display: block;
    }

    .qr-frame-spinner {
        width: 36px;
        height: 36px;
        color: var(--color-primary);
        animation: device-pair-spin 1.4s linear infinite;
    }

    @keyframes device-pair-spin {
        to { transform: rotate(360deg); }
    }

    .device-pair-actions {
        display: flex;
        flex-direction: column;
        gap: var(--space-sm);
        margin-top: var(--space-lg);
    }

    .device-pair-actions .btn {
        width: 100%;
        min-height: 44px;
    }

    /* On wider viewports, lay actions out as a centered row. The flex
       basis makes every button tend toward the same width regardless
       of label length — so a Confirm/Cancel pair reads symmetrically
       and a single Regenerate button (expired stage) sits centered
       in the same visual column as the rest. Primary moves to the
       right via order: 2 (Western convention for "forward" action). */
    @media (min-width: 768px) {
        .device-pair-actions {
            flex-direction: row;
            justify-content: center;
            gap: var(--space-md);
        }
        .device-pair-actions .btn {
            width: auto;
            flex: 0 1 12rem;
            min-width: 9rem;
        }
        .device-pair-actions .btn-primary {
            order: 2;
        }
    }

    .device-pair-hint-warning {
        display: flex;
        gap: var(--space-sm);
        align-items: flex-start;
        border-left: 3px solid var(--color-warning);
        background: var(--color-warning-subtle);
        color: var(--color-text-secondary);
        padding: var(--space-sm) var(--space-md);
        border-radius: var(--radius-sm);
        font-size: var(--text-sm);
        line-height: 1.5;
        margin-top: var(--space-md);
    }

    .device-pair-hint-warning svg {
        flex-shrink: 0;
        width: 16px;
        height: 16px;
        margin-top: 0.125rem;
        color: var(--color-warning);
    }

    /* Stage transitions are subtle by design — a brutal swap between
       loading / qr / confirm / done would feel jarring on a flow that
       takes ~30 seconds. Wrapped in prefers-reduced-motion so users
       who opt out get an instant swap. */
    @media (prefers-reduced-motion: no-preference) {
        [id^="device-pair-stage-"]:not([hidden]),
        [id^="device-link-stage-"]:not([hidden]) {
            animation: device-pair-fade 220ms ease-out;
        }

        @keyframes device-pair-fade {
            from { opacity: 0; transform: translateY(4px); }
            to   { opacity: 1; transform: translateY(0); }
        }
    }

    /* ==========================================================================
       Forms
       ==========================================================================
       Two layers:

       1. Native element baseline — :where(select, input, textarea) at
          specificity 0. Renders ANY native form control with the framework
          tokens (border, padding, font, focus ring, dark-mode), without
          requiring a class. Fulfils the documented promise "no CSS class
          needed on inputs" outside .form-group too (filter bars, table
          cells, inline forms). Lower-spec :where() means existing classes
          (.form-group rule below, .aff-input-sm width override, Tom Select
          wrappers, command-palette input) win without !important.

       2. .form-group — layout-only concerns (vertical stacking margin,
          label, full-width fields, textarea height). The visual rendering
          comes from layer 1.

       Excluded input types: checkbox / radio (own .checkbox-label),
       file / color / range (preserve native UI), hidden / submit / button
       / image / reset (non-visible or are buttons).

       Cascade note: this block lives in @layer components. Component CSS
       files (web/static/css/components/*.css), vendor themes (Tom Select),
       and per-module CSS are unlayered, so they ALWAYS win regardless of
       selector specificity. That is the intended escape hatch — the date
       field, command palette, password toggle, etc. continue to override
       freely without !important.
       ========================================================================== */

    /* ---- Native baseline (works everywhere, no class needed) ---- */
    :where(
        select,
        textarea,
        input[type="text"],
        input[type="search"],
        input[type="email"],
        input[type="number"],
        input[type="tel"],
        input[type="url"],
        input[type="password"],
        input[type="date"],
        input[type="datetime-local"],
        input[type="month"],
        input[type="time"],
        input[type="week"]
    ) {
        padding: 0.625rem 0.875rem;
        font-size: var(--text-base);
        font-family: inherit;
        line-height: 1.5;
        color: var(--color-text);
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border-strong);
        border-radius: var(--radius-md);
        min-height: var(--touch-target);
        transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
    }

    /* :focus-visible scoped to the same selector list as the visual
       baseline above — checkbox/radio focus is owned by the dedicated
       .checkbox-label / .checkbox-box pair (see line ~2540), and adding
       a box-shadow halo on top would compete with that pattern. */
    :where(
        select,
        textarea,
        input[type="text"],
        input[type="search"],
        input[type="email"],
        input[type="number"],
        input[type="tel"],
        input[type="url"],
        input[type="password"],
        input[type="date"],
        input[type="datetime-local"],
        input[type="month"],
        input[type="time"],
        input[type="week"]
    ):focus-visible {
        outline: 2px solid transparent;
        border-color: var(--color-primary);
        box-shadow: 0 0 0 3px var(--color-primary-light);
    }

    /* Composite input pattern (.input-wrapper)
       ---------------------------------------------------------------
       When an input/select/textarea sits inside a wrapper that owns
       its own focus indicator via :focus-within (search boxes,
       password fields with a visibility toggle, currency inputs,
       quantity steppers, etc.), the per-element focus ring above
       would stack with the wrapper's ring and produce a visible
       double border. Marking the wrapper `.input-wrapper` defers
       focus rendering to it — one ring per composite control,
       matching Material 3 / GOV.UK / IBM Carbon conventions.

       Contract:
         - The wrapper MUST style :focus-within itself (border-color,
           box-shadow, etc.). This rule only suppresses the inner
           ring; without a wrapper-level focus state, keyboard users
           lose every visible focus indicator on the control.
         - The selector mirrors the focus-visible block above so the
           neutralisation tracks any future addition to the input
           type list.

       Adopt by adding `.input-wrapper` next to your component class
       on the wrapper element (e.g. `.input-wrapper .my-search`).
       --------------------------------------------------------------- */
    /* Invalid state — the visual half of the field-error contract
       (docs/UI_FORMS.md §4). The selector is [aria-invalid="true"] rather
       than a parallel class: the attribute is what assistive technology
       reads, so the visual and the accessible state cannot drift apart.

       These live INSIDE @layer components, and before the .input-wrapper
       rule below, on purpose. Unlayered they outranked every layered rule
       and broke the "one ring per composite control" convention: a focused
       invalid password field drew the wrapper ring AND an inner ring. Equal
       specificity plus source order now lets the exclusion win. */
    :where(input, select, textarea)[aria-invalid="true"] {
        border-color: var(--color-danger-border);
    }

    /* The focus indicator stays unmistakable on an invalid field
       (WCAG 2.4.7): it changes hue, it does not disappear. */
    :where(input, select, textarea)[aria-invalid="true"]:focus-visible {
        border-color: var(--color-danger);
        box-shadow: 0 0 0 3px var(--color-danger-subtle);
    }

    /* Composite controls (password fields, search boxes) strip the inner
       border and let the wrapper own the chrome — so the wrapper is where
       the error has to show, or a marked password field renders no error
       chrome at all and only the message below betrays it. */
    .input-wrapper:has([aria-invalid="true"]) {
        border-color: var(--color-danger-border);
    }

    .input-wrapper:has([aria-invalid="true"]):focus-within {
        border-color: var(--color-danger);
        box-shadow: 0 0 0 3px var(--color-danger-subtle);
    }

    .input-wrapper :where(input, select, textarea):focus-visible {
        box-shadow: none;
        border-color: transparent;
    }

    /* Forced-colors safety net — Windows High Contrast users would
       otherwise lose every focus indication if a wrapper ever
       forgets to style :focus-within. The Highlight system colour
       is the standard ensure-it-renders fallback in this mode.

       The second rule prevents the global forced-colors `border: 1px
       solid CanvasText` (see end of style.css) from re-introducing a
       border on the bare inner control — the wrapper already carries
       its own border, so without this we'd see the exact double border
       the .input-wrapper convention is meant to eliminate. */
    @media (forced-colors: active) {
        .input-wrapper :where(input, select, textarea):focus-visible {
            border-color: Highlight;
        }
        .input-wrapper :where(input, select, textarea) {
            border: 0;
        }
    }

    /* :disabled — propagate the dimmed state to the wrapper so the
       chrome (border, background) dims along with the text content.
       Without this, the bare inner input would dim alone while the
       wrapper kept its full-saturation border — visually inconsistent
       with every other disabled input in the app. The inner control's
       own opacity is reset to 1 so the dim effect doesn't multiply
       (CSS opacity composes; 0.6 × 0.6 = 0.36 reads as broken). */
    .input-wrapper:has(:where(input, select, textarea):disabled) {
        opacity: 0.6;
        cursor: not-allowed;
    }
    .input-wrapper :where(input, select, textarea):disabled {
        opacity: 1;
    }

    /* Currency / amount input (CoreAmountInput helper)
       ---------------------------------------------------------------
       Composite input combining a numeric field and a trailing
       currency suffix (e.g. "1’234.56" + " CHF"). Mounted by
       window.CoreAmountInput.attach() onto any element with
       data-amount-input.

       Chrome (border, radius, background, min-height, padding,
       font-size) mirrors the framework's native :where(select, input,
       textarea) baseline (line ~1500) so a CoreAmountInput sits next
       to a date picker or a text field with the same visual weight —
       same border colour, same elevation, same touch target. The
       wrapper owns the focus ring per the .input-wrapper convention;
       the inner input is borderless so the ring isn't doubled.
       --------------------------------------------------------------- */
    .input-wrapper.hwc-amount-input {
        display: inline-flex;
        align-items: center;
        gap: var(--space-xs, 0.5rem);
        /* Match the native :where(input) baseline so the input visually
           reads as a peer of every other field in the form, not a
           low-contrast wrapper that disappears on a card. */
        border: 1px solid var(--color-border-strong);
        border-radius: var(--radius-md);
        background-color: var(--color-bg-elevated);
        min-height: var(--touch-target);
        padding: 0 0.875rem;
        transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
    }

    .input-wrapper.hwc-amount-input:focus-within {
        border-color: var(--color-primary);
        box-shadow: 0 0 0 3px var(--color-primary-subtle);
    }

    .input-wrapper.hwc-amount-input > input {
        flex: 1;
        border: none;
        background: transparent;
        /* Reset the native :where(input) padding — the wrapper now owns
           the horizontal chrome and the touch target, so the inner
           input only contributes content. */
        padding: 0;
        min-height: auto;
        font-size: var(--text-base);
        line-height: 1.5;
        text-align: right;
        font-variant-numeric: tabular-nums;
        min-width: 0;
    }

    .input-wrapper.hwc-amount-input > input:focus,
    .input-wrapper.hwc-amount-input > input:focus-visible {
        outline: 2px solid transparent;
        box-shadow: none;
    }

    .hwc-amount-suffix {
        color: var(--color-text-muted);
        font-size: var(--font-size-sm, 0.875rem);
        font-weight: 500;
        user-select: none;
        flex-shrink: 0;
    }

    :where(input, textarea)::placeholder {
        color: var(--color-text-muted);
        opacity: 1; /* Firefox lowers placeholder opacity by default */
    }

    /* :disabled scoped to text-like inputs + select + textarea. Native
       checkboxes/radios have their own disabled rendering managed by the
       UA; restating opacity 0.6 here would double-dim the .checkbox-box
       sibling pattern. */
    :where(
        select,
        textarea,
        input[type="text"],
        input[type="search"],
        input[type="email"],
        input[type="number"],
        input[type="tel"],
        input[type="url"],
        input[type="password"],
        input[type="date"],
        input[type="datetime-local"],
        input[type="month"],
        input[type="time"],
        input[type="week"]
    ):disabled {
        opacity: 0.6;
        cursor: not-allowed;
    }

    /* Hide number input spinners — financial UI never wants them. */
    :where(input[type="number"])::-webkit-inner-spin-button,
    :where(input[type="number"])::-webkit-outer-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }
    :where(input[type="number"]) {
        -moz-appearance: textfield;
    }

    /* Custom chevron for <select> — replaces the inconsistent native arrow
       (Chrome triangle vs Safari blue arrow vs Firefox different glyph)
       with the framework's Lucide chevron-down. CSP-safe: data: URI is
       allowed by `img-src 'self' data: blob:` (security.go:93). Logical
       properties (padding-inline-end, position-x: right) keep the chevron
       on the trailing edge in both LTR and RTL writing modes. The fill
       hex matches --color-text-muted exactly (light: #475569, dark:
       #94a3b8 — the values from tokens.css's @supports-not fallback) so
       the arrow tracks the muted text colour. */
    :where(select) {
        appearance: none;
        padding-inline-end: 2.25rem;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 0.625rem center;
        background-size: 1rem 1rem;
    }

    [data-theme="dark"] :where(select) {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    }

    /* <select multiple> renders as a list box — drop the chevron and
       single-line height. */
    :where(select[multiple]) {
        appearance: auto;
        padding-inline-end: 0.875rem;
        background-image: none;
        min-height: auto;
    }

    /* Inline-edit inside table cells: tighter so the row keeps its
       compact rhythm. Used by mod-rag/admin/documents.html and similar. */
    :where(td) :where(select, textarea, input) {
        min-height: auto;
        padding: 0.25rem 0.5rem;
    }

    /* Reduced motion respects user preference. */
    @media (prefers-reduced-motion: reduce) {
        :where(select, textarea, input) {
            transition: none;
        }
    }

    /* ---- Layout concerns scoped to .form-group ---- */
    .form-group {
        margin-bottom: 1.25rem;
    }

    .form-group label {
        display: block;
        margin-bottom: var(--space-sm);
        font-size: 0.875rem;
        font-weight: 500;
        color: var(--color-text-secondary);
    }

    /*
     * Inside .form-group fields stretch to 100% width — that is the
     * vertical-form layout convention. Visual rendering (border, padding,
     * colours, focus ring, placeholder, spinner suppression, dark-mode
     * chevron) lives on the element-level rule above and is shared with
     * filter bars, table cells and any inline use.
     *
     * Checkboxes and radios are excluded: stretching them to 100% turns
     * them into 400-px boxes. They use the .checkbox-label / .checkbox-box
     * pair instead.
     */
    .form-group :is(input:not([type="checkbox"]):not([type="radio"]), select, textarea) {
        width: 100%;
    }

    .form-group textarea {
        min-height: 120px;
        resize: vertical;
    }

    .form-group .form-static {
        padding: 0.625rem 0.875rem;
        font-size: var(--text-base);
        line-height: 1.5;
        color: var(--color-text-secondary);
        background-color: var(--color-bg-subtle);
        border: 1px dashed var(--color-border);
        border-radius: var(--radius-md);
    }

    /* Password input with toggle — composite control following the
       .input-wrapper pattern (see "Composite input pattern" block above
       and CSS_CONVENTIONS.md). The wrapper owns the visual chrome
       (border, padding, background, focus ring); the inner <input> is
       bare so the two no longer compete for the focus indicator. The
       baseline values mirror the framework's standalone-input default
       so the visual identity is preserved across the migration. */
    .password-input-wrapper {
        position: relative;
        display: flex;
        align-items: center;
        padding: 0.625rem 0.875rem;
        font-size: var(--text-base);
        line-height: 1.5;
        color: var(--color-text);
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border-strong);
        border-radius: var(--radius-md);
        min-height: var(--touch-target);
        transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
    }

    /* The wrapper's :focus-within ring fires both when the inner
       <input> AND when the .password-toggle has focus. The toggle
       also keeps its own outline (see below) — that dual indication
       is intentional: the toggle is a sibling interactive element,
       Tab-able on its own, and users navigating by keyboard need to
       know which sub-element is currently focused. Same precedent as
       the search ✕ button in mod-budgetcontrol's bc-filter-toolbar-search. */
    .password-input-wrapper:focus-within {
        border-color: var(--color-primary);
        box-shadow: 0 0 0 3px var(--color-primary-light);
    }

    .password-input-wrapper input {
        flex: 1;
        /* Strip the framework baseline — the wrapper now owns chrome. */
        padding: 0;
        border: 0;
        background: transparent;
        outline: none;
        font: inherit;
        color: inherit;
        min-height: 0;
        /* Reserve room for the floating .password-toggle on the right.
           Toggle is right:0.5rem + width:2.25rem = 2.75rem from the
           wrapper's padding edge. We add a bit more (2.5rem on the
           input's content side, on top of the wrapper's 0.875rem
           padding-right = 3.375rem total to the wrapper's border)
           so a long password with proportional fonts stays clear of
           the toggle's hit area. */
        padding-right: 2.5rem;
    }

    .password-toggle {
        position: absolute;
        right: 0.5rem;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 2.25rem;
        height: 2.25rem;
        background: transparent;
        border: none;
        border-radius: var(--radius-sm);
        color: var(--color-text-muted);
        cursor: pointer;
        transition: color var(--transition-fast);
    }

    .password-toggle:hover {
        color: var(--color-text);
    }

    .password-toggle:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: 2px;
    }

    .password-toggle .icon-hide {
        display: none;
    }

    .password-toggle[aria-pressed="true"] .icon-show {
        display: none;
    }

    .password-toggle[aria-pressed="true"] .icon-hide {
        display: block;
    }

    /* Password strength indicator */
    .password-strength {
        margin-top: var(--space-sm);
    }

    .password-strength-bar {
        height: 4px;
        background-color: var(--color-border);
        border-radius: 2px;
        overflow: hidden;
    }

    .password-strength-fill {
        height: 100%;
        width: 0;
        border-radius: 2px;
        transition: width var(--transition-fast), background-color var(--transition-fast);
    }

    .password-strength-fill[data-strength="weak"] {
        width: 33%;
        background-color: var(--color-danger);
    }

    .password-strength-fill[data-strength="medium"] {
        width: 66%;
        background-color: var(--color-warning);
    }

    .password-strength-fill[data-strength="strong"] {
        width: 100%;
        background-color: var(--color-success);
    }

    .password-strength-text {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-top: var(--space-xs);
        font-size: 0.75rem;
        color: var(--color-text-muted);
    }

    .password-strength-label {
        font-weight: 500;
    }

    .password-strength-label[data-strength="weak"] {
        color: var(--color-danger);
    }

    .password-strength-label[data-strength="medium"] {
        color: var(--color-warning);
    }

    .password-strength-label[data-strength="strong"] {
        color: var(--color-success);
    }

    /* Password requirements checklist */
    .password-requirements {
        margin-top: var(--space-sm);
        padding: var(--space-sm) var(--space-md);
        background: var(--color-bg-subtle);
        border-radius: var(--radius-md);
        border: 1px solid var(--color-border);
    }

    .password-requirements-title {
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--color-text-muted);
        text-transform: uppercase;
        letter-spacing: 0.025em;
        margin-bottom: var(--space-xs);
    }

    .password-requirements-list {
        list-style: none;
        padding: 0;
        margin: 0;
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
    }

    .password-requirements-list li {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        font-size: 0.8125rem;
        color: var(--color-text-muted);
        transition: color var(--transition-fast);
    }

    .password-requirements-list li.valid {
        color: var(--color-success);
    }

    .password-requirements-list li.invalid {
        color: var(--color-danger);
    }

    .password-rule-icon {
        width: 14px;
        height: 14px;
        flex-shrink: 0;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .password-rule-icon::before {
        content: "○";
        font-size: 0.625rem;
    }

    .password-requirements-list li.valid .password-rule-icon::before {
        content: "✓";
        font-size: 0.875rem;
    }

    .password-requirements-list li.invalid .password-rule-icon::before {
        content: "✗";
        font-size: 0.875rem;
    }

    /* Password match feedback */
    .password-match-feedback {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin-top: var(--space-xs);
        font-size: 0.8125rem;
    }

    .password-match-feedback.match {
        color: var(--color-success);
    }

    .password-match-feedback.no-match {
        color: var(--color-danger);
    }

    .password-match-icon {
        width: 14px;
        height: 14px;
        flex-shrink: 0;
    }

    .password-match-feedback.match .password-match-icon::before {
        content: "✓";
    }

    .password-match-feedback.no-match .password-match-icon::before {
        content: "✗";
    }

    /* ==========================================================================
       Alerts
       ========================================================================== */
    .alert {
        padding: 0.875rem var(--space-md);
        margin-bottom: 1.25rem;
        border-radius: var(--radius-md);
        font-size: 0.875rem;
    }

    .alert-error {
        background-color: light-dark(#fef2f2, #450a0a);
        border: 1px solid light-dark(#fecaca, #7f1d1d);
        color: light-dark(#991b1b, #fecaca);
    }

    .alert-success {
        background-color: light-dark(#f0fdf4, #052e16);
        border: 1px solid light-dark(#bbf7d0, #166534);
        color: light-dark(#166534, #bbf7d0);
        transition: opacity 0.4s ease-out;
    }

    .alert-info {
        background-color: light-dark(#eff6ff, #1e3a5f);
        border: 1px solid light-dark(#bfdbfe, #1e40af);
        color: light-dark(#1e40af, #bfdbfe);
    }

    .alert-info a {
        color: inherit;
        word-break: break-all;
    }

    .alert-warning {
        background-color: light-dark(#fffbeb, #451a03);
        border: 1px solid light-dark(#fde68a, #92400e);
        color: light-dark(#92400e, #fde68a);
    }

    /* Alias: use .alert-error instead */
    .alert-danger {
        background-color: light-dark(#fef2f2, #450a0a);
        border: 1px solid light-dark(#fecaca, #7f1d1d);
        color: light-dark(#991b1b, #fecaca);
    }

    /* Fallback for alerts without light-dark() */
    @supports not (color: light-dark(#000, #fff)) {
        .alert-error {
            background-color: #fef2f2;
            border: 1px solid #fecaca;
            color: #991b1b;
        }

        .alert-success {
            background-color: #f0fdf4;
            border: 1px solid #bbf7d0;
            color: #166534;
            transition: opacity 0.4s ease-out;
        }

        .alert-info {
            background-color: #eff6ff;
            border: 1px solid #bfdbfe;
            color: #1e40af;
        }

        .alert-warning {
            background-color: #fffbeb;
            border: 1px solid #fde68a;
            color: #92400e;
        }

        /* Alias: use .alert-error instead */
        .alert-danger {
            background-color: #fef2f2;
            border: 1px solid #fecaca;
            color: #991b1b;
        }

        [data-theme="dark"] .alert-error {
            background-color: #450a0a;
            border-color: #7f1d1d;
            color: #fecaca;
        }

        [data-theme="dark"] .alert-success {
            background-color: #052e16;
            border-color: #166534;
            color: #bbf7d0;
        }

        [data-theme="dark"] .alert-info {
            background-color: #1e3a5f;
            border-color: #1e40af;
            color: #bfdbfe;
        }

        [data-theme="dark"] .alert-warning {
            background-color: #451a03;
            border-color: #92400e;
            color: #fde68a;
        }

        /* Alias: use .alert-error instead */
        [data-theme="dark"] .alert-danger {
            background-color: #450a0a;
            border-color: #7f1d1d;
            color: #fecaca;
        }

        .admin-badge {
            background-color: rgba(245, 158, 11, 0.15);
            border: 1px solid rgba(245, 158, 11, 0.3);
        }

        .role-badge-admin {
            border-color: rgba(59, 130, 246, 0.3);
        }

        .status-badge.status-enabled {
            background-color: rgba(34, 197, 94, 0.1);
        }

        [data-theme="dark"] .admin-badge {
            background-color: rgba(245, 158, 11, 0.2);
            border-color: rgba(245, 158, 11, 0.4);
        }

        [data-theme="dark"] .role-badge-admin {
            border-color: rgba(59, 130, 246, 0.4);
        }

        [data-theme="dark"] .status-badge.status-enabled {
            background-color: rgba(34, 197, 94, 0.15);
        }
    }

    /* ==========================================================================
       Language switcher (legacy - kept for auth pages)
       ========================================================================== */
    .language-switcher {
        display: inline-flex;
    }

    .language-form {
        margin: 0;
    }

    .language-select {
        padding: var(--space-xs) var(--space-sm);
        font-size: 0.875rem;
        background-color: var(--color-bg-subtle);
        color: var(--color-text);
        border: 1px solid var(--color-border-strong);
        border-radius: var(--radius-sm);
        cursor: pointer;
        /* Compact picker — opt out of the framework chevron baseline; this
           legacy switcher uses the OS dropdown arrow. */
        appearance: auto;
        background-image: none;
        min-height: auto;
    }

    .language-select:focus {
        outline: 2px solid transparent;
        border-color: var(--color-primary);
    }

    /* ==========================================================================
       Preference switchers — two contextual variants share the same visual
       and behavioural pattern; selector unions keep the rules DRY across
       theme and language pickers.

       Variants:
       - .theme-radio-list / .language-radio-list:
           inline radio group, used inside already-open dropdowns
           (user menu, landing mobile menu) where a popover would add an
           unnecessary extra step.
       - .theme-menu / .language-menu:
           popover menu, used as a standalone navbar button (auth header,
           landing desktop header). Open/close, light-dismiss, flip-up and
           shift positioning are handled by the shared MenuPopover JS helper.
       ========================================================================== */

    /* Inline radio list */
    .theme-radio-list,
    .language-radio-list {
        display: flex;
        flex-direction: column;
        padding: 0.25rem 0;
    }

    .theme-radio,
    .language-radio {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        width: 100%;
        min-height: var(--touch-target);
        padding: 0.5rem 1rem;
        background: transparent;
        border: none;
        color: var(--color-text-secondary);
        font: inherit;
        text-align: left;
        cursor: pointer;
        transition: background-color 0.15s, color 0.15s;
    }

    .theme-radio:hover,
    .language-radio:hover {
        background-color: var(--color-bg-hover);
    }

    .theme-radio:focus-visible,
    .language-radio:focus-visible {
        outline: 2px solid transparent;
        background-color: var(--color-bg-hover);
        box-shadow: inset 2px 0 0 var(--color-primary);
    }

    .theme-radio[aria-checked="true"],
    .language-radio[aria-checked="true"] {
        color: var(--color-primary);
        background-color: var(--color-primary-light);
    }

    .theme-radio svg {
        flex-shrink: 0;
    }

    /* Language radio: label fills the row, the trailing check appears on the
       active item (theme uses a leading icon instead, so this is the only
       language-specific rule). */
    .language-radio-form {
        margin: 0;
    }

    .language-radio span {
        flex: 1;
    }

    .language-radio-check {
        flex-shrink: 0;
        opacity: 0;
    }

    .language-radio[aria-checked="true"] .language-radio-check {
        opacity: 1;
    }

    /* Cap the language list at ~8 items and scroll beyond — graceful
       degradation when an admin enables many languages, without needing
       a separate fallback component. The cap is derived from the touch
       target token so item count stays consistent if the token changes. */
    .language-radio-list {
        max-height: calc(8 * var(--touch-target));
        overflow-y: auto;
    }

    /* Popover menu (auth header, landing desktop header) */
    .theme-menu,
    .language-menu {
        position: relative;
        display: inline-flex;
    }

    .theme-menu-trigger,
    .language-menu-trigger {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 36px;
        height: 36px;
        padding: 0;
        background-color: transparent;
        border: 1px solid transparent;
        border-radius: var(--radius-sm);
        color: var(--color-text-secondary);
        cursor: pointer;
        transition: background-color 0.2s, border-color 0.2s, color 0.2s;
    }

    .theme-menu-trigger:hover,
    .language-menu-trigger:hover {
        background-color: var(--color-bg-hover);
        color: var(--color-primary);
    }

    .theme-menu-trigger:focus-visible,
    .language-menu-trigger:focus-visible {
        outline: 2px solid transparent;
        border-color: var(--color-primary);
        box-shadow: 0 0 0 2px var(--color-primary-light);
    }

    .theme-menu-icon {
        display: none;
    }

    .theme-menu[data-theme-preference="light"] .theme-menu-icon-light,
    .theme-menu[data-theme-preference="system"] .theme-menu-icon-system,
    .theme-menu[data-theme-preference="dark"] .theme-menu-icon-dark {
        display: block;
    }

    /* Popover panel — standard anchored popover. position:absolute against
       the positioned parent (.theme-menu / .language-menu) means the
       containing block is predictable across all browsers. The base state
       uses the [hidden] attribute for SSR-safe initial rendering; JS
       toggles it on open. */
    .theme-menu-popover,
    .language-menu-popover {
        display: flex;
        flex-direction: column;
        position: absolute;
        top: calc(100% + 0.375rem);
        right: 0;
        z-index: var(--z-dropdown);
        min-width: 180px;
        padding: 0.25rem;
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-md, 0 8px 16px rgba(0, 0, 0, 0.12));
        color: var(--color-text);
    }

    .theme-menu-popover[hidden],
    .language-menu-popover[hidden] {
        display: none;
    }

    /* Flip upward when the menu would overflow the viewport bottom */
    .theme-menu-popover.is-flip-up,
    .language-menu-popover.is-flip-up {
        top: auto;
        bottom: calc(100% + 0.375rem);
    }

    /* Same cap as .language-radio-list — see comment above. The popover
       handles many-language deployments by scrolling internally rather
       than overflowing the viewport. Theme always has 3 fixed options
       so the same rule isn't applied to .theme-menu-popover. */
    .language-menu-popover {
        max-height: calc(8 * var(--touch-target));
        overflow-y: auto;
    }

    .theme-menu-item,
    .language-menu-item {
        display: flex;
        align-items: center;
        gap: 0.625rem;
        width: 100%;
        min-height: var(--touch-target);
        padding: 0.5rem 0.625rem;
        background: transparent;
        border: none;
        border-radius: var(--radius-sm);
        color: var(--color-text-secondary);
        font: inherit;
        text-align: left;
        cursor: pointer;
        transition: background-color 0.15s, color 0.15s;
    }

    .theme-menu-item:hover,
    .language-menu-item:hover {
        background-color: var(--color-bg-hover);
    }

    .theme-menu-item:focus-visible,
    .language-menu-item:focus-visible {
        outline: 2px solid transparent;
        background-color: var(--color-bg-hover);
        color: var(--color-primary);
    }

    .theme-menu-item[aria-checked="true"],
    .language-menu-item[aria-checked="true"] {
        color: var(--color-primary);
    }

    .theme-menu-item svg[aria-hidden="true"]:first-of-type {
        flex-shrink: 0;
    }

    .theme-menu-item span,
    .language-menu-item span {
        flex: 1;
    }

    .theme-menu-check,
    .language-menu-check {
        flex-shrink: 0;
        opacity: 0;
    }

    .theme-menu-item[aria-checked="true"] .theme-menu-check,
    .language-menu-item[aria-checked="true"] .language-menu-check {
        opacity: 1;
    }

    /* Wrap each language item in its own POST form; reset default form margin
       so the popover spacing comes from the panel padding only. */
    .language-menu-form {
        margin: 0;
    }

    /* ==========================================================================
       Admin Badge
       ========================================================================== */
    .admin-badge {
        display: inline-flex;
        align-items: center;
        padding: 0.125rem 0.5rem;
        font-size: 0.625rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--color-warning);
        background-color: light-dark(rgba(245, 158, 11, 0.15), rgba(245, 158, 11, 0.2));
        border: 1px solid light-dark(rgba(245, 158, 11, 0.3), rgba(245, 158, 11, 0.4));
        border-radius: var(--radius-sm);
    }

    /* ==========================================================================
       Section title
       ========================================================================== */
    .section-title {
        font-size: 1.125rem;
        font-weight: 600;
        color: var(--color-text-secondary);
        margin-top: var(--space-xl);
        margin-bottom: var(--space-md);
        padding-bottom: var(--space-sm);
        border-bottom: 2px solid var(--color-border);
    }

    /* ==========================================================================
       Dashboard
       ========================================================================== */
    .dashboard-welcome {
        margin-bottom: var(--space-md);
    }

    .welcome-card {
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        padding: var(--space-md);
        box-shadow: var(--shadow-sm);
    }

    .welcome-card h3 {
        font-size: 1.125rem;
        font-weight: 600;
        color: var(--color-text);
        margin-bottom: var(--space-sm);
    }

    .welcome-card p {
        color: var(--color-text-secondary);
        font-size: 0.875rem;
    }

    .dashboard-placeholder {
        display: grid;
        gap: var(--space-md);
    }

    .placeholder-card {
        background-color: var(--color-bg-elevated);
        border-radius: var(--radius-md);
        padding: var(--space-xl);
        box-shadow: var(--shadow-md);
        text-align: center;
        border: 2px dashed var(--color-border);
    }

    .placeholder-icon {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 64px;
        height: 64px;
        background-color: var(--color-bg-subtle);
        border-radius: 50%;
        margin-bottom: var(--space-md);
        color: var(--color-text-muted);
    }

    .placeholder-icon svg {
        width: 32px;
        height: 32px;
    }

    .placeholder-card h4 {
        font-size: 1rem;
        font-weight: 600;
        color: var(--color-text);
        margin-bottom: var(--space-sm);
    }

    .placeholder-card p {
        color: var(--color-text-secondary);
        font-size: 0.875rem;
        max-width: 300px;
        margin: 0 auto;
    }

    /* ==========================================================================
       Error pages
       ========================================================================== */
    .error-code {
        font-size: clamp(4rem, 15vw, 6rem);
        font-weight: 700;
        color: var(--color-border);
        line-height: 1;
        margin-bottom: var(--space-sm);
    }

    .error-title {
        font-size: 1.5rem;
        font-weight: 600;
        color: var(--color-text);
        margin-bottom: var(--space-sm);
    }

    .error-message {
        font-size: 1rem;
        color: var(--color-text-secondary);
        margin-bottom: var(--space-lg);
    }

    /* ==========================================================================
       Credentials list
       ========================================================================== */
    .credentials-list {
        margin: var(--space-md) 0;
    }

    .credential-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: var(--space-sm) var(--space-md);
        background-color: var(--color-bg-subtle);
        border-radius: var(--radius-md);
        margin-bottom: var(--space-sm);
        gap: var(--space-md);
        container-type: inline-size;
    }

    .credential-info {
        display: flex;
        flex-direction: column;
        min-width: 0;
    }

    .credential-name {
        font-weight: 500;
        color: var(--color-text);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .credential-date {
        font-size: 0.75rem;
        color: var(--color-text-muted);
    }

    .credential-actions {
        display: flex;
        gap: var(--space-sm);
        flex-shrink: 0;
    }

    @container (max-width: 400px) {
        .credential-item {
            flex-direction: column;
            align-items: stretch;
        }

        .credential-actions {
            margin-top: var(--space-sm);
            justify-content: flex-end;
        }
    }

    .inline-form {
        display: inline;
    }

    /* ==========================================================================
       Recovery codes
       ========================================================================== */
    .recovery-codes-display {
        background-color: var(--color-bg-subtle);
        border-radius: var(--radius-md);
        padding: var(--space-md);
        margin: var(--space-md) 0;
    }

    .warning-text {
        color: var(--color-warning);
        font-weight: 500;
        margin-bottom: var(--space-md);
    }

    .codes-list {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
        gap: var(--space-sm);
        margin-bottom: var(--space-md);
    }

    .recovery-code-item {
        display: flex;
        align-items: center;
        background-color: var(--color-bg-elevated);
        padding: var(--space-sm) var(--space-md);
        border-radius: var(--radius-sm);
        border: 1px solid var(--color-border);
    }

    .code-number {
        font-size: 0.75rem;
        color: var(--color-text-muted);
        margin-right: var(--space-sm);
        min-width: 1.5rem;
    }

    .recovery-code {
        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        font-size: 0.875rem;
        letter-spacing: 0.05em;
        color: var(--color-text);
    }

    .recovery-phrase-box {
        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        font-size: 1rem;
        line-height: 1.6;
        padding: var(--space-md);
        background: var(--color-surface-muted, var(--color-surface));
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        color: var(--color-text);
        word-spacing: 0.4em;
        user-select: all;
        min-height: 4.5em;
    }

    .recovery-codes-actions {
        display: flex;
        align-items: center;
        gap: var(--space-md);
        padding-top: var(--space-sm);
        border-top: 1px solid var(--color-border);
    }

    .copy-status {
        font-size: 0.875rem;
        transition: opacity var(--transition-fast);
    }

    .copy-status.success {
        color: var(--color-success);
    }

    .copy-status.error {
        color: var(--color-danger);
    }

    .recovery-status {
        color: var(--color-text-secondary);
        margin: var(--space-md) 0;
    }

    .status-enabled {
        color: var(--color-success);
    }

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

    /* ==========================================================================
       Modal Actions (legacy support for forms with button groups)
       ========================================================================== */
    .modal-actions {
        display: flex;
        justify-content: flex-end;
        gap: var(--space-sm);
        margin-top: var(--space-lg);
    }

    /* ==========================================================================
       2FA page
       ========================================================================== */
    .twofa-section {
        margin: var(--space-lg) 0;
    }

    .twofa-section h3 {
        font-size: 1rem;
        font-weight: 600;
        margin-bottom: var(--space-sm);
        color: var(--color-text);
    }

    .twofa-section p {
        font-size: 0.875rem;
        color: var(--color-text-secondary);
        margin-bottom: var(--space-md);
    }

    .divider {
        display: flex;
        align-items: center;
        margin: var(--space-lg) 0;
    }

    .divider::before,
    .divider::after {
        content: '';
        flex: 1;
        height: 1px;
        background-color: var(--color-border);
    }

    .divider span {
        padding: 0 var(--space-md);
        color: var(--color-text-muted);
        font-size: 0.875rem;
    }

    .status-message {
        margin-top: var(--space-md);
        font-size: 0.875rem;
        color: var(--color-text-secondary);
        text-align: center;
    }

    .status-message.error {
        color: var(--color-danger);
    }

    /* ==========================================================================
       Checkbox
       ========================================================================== */
    .form-checkbox {
        margin: var(--space-lg) 0;
    }

    .checkbox-label {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        cursor: pointer;
        font-size: 0.875rem;
        color: var(--color-text);
        user-select: none;
        position: relative;
        min-height: var(--touch-target);
        padding: var(--space-xs) 0;
    }

    .checkbox-label:has(.checkbox-content) {
        align-items: flex-start;
    }

    .checkbox-label input[type="checkbox"] {
        position: absolute;
        opacity: 0;
        width: 0;
        height: 0;
        pointer-events: none;
    }

    .checkbox-box {
        position: relative;
        flex-shrink: 0;
        width: 20px;
        height: 20px;
        border: 2px solid var(--color-border);
        border-radius: var(--radius-sm);
        background-color: var(--color-bg-elevated);
        transition: var(--motion-hover);
    }

    .checkbox-box::after {
        content: '';
        position: absolute;
        display: none;
        left: 6px;
        top: 2px;
        width: 5px;
        height: 10px;
        border: solid var(--color-primary-contrast);
        border-width: 0 2px 2px 0;
        transform: rotate(45deg);
    }

    .checkbox-label input[type="checkbox"]:checked + .checkbox-box {
        background-color: var(--color-primary);
        border-color: var(--color-primary);
    }

    .checkbox-label input[type="checkbox"]:checked + .checkbox-box::after {
        display: block;
    }

    .checkbox-label input[type="checkbox"]:focus-visible + .checkbox-box {
        outline: 2px solid var(--color-primary);
        outline-offset: 2px;
    }

    .checkbox-label:hover .checkbox-box {
        border-color: var(--color-primary);
    }

    /* Simplified checkbox with native styling for form checkboxes */
    .checkbox-group {
        display: flex;
        flex-direction: column;
        gap: var(--space-sm);
        margin-top: var(--space-sm);
    }

    .checkbox-group .checkbox-label {
        display: flex;
        gap: var(--space-sm);
        padding: var(--space-sm) var(--space-md);
        background-color: var(--color-bg-subtle);
        border-radius: var(--radius-md);
        border: 1px solid var(--color-border);
        transition: var(--motion-hover);
        cursor: pointer;
    }

    .checkbox-group .checkbox-label:hover {
        border-color: var(--color-primary);
        background-color: var(--color-bg-elevated);
    }

    .checkbox-group .checkbox-label:has(input:checked) {
        border-color: var(--color-primary);
        background-color: var(--color-primary-light);
    }

    .checkbox-group .checkbox-label input[type="checkbox"] {
        position: static;
        opacity: 1;
        width: 18px;
        height: 18px;
        pointer-events: auto;
        accent-color: var(--color-primary);
        cursor: pointer;
        flex-shrink: 0;
    }

    .checkbox-text {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        font-size: 0.875rem;
        color: var(--color-text);
    }

    .badge-small {
        display: inline-flex;
        padding: 0.125rem 0.375rem;
        font-size: 0.6875rem;
        font-weight: 500;
        border-radius: var(--radius-sm);
        background-color: var(--color-bg-subtle);
        color: var(--color-text-muted);
    }

    .badge-small.badge-admin {
        color: var(--color-primary);
        background-color: var(--color-primary-light);
    }

    .checkbox-content {
        display: flex;
        flex-direction: column;
        gap: 2px;
        line-height: 1.4;
    }

    .checkbox-title {
        font-weight: 500;
        color: var(--color-text);
    }

    .checkbox-hint {
        font-size: 0.75rem;
        color: var(--color-text-muted);
        font-weight: 400;
    }

    /* ==========================================================================
       Radio group — the selectable-card twin of .checkbox-group for an exclusive
       choice. The native radio is branded with accent-color (no hand-drawn control,
       matching the simplified checkbox above); the selected option's card is
       highlighted. Reuses .checkbox-content / .checkbox-title / .checkbox-hint for
       rich option text (title + description).
       ========================================================================== */
    .radio-group {
        display: flex;
        flex-direction: column;
        gap: var(--space-sm);
        margin-top: var(--space-sm);
    }

    .radio-option {
        display: flex;
        align-items: flex-start;
        gap: var(--space-sm);
        padding: var(--space-sm) var(--space-md);
        min-height: var(--touch-target);
        background-color: var(--color-bg-subtle);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        font-size: 0.875rem;
        color: var(--color-text);
        cursor: pointer;
        transition: var(--motion-hover);
    }

    .radio-option:hover {
        border-color: var(--color-primary);
        background-color: var(--color-bg-elevated);
    }

    .radio-option:has(input:checked) {
        border-color: var(--color-primary);
        background-color: var(--color-primary-light);
    }

    .radio-option input[type="radio"] {
        width: 18px;
        height: 18px;
        margin-top: 0.125rem;
        accent-color: var(--color-primary);
        cursor: pointer;
        flex-shrink: 0;
    }

    /* Progressive disclosure: a .radio-option-extra block placed immediately after an
       option shows only while that option is selected. CSS :has() — inert on older
       browsers, where the block simply stays visible (never hidden), so its field is
       always reachable. NB: a field inside here is only display:none, not disabled, so
       it is still constraint-validated when hidden — avoid `required`/`type="url"` on
       it (a hidden invalid value blocks submit unfocusably) and validate server-side. */
    .radio-option-extra {
        padding: 0 var(--space-md);
    }

    .radio-option:not(:has(input:checked)) + .radio-option-extra {
        display: none;
    }

    /* ==========================================================================
       Admin Components
       ========================================================================== */

    /* Admin stats grid */
    .admin-stats,
    .stat-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: var(--space-md);
        margin-bottom: var(--space-xl);
    }

    /* Stat cards */
    .stat-card {
        display: flex;
        align-items: center;
        gap: var(--space-md);
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        padding: var(--space-md);
        box-shadow: var(--shadow-sm);
        position: relative;
        overflow: hidden;
    }

    .stat-card::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 4px;
        height: 100%;
        background-color: var(--color-primary);
    }

    .stat-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 48px;
        height: 48px;
        background-color: var(--color-primary-light);
        border-radius: var(--radius-md);
        color: var(--color-primary);
        flex-shrink: 0;
    }

    .stat-icon svg {
        width: 24px;
        height: 24px;
    }

    .stat-content {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-width: 0;
    }

    .stat-value {
        font-size: 1.5rem;
        font-weight: 700;
        color: var(--color-text);
        line-height: 1.2;
    }

    .stat-label {
        font-size: 0.875rem;
        color: var(--color-text-secondary);
        margin-top: 0.125rem;
    }

    .stat-link {
        font-size: 0.75rem;
        color: var(--color-primary);
        text-decoration: none;
        white-space: nowrap;
        transition: color var(--transition-fast);
    }

    .stat-link:hover {
        color: var(--color-primary-hover);
        text-decoration: underline;
    }

    /* Quick actions */
    .admin-quick-actions {
        margin-bottom: var(--space-xl);
    }

    .admin-quick-actions h3 {
        font-size: 1rem;
        font-weight: 600;
        color: var(--color-text);
        margin-bottom: var(--space-md);
    }

    .quick-actions-grid {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: var(--space-md);
    }

    .quick-action-card {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: var(--space-sm);
        padding: var(--space-md);
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        text-decoration: none;
        color: var(--color-text);
        transition: var(--motion-hover);
        min-height: var(--touch-target);
    }

    .quick-action-card:hover {
        border-color: var(--color-primary);
        box-shadow: var(--shadow-md);
        transform: translateY(-2px);
        text-decoration: none;
    }

    /* The focus ring, restored where a hover shadow would swallow it.
       This card is an <a>, so it takes keyboard focus, and the global
       `:focus-visible { box-shadow: var(--focus-ring) }` lives in @layer base
       while the hover rule above lives in @layer components — LAYERS BEAT
       SPECIFICITY, so no amount of specificity in base could win. Restated
       here, in the same layer and after the hover rule, it does.
       Measured before this rule: a keyboard-focused card that was also hovered
       painted --shadow-md and no ring at all. WCAG 2.4.7 (level A). */
    .quick-action-card:focus-visible {
        box-shadow: var(--focus-ring);
    }

    .quick-action-card svg {
        width: 28px;
        height: 28px;
        color: var(--color-primary);
    }

    .quick-action-card span {
        font-size: 0.8125rem;
        font-weight: 500;
        text-align: center;
    }

    /* ==========================================================================
       Navigation Cards
       Reusable component for settings/admin navigation links with icon
       ========================================================================== */
    .nav-card-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
        gap: var(--space-md);
    }

    .nav-card {
        display: flex;
        align-items: center;
        gap: var(--space-md);
        padding: var(--space-lg);
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        text-decoration: none;
        color: var(--color-text);
        transition: var(--motion-hover);
    }

    .nav-card:hover {
        border-color: var(--color-primary);
        box-shadow: var(--shadow-md);
        transform: translateY(-2px);
        text-decoration: none;
    }

    .nav-card-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 48px;
        height: 48px;
        background-color: var(--color-primary);
        border-radius: var(--radius-md);
        color: var(--color-primary-contrast);
        flex-shrink: 0;
    }

    .nav-card-icon svg {
        width: 24px;
        height: 24px;
    }

    .nav-card-content h3 {
        margin: 0 0 0.25rem 0;
        font-size: 1rem;
        font-weight: 600;
        color: var(--color-text);
    }

    .nav-card-content p {
        margin: 0;
        font-size: 0.875rem;
        color: var(--color-text-muted);
    }

    /* Stat card details (sub-statistics) */
    .stat-details {
        display: flex;
        gap: var(--space-sm);
        margin-top: var(--space-xs);
        flex-wrap: wrap;
    }

    .stat-detail {
        font-size: 0.75rem;
        padding: 0.125rem 0.375rem;
        border-radius: var(--radius-sm);
    }

    .stat-detail-success {
        background-color: var(--color-success-light);
        color: var(--color-success);
    }

    .stat-detail-warning {
        background-color: var(--color-warning-light);
        color: var(--color-warning);
    }

    /* Warning state for stat cards */
    .stat-card-warning::before {
        background-color: var(--color-warning);
    }

    .stat-icon-warning {
        background-color: var(--color-warning-light);
        color: var(--color-warning);
    }

    /* Recent activity section */
    .admin-recent-activity {
        margin-bottom: var(--space-xl);
    }

    .recent-activity-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: var(--space-md);
    }

    .recent-activity-header h3 {
        font-size: 1rem;
        font-weight: 600;
        color: var(--color-text);
        margin: 0;
    }

    .recent-activity-link {
        font-size: 0.875rem;
        color: var(--color-primary);
        text-decoration: none;
    }

    .recent-activity-link:hover {
        text-decoration: underline;
    }

    .recent-activity-list {
        background-color: var(--color-bg-elevated);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-md);
        overflow: hidden;
    }

    .recent-activity-item {
        display: flex;
        align-items: center;
        gap: var(--space-md);
        padding: var(--space-sm) var(--space-md);
        border-bottom: 1px solid var(--color-border);
    }

    .recent-activity-item:last-child {
        border-bottom: none;
    }

    .recent-activity-item-failure {
        background-color: var(--color-danger-light);
    }

    .recent-activity-time {
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        min-width: 50px;
        flex-shrink: 0;
    }

    .activity-date {
        font-size: 0.75rem;
        color: var(--color-text-secondary);
    }

    .activity-time {
        font-size: 0.75rem;
        font-weight: 500;
        color: var(--color-text);
    }

    .recent-activity-content {
        flex: 1;
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 0.125rem;
    }

    .activity-action {
        font-size: 0.875rem;
        font-weight: 500;
        color: var(--color-text);
    }

    .activity-user {
        font-size: 0.75rem;
        color: var(--color-text-secondary);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .recent-activity-status {
        flex-shrink: 0;
    }

    .status-dot {
        display: block;
        width: 8px;
        height: 8px;
        border-radius: 50%;
    }

    .status-dot-success {
        background-color: var(--color-success);
    }

    .status-dot-failure {
        background-color: var(--color-danger);
    }

    .recent-activity-empty {
        padding: var(--space-lg);
        text-align: center;
        color: var(--color-text-secondary);
        background-color: var(--color-bg-elevated);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-md);
    }

    /* Admin tables */
    .admin-table-container {
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        box-shadow: var(--shadow-sm);
        overflow: hidden;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .admin-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 0.875rem;
        min-width: 600px;
    }

    /* Modifier: no arbitrary floor — the table is exactly as wide as its
       content needs. The 600px above is sized for a browse table of 6-9
       columns; on a narrower summary it is padding that pushes real columns off
       a phone. Measured at 412px (container 328-378px):
         /loans "Encours par devise"  2 cols — natural 328px, floored to 600 →
             the right-aligned quantities sat at x≈600-640, i.e. a column of
             currency codes next to blank space;
         /charts/value per-currency   4 cols — natural 482px, floored to 600 →
             118px of pure padding scrolled out of reach for nothing.
       Keep the scroll container either way: it is what signposts the overflow,
       and with this modifier a table can still be wider than its container —
       it just stops being wider than its own content. */
    .admin-table--compact {
        min-width: 0;
    }

    .admin-table thead {
        background-color: var(--color-bg-subtle);
        border-bottom: 2px solid var(--color-border);
    }

    .admin-table th {
        padding: var(--space-md) var(--space-md);
        text-align: left;
        font-weight: 600;
        color: var(--color-text-secondary);
        font-size: 0.75rem;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        white-space: nowrap;
    }

    /* Sortable column headers (see components/sort-header.html). */
    .admin-table th.sortable {
        padding: 0;
    }

    .admin-table th.sortable .sort-link {
        display: inline-flex;
        align-items: center;
        gap: var(--space-xs);
        width: 100%;
        padding: var(--space-md) var(--space-md);
        color: inherit;
        font: inherit;
        letter-spacing: inherit;
        text-transform: inherit;
        text-decoration: none;
        cursor: pointer;
        user-select: none;
        white-space: nowrap;
        transition: color var(--transition-fast), background-color var(--transition-fast);
    }

    .admin-table th.sortable .sort-link:hover,
    .admin-table th.sorted .sort-link {
        color: var(--color-text);
    }

    .admin-table th.sortable .sort-link:hover {
        background-color: var(--color-bg-hover);
    }

    .admin-table th.sortable .sort-link:focus-visible {
        outline: 2px solid var(--color-primary);
        outline-offset: -2px;
    }

    .admin-table th.sortable .sort-indicator {
        font-size: 0.85em;
        line-height: 1;
        opacity: 0.4;
    }

    .admin-table th.sortable .sort-indicator-active {
        opacity: 1;
        color: var(--color-primary);
    }

    /* Numeric columns: right-align + tabular figures (opt-in via .col-numeric). */
    .admin-table th.col-numeric,
    .admin-table td.col-numeric {
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

    .admin-table th.col-numeric.sortable .sort-link {
        justify-content: flex-end;
    }

    .admin-table td {
        padding: var(--space-md) var(--space-md);
        color: var(--color-text);
        border-bottom: 1px solid var(--color-border);
        vertical-align: middle;
    }

    .admin-table tbody tr {
        transition: background-color var(--transition-fast);
    }

    .admin-table tbody tr:hover {
        background-color: var(--color-bg-subtle);
    }

    .admin-table tbody tr:last-child td {
        border-bottom: none;
    }

    .actions-cell {
        white-space: nowrap;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: var(--space-xs);
    }

    /* Badges */
    .role-badge {
        display: inline-flex;
        align-items: center;
        padding: 0.25rem 0.625rem;
        font-size: 0.75rem;
        font-weight: 500;
        color: var(--color-text);
        background-color: var(--color-bg-subtle);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-full);
    }

    .role-badge-admin {
        color: var(--color-primary);
        background-color: var(--color-primary-light);
        border-color: light-dark(rgba(59, 130, 246, 0.3), rgba(59, 130, 246, 0.4));
    }

    .role-badge-none {
        color: var(--color-text-muted);
        background-color: transparent;
        border-style: dashed;
    }

    .role-badge-more {
        color: var(--color-text-muted);
        background-color: var(--color-bg-muted);
        cursor: help;
    }

    .role-badge + .role-badge {
        margin-left: 0.25rem;
    }

    .status-badge {
        display: inline-flex;
        align-items: center;
        gap: var(--space-xs);
        padding: 0.125rem 0.5rem;
        font-size: 0.75rem;
        font-weight: 500;
        border-radius: var(--radius-full);
        background-color: var(--color-bg-subtle);
        color: var(--color-text-secondary);
        white-space: nowrap;
    }

    .status-badge.status-enabled {
        color: var(--color-success);
        background-color: light-dark(rgba(34, 197, 94, 0.1), rgba(34, 197, 94, 0.15));
    }

    .status-badge.status-disabled {
        color: var(--color-text-muted);
        background-color: var(--color-bg-subtle);
    }

    /* User account status badges */
    .status-badge.status-active {
        color: var(--color-success);
        background-color: light-dark(rgba(34, 197, 94, 0.1), rgba(34, 197, 94, 0.15));
    }

    .status-badge.status-suspended {
        color: var(--color-danger);
        background-color: light-dark(rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.15));
    }

    .status-badge.status-pending {
        color: light-dark(#92400e, #fbbf24);
        background-color: light-dark(rgba(245, 158, 11, 0.15), rgba(245, 158, 11, 0.2));
    }

    .status-badge.status-danger {
        color: var(--color-danger);
        background-color: light-dark(rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.15));
    }

    .status-badge.status-inactive {
        color: var(--color-text-muted);
        background-color: var(--color-bg-subtle);
    }

    .status-badge-icon {
        width: 12px;
        height: 12px;
    }

    /* General purpose badges */
    .badge {
        display: inline-flex;
        align-items: center;
        padding: 0.125rem 0.5rem;
        font-size: 0.75rem;
        font-weight: 500;
        border-radius: var(--radius-sm);
        background-color: var(--color-bg-subtle);
        color: var(--color-text-secondary);
        white-space: nowrap;
    }

    .badge-success {
        color: var(--color-success);
        background-color: var(--color-success-light);
    }

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

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

    .badge-warning {
        color: light-dark(#92400e, #fbbf24);
        background-color: var(--color-warning-light);
    }

    .badge-info {
        color: var(--color-primary);
        background-color: var(--color-primary-light);
    }

    .badge-primary {
        color: var(--color-primary);
        background-color: var(--color-primary-light);
    }

    .badge-secondary {
        color: var(--color-text-muted);
        background-color: var(--color-bg-subtle);
    }

    .permissions-count,
    .permissions-info {
        font-size: 0.875rem;
        color: var(--color-text-secondary);
    }

    /* Back link */
    .back-link {
        display: inline-flex;
        align-items: center;
        gap: var(--space-xs);
        margin-bottom: var(--space-lg);
        font-size: 0.875rem;
        color: var(--color-text-secondary);
        text-decoration: none;
        transition: color var(--transition-fast);
        min-height: var(--touch-target);
    }

    .back-link:hover {
        color: var(--color-primary);
        text-decoration: none;
    }

    .back-link svg {
        width: 16px;
        height: 16px;
    }

    /* Admin form */
    .admin-form-container {
        max-width: 640px;
    }

    .form-card {
        background-color: var(--color-bg-elevated);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        padding: var(--space-md);
        box-shadow: var(--shadow-sm);
    }

    .form-card h3 {
        font-size: 1.125rem;
        font-weight: 600;
        color: var(--color-text);
        margin-bottom: var(--space-lg);
        padding-bottom: var(--space-md);
        border-bottom: 1px solid var(--color-border);
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        flex-wrap: wrap;
    }

    .role-type-label {
        font-size: 0.75rem;
        font-weight: 400;
        color: var(--color-text-muted);
    }

    .form-info {
        margin: var(--space-lg) 0;
        padding: var(--space-md);
        background-color: var(--color-bg-subtle);
        border-radius: var(--radius-md);
        border-left: 3px solid var(--color-primary);
    }

    .form-info p {
        font-size: 0.875rem;
        color: var(--color-text-secondary);
        margin: 0;
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        flex-wrap: wrap;
    }

    .form-info strong {
        color: var(--color-text);
    }

    .form-actions {
        display: flex;
        gap: var(--space-sm);
        margin-top: var(--space-lg);
        padding-top: var(--space-lg);
        border-top: 1px solid var(--color-border);
    }

    /* Permissions fieldset */
    fieldset.form-group {
        border: none;
        padding: 0;
        margin: 0 0 1.25rem 0;
    }

    fieldset.form-group legend {
        display: block;
        margin-bottom: var(--space-sm);
        font-size: 0.875rem;
        font-weight: 500;
        color: var(--color-text-secondary);
    }

    .permissions-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: var(--space-sm);
        margin-top: var(--space-sm);
    }

    .permissions-grid .checkbox-label {
        padding: var(--space-sm) var(--space-md);
        background-color: var(--color-bg-subtle);
        border-radius: var(--radius-md);
        border: 1px solid var(--color-border-strong);
        transition: var(--motion-hover);
    }

    .permissions-grid .checkbox-label:hover {
        border-color: var(--color-primary);
        background-color: var(--color-bg-elevated);
    }

    .permissions-grid .checkbox-label .checkbox-content span {
        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        font-size: 0.8125rem;
        color: var(--color-text);
    }

    .permissions-grid .checkbox-label .checkbox-content small {
        display: block;
        font-size: 0.75rem;
        color: var(--color-text-muted);
        margin-top: 0.125rem;
        font-family: inherit;
    }
}

/* ==========================================================================
   View Transitions — intentionally not enabled globally

   Cross-document view transitions (`@view-transition { navigation: auto }`)
   are a tempting nice-to-have: the browser crossfades between pages with
   zero JS. In practice they regress click responsiveness on dashboard-
   style UIs where users rapid-click through the sidebar.

   Chromium today swallows the second click when it arrives while the
   browser is still capturing the outgoing frame for the first navigation
   (tracked upstream under issues around rapid same-origin nav). The
   admin-first priority here is reliability, so we do NOT opt in.

   Per-element opt-ins remain possible with `view-transition-name` on
   small components that don't participate in navigation (e.g. a
   modal backdrop that should crossfade when opened). Add them locally
   if needed — do not re-introduce a global @view-transition rule.
   ========================================================================== */

/* ==========================================================================
   Utilities Layer - Helper classes
   ========================================================================== */
@layer utilities {
    /* Display */
    .hidden {
        display: none !important;
    }

    .d-flex {
        display: flex;
    }

    .d-grid {
        display: grid;
    }

    .d-inline-flex {
        display: inline-flex;
    }

    .d-block {
        display: block;
    }

    /* Flexbox direction & wrap */
    .flex-column {
        flex-direction: column;
    }

    .flex-wrap {
        flex-wrap: wrap;
    }

    /* Flexbox alignment */
    .items-center {
        align-items: center;
    }

    .items-start {
        align-items: flex-start;
    }

    .justify-between {
        justify-content: space-between;
    }

    .justify-center {
        justify-content: center;
    }

    .justify-end {
        justify-content: flex-end;
    }

    /* Gap (using design tokens) */
    .gap-xs {
        gap: var(--space-xs);
    }

    .gap-sm {
        gap: var(--space-sm);
    }

    .gap-md {
        gap: var(--space-md);
    }

    .gap-lg {
        gap: var(--space-lg);
    }

    .gap-xl {
        gap: var(--space-xl);
    }

    /* Text alignment */
    .text-center {
        text-align: center;
    }

    .text-right {
        text-align: right;
    }

    /* Single-line truncation with an ellipsis. The max-width caps a table cell so
       a long value (e.g. a verbose imported description) does not push the other
       columns out — pair with a title attribute for the full text on hover.

       `min(24rem, 100%)` and not a bare `24rem`: 24rem is 384px, wider than the
       content area of a 412px phone, so outside a table the element ran 89px
       past its card — measured on /theta-nodes/nodes/1 at Pixel 7, right edge
       485px against a card ending at 396px. And nothing scrolled: the document
       stayed 412/412, so the tail of the value was not clipped but UNREACHABLE,
       the same shape check-table-overflow exists for, one element to the left.
       Capping at the container makes the ellipsis do its job at every width. */
    .text-truncate {
        max-width: min(24rem, 100%);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* max-width (and thus the ellipsis) has no effect on inline elements;
       inline-block makes the truncation effective for <code> hosts (long
       hashes/addresses in tables) while <td> hosts keep their display. */
    code.text-truncate {
        display: inline-block;
        vertical-align: bottom;
    }

    /* In tables, hex addresses/hashes truncate hard (prefix + ellipsis, the
       usual crypto-explorer pattern): a 42-char 0x address fits under 24rem
       untruncated and pushes the action column out of the viewport. The full
       value stays reachable (title tooltip + detail pages). */
    .admin-table code.text-truncate {
        max-width: 16ch;
    }

    /* The percentage shown BESIDE an inline progress bar (a table cell) rather
       than overlaid — the centred `.progress-percent` is low-contrast once the
       bar is full. Everything else about that layout is utility classes
       (`d-flex items-center gap-sm`, `flex-1`, `text-right`); the fixed width is
       not, and it keeps the column from reflowing between a "5%" row and a
       "100%" row.

       Lives HERE, with the utilities, and not beside the progress-bar family in
       components/backup.css: that file is linked globally from layout/base.html
       and layout/app.html, but nothing in its name or header says so, and its
       two consumers are modules (mod-loans, mod-theta-nodes). Scoping that sheet
       per-page one day would have broken them silently. */
    .progress-value {
        min-width: 3ch;
    }

    /* A value the user is meant to COPY, not read: one click selects all of it.
       Named for the intent rather than shipped as a `user-select` utility, and
       deliberately not folded into `code.text-truncate` — that class also
       styles 16ch-truncated hashes inside tables, where select-all would fight
       range selection across a row. */
    .select-all {
        user-select: all;
    }

    /* A long machine-readable value shown in full (a node summary, an address
       list, a recovery blob) — the block counterpart of `code.text-truncate`.
       Breaks anywhere, because these values have no spaces to break at.
       Spacing is left to the utility classes (`mt-md`, `mb-xs`): this is a
       component, not a layout.

       NOT named `.code-block`: admin-landing.css already defines that name for
       a pre-formatted code SAMPLE (`white-space: pre`, horizontal scroll), the
       opposite wrapping behaviour. It is loaded on four admin pages only, so
       there is no collision today — and two same-named classes with opposite
       semantics is exactly the trap that survives until someone widens a
       stylesheet's scope. */
    .code-value {
        display: block;
        padding: var(--space-sm);
        background-color: var(--color-bg-subtle);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-sm);
        overflow-wrap: anywhere;
        word-break: break-all;
        user-select: all;
        font-size: var(--text-sm);
        line-height: var(--leading-snug);
    }

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

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

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

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

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

    /* Font utilities */
    .font-bold {
        font-weight: 700;
    }

    .font-semibold {
        font-weight: 600;
    }

    .font-lg {
        font-size: 1.25rem;
    }

    .font-xl {
        font-size: 1.5rem;
    }

    .font-2xl {
        font-size: 2rem;
    }

    /* Spacing - margin bottom */
    .mb-0 {
        margin-bottom: 0;
    }

    .mb-xs {
        margin-bottom: var(--space-xs);
    }

    .mb-sm {
        margin-bottom: var(--space-sm);
    }

    .mb-md {
        margin-bottom: var(--space-md);
    }

    .mb-lg {
        margin-bottom: var(--space-lg);
    }

    .mb-xl {
        margin-bottom: var(--space-xl);
    }

    /* Spacing - margin top */
    .mt-0 {
        margin-top: 0;
    }

    .mt-xs {
        margin-top: var(--space-xs);
    }

    .mt-sm {
        margin-top: var(--space-sm);
    }

    .mt-md {
        margin-top: var(--space-md);
    }

    .mt-lg {
        margin-top: var(--space-lg);
    }

    .mt-xl {
        margin-top: var(--space-xl);
    }

    /* Spacing - horizontal auto (centering) */
    .mx-auto {
        margin-left: auto;
        margin-right: auto;
    }

    /* Padding - vertical (top + bottom) */
    .py-sm {
        padding-top: var(--space-sm);
        padding-bottom: var(--space-sm);
    }

    .py-md {
        padding-top: var(--space-md);
        padding-bottom: var(--space-md);
    }

    .py-lg {
        padding-top: var(--space-lg);
        padding-bottom: var(--space-lg);
    }

    .py-xl {
        padding-top: var(--space-xl);
        padding-bottom: var(--space-xl);
    }

    /* Display - additional */
    .d-inline {
        display: inline;
    }

    .d-contents {
        display: contents;
    }

    /* Text transforms */
    .text-uppercase {
        text-transform: uppercase;
    }

    .text-lowercase {
        text-transform: lowercase;
    }

    /* Flexbox - additional */
    .flex-1 {
        flex: 1;
    }

    /* Spacing - margin right */
    .mr-xs {
        margin-right: var(--space-xs);
    }

    .mr-sm {
        margin-right: var(--space-sm);
    }

    /* Spacing - margin left */
    .ml-xs {
        margin-left: var(--space-xs);
    }

    .ml-sm {
        margin-left: var(--space-sm);
    }

    /* Sizing */
    .h-full {
        height: 100%;
    }

    .max-w-xs {
        max-width: 100px;
    }

    .max-w-sm {
        max-width: 400px;
    }

    .max-w-md {
        max-width: 500px;
    }

    .max-w-lg {
        max-width: 700px;
    }

    /* Border radius */
    .rounded-full {
        border-radius: var(--radius-full);
    }

    /* Font - additional */
    .font-mono {
        font-family: monospace;
    }

    .font-sm {
        font-size: 0.875rem;
    }

    /* Grid layouts */
    .grid-2 {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: var(--space-md);
    }

    .grid-auto-fit {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: var(--space-md);
    }

    /* Dividers */
    .section-divider {
        padding-top: var(--space-lg);
        border-top: 1px solid var(--color-border);
    }

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

    /* Skip link - hidden until keyboard-focused (WCAG 2.4.1 Bypass Blocks) */
    .skip-link {
        position: absolute;
        top: 0;
        left: 0;
        padding: var(--space-sm) var(--space-md);
        background: var(--color-primary);
        color: var(--color-primary-contrast);
        font-weight: 600;
        text-decoration: none;
        border-radius: 0 0 var(--radius-md) 0;
        box-shadow: var(--shadow-lg);
        z-index: var(--z-skip-link);
        transform: translateY(-100%);
        transition: transform var(--transition-fast);
    }

    .skip-link:focus {
        transform: translateY(0);
        outline: 2px solid var(--color-text-inverted);
        outline-offset: -4px;
    }

    /* Remove default focus outline on the landing anchor target itself */
    #main-content:focus {
        outline: none;
    }

    /* SVG sprite icons rendered by {{icon "name"}} template helper.
       Inherits color via currentColor, never shrinks in flex containers. */
    .icon {
        display: inline-block;
        vertical-align: middle;
        flex-shrink: 0;
        fill: none;
        stroke: currentColor;
    }
}

/* ==========================================================================
   Responsive Styles - Mobile grid stacking
   ========================================================================== */
@media (max-width: 767px) {
    .grid-2 {
        grid-template-columns: 1fr;
    }
}

/* ==========================================================================
   Responsive Styles - Tablet (768px+)
   ========================================================================== */
@media (min-width: 768px) {
    :root {
        /* Default: mini (collapsed, icons-only) on tablet+ */
        --sidebar-width: var(--sidebar-width-mini);
    }

    .app-layout {
        padding-bottom: 0;
    }

    /* Header hidden on tablet+ when sidebar is visible */
    .app-header {
        display: none;
    }

    /* Main content - no top margin when header is hidden */
    .main-content {
        margin-top: 0;
    }

    /* Sidebar visible as mini */
    .sidebar {
        transform: translateX(0);
        width: var(--sidebar-width-mini);
        /* Allow dropdowns to overflow sidebar bounds (user menu) */
        overflow: visible;
    }

    .sidebar-overlay {
        display: none;
    }

    .sidebar-header {
        padding: var(--space-sm);
        flex-direction: column;
        align-items: center;
        gap: 0;
    }

    /* Tablet+: hide sidebar logo (shown in content-top-bar instead) */
    .sidebar-logo {
        display: none;
    }

    .sidebar-close {
        display: none;
    }

    /* Tablet+: show sidebar toggle (hamburger) */
    .sidebar-toggle {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 32px;
        height: 32px;
        background: none;
        border: none;
        color: var(--sidebar-text);
        cursor: pointer;
        border-radius: var(--radius-md);
        padding: 0;
        flex-shrink: 0;
        transition: background var(--transition-fast);
    }

    .sidebar-toggle:hover {
        background: rgba(255, 255, 255, 0.1);
    }

    /* Mini mode: hide section headers and chevrons */
    .nav-section-header {
        display: none;
    }

    .nav-section-title {
        display: none;
    }

    .nav-section-chevron {
        display: none;
    }

    /* In mini mode, always show all items (ignore collapsed state) */
    .nav-section.collapsed .nav-section-items {
        max-height: none;
    }

    .nav-item {
        padding: 0.75rem;
        justify-content: center;
        overflow: visible;
    }

    .nav-label {
        display: none;
    }

    /* Allow tooltips to overflow outside nav containers in mini mode */
    .sidebar-nav {
        overflow: visible;
    }

    .nav-section-items {
        overflow: visible;
    }

    /* Utility zone in mini mode */
    .sidebar-utility {
        align-items: center;
    }

    .sidebar-utility-item {
        justify-content: center;
        padding: 0.75rem;
        overflow: visible;
        position: relative;
    }

    .sidebar-utility-label {
        display: none;
    }

    .sidebar-utility-badge {
        position: absolute;
        top: 4px;
        right: 4px;
        margin-left: 0;
        min-width: 16px;
        height: 16px;
        font-size: 0.625rem;
        padding: 0 4px;
    }

    /* Tooltips in mini mode for all sidebar elements with data-tooltip */
    .nav-item[data-tooltip]:hover::after,
    .sidebar-toggle[data-tooltip]:hover::after,
    .sidebar-utility-item[data-tooltip]:hover::after,
    .user-menu-trigger[data-tooltip]:hover::after {
        content: attr(data-tooltip);
        position: absolute;
        left: calc(100% + var(--space-sm));
        top: 50%;
        transform: translateY(-50%);
        padding: var(--space-xs) var(--space-sm);
        background-color: var(--color-text);
        color: var(--color-text-inverted);
        font-size: 0.75rem;
        border-radius: var(--radius-sm);
        white-space: nowrap;
        z-index: 10;
    }

    /* Toggle and user-menu-trigger need relative positioning for tooltip */
    .sidebar-toggle,
    .user-menu-trigger {
        position: relative;
    }

    /* Hide user menu tooltip when dropdown is open */
    .user-menu.open .user-menu-trigger[data-tooltip]:hover::after {
        display: none;
    }

    /* Tooltips for content-top-bar elements (positioned below) */
    .content-top-bar [data-tooltip] {
        position: relative;
    }

    .content-top-bar [data-tooltip]:hover::after,
    .content-top-bar [data-tooltip]:focus-visible::after {
        content: attr(data-tooltip);
        position: absolute;
        top: calc(100% + var(--space-xs));
        left: 50%;
        transform: translateX(-50%);
        padding: var(--space-xs) var(--space-sm);
        background-color: var(--color-text);
        color: var(--color-text-inverted);
        font-size: 0.75rem;
        border-radius: var(--radius-sm);
        white-space: nowrap;
        z-index: 10;
        pointer-events: none;
    }

    /* Hide tooltip when element with a popup has it open */
    .content-top-bar [aria-haspopup][aria-expanded="true"][data-tooltip]:hover::after,
    .content-top-bar [aria-haspopup][aria-expanded="true"][data-tooltip]:focus-visible::after {
        display: none;
    }

    .sidebar-footer {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: var(--space-sm);
    }

    /* User menu in sidebar footer - mini sidebar */
    .sidebar-footer .user-menu {
        width: auto;
    }

    .sidebar-footer .user-menu-trigger {
        justify-content: center;
        padding: var(--space-sm);
    }

    .sidebar-footer .user-name {
        display: none;
    }

    .sidebar-footer .user-menu-chevron {
        display: none;
    }

    .sidebar-footer .user-menu-dropdown {
        left: 0;
        right: auto;
        bottom: 100%;
        top: auto;
        margin-bottom: var(--space-xs);
    }

    /* Main content */
    .main-content {
        margin-left: var(--sidebar-width);
    }

    .content-body {
        padding: var(--space-lg);
        padding-bottom: calc(var(--space-lg) + env(safe-area-max-inset-bottom, env(safe-area-inset-bottom, 0px)));
        scroll-padding-bottom: calc(var(--space-lg) + env(safe-area-max-inset-bottom, env(safe-area-inset-bottom, 0px)));
    }

    /* Tablet+: content-top-bar back in normal flow (not overlaying header) */
    .content-top-bar {
        position: relative;
        top: auto;
        right: auto;
        height: auto;
        padding: var(--space-xs) var(--space-lg);
        background: none;
        pointer-events: auto;
        flex-shrink: 0;
        z-index: var(--z-dropdown);
    }

    /* Logo visible in content-top-bar on tablet+ */
    .content-top-bar-logo {
        display: flex;
        align-items: center;
        gap: var(--space-xs);
        text-decoration: none;
        color: var(--color-text);
        font-weight: 600;
        font-size: 1rem;
        margin-right: auto;
        flex-shrink: 0;
    }

    .content-top-bar-logo:hover {
        text-decoration: none;
    }

    .content-top-bar-logo-image {
        height: 48px;
        width: auto;
    }

    /* Admin stats */
    .admin-stats,
    .stat-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    /* Permissions grid */
    .permissions-grid {
        grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    }

    /* Form card */
    .form-card {
        padding: var(--space-lg);
    }
}

/* ==========================================================================
   Responsive Styles - Sidebar expanded state (tablet+)
   The expanded state is controlled via html.sidebar-expanded class to prevent
   flash on page load. The class is set early by sidebar-init.js.
   ========================================================================== */
@media (min-width: 768px) {
    /* Keep --sidebar-width in sync with the real sidebar width so every
       consumer of var(--sidebar-width) (main-content, selection-bar, any
       future fixed element) picks up the expanded state automatically. */
    html.sidebar-expanded {
        --sidebar-width: var(--sidebar-width-full);
    }

    html.sidebar-expanded .sidebar {
        width: var(--sidebar-width-full);
    }

    /* .main-content's margin-left already reads var(--sidebar-width)
       above, so the override that used to duplicate sidebar-width-full
       here is dropped. Kept the explicit override below only when the
       selector needs to be scoped (sidebar, app-header). */

    html.sidebar-expanded .app-header {
        left: var(--sidebar-width-full);
    }

    html.sidebar-expanded .sidebar-header {
        padding: var(--space-md) var(--space-lg);
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        gap: var(--space-sm);
    }

    /* Restore scrolling and overflow in expanded mode */
    html.sidebar-expanded .sidebar-nav {
        overflow-y: auto;
    }

    html.sidebar-expanded .nav-section-items {
        overflow: hidden;
    }

    html.sidebar-expanded .nav-section-header {
        display: flex;
    }

    html.sidebar-expanded .nav-section-title {
        display: flex;
    }

    html.sidebar-expanded .nav-section-chevron {
        display: block;
    }

    /* Restore collapsed state in expanded mode */
    html.sidebar-expanded .nav-section.collapsed .nav-section-items {
        max-height: 0;
    }

    html.sidebar-expanded .nav-item {
        overflow: hidden;
        padding: 0.75rem var(--space-lg);
        justify-content: flex-start;
    }

    html.sidebar-expanded .nav-label {
        display: block;
    }

    /* Utility zone in expanded mode */
    html.sidebar-expanded .sidebar-utility-item {
        overflow: hidden;
        padding: var(--space-sm) var(--space-lg);
        justify-content: flex-start;
    }

    html.sidebar-expanded .sidebar-utility-label {
        display: block;
    }

    html.sidebar-expanded .sidebar-utility-badge {
        position: static;
        margin-left: auto;
        min-width: 18px;
        height: 18px;
        font-size: 0.6875rem;
        padding: 0 5px;
    }

    /* Hide all tooltips when sidebar is expanded (labels are visible) */
    html.sidebar-expanded .nav-item[data-tooltip]:hover::after,
    html.sidebar-expanded .sidebar-toggle[data-tooltip]:hover::after,
    html.sidebar-expanded .sidebar-utility-item[data-tooltip]:hover::after,
    html.sidebar-expanded .user-menu-trigger[data-tooltip]:hover::after {
        display: none;
    }

    /* Sidebar footer - expanded sidebar */
    html.sidebar-expanded .sidebar-footer {
        align-items: stretch;
    }

    html.sidebar-expanded .sidebar-footer .user-menu {
        width: 100%;
    }

    html.sidebar-expanded .sidebar-footer .user-menu-trigger {
        justify-content: flex-start;
    }

    html.sidebar-expanded .sidebar-footer .user-name {
        display: block;
    }

    html.sidebar-expanded .sidebar-footer .user-menu-chevron {
        display: block;
    }

    /* Cursor: pointer on mini sidebar to indicate it's clickable to expand */
    html:not(.sidebar-expanded) .sidebar {
        cursor: pointer;
    }

    /* Reset cursor on interactive elements within mini sidebar */
    html:not(.sidebar-expanded) .sidebar a,
    html:not(.sidebar-expanded) .sidebar button {
        cursor: pointer;
    }

    /* Reset cursor when expanded */
    html.sidebar-expanded .sidebar {
        cursor: default;
    }
}

/* ==========================================================================
   Responsive Styles - Desktop (1024px+)
   Unified behavior with tablet: mini by default, .expanded when user opens
   ========================================================================== */
@media (min-width: 1024px) {
    /* Note: overflow: visible for sidebar is inherited from tablet (768px+) */

    /* Larger content padding on desktop */
    .content-body {
        padding: var(--space-xl);
        padding-bottom: calc(var(--space-xl) + env(safe-area-max-inset-bottom, env(safe-area-inset-bottom, 0px)));
        scroll-padding-bottom: calc(var(--space-xl) + env(safe-area-max-inset-bottom, env(safe-area-inset-bottom, 0px)));
    }

    .content-top-bar {
        padding: var(--space-xs) var(--space-xl);
    }

    /* Desktop inherits tablet's mini-by-default behavior.
       No need to override most tablet rules - they work correctly. */
}

/* ==========================================================================
   No Sidebar Layout
   Used when non-admin users have access to only one navigation item.
   The sidebar is hidden and content extends to full width.
   Header is shown since user-menu is not available in sidebar.
   ========================================================================== */
.no-sidebar .main-content {
    margin-left: 0;
    /* Mirror the mobile/header offset so the header reserves status-bar inset */
    margin-top: calc(var(--header-height) + env(safe-area-inset-top, 0px));
}

.no-sidebar .app-header {
    display: flex;
    justify-content: space-between;
    left: 0;
}

/* Hide hamburger when there's no sidebar to open */
.no-sidebar .header-menu-toggle {
    display: none;
}

/* Show logo in no-sidebar mode */
.no-sidebar .header-logo {
    display: flex;
}

/* In no-sidebar mode: logo image styling */
.no-sidebar .header-logo-image {
    height: 32px;
    width: auto;
}

/* Show user-menu in header when no sidebar (only way to access profile/logout) */
.no-sidebar .app-header .user-menu {
    display: flex;
}

/* ==========================================================================
   Container queries for content-body children
   ========================================================================== */
@container (min-width: 500px) {
    .dashboard-placeholder {
        grid-template-columns: repeat(2, 1fr);
    }

    .admin-stats,
    .stat-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .codes-list {
        grid-template-columns: repeat(2, 1fr);
    }
}

@container (min-width: 800px) {
    .dashboard-placeholder {
        grid-template-columns: repeat(3, 1fr);
    }

    .quick-actions-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .admin-stats,
    .stat-grid {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* ========================================
   Branding Settings
   ======================================== */

.branding-item {
    padding: 1.5rem 0;
    border-bottom: 1px solid var(--color-border);
}

.branding-item:first-of-type {
    padding-top: 0;
}

.branding-item:last-of-type {
    border-bottom: none;
    padding-bottom: 0;
}

.branding-label {
    display: block;
    font-weight: 500;
    margin-bottom: 0.75rem;
    color: var(--color-text);
}

/* Inline row: preview + buttons aligned horizontally */
.branding-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

/* Preview container */
.branding-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.branding-preview-logo {
    width: 300px;
    height: 100px;
    padding: 0.75rem;
}

.branding-preview-favicon {
    width: 80px;
    height: 80px;
    padding: 0.5rem;
}

.branding-preview-avatar {
    width: 96px;
    height: 96px;
    border-radius: 50%;
}

.branding-preview-avatar .branding-current-image,
.branding-preview-avatar .branding-preview-image {
    border-radius: 50%;
}

.branding-preview-empty {
    border-style: dashed;
}

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

.branding-preview .branding-current-image,
.branding-preview .branding-preview-image {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.branding-preview.has-preview .branding-current-image,
.branding-preview.has-preview .branding-placeholder-icon {
    display: none;
}

/* Form inline layout */
.branding-form {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

/* Hide file input visually but keep accessible */
.file-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.file-input:focus + .btn {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* Branding form actions and delete button */
.branding-form-actions {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--color-border);
}

.branding-delete-action {
    margin-top: 0.75rem;
}

/* Branding actions container */
.branding-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* Logo dimensions display */
.branding-dimensions {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    padding: 0.25rem 0.5rem;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
    white-space: nowrap;
}

/* Theme toggle buttons for logo preview */
.branding-theme-toggle {
    display: flex;
    gap: 0.25rem;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
    padding: 0.125rem;
    margin-top: 0.5rem;
}

.branding-theme-btn {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
    background: transparent;
    border: none;
    border-radius: var(--radius-xs);
    cursor: pointer;
    transition: var(--motion-hover);
}

.branding-theme-btn:hover {
    color: var(--color-text-secondary);
}

.branding-theme-btn.active {
    background: var(--color-bg-elevated);
    color: var(--color-text);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

/* Logo preview theme variants */
.branding-preview-logo.preview-dark {
    background: #1f2937;
    border-color: #374151;
}

/* Responsive adjustments for branding */
@media (max-width: 480px) {
    .branding-row {
        flex-direction: column;
        align-items: flex-start;
    }

    .branding-form {
        width: 100%;
    }

    .branding-form .btn {
        flex: 1;
        justify-content: center;
    }
}

/* ========================================
   Logo Theme Variants (light/dark switching)
   Uses data-theme attribute set by theme-init.js.
   When only logo_url is set (no dark variant), no classes are added
   and the single logo displays normally in all themes.
   ======================================== */
.logo-dark {
    display: none;
}

[data-theme="dark"] .logo-light {
    display: none;
}

[data-theme="dark"] .logo-dark {
    display: block;
}

/* ========================================
   Theme Customization
   ======================================== */

.color-input-wrapper {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.color-input {
    width: 48px;
    height: 40px;
    padding: 2px;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    cursor: pointer;
    background: var(--color-bg-elevated);
}

.color-input::-webkit-color-swatch-wrapper {
    padding: 2px;
}

.color-input::-webkit-color-swatch {
    border-radius: var(--radius-sm);
    border: none;
}

.color-input::-moz-color-swatch {
    border-radius: var(--radius-sm);
    border: none;
}

.color-text-input {
    width: 100px;
    font-family: monospace;
    text-transform: uppercase;
}

.form-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1.5rem;
}

/* The row already spaces its children with `gap`; a margin on top of it doubles
   the gutter on the last line. This used to be restated inside the profile
   accordion and the auth form, which is where it was noticed both times. */
.form-row .form-group {
    margin-bottom: 0;
}

.form-actions {
    display: flex;
    gap: 0.75rem;
    margin-top: 1.5rem;
    /* Trailing breathing room so a sibling block (activity timeline,
     * danger zone, validation summary, etc.) does not visually fuse with
     * the Save / Cancel buttons. Symmetric with margin-top above. */
    margin-bottom: 1.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--color-border);
}

/* Settings List - for toggle switches with labels */
.settings-list {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin-bottom: 1.5rem;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-md);
    padding: 0.25rem 1rem;
}

/* A settings list drops its own tint inside a tinted panel.
   The component paints --color-bg-subtle, which is right in a white .card —
   where fourteen of its fifteen callers live. Inside a .profile-subsection,
   already painted with that same token, it becomes a panel indistinguishable
   from its container: measured 1.00:1, identical sRGB bytes.
   The answer is not another shade. A run of facts is not an object, so it does
   not need a panel at all — the rows already carry their own rules. This
   removes a painted level rather than adding one. */
.profile-subsection .settings-list {
    background: none;
    padding-inline: 0;
}

.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    padding: var(--space-md) 0;
    border-bottom: 1px solid var(--color-border);
}

.settings-row:first-child {
    padding-top: var(--space-md);
}

.settings-row:last-child {
    border-bottom: none;
    padding-bottom: var(--space-md);
}

.settings-row-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    min-width: 0;
}

.settings-row-label {
    font-weight: 500;
    color: var(--color-text);
}

.settings-row-help {
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
    line-height: 1.4;
}

.settings-row-warning {
    font-size: 0.8125rem;
    color: var(--color-warning-dark);
    line-height: 1.4;
}

/* A copyable command shown next to a setting — the MCP client invocation on
   the API & MCP page is the first of these.
   `overflow-x: auto` on the block itself rather than a wrapper: a command line
   is one long unbreakable string, and wrapping it would produce a snippet that
   is wrong when pasted. Scrolling keeps it exact and keeps the page body from
   scrolling sideways with it. */
.settings-code {
    margin: 0;
    padding: var(--space-md);
    background-color: var(--color-bg-subtle);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--color-text);
    overflow-x: auto;
}

/* ==========================================================================
   API tokens — the credential list, the scope preview, the connection forms

   Distinct from .credential-item on purpose. That component is shared with the
   security keys, which carry a name and a date and read fine as one line; a
   token carries five facts, and stacking them into one run of grey text is
   legible only to a reader who already knows which fragment is which. Here
   every value sits under its own label.
   ========================================================================== */

.token-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    margin: var(--space-md) 0;
}

/* Elevated, not tinted. A .profile-subsection is ALREADY --color-bg-subtle, so
   a card painted with the same token sits on its container at a measured
   contrast of 1.00:1 — identical sRGB bytes — separated only by a border that
   scores 1.08:1 against both. Nothing reads as an object.

   The rule this restores is the one the framework already follows one level up:
   surfaces ALTERNATE. Canvas tinted, card elevated, subsection tinted, panel
   elevated. Measured, .card on .profile-subsection is 1.17:1 — and so is
   .token-create, which is why it was the only panel on this page that read. */
.token-card {
    background-color: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-md);
    box-shadow: var(--shadow-xs);
}

/* A credential that can no longer be used stays readable but stops competing
   with the ones that can. */
.token-card[data-token-state="revoked"],
.token-card[data-token-state="expired"] {
    opacity: 0.72;
}

.token-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-md);
}

.token-card-name {
    margin: 0;
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--color-text);
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-xs);
    min-width: 0;
}

/* auto-fit rather than a fixed column count: the same markup gives five
   columns on a settings page and one on a phone, with no breakpoint to keep in
   agreement with the number of facts. */
.token-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: var(--space-sm) var(--space-md);
    margin: var(--space-sm) 0 0;
    padding-top: var(--space-sm);
    border-top: 1px solid var(--color-border-subtle);
}

.token-fact {
    min-width: 0;
}

.token-fact dt {
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-subtle);
}

.token-fact dd {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
    overflow-wrap: anywhere;
}

.token-fact dd.token-fact-alert,
.token-fact dd.token-fact-alert .token-fact-sub {
    color: var(--color-danger-text);
}

.token-fact-sub {
    display: block;
    font-size: 0.6875rem;
    color: var(--color-text-subtle);
}

/* The secret, in the one response that carries it. */
.token-issued {
    background-color: var(--color-warning-subtle);
    border: 1px solid var(--color-warning-border);
    border-radius: var(--radius-md);
    padding: var(--space-md);
    margin: var(--space-md) 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.token-issued-title {
    margin: 0;
    font-weight: 600;
    color: var(--color-warning-text);
}

.token-issued-secret {
    background-color: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: var(--space-sm) var(--space-md);
    font-family: var(--font-mono);
    font-size: 0.875rem;
    color: var(--color-text);
    overflow-wrap: anywhere;
}

.token-issued-next {
    margin: var(--space-xs) 0 0;
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
}

/* Issuing a credential is an act, and it gets a name. Unlabelled fields under
   the list read as though they described the tokens above them. */
.token-create {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-elevated);
    /* Same elevation as its two neighbours. While the shadow tokens were dead
       the three panels were indistinguishable; once they paint, a panel without
       one sits lower than the two around it — and this is the only one of the
       three that carries a control. */
    box-shadow: var(--shadow-xs);
    margin-top: var(--space-md);
}

.token-create > summary {
    cursor: pointer;
    padding: var(--space-sm) var(--space-md);
    font-weight: 600;
    color: var(--color-text);
    list-style: none;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

.token-create > summary::-webkit-details-marker {
    display: none;
}

.token-create > summary::before {
    content: "+";
    font-family: var(--font-mono);
    color: var(--color-text-muted);
}

.token-create[open] > summary::before {
    content: "–";
}

.token-create[open] > summary {
    border-bottom: 1px solid var(--color-border-subtle);
}

.token-create-body {
    padding: var(--space-md);
}

/* What each role opens, by name, above the selector — never behind a
   disclosure. Someone who does not yet know which role to pick would have to
   open several to compare, and comparing is the task. */
.role-scope {
    margin-top: var(--space-sm);
    background-color: var(--color-bg-subtle);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    padding: 0 var(--space-md);
}

.role-scope-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-md);
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--color-border-subtle);
}

.role-scope-row:last-child {
    border-bottom: none;
}

.role-scope-main {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.role-scope-name {
    font-weight: 600;
    font-size: 0.8125rem;
    color: var(--color-text);
}

.role-scope-slug {
    font-weight: 400;
    color: var(--color-text-subtle);
}

.role-scope-desc,
.role-scope-tools {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    line-height: 1.45;
}

.role-scope-tools-label {
    font-weight: 600;
    color: var(--color-text-subtle);
}

/* One disclosure per configuration SHAPE, with the clients that use it named
   in the summary. */
/* Elevated for the same reason as .token-card, and with one more of its own:
   the summary is a control. Five identically-tinted bars stacked on the same
   tint read as a striped list, not as five things you can open — the boundary
   that says "this is operable" scored 1.08:1 against the surface behind it. */
.connect-form {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-bg-elevated);
    box-shadow: var(--shadow-xs);
    margin-top: var(--space-sm);
}

.connect-form > summary {
    cursor: pointer;
    padding: var(--space-sm) var(--space-md);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--color-text);
    list-style: none;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-sm);
}

.connect-form > summary::-webkit-details-marker {
    display: none;
}

.connect-form > summary::before {
    content: "▸";
    color: var(--color-text-subtle);
    font-size: 0.75rem;
}

.connect-form[open] > summary::before {
    content: "▾";
}

.connect-form-clients {
    font-weight: 400;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.connect-form-body {
    padding: 0 var(--space-md) var(--space-md);
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.copy-control {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

/* An auxiliary phrase on a field label: why the field exists, in the label
   rather than in help text underneath, so it is read before the input and not
   after it. */
.form-label-aux {
    font-weight: 400;
    color: var(--color-text-muted);
}

@media (max-width: 480px) {
    .token-card-head,
    .role-scope-row {
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-sm);
    }
}

/* Settings list mobile responsiveness */
@media (max-width: 480px) {
    .settings-row {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-sm);
    }

    .settings-row .toggle-switch {
        align-self: flex-end;
    }
}

/* Toggle Switch */
.toggle-switch {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 24px;
    flex-shrink: 0;
}

.toggle-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

.toggle-slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: var(--color-bg-muted);
    transition: 0.3s;
    border-radius: 24px;
}

.toggle-slider:before {
    position: absolute;
    content: "";
    height: 18px;
    width: 18px;
    left: 3px;
    bottom: 3px;
    /* WHITE, not --color-primary-contrast, and the distinction is the whole
       point: this knob's background is the TRACK, and the track is
       --color-primary only when the switch is on. At rest it is
       --color-bg-muted, so the contrast token — ink in dark mode — put a dark
       knob on a dark track and measured 1.26:1. The control still worked and
       showed nothing. White reads on both: 14.27:1 at rest, 3.04:1 when on,
       which clears the 3:1 that WCAG 1.4.11 asks of a control's meaningful
       part. A rule about content laid on the primary SURFACE does not reach an
       element that merely sometimes sits on it. */
    background-color: #ffffff;
    transition: 0.3s;
    border-radius: 50%;
}

.toggle-switch input:checked + .toggle-slider {
    background-color: var(--color-primary);
}

.toggle-switch input:checked + .toggle-slider:before {
    transform: translateX(20px);
}

@media (max-width: 480px) {
    .form-row {
        grid-template-columns: 1fr;
    }

    .form-actions {
        flex-direction: column;
    }

    .form-actions .btn {
        width: 100%;
    }
}

/* ==========================================================================
   Page Header
   ========================================================================== */

.page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-md);
    margin-bottom: var(--space-lg);
}

.page-header h1,
.page-header h2 {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--color-text);
}

/* Back button + title pattern: keep the title anchored next to the back
   button. Without this, space-between pushes a lone title to the right
   edge; with trailing actions the title sat centered instead of left. */
.page-header > .btn:first-child + .page-title {
    margin-inline-end: auto;
}

.page-title {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--color-text);
}

.page-description {
    flex-basis: 100%;
    margin: 0;
    font-size: 0.875rem;
    color: var(--color-text-muted);
}

.page-actions {
    display: flex;
    gap: var(--space-sm);
}

/* Modifier for complex headers (filters, multiple action groups) */
.page-header-with-actions {
    align-items: flex-start;
}

/* ==========================================================================
   Section header — a mid-page section title with an optional right-aligned
   action (vs .page-header, which is the single top-of-page header). Nesting a
   .section-title inside .page-header makes the flex line absorb the title's own
   margin-top, so the section ends up collé against the content above; this
   wrapper OWNS the top spacing, so the gap is reliable (and works on mobile,
   unlike the media-scoped .section-title margin). The inner .section-title keeps
   its size/colour/divider — only its margins are reset (the wrapper provides them).
   ========================================================================== */
.section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-md);
    margin-top: var(--space-xl);
    margin-bottom: var(--space-md);
}

.section-header .section-title {
    margin: 0;
}

/* ==========================================================================
   Back Button Component
   ========================================================================== */

.back-button {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    flex-shrink: 0;
}

.back-button-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

/* ==========================================================================
   Audit Logs Styles
   ========================================================================== */

/* Dropdown */
.dropdown {
    position: relative;
    display: inline-block;
}

.dropdown-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
}

.dropdown-menu {
    position: absolute;
    top: 100%;
    right: 0;
    min-width: 160px;
    padding: var(--space-xs) 0;
    margin-top: var(--space-xs);
    background-color: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    z-index: var(--z-dropdown);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity var(--transition-fast), transform var(--transition-fast), visibility var(--transition-fast);
}

.dropdown.open .dropdown-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    color: var(--color-text);
    text-decoration: none;
    font-size: 0.875rem;
    transition: background-color var(--transition-fast);
}

.dropdown-item:hover {
    background-color: var(--color-bg-subtle);
    text-decoration: none;
}

.dropdown-item svg {
    color: var(--color-text-secondary);
}

/* Dropdown with descriptions */
.dropdown-menu-wide {
    min-width: 280px;
}

.dropdown-item-desc {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: var(--space-sm) var(--space-md);
}

.dropdown-item-title {
    font-weight: 500;
    color: var(--color-text);
}

.dropdown-item-subtitle {
    font-size: 0.75rem;
    color: var(--color-text-secondary);
    line-height: 1.3;
}

/* Audit retention alert */
.audit-retention-alert {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-md);
}

.audit-retention-alert .alert-content {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

.audit-purge-form {
    margin: 0;
}

/* Audit filters */
.audit-filters-card {
    padding: var(--space-md);
}

.audit-filters-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.audit-filters-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--space-md);
    align-items: end;
}

.audit-filters-actions {
    display: flex;
    gap: var(--space-sm);
    align-items: flex-end;
    padding-top: var(--space-md);
}

/* Audit results info */
.audit-results-info {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
    font-size: 0.875rem;
    color: var(--color-text-secondary);
}

.audit-date-range {
    font-style: italic;
}

/* Audit table */
.audit-table {
    min-width: 800px;
}

.audit-col-date {
    width: 140px;
}

.audit-col-user {
    min-width: 150px;
}

.audit-col-action {
    min-width: 150px;
}

.audit-col-entity {
    min-width: 100px;
}

.audit-col-status {
    width: 90px;
}

.audit-col-ip {
    width: 120px;
}

.audit-col-details {
    width: 50px;
    text-align: center;
}

/* Audit cell styles */
.audit-cell-date .audit-date,
.audit-cell-date .audit-time,
.audit-cell-user .audit-user-name,
.audit-cell-user .audit-user-email,
.audit-cell-entity .audit-entity-type,
.audit-cell-entity .audit-entity-id {
    display: block;
}

.audit-date {
    font-weight: 500;
    color: var(--color-text);
}

.audit-time {
    font-size: 0.75rem;
    color: var(--color-text-secondary);
    margin-top: 2px;
}

.audit-user-name {
    font-weight: 500;
    color: var(--color-text);
}

.audit-user-email {
    font-size: 0.75rem;
    color: var(--color-text-secondary);
    margin-top: 2px;
}

.audit-user-unknown,
.audit-user-system {
    font-style: italic;
    color: var(--color-text-muted);
}

/* Audit action badge */
.audit-action-badge {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 500;
    font-family: var(--font-mono, ui-monospace, monospace);
    color: var(--color-text-secondary);
    background-color: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

/* Audit entity */
.audit-entity-type {
    font-weight: 500;
    color: var(--color-text);
}

.audit-entity-id {
    font-size: 0.75rem;
    color: var(--color-text-secondary);
    font-family: var(--font-mono, ui-monospace, monospace);
    margin-top: 2px;
}

/* Audit cell IP */
.audit-cell-ip {
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
}

/* Audit details toggle */
.audit-details-toggle {
    padding: var(--space-xs);
    border-radius: var(--radius-sm);
    transition: transform var(--transition-fast);
}

.audit-details-toggle.expanded svg {
    transform: rotate(180deg);
}

/* Audit details row */
.audit-details-row {
    background-color: var(--color-bg-subtle);
}

.audit-details-row td {
    padding: 0 !important;
}

.audit-details-content {
    padding: var(--space-md);
    border-top: 1px solid var(--color-border);
}

.audit-changes-json {
    margin: var(--space-sm) 0 0 0;
    padding: var(--space-sm);
    background-color: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    font-family: var(--font-mono, ui-monospace, monospace);
    white-space: pre-wrap;
    word-break: break-word;
    overflow-x: auto;
    max-height: 200px;
    overflow-y: auto;
}

/* Pagination — see /static/css/components/pagination.css */
/* Styles moved to a dedicated stylesheet so client-side renderers
   (E2E modules) can opt into the same look without pulling all of
   style.css. */

/* Button icon */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.btn-icon:hover {
    background-color: var(--color-bg-subtle);
    color: var(--color-text);
}

/* Button outline danger */
.btn-outline-danger {
    color: var(--color-danger);
    background-color: transparent;
    border: 1px solid var(--color-danger);
}

.btn-outline-danger:hover {
    color: #fff;
    background-color: var(--color-danger);
}

/* ==========================================================================
   Permissions Admin Page
   ========================================================================== */

/* Info card with icon */
.permissions-info-card {
    margin-bottom: var(--space-md);
}

.card-body-info {
    display: flex;
    align-items: flex-start;
    gap: var(--space-md);
    padding: var(--space-md);
    background: light-dark(#e8f4fd, rgba(59, 130, 246, 0.1));
    border: 1px solid light-dark(#b8daff, rgba(59, 130, 246, 0.3));
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
}

.card-body-info .info-icon {
    flex-shrink: 0;
    color: var(--color-primary);
    margin-top: 2px;
}

.card-body-info p {
    margin: 0;
    font-size: 0.875rem;
    color: light-dark(#004085, var(--color-text-secondary));
    line-height: 1.5;
}

/* Scope legend */
.scope-legend {
    display: flex;
    gap: var(--space-md);
    flex-wrap: wrap;
}

/* Scope badges */
.scope-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.625rem;
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    font-weight: 500;
    white-space: nowrap;
}

.scope-badge svg {
    flex-shrink: 0;
}

.scope-badge.scope-global {
    background: light-dark(#e3f2fd, rgba(33, 150, 243, 0.15));
    color: light-dark(#1565c0, #64b5f6);
}

.scope-badge.scope-owned {
    background: light-dark(#fff3e0, rgba(255, 152, 0, 0.15));
    color: light-dark(#e65100, #ffb74d);
}

.scope-badge.scope-relation {
    background: light-dark(#f3e5f5, rgba(156, 39, 176, 0.15));
    color: light-dark(#7b1fa2, #ce93d8);
}

.scope-badge .relation-code {
    opacity: 0.75;
    margin-left: 0.125rem;
    font-weight: 400;
}

/* Filter card */
.permissions-filter-card {
    margin-bottom: var(--space-md);
}

.permissions-filter-form {
    display: flex;
    align-items: flex-end;
    gap: var(--space-md);
}

.permissions-filter-form .form-group {
    margin: 0;
    min-width: 200px;
}

/* Module card */
.module-card {
    margin-bottom: var(--space-md);
}

.module-header {
    border-bottom: 1px solid var(--color-border);
    padding-bottom: var(--space-sm);
    margin-bottom: var(--space-md);
}

.module-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

.permission-count {
    font-weight: 400;
    color: var(--color-text-muted);
    font-size: 0.875rem;
}

/* Permission code */
.permission-code {
    background: var(--color-bg-subtle);
    padding: 0.125rem 0.5rem;
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
    color: var(--color-text);
}

/* Page header info badge */
.page-header-info {
    font-size: 0.875rem;
    color: var(--color-text-muted);
    font-weight: 400;
    margin-left: auto;
}

/* Responsive page header and audit styles */
@media (max-width: 768px) {
    /* Page header responsive */
    .page-header {
        gap: var(--space-sm);
    }

    .page-header h1,
    .page-header h2,
    .page-title {
        font-size: 1.25rem;
    }

    /* Title followed by action button: stack vertically */
    .page-header .page-title:first-child {
        flex: 1 1 100%;
    }

    /* Back button + title pattern: keep on same line */
    .page-header > .btn:first-child + .page-title {
        flex: 1 1 auto;
        font-size: 1.125rem;
    }

    /* Action buttons take full width */
    .page-header > .btn:last-child:not(.btn-sm):not(.btn-small) {
        width: 100%;
    }

    /* Back button stays compact */
    .page-header > .btn.btn-sm:first-child,
    .page-header > .btn.btn-small:first-child {
        width: auto;
        flex-shrink: 0;
    }

    .page-header-with-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .page-actions {
        width: 100%;
        flex-wrap: wrap;
        justify-content: flex-end;
    }

    .page-actions .btn {
        flex: 1 1 auto;
        justify-content: center;
    }

    /* Audit-specific responsive styles */
    .audit-filters-row {
        grid-template-columns: 1fr;
    }

    .audit-filters-actions {
        flex-direction: column;
    }

    .audit-filters-actions .btn {
        width: 100%;
    }

    .audit-retention-alert {
        flex-direction: column;
        align-items: stretch;
    }

    .audit-purge-form {
        text-align: right;
    }
}

/* ==========================================================================
   Language Management - Admin section
   ========================================================================== */

/* Language badges */
.language-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Static translations table */
.static-translations-table .col-key {
    width: 40%;
    font-size: 0.875rem;
}

.static-translations-table .col-key code {
    word-break: break-all;
}

.static-translations-table .col-value {
    width: 60%;
}

/* Static translations filters */
.static-filters {
    margin-bottom: 0;
}

.static-filters .form-row {
    align-items: flex-end;
}

.static-filters .form-group-actions {
    display: flex;
    gap: 0.5rem;
    padding-bottom: 0;
}

/* Translation progress indicators */
.translation-progress {
    display: inline-block;
    padding: 0.25rem 0.5rem;
    border-radius: var(--radius-sm);
    font-size: 0.75rem;
    font-weight: 500;
}

.translation-progress.progress-complete {
    background-color: light-dark(#dcfce7, rgba(34, 197, 94, 0.2));
    color: light-dark(#166534, #86efac);
}

.translation-progress.progress-partial {
    background-color: light-dark(#fef9c3, rgba(245, 158, 11, 0.2));
    color: light-dark(#854d0e, #fcd34d);
}

.translation-progress.progress-none {
    background-color: light-dark(#fee2e2, rgba(239, 68, 68, 0.2));
    color: light-dark(#991b1b, #fca5a5);
}

/* Translation card for edit page */
.translation-card {
    margin-bottom: 1.5rem;
}

.translation-card .card-title {
    margin-bottom: 1rem;
    font-size: 1rem;
}

/* Translation tabs */
.translation-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--color-border);
    padding-bottom: 0.5rem;
}

.translation-tab {
    padding: 0.5rem 1rem;
    border: none;
    background: transparent;
    color: var(--color-text-secondary);
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    transition: var(--transition-fast);
    position: relative;
}

.translation-tab:hover {
    background: var(--color-bg-subtle);
    color: var(--color-text);
}

.translation-tab.active {
    background: var(--color-primary);
    color: var(--color-primary-contrast);
}

.translation-tab .tab-warning {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1rem;
    height: 1rem;
    margin-left: 0.25rem;
    font-size: 0.625rem;
    font-weight: 700;
    background: var(--color-warning);
    color: white;
    border-radius: 50%;
}

.translation-tab.active .tab-warning {
    background: white;
    color: var(--color-warning);
}

/* Translation panels */
.translation-panel {
    display: none;
}

.translation-panel.active {
    display: block;
}

/* Translation reference */
.translation-reference {
    margin-bottom: 1rem;
    padding: 0.75rem;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--color-primary);
}

.translation-reference label {
    display: block;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--color-text-secondary);
    margin-bottom: 0.25rem;
}

.translation-reference .reference-text {
    font-size: 0.875rem;
    color: var(--color-text);
    white-space: pre-wrap;
}

/* Translation input */
.translation-input {
    width: 100%;
    min-height: 80px;
    resize: vertical;
}

/* Responsive for translation interface */
@media (max-width: 768px) {
    .translation-tabs {
        flex-direction: column;
        gap: 0.125rem;
    }

    .translation-tab {
        border-radius: var(--radius-sm);
        text-align: left;
    }

    .static-filters .form-row {
        flex-direction: column;
    }

    .static-filters .form-group-actions {
        flex-direction: column;
    }

    .static-filters .form-group-actions .btn {
        width: 100%;
    }
}

/* ==========================================================================
   TOTP Setup Styles
   ========================================================================== */

/* TOTP setup container */
.totp-setup {
    display: flex;
    flex-direction: column;
    gap: var(--space-xl);
}

.totp-setup-step {
    padding-bottom: var(--space-lg);
    border-bottom: 1px solid var(--color-border);
}

.totp-setup-step:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.totp-setup-step h3 {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: var(--space-sm);
    color: var(--color-text);
}

.totp-setup-step p {
    color: var(--color-text-secondary);
    margin-bottom: var(--space-md);
}

/* QR code container */
.totp-qr-container {
    text-align: center;
}

.totp-qr-code {
    display: inline-block;
    padding: var(--space-md);
    background: white;
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
}

.totp-qr-code img {
    display: block;
    max-width: 256px;
    height: auto;
}

/* Manual secret entry */
.totp-secret-manual {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-md);
    background: var(--color-bg-subtle);
    border-radius: var(--radius-md);
}

.totp-secret-label {
    font-size: 0.875rem;
    color: var(--color-text-secondary);
    margin: 0;
}

.totp-secret-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-size: 1rem;
    letter-spacing: 0.1em;
    padding: var(--space-sm) var(--space-md);
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    user-select: all;
}

/* TOTP verify form */
.totp-verify-form {
    max-width: 300px;
    margin: 0 auto;
}

.totp-verify-form input[type="text"] {
    text-align: center;
    font-size: 1.25rem;
    letter-spacing: 0.2em;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}

/* TOTP disable form (inline in profile) */
.totp-disable-form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-sm);
}

.totp-disable-form .form-group-inline {
    flex: 1;
    min-width: 200px;
}

.totp-disable-form .form-group-inline input {
    width: 100%;
    margin: 0;
}

/* Responsive adjustments */
@media (max-width: 480px) {
    .totp-secret-manual {
        padding: var(--space-sm);
    }

    .totp-secret-code {
        font-size: 0.75rem;
        word-break: break-all;
    }

    .totp-disable-form {
        flex-direction: column;
    }

    .totp-disable-form .form-group-inline {
        width: 100%;
    }

    .totp-disable-form .btn {
        width: 100%;
    }
}

/* ==========================================================================
   Inline Confirmation Component
   ========================================================================== */

/* Inline confirm wrapper */
.inline-confirm-wrapper {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
}

/* Inline confirm buttons */
.inline-confirm-yes,
.inline-confirm-no {
    padding: 0.25rem 0.75rem;
    font-size: 0.875rem;
    border-radius: var(--radius-sm);
    border: 1px solid;
    cursor: pointer;
    transition: var(--motion-hover);
    white-space: nowrap;
}

.inline-confirm-yes {
    background: var(--color-danger);
    color: white;
    border-color: var(--color-danger);
}

.inline-confirm-yes:hover {
    background: var(--color-danger-hover);
    border-color: var(--color-danger-hover);
}

.inline-confirm-no {
    background: var(--color-bg-elevated);
    color: var(--color-text);
    border-color: var(--color-border);
}

.inline-confirm-no:hover {
    background: var(--color-bg-subtle);
}

/* Active state for element being confirmed */
.inline-confirm-active {
    display: inline-flex !important;
    align-items: center;
}

/* Focus visible for keyboard navigation */
.inline-confirm-yes:focus-visible,
.inline-confirm-no:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   Inline Confirm - Floating Mode
   -------------------------------------------------------------------------- */

/* Source element marker */
.inline-confirm-source {
    position: relative;
}

/* Floating bubble container */
.inline-confirm-floating {
    position: absolute;
    z-index: var(--z-widget);
    pointer-events: auto;
    opacity: 0;
    transform: scale(0.95);
    transition: opacity 150ms ease-out, transform 150ms ease-out;
}

/* Visible state */
.inline-confirm-floating-visible {
    opacity: 1;
    transform: scale(1);
}

/* Hiding state (exit animation) */
.inline-confirm-floating-hiding {
    opacity: 0;
    transform: scale(0.95);
    transition: opacity 100ms ease-in, transform 100ms ease-in;
}

/* Content wrapper */
.inline-confirm-floating-content {
    background: var(--color-bg-elevated, #fff);
    border: 1px solid var(--color-border, #e5e7eb);
    border-radius: var(--radius-lg, 12px);
    box-shadow: var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05));
    padding: 0.875rem 1rem;
    min-width: 180px;
    max-width: 280px;
    text-align: center;
}

/* Confirmation text */
.inline-confirm-floating-text {
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--color-text, #111827);
    margin-bottom: 0.75rem;
    line-height: 1.4;
}

/* Action buttons container */
.inline-confirm-floating-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: center;
}

/* Floating buttons */
.inline-confirm-floating-yes,
.inline-confirm-floating-no {
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    font-weight: 500;
    border-radius: var(--radius-md, 8px);
    border: 1px solid;
    cursor: pointer;
    transition: background-color 150ms ease, border-color 150ms ease, transform 100ms ease;
    min-width: 70px;
    /* Touch-friendly size (min 44px height) */
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.inline-confirm-floating-yes {
    background: var(--color-danger, #dc2626);
    color: white;
    border-color: var(--color-danger, #dc2626);
}

.inline-confirm-floating-yes:hover {
    background: var(--color-danger-hover, #b91c1c);
    border-color: var(--color-danger-hover, #b91c1c);
}

.inline-confirm-floating-yes:active {
    transform: scale(0.98);
}

/* Success variant for confirm button */
.inline-confirm-floating-yes.btn-success {
    background: var(--color-success, #22c55e);
    border-color: var(--color-success, #22c55e);
}

.inline-confirm-floating-yes.btn-success:hover {
    background: var(--color-success-hover, #16a34a);
    border-color: var(--color-success-hover, #16a34a);
}

/* Warning variant for confirm button */
.inline-confirm-floating-yes.btn-warning {
    background: var(--color-warning, #f59e0b);
    border-color: var(--color-warning, #f59e0b);
    color: #000;
}

.inline-confirm-floating-yes.btn-warning:hover {
    background: var(--color-warning-hover, #d97706);
    border-color: var(--color-warning-hover, #d97706);
}

/* Cancel button */
.inline-confirm-floating-no {
    background: var(--color-bg-subtle, #f3f4f6);
    color: var(--color-text, #111827);
    border-color: var(--color-border, #e5e7eb);
}

.inline-confirm-floating-no:hover {
    background: var(--color-bg-muted, #e5e7eb);
    border-color: var(--color-border-strong, #d1d5db);
}

.inline-confirm-floating-no:active {
    transform: scale(0.98);
}

/* Focus visible for keyboard navigation */
.inline-confirm-floating-yes:focus-visible,
.inline-confirm-floating-no:focus-visible {
    outline: 2px solid var(--color-primary, #3b82f6);
    outline-offset: 2px;
}

/* Arrow pointer */
.inline-confirm-floating-arrow {
    position: absolute;
    width: 12px;
    height: 12px;
    background: var(--color-bg-elevated, #fff);
    border: 1px solid var(--color-border, #e5e7eb);
    transform: rotate(45deg);
    pointer-events: none;
}

/* Arrow position based on placement */
.inline-confirm-floating[data-placement="top"] .inline-confirm-floating-arrow {
    bottom: -7px;
    border-top: none;
    border-left: none;
}

.inline-confirm-floating[data-placement="bottom"] .inline-confirm-floating-arrow {
    top: -7px;
    border-bottom: none;
    border-right: none;
}

/* Dark mode */
[data-theme="dark"] .inline-confirm-floating-content,
.dark .inline-confirm-floating-content {
    background: var(--color-bg-elevated, #1f2937);
    border-color: var(--color-border, #374151);
}

[data-theme="dark"] .inline-confirm-floating-arrow,
.dark .inline-confirm-floating-arrow {
    background: var(--color-bg-elevated, #1f2937);
    border-color: var(--color-border, #374151);
}

[data-theme="dark"] .inline-confirm-floating-no,
.dark .inline-confirm-floating-no {
    background: var(--color-bg-subtle, #374151);
    border-color: var(--color-border, #4b5563);
}

[data-theme="dark"] .inline-confirm-floating-no:hover,
.dark .inline-confirm-floating-no:hover {
    background: var(--color-bg-muted, #4b5563);
}

/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
    .inline-confirm-floating,
    .inline-confirm-floating-visible,
    .inline-confirm-floating-hiding {
        transition: none;
        transform: none;
    }
}

/* ==========================================================================
   Forced-colors mode (Windows High Contrast / system-level overrides)

   When the OS substitutes its own palette for accessibility reasons, the
   browser ignores most colours we set. The CanvasText / Canvas / Highlight
   / ButtonFace system colour keywords are guaranteed to remain visible,
   so we use them to keep cards, inputs and focus rings legible.

   `forced-color-adjust: auto` is the default — we only override it locally
   on subtle UI (skeletons, decorative gradients) where forced colours
   would create an opaque rectangle that hides content.
   ========================================================================== */
@media (forced-colors: active) {
    /* Make every interactive surface keep a visible border, even when
       our background tokens are flattened by the OS. */
    .card,
    .auth-card,
    .modal,
    .dropdown,
    .toast,
    .alert,
    :where(
        select,
        textarea,
        input[type="text"],
        input[type="search"],
        input[type="email"],
        input[type="number"],
        input[type="tel"],
        input[type="url"],
        input[type="password"],
        input[type="date"],
        input[type="datetime-local"],
        input[type="month"],
        input[type="time"],
        input[type="week"]
    ) {
        border: 1px solid CanvasText;
    }

    /* Buttons: rely on system Button* colours so disabled / hover states
       remain distinguishable. */
    .btn {
        border: 1px solid ButtonText;
        forced-color-adjust: none;
        background-color: ButtonFace;
        color: ButtonText;
    }
    .btn-primary,
    .btn-danger,
    .btn-success {
        background-color: Highlight;
        color: HighlightText;
        border-color: Highlight;
    }
    .btn:disabled,
    .btn[disabled] {
        color: GrayText;
        border-color: GrayText;
    }

    /* Focus ring: replace the brand-coloured halo with the system Highlight
       so focus stays visible on any forced palette. */
    *:focus-visible {
        outline: 2px solid Highlight;
        outline-offset: 2px;
        box-shadow: none;
    }

    /* Active sidebar item: the emerald accent bar disappears under forced
       colours; fall back to a system underline. */
    .nav-item.active {
        text-decoration: underline;
        text-underline-offset: 4px;
    }
    .nav-item.active::before {
        background-color: Highlight;
    }

    /* Skeletons would render as opaque blocks — fade them out. */
    .skeleton::after {
        animation: none;
        background-image: none;
    }

    /* Sprite icons: keep them stroked so they remain visible. */
    .icon use {
        forced-color-adjust: auto;
    }
}

/* ==========================================================================
   Higher contrast preference (user explicitly requests more contrast,
   independent of the forced-colors OS feature). Tightens borders and
   removes the subtle text variants.
   ========================================================================== */
@media (prefers-contrast: more) {
    :root {
        --color-border-subtle: var(--color-border-strong);
        --color-border:        var(--color-border-strong);
        --color-text-muted:    var(--color-text-secondary);
        --color-text-subtle:   var(--color-text-secondary);
    }

    .card,
    .auth-card {
        border-width: 2px;
    }

    a:not(.btn) {
        text-decoration: underline;
    }
}

/* Mobile adjustments */
@media (max-width: 480px) {
    .inline-confirm-floating-content {
        min-width: 160px;
        padding: 0.75rem;
    }

    .inline-confirm-floating-text {
        font-size: 0.875rem;
    }

    .inline-confirm-floating-yes,
    .inline-confirm-floating-no {
        padding: 0.5rem 0.75rem;
        min-width: 60px;
    }
}

/* ==========================================================================
   Clickable Rows
   ========================================================================== */

.clickable-row[data-href] {
    cursor: pointer;
    transition: background-color var(--transition-fast);
}

.clickable-row[data-href]:hover {
    background-color: var(--color-bg-subtle);
}

/* Prevent propagation on interactive elements within rows */
.clickable-row a,
.clickable-row button,
.clickable-row input,
.clickable-row select,
.clickable-row .no-propagate {
    cursor: auto;
}

/* ==========================================================================
   Drag & Drop Component
   ========================================================================== */

/* Drag handle */
.drag-handle {
    cursor: move;
    cursor: grab;
    color: var(--color-text-secondary);
    transition: color var(--transition-fast);
    touch-action: none;
    user-select: none;
}

.drag-handle:hover {
    color: var(--color-text);
}

.drag-handle:active {
    cursor: grabbing;
}

/* Item being dragged (position:fixed, floating above content) */
.dragging {
    box-shadow: var(--shadow-lg);
    cursor: grabbing !important;
}

/* Placeholder during drag */
.drag-placeholder {
    background: var(--color-bg-subtle);
    border: 2px dashed var(--color-border);
    border-radius: var(--radius-md);
    opacity: 0.5;
}

/* Table row placeholder */
tr.drag-placeholder {
    border-radius: 0;
}

tr.drag-placeholder td {
    background: var(--color-bg-subtle);
    border-top: 2px dashed var(--color-border);
    border-bottom: 2px dashed var(--color-border);
}

/* ==========================================================================
   Timeline Component
   Compact vertical timeline with colored dots and connecting line.
   Used for activity history on detail pages and workspace activity feeds.
   ========================================================================== */

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

.timeline-item {
    display: flex;
    align-items: flex-start;
    gap: var(--space-sm);
    padding-bottom: var(--space-sm);
    position: relative;
}

.timeline-item:last-child {
    padding-bottom: 0;
}

/* Vertical connecting line between dots */
.timeline-item:not(:last-child)::before {
    content: '';
    position: absolute;
    left: 4px;
    top: 14px;
    bottom: 0;
    width: 1px;
    background: var(--color-border);
}

/* Colored dot */
.timeline-dot {
    flex-shrink: 0;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-top: 5px;
    background: var(--color-text-muted);
}

.timeline-dot-create  { background: var(--color-success); }
.timeline-dot-update  { background: var(--color-primary); }
.timeline-dot-delete  { background: var(--color-danger); }
.timeline-dot-restore { background: var(--color-warning); }

.timeline-content {
    flex: 1;
    min-width: 0;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-md);
}

.timeline-text {
    font-size: 0.875rem;
    color: var(--color-text);
}

.timeline-time {
    flex-shrink: 0;
    font-size: 0.75rem;
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* ==========================================================================
   Empty State Component
   ========================================================================== */

.empty-state {
    text-align: center;
    padding: var(--space-2xl) var(--space-lg);
    color: var(--color-text-muted);
}

/* Inline empty-state usage (on td/p without sub-components) */
td.empty-state,
p.empty-state {
    font-style: italic;
    padding: var(--space-md) 0;
}

.empty-state-icon {
    font-size: 4rem;
    margin-bottom: var(--space-md);
    opacity: 0.5;
}

.empty-state-icon svg {
    width: 3.5rem;
    height: 3.5rem;
    stroke: currentColor;
}

.empty-state-title {
    font-size: 1.5rem;
    font-weight: 600;
    margin-bottom: var(--space-sm);
    color: var(--color-text);
}

.empty-state-text {
    font-size: 1rem;
    margin-bottom: var(--space-lg);
    max-width: 500px;
    margin-left: auto;
    margin-right: auto;
}

.empty-state-action {
    margin-top: var(--space-lg);
}

/* Compact variant, for an empty list INSIDE a page whose action sits right
   below it rather than for a page that is empty.
   The full-size treatment — a 3.5rem icon, a 1.5rem heading and 2xl padding —
   is right when the empty state IS the page. Used in a settings subsection it
   ran to roughly 400px and pushed the form it points at off the first screen,
   which is the opposite of what it is for. */
/* Two classes on purpose. The responsive block below restates .empty-state's
   padding at (0,1,0) and sits LATER in the file, so a single-class variant is
   beaten by it under 480px — the compact form would get MORE padding on a phone
   than on a desktop, and only that one declaration would be lost, which is
   invisible to a reader checking that the rule exists. */
.empty-state.empty-state-compact {
    padding: var(--space-lg) var(--space-md);
}

.empty-state-compact .empty-state-icon {
    margin-bottom: var(--space-sm);
}

.empty-state-compact .empty-state-icon svg {
    width: 2rem;
    height: 2rem;
}

.empty-state-compact .empty-state-title {
    font-size: 1.0625rem;
    margin-bottom: var(--space-xs);
}

.empty-state-compact .empty-state-text {
    font-size: 0.875rem;
    margin-bottom: 0;
}

/* Responsive adjustments */
@media (max-width: 480px) {
    .empty-state {
        padding: var(--space-xl) var(--space-md);
    }

    .empty-state-icon {
        font-size: 3rem;
    }

    .empty-state-icon svg {
        width: 2.5rem;
        height: 2.5rem;
    }

    .empty-state-title {
        font-size: 1.25rem;
    }

    .empty-state-text {
        font-size: 0.9375rem;
    }
}

/* ==========================================================================
   Profile subsections
   The accordion that used to wrap these is gone: the personal settings surface
   is one page per topic, so there is nothing left to collapse. Subsections
   remain — they group the two or three related forms inside a single page, and
   they are the HTMX swap targets.
   ========================================================================== */

.profile-subsection {
    padding: var(--space-md);
    background-color: var(--color-bg-subtle);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
}

.profile-subsection:last-child {
    margin-bottom: 0;
}

.profile-subsection-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-sm);
    flex-wrap: wrap;
    gap: var(--space-sm);
}

.profile-subsection-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-text);
    margin: 0;
}

.profile-subsection-description {
    font-size: 0.875rem;
    color: var(--color-text-secondary);
    margin: 0 0 var(--space-md) 0;
}

.profile-subsection-status {
    font-size: 0.875rem;
    color: var(--color-text-secondary);
}

.profile-subsection-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-top: var(--space-md);
}

/* Avatar section within profile */
.profile-avatar-section {
    display: flex;
    align-items: flex-start;
    gap: var(--space-lg);
    margin-bottom: var(--space-lg);
    padding-bottom: var(--space-lg);
    border-bottom: 1px solid var(--color-border);
}

.profile-avatar-preview {
    flex-shrink: 0;
    width: 96px;
    height: 96px;
    border-radius: var(--radius-full);
    background-color: var(--color-bg-subtle);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border: 2px solid var(--color-border);
}

.profile-avatar-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.profile-avatar-preview .avatar-placeholder-icon {
    width: 40px;
    height: 40px;
    color: var(--color-text-muted);
}

.profile-avatar-actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.profile-avatar-hint {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    margin-top: var(--space-xs);
}

/* Form help text */
.form-help {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    margin-top: var(--space-xs);
    margin-bottom: 0;
}

/* Field-level validation message — the text half of the field-error contract
   (web/templates/components/field-error.html, pkg/forms.FieldErrors). The
   input state lives in @layer components, next to the .input-wrapper
   convention it has to coexist with.

   Visible by default, and that is the difference from the rules it replaces.
   components/form-validation.css declared `.form-error { display: none }`,
   revealed only under a `.was-validated` / `.validate-on-change` ancestor —
   classes no template ever set. Since no layout linked that sheet either, the
   two existing messages rendered as plain unstyled paragraphs; linking it
   as-is would have HIDDEN them instead of styling them. The server renders
   this message only when the field is actually in error, so there is nothing
   left to gate it on. */
.form-error {
    font-size: 0.75rem;
    color: var(--color-danger-text);
    margin-top: var(--space-xs);
    margin-bottom: 0;
}

/* Required-field marker. docs/UI_FORMS.md §1 states this is "styled
   framework-wide"; until now nothing styled it — the only rule naming
   `required` was `.form-label.required::after`, in the sheet no layout
   loaded, and it targeted a class on the LABEL while all 75 uses in the
   workspace put it on a <span> inside the label. The asterisk is literal
   text in the markup, so it rendered either way; what was missing is the
   colour that tells it apart from ordinary label text. */
.required {
    color: var(--color-danger-text);
}


/* Responsive: Tablet and up */
@media (min-width: 768px) {
    .profile-avatar-section {
        gap: var(--space-xl);
    }

    .profile-avatar-preview {
        width: 120px;
        height: 120px;
    }

    .profile-avatar-actions {
        flex-direction: row;
        flex-wrap: wrap;
    }
}

/* Responsive: Mobile */
@media (max-width: 767px) {
    .profile-avatar-section {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }

    .profile-avatar-actions {
        width: 100%;
    }

    .profile-avatar-actions .btn {
        width: 100%;
    }

    .profile-subsection-header {
        flex-direction: column;
        align-items: flex-start;
    }

    .profile-subsection-actions {
        flex-direction: column;
    }

    .profile-subsection-actions .btn {
        width: 100%;
    }
}

/* ==========================================================================
   Admin Modules Page
   ========================================================================== */

/* Module name cell with dependency indicators */
.module-name-cell {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.module-name-cell strong {
    font-weight: 600;
}

.module-id {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
}

.module-deps-indicator {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.25rem;
}

.dep-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.6875rem;
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
}

.dep-requires {
    background-color: light-dark(#e0f2fe, rgba(56, 189, 248, 0.15));
    color: light-dark(#0369a1, #7dd3fc);
}

.dep-required-by {
    background-color: light-dark(#fef3c7, rgba(245, 158, 11, 0.15));
    color: light-dark(#b45309, #fcd34d);
}

.dep-optional {
    background-color: light-dark(#f3e8ff, rgba(168, 85, 247, 0.15));
    color: light-dark(#7e22ce, #c084fc);
}

.dep-badge svg {
    width: 10px;
    height: 10px;
}

/* Module features badges */
.module-features {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.feature-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: var(--radius-sm);
    background-color: var(--color-bg-subtle);
    color: var(--color-text-muted);
    transition: background-color 0.2s, color 0.2s;
}

.feature-badge:hover {
    background-color: var(--color-primary);
    color: var(--color-primary-contrast);
}

.feature-badge svg {
    width: 14px;
    height: 14px;
}

.feature-badge-special {
    background-color: light-dark(#dbeafe, rgba(59, 130, 246, 0.2));
    color: light-dark(#1d4ed8, #60a5fa);
}

/* Module row disabled state */
.module-row-disabled {
    opacity: 0.6;
}

.module-row-disabled .module-name-cell strong {
    color: var(--color-text-muted);
}

/* Module overview card (detail page) */
.module-overview-card {
    margin-bottom: var(--space-md);
}

.module-header-detail {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: var(--space-md);
}

.module-info {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.module-info .module-title {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 600;
}

.module-id-code {
    font-size: 0.8125rem;
    background-color: var(--color-bg-subtle);
    padding: 0.25rem 0.5rem;
    border-radius: var(--radius-sm);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
}

.module-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.module-description {
    color: var(--color-text-muted);
    margin-bottom: var(--space-md);
}

.module-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-lg);
}

.meta-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    /* Flex items default to `min-width: auto`, i.e. they refuse to shrink below
       their content. Measured on a Pixel 7: a .meta-item holding a 42-char
       address computed 444px inside a 330px .module-meta, so it ran 89px past
       the card — and the document stayed 412/412, so nothing scrolled and the
       tail of the value was UNREACHABLE rather than clipped. With min-width: 0
       the item shrinks and the child's `text-truncate` ellipsis does its job.
       Same remedy the framework already applies in callout-card.css,
       command-palette.css, filters.css and workspace-picker.css. */
    min-width: 0;
}

.meta-label {
    color: var(--color-text-muted);
    font-size: 0.875rem;
}

.meta-value {
    font-weight: 500;
    /* Also a flex item (its parent .meta-item is display:flex), so it inherits
       the same `min-width: auto` refusal to shrink. Fixing only the parent left
       the value 89px outside the card — the hole one level down, which is how
       this workspace has learned to look for the second occurrence. */
    min-width: 0;
}

/* Capabilities grid */
.capabilities-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-md);
}

.capability-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--space-md);
    border-radius: var(--radius-md);
    text-align: center;
    gap: 0.5rem;
    transition: background-color 0.2s;
}

.capability-item svg {
    flex-shrink: 0;
}

.capability-active {
    background-color: light-dark(#dcfce7, rgba(34, 197, 94, 0.15));
    color: light-dark(#166534, #86efac);
}

.capability-active svg {
    stroke: light-dark(#16a34a, #4ade80);
}

.capability-inactive {
    background-color: var(--color-bg-subtle);
    color: var(--color-text-muted);
}

.capability-inactive svg {
    opacity: 0.5;
}

.capability-special {
    background-color: light-dark(#dbeafe, rgba(59, 130, 246, 0.2));
    color: light-dark(#1d4ed8, #60a5fa);
}

.capability-special svg {
    stroke: light-dark(#2563eb, #3b82f6);
}

.capability-label {
    font-weight: 500;
    font-size: 0.875rem;
}

.capability-detail {
    font-size: 0.75rem;
    opacity: 0.8;
}

/* Permissions list (detail page) */
.permissions-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.permission-item {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem;
    background-color: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
}

.permission-scope {
    font-size: 0.6875rem;
    text-transform: uppercase;
    font-weight: 600;
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
}

.scope-global {
    background-color: light-dark(#fee2e2, rgba(239, 68, 68, 0.2));
    color: light-dark(#991b1b, #fca5a5);
}

.scope-owned {
    background-color: light-dark(#dcfce7, rgba(34, 197, 94, 0.2));
    color: light-dark(#166534, #86efac);
}

.scope-workspace {
    background-color: light-dark(#dbeafe, rgba(59, 130, 246, 0.2));
    color: light-dark(#1d4ed8, #60a5fa);
}

.scope-relation {
    background-color: light-dark(#fef3c7, rgba(245, 158, 11, 0.2));
    color: light-dark(#b45309, #fcd34d);
}

.permission-desc {
    color: var(--color-text-muted);
    font-size: 0.875rem;
    flex: 1;
}

/* Navigation items list */
.nav-items-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.nav-item-row {
    padding: 0.75rem;
    background-color: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
}

.nav-item-main {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}

.nav-context-badge {
    font-size: 0.6875rem;
    text-transform: uppercase;
    font-weight: 600;
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
}

.context-app {
    background-color: light-dark(#dcfce7, rgba(34, 197, 94, 0.2));
    color: light-dark(#166534, #86efac);
}

.context-admin {
    background-color: light-dark(#fef3c7, rgba(245, 158, 11, 0.2));
    color: light-dark(#b45309, #fcd34d);
}

.nav-item-label {
    font-weight: 500;
}

.nav-item-url {
    font-size: 0.75rem;
    background-color: var(--color-bg);
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
}

.nav-item-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.nav-item-admin-only {
    color: light-dark(#dc2626, #f87171);
    font-weight: 500;
}

/* Widgets list */
.widgets-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.widget-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    background-color: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
}

.widget-type {
    font-size: 0.75rem;
    background-color: var(--color-bg);
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
}

.widget-name {
    color: var(--color-text-muted);
    font-size: 0.875rem;
}

/* Relations list */
.relations-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.relation-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    background-color: var(--color-bg-subtle);
    border-radius: var(--radius-sm);
}

.relation-code {
    font-size: 0.75rem;
    background-color: var(--color-bg);
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
}

.relation-flow {
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.relation-name {
    color: var(--color-text);
    font-size: 0.875rem;
}

/* Dependency type badges (detail page) */
.dep-type-badge {
    display: inline-block;
    font-size: 0.6875rem;
    padding: 0.0625rem 0.375rem;
    border-radius: var(--radius-full, 9999px);
    font-weight: 500;
    line-height: 1.4;
}

.dep-type-required {
    background-color: light-dark(#e0f2fe, rgba(56, 189, 248, 0.15));
    color: light-dark(#0369a1, #7dd3fc);
}

.dep-type-optional {
    background-color: light-dark(#f3e8ff, rgba(168, 85, 247, 0.15));
    color: light-dark(#7e22ce, #c084fc);
}

/* Module action buttons group */
.module-action-buttons {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

/* Dependencies section improvements */
.dependency-name {
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
    font-size: 0.875rem;
    text-decoration: none;
    color: inherit;
}

.dependency-name:hover {
    text-decoration: underline;
    color: var(--color-primary);
}

/* Stats card for modules */
.modules-stats-card {
    margin-bottom: var(--space-md);
}

.modules-info-card {
    margin-bottom: var(--space-md);
}

.modules-info-card .card-body-info {
    display: flex;
    align-items: flex-start;
    gap: var(--space-sm);
    color: var(--color-text-muted);
    font-size: 0.875rem;
}

.modules-info-card .info-icon {
    flex-shrink: 0;
    margin-top: 0.125rem;
}

/* Responsive adjustments */
@media (max-width: 767px) {
    .module-header-detail {
        flex-direction: column;
        gap: var(--space-md);
    }

    .capabilities-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .permission-item {
        flex-direction: column;
        align-items: flex-start;
    }

    .nav-item-main {
        flex-direction: column;
        align-items: flex-start;
    }
}
