/*
 * Q-Mgr Layout Styles
 * Pure Bootstrap-based layout with custom theming
 */

/* ================================
   Layout Variables
   ================================ */
:root {
    --header-height: 64px;
    --sidebar-width: 280px;
    --sidebar-collapsed-width: 72px;
    --footer-height: 50px;
}

/* ================================
   App Container
   ================================ */
.qm-app {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* ================================
   Header Styles
   ================================ */
.qm-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    z-index: 1030;
    transition: all 0.3s ease;
}

/* Dark Mode Header */
[data-theme="dark"] .qm-header {
    background: linear-gradient(135deg, var(--qm-bg-dark) 0%, var(--qm-bg-card) 100%);
    border-bottom: 1px solid var(--qm-border);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

/* Light Mode Header */
[data-theme="light"] .qm-header {
    background: linear-gradient(135deg, var(--qm-bg-card) 0%, var(--qm-bg-elevated) 100%);
    border-bottom: 1px solid var(--qm-border);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
}

.header-left,
.header-right {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Sidebar Toggle */
.sidebar-toggle {
    width: 40px;
    height: 40px;
    border: none;
    border-radius: var(--qm-radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    font-size: var(--qm-text-stat);
}

[data-theme="dark"] .sidebar-toggle {
    background: transparent;
    color: var(--qm-text-primary);
}

[data-theme="dark"] .sidebar-toggle:hover {
    background: var(--qm-primary-light);
    color: var(--qm-primary);
}

[data-theme="light"] .sidebar-toggle {
    background: transparent;
    color: var(--qm-text-primary);
}

[data-theme="light"] .sidebar-toggle:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
    color: var(--qm-primary);
}

/* Brand */
.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
}

.brand-logo {
    width: 38px;
    height: 38px;
    border-radius: var(--qm-radius-md);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.3s ease;
}

.brand-logo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Dark theme brand logo background */
[data-theme="dark"] .brand-logo {
    background: var(--qm-bg-dark);
    border: 1px solid rgba(var(--qm-primary-rgb), 0.3);
}

/* Light theme brand logo background */
[data-theme="light"] .brand-logo {
    background: var(--qm-bg-card);
    border: 1px solid var(--qm-border-hover);
    box-shadow: 0 2px 10px rgba(var(--qm-primary-rgb), 0.2);
}

.brand:hover .brand-logo {
    transform: scale(1.05);
}

.brand-icon {
    width: 38px;
    height: 38px;
    background: var(--qm-primary);
    border-radius: var(--qm-radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--qm-text-xl);
    color: var(--qm-text-on-primary);
}

.brand-text {
    font-size: var(--qm-text-xl);
    font-weight: 700;
    font-family: 'Poppins', sans-serif;
    letter-spacing: -0.02em;
}

[data-theme="dark"] .brand-text {
    color: var(--qm-text-primary);
}

[data-theme="light"] .brand-text {
    color: var(--qm-text-primary);
}

/* Header Buttons */
.header-btn {
    width: 40px;
    height: 40px;
    border: none;
    border-radius: var(--qm-radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    font-size: var(--qm-text-lg);
}

[data-theme="dark"] .header-btn {
    background: transparent;
    color: var(--qm-text-secondary);
}

[data-theme="dark"] .header-btn:hover {
    background: var(--qm-primary-light);
    color: var(--qm-primary);
}

[data-theme="light"] .header-btn {
    background: transparent;
    color: var(--qm-text-secondary);
}

[data-theme="light"] .header-btn:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
    color: var(--qm-primary);
}

/* Header Notifications */
.header-notifications {
    position: relative;
}

.notification-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    background: var(--qm-danger);
    border-radius: var(--qm-radius-full);
    font-size: var(--qm-text-xs);
    font-weight: 600;
    color: var(--qm-text-on-primary);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Header Date/Time */
.header-datetime {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    padding: 0 16px;
    line-height: 1.3;
}

[data-theme="dark"] .header-datetime {
    border-left: 1px solid var(--qm-border);
    border-right: 1px solid var(--qm-border);
}

[data-theme="light"] .header-datetime {
    border-left: 1px solid var(--qm-border);
    border-right: 1px solid var(--qm-border);
}

.header-datetime .date {
    font-size: var(--qm-text-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

[data-theme="dark"] .header-datetime .date {
    color: var(--qm-text-muted);
}

[data-theme="light"] .header-datetime .date {
    color: var(--qm-text-muted);
}

.header-datetime .time {
    font-size: var(--qm-text-lg);
    font-weight: 600;
    font-family: 'JetBrains Mono', monospace;
}

[data-theme="dark"] .header-datetime .time {
    color: var(--qm-text-primary);
}

[data-theme="light"] .header-datetime .time {
    color: var(--qm-text-primary);
}

/* User Dropdown */
.user-dropdown {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px 6px 6px;
    border: none;
    border-radius: 50px;
    cursor: pointer;
    transition: all 0.2s ease;
}

[data-theme="dark"] .user-dropdown {
    background: rgba(255, 255, 255, 0.05);
    color: var(--qm-text-secondary);
}

[data-theme="dark"] .user-dropdown:hover {
    background: var(--qm-primary-light);
}

[data-theme="light"] .user-dropdown {
    background: rgba(0, 0, 0, 0.05);
    color: var(--qm-text-secondary);
}

[data-theme="light"] .user-dropdown:hover {
    background: var(--qm-primary-light);
}

/* The header avatar is QAvatar; this only sizes it for the header row and keeps it round. */
.q-avatar.header-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    font-weight: 600;
    font-size: var(--qm-text-base);
}

/* Dropdown Menu */
[data-theme="dark"] .dropdown-menu {
    background: var(--qm-bg-card);
    border: 1px solid var(--qm-border);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

[data-theme="dark"] .dropdown-header {
    color: var(--qm-text-primary);
}

[data-theme="dark"] .dropdown-item {
    color: var(--qm-text-secondary);
}

[data-theme="dark"] .dropdown-item:hover {
    background: var(--qm-primary-light);
    color: var(--qm-primary);
}

[data-theme="dark"] .dropdown-divider {
    border-color: var(--qm-border);
}

[data-theme="light"] .dropdown-menu {
    background: var(--qm-bg-card);
    border: 1px solid var(--qm-border);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
}

[data-theme="light"] .dropdown-header {
    color: var(--qm-text-primary);
}

[data-theme="light"] .dropdown-item {
    color: var(--qm-text-secondary);
}

[data-theme="light"] .dropdown-item:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
    color: var(--qm-primary);
}

[data-theme="light"] .dropdown-divider {
    border-color: var(--qm-border);
}

/* ================================
   Sidebar Styles
   ================================ */
.qm-sidebar {
    position: fixed;
    top: var(--header-height);
    left: 0;
    bottom: 0;
    width: var(--sidebar-width);
    display: flex;
    flex-direction: column;
    z-index: 1020;
    transition: all 0.3s ease;
    overflow: hidden;
}

.qm-sidebar.collapsed {
    width: var(--sidebar-collapsed-width);
}

/* Icon-only collapsed state on desktop */
@media (min-width: 993px) {
    .qm-sidebar.collapsed {
        transform: translateX(0);
    }

    .qm-sidebar.collapsed .sidebar-header {
        padding: 16px 12px;
        justify-content: center;
    }

    .qm-sidebar.collapsed .sidebar-title {
        display: none;
    }

    .qm-sidebar.collapsed .nav-link {
        justify-content: center;
        padding: 12px;
    }

    .qm-sidebar.collapsed .nav-link span,
    .qm-sidebar.collapsed .nav-link .submenu-arrow {
        display: none;
    }

    .qm-sidebar.collapsed .nav-link i:first-child {
        font-size: var(--qm-text-xl);
        width: auto;
    }

    .qm-sidebar.collapsed .submenu {
        display: none;
    }

    .qm-sidebar.collapsed .sidebar-footer {
        padding: 12px;
    }

    .qm-sidebar.collapsed .branch-selector {
        justify-content: center;
        padding: 12px;
    }

    .qm-sidebar.collapsed .branch-info,
    .qm-sidebar.collapsed .branch-selector > i:last-child {
        display: none;
    }

    .qm-sidebar.collapsed .branch-selector > i:first-child {
        margin: 0;
    }

    /* Hover expand effect */
    .qm-sidebar.collapsed:hover {
        width: var(--sidebar-width);
        box-shadow: 10px 0 40px rgba(0, 0, 0, 0.3);
    }

    .qm-sidebar.collapsed:hover .sidebar-title,
    .qm-sidebar.collapsed:hover .nav-link span,
    .qm-sidebar.collapsed:hover .nav-link .submenu-arrow,
    .qm-sidebar.collapsed:hover .branch-info,
    .qm-sidebar.collapsed:hover .branch-selector > i:last-child {
        display: block;
    }

    .qm-sidebar.collapsed:hover .sidebar-header {
        padding: 20px 20px 12px;
        justify-content: flex-start;
    }

    .qm-sidebar.collapsed:hover .nav-link {
        justify-content: flex-start;
        padding: 12px 16px;
    }

    .qm-sidebar.collapsed:hover .nav-link i:first-child {
        font-size: var(--qm-text-lg);
        width: 24px;
    }

    .qm-sidebar.collapsed:hover .submenu {
        display: block;
    }

    .qm-sidebar.collapsed:hover .sidebar-footer {
        padding: 16px;
    }

    .qm-sidebar.collapsed:hover .branch-selector {
        justify-content: flex-start;
        padding: 14px 16px;
    }

    /* Main content adjustment for collapsed sidebar */
    .qm-main.expanded {
        margin-left: var(--sidebar-collapsed-width);
    }
}

[data-theme="dark"] .qm-sidebar {
    background: linear-gradient(180deg, var(--qm-bg-dark) 0%, var(--qm-bg-card) 100%);
    border-right: 1px solid var(--qm-border);
}

[data-theme="light"] .qm-sidebar {
    background: var(--qm-gradient-sidebar);
    border-right: 1px solid var(--qm-border);
}

/* Sidebar Header */
.sidebar-header {
    padding: 20px 20px 12px;
}

[data-theme="dark"] .sidebar-header {
    border-bottom: 1px solid var(--qm-border);
}

[data-theme="light"] .sidebar-header {
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.sidebar-title {
    font-size: var(--qm-text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.15em;
}

[data-theme="dark"] .sidebar-title {
    color: var(--qm-text-muted);
}

[data-theme="light"] .sidebar-title {
    color: var(--qm-text-muted);
}

/* Sidebar Navigation */
.sidebar-nav {
    flex: 1;
    overflow-y: auto;
    padding: 12px 0;
}

.nav-menu {
    list-style: none;
    padding: 0;
    margin: 0;
}

.nav-item {
    margin: 2px 8px;
}

.nav-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-radius: var(--qm-radius-md);
    text-decoration: none;
    transition: all 0.2s ease;
    font-size: var(--qm-text-base);
    font-weight: 500;
}

.nav-link i:first-child {
    font-size: var(--qm-text-lg);
    width: 24px;
    text-align: center;
}

[data-theme="dark"] .nav-link {
    color: var(--qm-text-secondary);
}

[data-theme="dark"] .nav-link:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
    color: var(--qm-primary);
}

[data-theme="dark"] .nav-link.active {
    background: var(--qm-gradient-primary);
    color: var(--qm-text-on-primary);
}

[data-theme="light"] .nav-link {
    color: var(--qm-text-secondary);
}

[data-theme="light"] .nav-link:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
    color: var(--qm-primary);
}

[data-theme="light"] .nav-link.active {
    background: var(--qm-gradient-primary);
    color: var(--qm-text-on-primary);
}

/* Modules-available badge — the only nav-level "more modules exist" signal (an unpurchased
   module itself is never shown in the tree, per explicit direction: it doesn't scale). */
.nav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 5px;
    margin-left: 8px;
    background: var(--qm-primary);
    color: var(--qm-text-on-primary);
    border-radius: var(--qm-radius-full);
    font-size: var(--qm-text-xs);
    font-weight: 700;
    line-height: 1;
}

/* Submenu Arrow */
.submenu-arrow {
    margin-left: auto;
    font-size: var(--qm-text-sm);
    transition: transform 0.2s ease;
}

.nav-item.has-submenu.open .submenu-arrow {
    transform: rotate(180deg);
}

/* Submenu */
.submenu {
    list-style: none;
    padding: 0;
    margin: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease;
}

.nav-item.has-submenu.open .submenu {
    max-height: 500px;
}

.submenu li {
    margin: 2px 0;
}

.submenu a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px 10px 52px;
    border-radius: var(--qm-radius-md);
    text-decoration: none;
    font-size: var(--qm-text-base);
    transition: all 0.2s ease;
}

.submenu a i {
    font-size: var(--qm-text-base);
    width: 18px;
    text-align: center;
}

[data-theme="dark"] .submenu a {
    color: var(--qm-text-muted);
}

[data-theme="dark"] .submenu a:hover {
    background: rgba(var(--qm-primary-rgb), 0.08);
    color: var(--qm-primary);
}

[data-theme="dark"] .submenu a.active {
    background: var(--qm-primary-light);
    color: var(--qm-primary);
}

[data-theme="light"] .submenu a {
    color: var(--qm-text-secondary);
}

[data-theme="light"] .submenu a:hover {
    background: rgba(var(--qm-primary-rgb), 0.08);
    color: var(--qm-primary);
}

[data-theme="light"] .submenu a.active {
    background: rgba(var(--qm-primary-rgb), 0.15);
    color: var(--qm-primary);
}

/* Sidebar Footer */
.sidebar-footer {
    padding: 16px;
    margin-top: auto;
}

[data-theme="dark"] .sidebar-footer {
    border-top: 1px solid var(--qm-border);
}

[data-theme="light"] .sidebar-footer {
    border-top: 1px solid rgba(0, 0, 0, 0.08);
}

/* Branch Selector */
.branch-selector {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: var(--qm-radius-md);
    cursor: pointer;
    transition: all 0.2s ease;
}

[data-theme="dark"] .branch-selector {
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--qm-border);
}

[data-theme="dark"] .branch-selector:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
    border-color: rgba(var(--qm-primary-rgb), 0.3);
}

[data-theme="dark"] .branch-selector i {
    color: var(--qm-primary);
}

[data-theme="light"] .branch-selector {
    background: rgba(0, 0, 0, 0.03);
    border: 1px solid rgba(0, 0, 0, 0.08);
}

[data-theme="light"] .branch-selector:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
    border-color: rgba(var(--qm-primary-rgb), 0.3);
}

[data-theme="light"] .branch-selector i {
    color: var(--qm-primary);
}

.branch-info {
    flex: 1;
    min-width: 0;
}

.branch-label {
    display: block;
    font-size: var(--qm-text-xs);
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

[data-theme="dark"] .branch-label {
    color: var(--qm-text-muted);
}

[data-theme="light"] .branch-label {
    color: var(--qm-text-muted);
}

.branch-name {
    display: block;
    font-size: var(--qm-text-base);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

[data-theme="dark"] .branch-name {
    color: var(--qm-text-primary);
}

[data-theme="light"] .branch-name {
    color: var(--qm-text-primary);
}

/* ================================
   Main Content Styles
   ================================ */
.qm-main {
    margin-left: var(--sidebar-width);
    margin-top: var(--header-height);
    min-height: calc(100vh - var(--header-height));
    display: flex;
    flex-direction: column;
    transition: all 0.3s ease;
}

.qm-main.expanded {
    margin-left: 0;
}

[data-theme="dark"] .qm-main {
    background: var(--qm-bg-dark);
}

[data-theme="light"] .qm-main {
    background: var(--qm-bg-dark);
}

.page-container {
    flex: 1;
    padding: 24px;
}

/* ================================
   Footer Styles
   ================================ */
.qm-footer {
    height: var(--footer-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 24px;
    font-size: var(--qm-text-base);
}

[data-theme="dark"] .qm-footer {
    background: var(--qm-bg-dark);
    border-top: 1px solid var(--qm-border);
    color: var(--qm-text-muted);
}

[data-theme="light"] .qm-footer {
    background: var(--qm-bg-darker);
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    color: var(--qm-text-muted);
}

.footer-links {
    display: flex;
    align-items: center;
    gap: 20px;
}

.footer-links a {
    text-decoration: none;
}

[data-theme="dark"] .footer-links a {
    color: var(--qm-primary);
}

[data-theme="light"] .footer-links a {
    color: var(--qm-primary);
}

.footer-links .version {
    font-family: monospace;
}

/* ================================
   Modal Styles
   ================================ */
[data-theme="dark"] .modal-content {
    background: var(--qm-bg-card);
    border: 1px solid var(--qm-border);
}

[data-theme="dark"] .modal-header {
    border-bottom: 1px solid var(--qm-border);
}

[data-theme="dark"] .modal-title {
    color: var(--qm-text-primary);
}

[data-theme="dark"] .btn-close {
    filter: invert(1);
}

[data-theme="light"] .modal-content {
    background: var(--qm-bg-card);
    border: 1px solid var(--qm-border);
}

[data-theme="light"] .modal-header {
    border-bottom: 1px solid var(--qm-border);
}

[data-theme="light"] .modal-title {
    color: var(--qm-text-primary);
}

/* Branch List */
.branch-list {
    padding: 8px;
}

.branch-item {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px;
    border-radius: var(--qm-radius-md);
    cursor: pointer;
    transition: all 0.2s ease;
    margin-bottom: 4px;
}

[data-theme="dark"] .branch-item {
    color: var(--qm-text-secondary);
}

[data-theme="dark"] .branch-item:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
}

[data-theme="dark"] .branch-item.active {
    background: var(--qm-primary-light);
    border: 1px solid rgba(var(--qm-primary-rgb), 0.3);
}

[data-theme="dark"] .branch-item.active i {
    color: var(--qm-primary);
}

[data-theme="light"] .branch-item {
    color: var(--qm-text-secondary);
}

[data-theme="light"] .branch-item:hover {
    background: rgba(var(--qm-primary-rgb), 0.1);
}

[data-theme="light"] .branch-item.active {
    background: rgba(var(--qm-primary-rgb), 0.15);
    border: 1px solid rgba(var(--qm-primary-rgb), 0.3);
}

[data-theme="light"] .branch-item.active i {
    color: var(--qm-primary);
}

.branch-item i {
    font-size: var(--qm-text-xl);
}

.branch-item-info {
    flex: 1;
}

.branch-item-name {
    display: block;
    font-weight: 600;
}

[data-theme="dark"] .branch-item-name {
    color: var(--qm-text-primary);
}

[data-theme="light"] .branch-item-name {
    color: var(--qm-text-primary);
}

.branch-item-address {
    display: block;
    font-size: var(--qm-text-sm);
}

[data-theme="dark"] .branch-item-address {
    color: var(--qm-text-muted);
}

[data-theme="light"] .branch-item-address {
    color: var(--qm-text-muted);
}

/* ================================
   Notifications Panel
   ================================ */
.notifications-panel {
    position: fixed;
    top: calc(var(--header-height) + 10px);
    right: 20px;
    width: 380px;
    max-height: 500px;
    border-radius: var(--qm-radius-lg);
    overflow: hidden;
    z-index: 1050;
}

[data-theme="dark"] .notifications-panel {
    background: var(--qm-bg-card);
    border: 1px solid var(--qm-border);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

[data-theme="light"] .notifications-panel {
    background: var(--qm-bg-card);
    border: 1px solid var(--qm-border);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
}

.notifications-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 20px;
}

[data-theme="dark"] .notifications-header {
    border-bottom: 1px solid var(--qm-border);
}

[data-theme="dark"] .notifications-header h6 {
    color: var(--qm-text-primary);
    margin: 0;
}

[data-theme="light"] .notifications-header {
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

[data-theme="light"] .notifications-header h6 {
    color: var(--qm-text-primary);
    margin: 0;
}

.notifications-list {
    max-height: 400px;
    overflow-y: auto;
}

/* Token-only, so it needs no [data-theme] counterpart — the header above predates the token
   layer, which is why that one still carries a pair of overrides. */
.notifications-footer {
    border-top: 1px solid var(--qm-border);
}

.notifications-footer a {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 20px;
    font-size: var(--qm-text-base);
    color: var(--qm-text-secondary);
    text-decoration: none;
    transition: background 0.15s ease, color 0.15s ease;
}

.notifications-footer a:hover {
    background: var(--qm-bg-elevated);
    color: var(--qm-primary);
}

.notifications-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 48px 20px;
}

[data-theme="dark"] .notifications-empty {
    color: var(--qm-text-muted);
}

[data-theme="light"] .notifications-empty {
    color: var(--qm-text-muted);
}

.notifications-empty i:not(.q-btn__icon) {
    font-size: var(--qm-empty-icon);
    margin-bottom: 4px;
}

.notification-item {
    display: flex;
    gap: 14px;
    padding: 12px 16px;
    min-height: var(--q-control-h-lg);
    font-size: var(--q-control-font);
    transition: background 0.2s ease;
}

[data-theme="dark"] .notification-item {
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

[data-theme="dark"] .notification-item:hover {
    background: rgba(255, 255, 255, 0.03);
}

[data-theme="dark"] .notification-item.unread {
    background: rgba(var(--qm-primary-rgb), 0.08);
}

[data-theme="light"] .notification-item {
    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

[data-theme="light"] .notification-item:hover {
    background: rgba(0, 0, 0, 0.03);
}

[data-theme="light"] .notification-item.unread {
    background: rgba(var(--qm-primary-rgb), 0.08);
}

.notification-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--qm-radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.notification-icon.info {
    background: rgba(var(--qm-primary-rgb), 0.15);
    color: var(--qm-primary);
}

.notification-icon.success {
    background: rgba(var(--qm-success-rgb), 0.15);
    color: var(--qm-accent-green);
}

.notification-icon.warning {
    background: rgba(var(--qm-warning-rgb), 0.15);
    color: var(--qm-warning);
}

.notification-icon.error {
    background: rgba(var(--qm-danger-rgb), 0.15);
    color: var(--qm-danger);
}

.notification-content {
    flex: 1;
    min-width: 0;
}

.notification-title {
    display: block;
    font-weight: 600;
    font-size: var(--qm-text-base);
}

[data-theme="dark"] .notification-title {
    color: var(--qm-text-primary);
}

[data-theme="light"] .notification-title {
    color: var(--qm-text-primary);
}

.notification-message {
    display: block;
    font-size: var(--qm-text-base);
    margin-top: 2px;
}

[data-theme="dark"] .notification-message {
    color: var(--qm-text-secondary);
}

[data-theme="light"] .notification-message {
    color: var(--qm-text-secondary);
}

.notification-time {
    display: block;
    font-size: var(--qm-text-xs);
    margin-top: 6px;
}

[data-theme="dark"] .notification-time {
    color: var(--qm-text-muted);
}

[data-theme="light"] .notification-time {
    color: var(--qm-text-muted);
}

/* ================================
   Responsive Styles
   ================================ */

/* Tablet - Icon-only sidebar auto-collapsed */
@media (max-width: 992px) {
    :root {
        --header-height: 60px;
        --sidebar-collapsed-width: 64px;
    }

    /* Auto-collapse to icon-only on tablet */
    .qm-sidebar {
        width: var(--sidebar-collapsed-width);
    }

    .qm-sidebar .sidebar-header {
        padding: 16px 10px;
        display: flex;
        justify-content: center;
    }

    .qm-sidebar .sidebar-title {
        display: none;
    }

    .qm-sidebar .nav-link {
        justify-content: center;
        padding: 12px 10px;
    }

    .qm-sidebar .nav-link span,
    .qm-sidebar .nav-link .submenu-arrow {
        display: none;
    }

    .qm-sidebar .nav-link i:first-child {
        font-size: var(--qm-text-xl);
        width: auto;
    }

    .qm-sidebar .submenu {
        display: none;
    }

    .qm-sidebar .sidebar-footer {
        padding: 10px;
    }

    .qm-sidebar .branch-selector {
        justify-content: center;
        padding: 10px;
    }

    .qm-sidebar .branch-info,
    .qm-sidebar .branch-selector > i:last-child {
        display: none;
    }

    /* Expand on hover for tablet */
    .qm-sidebar:hover {
        width: var(--sidebar-width);
        box-shadow: 10px 0 40px rgba(0, 0, 0, 0.5);
        z-index: 1025;
    }

    .qm-sidebar:hover .sidebar-title,
    .qm-sidebar:hover .nav-link span,
    .qm-sidebar:hover .nav-link .submenu-arrow,
    .qm-sidebar:hover .branch-info,
    .qm-sidebar:hover .branch-selector > i:last-child {
        display: block;
    }

    .qm-sidebar:hover .sidebar-header {
        padding: 20px 20px 12px;
        justify-content: flex-start;
    }

    .qm-sidebar:hover .nav-link {
        justify-content: flex-start;
        padding: 12px 16px;
    }

    .qm-sidebar:hover .nav-link i:first-child {
        font-size: var(--qm-text-lg);
        width: 24px;
    }

    .qm-sidebar:hover .submenu {
        display: block;
    }

    .qm-sidebar:hover .sidebar-footer {
        padding: 16px;
    }

    .qm-sidebar:hover .branch-selector {
        justify-content: flex-start;
        padding: 14px 16px;
    }

    /* Hidden on collapsed toggle */
    .qm-sidebar.collapsed {
        transform: translateX(-100%);
        width: 0;
    }

    .qm-main {
        margin-left: var(--sidebar-collapsed-width);
    }

    .qm-main.expanded {
        margin-left: 0;
    }

    .header-datetime {
        display: none;
    }

    /* Sidebar overlay when fully expanded on mobile */
    .sidebar-overlay {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 1015;
        opacity: 0;
        visibility: hidden;
        transition: all 0.3s ease;
    }

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

    .page-container {
        padding: 20px;
    }

    /* Footer adjustments */
    .qm-footer {
        flex-direction: column;
        gap: 8px;
        height: auto;
        padding: 12px 20px;
        text-align: center;
    }

    .footer-links {
        flex-wrap: wrap;
        justify-content: center;
        gap: 12px;
    }

    /* Brand adjustments for tablet */
    .brand-logo {
        width: 34px;
        height: 34px;
    }

    .brand-text {
        font-size: var(--qm-text-lg);
    }
}

/* Mobile phones */
@media (max-width: 576px) {
    :root {
        --header-height: 56px;
        --sidebar-collapsed-width: 0px;
    }

    .qm-header {
        padding: 0 12px;
    }

    /* Hide sidebar completely on mobile - use toggle to show */
    .qm-sidebar {
        transform: translateX(-100%);
        width: var(--sidebar-width);
    }

    .qm-sidebar.expanded {
        transform: translateX(0);
        width: var(--sidebar-width);
        box-shadow: 10px 0 40px rgba(0, 0, 0, 0.8);
    }

    /* Reset all the collapsed styles for mobile */
    .qm-sidebar.expanded .sidebar-header {
        padding: 20px 20px 12px;
        justify-content: flex-start;
    }

    .qm-sidebar.expanded .sidebar-title {
        display: block;
    }

    .qm-sidebar.expanded .nav-link {
        justify-content: flex-start;
        padding: 12px 16px;
    }

    .qm-sidebar.expanded .nav-link span,
    .qm-sidebar.expanded .nav-link .submenu-arrow {
        display: block;
    }

    .qm-sidebar.expanded .nav-link i:first-child {
        font-size: var(--qm-text-lg);
        width: 24px;
    }

    .qm-sidebar.expanded .submenu {
        display: block;
    }

    .qm-sidebar.expanded .sidebar-footer {
        padding: 16px;
    }

    .qm-sidebar.expanded .branch-selector {
        justify-content: flex-start;
        padding: 14px 16px;
    }

    .qm-sidebar.expanded .branch-info,
    .qm-sidebar.expanded .branch-selector > i:last-child {
        display: block;
    }

    .qm-main {
        margin-left: 0;
    }

    .qm-main.expanded {
        margin-left: 0;
    }

    /* Brand adjustments for mobile */
    .brand-logo {
        width: 32px;
        height: 32px;
        border-radius: var(--qm-radius-md);
    }

    .brand-text {
        display: none;
    }

    .brand-icon {
        width: 32px;
        height: 32px;
        font-size: var(--qm-text-md);
        border-radius: var(--qm-radius-md);
    }

    /* Ensure touch targets are at least 44px */
    .sidebar-toggle,
    .header-btn {
        width: 44px;
        height: 44px;
        min-width: 44px;
        min-height: 44px;
    }

    .header-right {
        gap: 4px;
    }

    .header-left {
        gap: 8px;
    }

    /* User dropdown improvements for mobile */
    .user-dropdown {
        padding: 4px 8px 4px 4px;
    }

    .user-dropdown .user-name {
        display: none;
    }

    .q-avatar.header-avatar {
        width: 32px;
        height: 32px;
        font-size: var(--qm-text-base);
    }

    /* Notification badge adjustments */
    .notification-badge {
        min-width: 16px;
        height: 16px;
        font-size: var(--qm-text-xs);
    }

    .notifications-panel {
        width: calc(100% - 24px);
        left: 12px;
        right: 12px;
        top: calc(var(--header-height) + 8px);
        max-height: calc(100vh - var(--header-height) - 20px);
    }

    .page-container {
        padding: 12px;
    }

    /* Sidebar full width on small screens */
    .qm-sidebar {
        width: 100%;
        max-width: 320px;
    }

    .qm-sidebar.expanded {
        box-shadow: 0 0 50px rgba(0, 0, 0, 0.8);
    }

    /* Larger touch targets for nav items */
    .nav-link {
        padding: 14px 16px;
        min-height: 48px;
    }

    .submenu a {
        padding: 12px 16px 12px 52px;
        min-height: 44px;
    }

    /* Branch selector touch target */
    .branch-selector {
        padding: 16px;
        min-height: 56px;
    }

    /* Footer for small screens */
    .qm-footer {
        font-size: var(--qm-text-sm);
        padding: 10px 12px;
    }

    .footer-links {
        gap: 8px;
    }

    /* Modal improvements for mobile */
    .modal-dialog {
        margin: 8px;
        max-width: calc(100% - 16px);
    }

    .modal-content {
        border-radius: var(--qm-radius-lg);
    }

    .branch-item {
        padding: 14px;
        min-height: 56px;
    }
}

/* Very small screens (320px and below) */
@media (max-width: 360px) {
    .qm-header {
        padding: 0 8px;
    }

    .header-left {
        gap: 4px;
    }

    .brand-icon {
        width: 32px;
        height: 32px;
        border-radius: var(--qm-radius-md);
        font-size: var(--qm-text-md);
    }

    .sidebar-toggle,
    .header-btn {
        width: 40px;
        height: 40px;
        min-width: 40px;
        min-height: 40px;
    }

    .page-container {
        padding: 8px;
    }

    .notifications-panel {
        width: calc(100% - 16px);
        left: 8px;
        right: 8px;
    }
}

/* Landscape orientation on mobile */
@media (max-height: 500px) and (orientation: landscape) {
    :root {
        --header-height: 48px;
    }

    .qm-sidebar {
        top: var(--header-height);
    }

    .sidebar-nav {
        padding: 8px 0;
    }

    .nav-link {
        padding: 10px 16px;
        min-height: 40px;
    }

    .sidebar-header {
        padding: 12px 16px 8px;
    }

    .sidebar-footer {
        padding: 12px;
    }

    .branch-selector {
        padding: 10px 12px;
    }
}

/* Touch device optimizations */
@media (hover: none) and (pointer: coarse) {
    /* Disable hover effects on touch devices for better performance */
    .nav-link:hover,
    .submenu a:hover,
    .header-btn:hover,
    .sidebar-toggle:hover,
    .branch-selector:hover,
    .branch-item:hover {
        transition: none;
    }

    /* Ensure all interactive elements have adequate touch targets */
    .nav-link,
    .submenu a,
    .branch-item,
    .branch-selector {
        -webkit-tap-highlight-color: rgba(var(--qm-primary-rgb), 0.2);
    }
}

/* The page and header gutters, per breakpoint, as variables — so the safe-area rule below can take
   the larger of the gutter and the notch. It used to say max(12px, …) OUTSIDE any media query, which
   every current browser applies, so every page on every desktop had a 12px gutter instead of 24px
   and the full-bleed .page-header (margin -24px) hung 12px past the edge. Measured 2026-09-16. */
:root { --qm-page-pad: 24px; --qm-header-pad: 20px; }
@media (max-width: 992px) { :root { --qm-page-pad: 20px; } }
@media (max-width: 576px) { :root { --qm-page-pad: 12px; --qm-header-pad: 12px; } }
@media (max-width: 360px) { :root { --qm-page-pad: 8px; --qm-header-pad: 8px; } }

/* Safe area insets for notched devices */
@supports (padding: max(0px)) {
    .qm-header {
        padding-left: max(var(--qm-header-pad), env(safe-area-inset-left));
        padding-right: max(var(--qm-header-pad), env(safe-area-inset-right));
    }

    .qm-sidebar {
        padding-left: env(safe-area-inset-left);
    }

    .page-container {
        padding-left: max(var(--qm-page-pad), env(safe-area-inset-left));
        padding-right: max(var(--qm-page-pad), env(safe-area-inset-right));
        padding-bottom: max(var(--qm-page-pad), env(safe-area-inset-bottom));
    }

    .qm-footer {
        padding-bottom: max(12px, env(safe-area-inset-bottom));
    }
}

/* Print styles */
@media print {
    .qm-header,
    .qm-sidebar,
    .qm-footer,
    .sidebar-overlay {
        display: none !important;
    }

    .qm-main {
        margin: 0 !important;
    }

    .page-container {
        padding: 0 !important;
    }
}

/* ================================
   Scrollbar Styles
   ================================ */
.sidebar-nav::-webkit-scrollbar {
    width: 6px;
}

[data-theme="dark"] .sidebar-nav::-webkit-scrollbar-track {
    background: transparent;
}

[data-theme="dark"] .sidebar-nav::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.1);
    border-radius: var(--qm-radius-sm);
}

[data-theme="dark"] .sidebar-nav::-webkit-scrollbar-thumb:hover {
    background: rgba(var(--qm-primary-rgb), 0.3);
}

[data-theme="light"] .sidebar-nav::-webkit-scrollbar-track {
    background: transparent;
}

[data-theme="light"] .sidebar-nav::-webkit-scrollbar-thumb {
    background: var(--qm-border);
    border-radius: var(--qm-radius-sm);
}

[data-theme="light"] .sidebar-nav::-webkit-scrollbar-thumb:hover {
    background: rgba(var(--qm-primary-rgb), 0.3);
}

/* ==========================================================================
   MOBILE OVERFLOW — the page must never scroll sideways
   --------------------------------------------------------------------------
   Reported as "overlapping items" on a phone: on the welfare timeline the
   heading, the points chips, the buttons and the record cards were all clipped
   on the LEFT, and "Notify Guardian" sat outside its own card.

   Nothing was overlapping. One row was wider than the phone, so the document
   itself grew past the viewport and the browser scrolled right — moving every
   other element with it. The row was .timeline-card-actions: four buttons in a
   `display:flex` with no `flex-wrap`.

   Three layers, because the bug needed all three to happen:

     1. min-width:0 — a flex/grid child defaults to min-width:auto, so it
        REFUSES to shrink below its content. That is what let one row widen the
        whole page instead of just itself. This is the actual root cause and
        the reason the symptom appeared page-wide rather than in one card.
     2. overflow-x:clip on the scroll container, so a row that still manages to
        be too wide is contained rather than moving the layout. `clip` rather
        than `hidden` because `hidden` creates a scroll container and would
        break `position:sticky` inside it.
     3. flex-wrap on the recurring row families below.

   Wide tables keep their own .table-scroll / overflow-x:auto wrappers: the aim
   is that THE PAGE never scrolls sideways, not that content gets cut off.
   ========================================================================== */

.qm-main {
    min-width: 0;
    overflow-x: clip;
}

/* Long unbroken strings — a pasted URL, a badge code, an email address — are
   the other way a child outgrows its column. */
.qm-main,
.admin-page,
.q-card,
.q-modal__body {
    overflow-wrap: break-word;
}

/* Direct children of a page or card can shrink. Without this every rule below
   is cosmetic: the row wraps, and the grid track it sits in stays too wide. */
.admin-page > *,
.q-card > *,
.page-header > *,
.filter-row > *,
.stats-grid > *,
.report-columns > * {
    min-width: 0;
}

/* The page header's button row has ONE definition (2026-09-17). About twenty pages each set their own gap
   (8, 10, 12, 14 or 16px) and the rest set none, where Blazor's trimmed whitespace left buttons touching,
   so two pages side by side never matched. Button sizes come from the control scale in q-components.css.
   NOTE: this block must stay separate from the min-width rule above. Merging them (which happened once,
   2026-09-17) puts `display: flex` on EVERY direct child of every page and card — it makes a component's
   own <style> element visible on the page, and it drops the min-width:0 the sideways-scroll fix rests on. */
.header-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--q-row-gap, 8px);
}

/* Every other row of buttons uses the same gap. These are the row names this codebase actually uses;
   a page rule that sets its own gap on one of them puts the drift back. */
.form-actions,
.modal-actions,
.card-actions,
.filter-actions,
.dialog-actions,
.q-modal__footer,
.branch-footer,
.ct-person-actions,
.tts-actions,
.q-filter-bar {
    gap: var(--q-row-gap, 8px);
}

/* The buttons at the foot of a dialog: a right-aligned row, clear of the last field. Five
   components carried an identical copy in their own <style>, each with a 24px top margin. */
.dialog-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--qm-block-gap, 12px);
}

/* A card following the filter bar needs air above it. Nine components wrote this rule into their
   own <style> — six of them byte-identical — under three different container names. Adjacent
   block margins collapse, so this does not stack with the bar's own margin-bottom. */
.admin-page .q-card,
.lessons-page .q-card,
.tts-page .q-card,
.myday-page .q-card {
    margin-top: var(--qm-block-gap, 12px);
}

/* One page title and one body size inside the app shell. Print sheets and public screens are outside
   .qm-main and keep their own paper and large-format sizes. */
.qm-main { font-size: var(--qm-text-base); }

.qm-main h1 {
    font-family: var(--qm-font-display);
    /* THE ONE HOME FOR THE TITLE SIZE. 28px until 2026-09-18, when it was set to 24px here and
       nothing changed on screen: qm-theme.css also carried `.page-header h1 { font-size: 28px }`,
       equal specificity and later in the cascade, so it won every time. That rule is gone (see the
       note there) and this one finally applies. 20px now — a title is the loudest thing on a page,
       it need not also be the tallest, and on a data-driven screen those pixels are a row of data.
       uniform-check.mjs asserts the computed size against this number on every page, AND that the
       rule winning the cascade is this one. */
    font-size: var(--qm-text-xl);
    font-weight: 700;
    line-height: 1.25;
}

@media (max-width: 640px) {
    .qm-main h1 { font-size: var(--qm-text-lg); }
}

/* THE OTHER HEADINGS ARE ON THE SCALE TOO (2026-09-19). Only the h1 had a size. An h2, h3 or h4 with
   no class rule of its own fell through to BOOTSTRAP's defaults — 32, 28 and 24px — so a section
   heading like "Additional Metrics" or a role name in Users & Roles rendered LARGER than the page
   title above it. Found by type-sweep-all.mjs across 54 pages.

   :where() keeps these at the specificity of a bare element selector, so any class rule a component
   sets (.q-card__title, .q-empty__title, a page's own heading class) still wins, and this only
   catches a heading nobody sized. It beats Bootstrap's equal-specificity rule on load order alone:
   bootstrap.min.css is linked first in App.razor. */
:where(.qm-main) h2 { font-size: var(--qm-text-lg); }
:where(.qm-main) h3,
:where(.qm-main) h4 { font-size: var(--qm-text-md); }
:where(.qm-main) h5,
:where(.qm-main) h6 { font-size: var(--qm-text-base); }



.page-header > *,
.filter-row > *,
.stats-grid > *,
.report-columns > * {
    min-width: 0;
}

@media (max-width: 768px) {
    /* Action and control rows wrap. Named by the families that actually recur
       across this codebase rather than by a blanket `div { flex-wrap: wrap }`,
       which would also wrap things that must not (see tabs below). */
    [class$="-actions"],
    [class*="-actions "],
    [class$="-footer"],
    [class$="-controls"],
    [class$="-toolbar"],
    .header-actions,
    .filter-row,
    .filter-actions,
    .form-actions,
    .card-actions,
    .modal-actions,
    .batch-bar,
    .points-summary {
        flex-wrap: wrap !important;
    }

    /* Tabs scroll, they do not wrap. A wrapped tab strip reads as broken in a
       way a wrapped button row does not. */
    .report-tabs,
    .tabs,
    .filter-bar,
    .nav-tabs {
        flex-wrap: nowrap !important;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: thin;
    }
    .report-tabs > *,
    .tabs > *,
    .filter-bar > *,
    .nav-tabs > * {
        flex-shrink: 0;
    }

    /* A button in a wrapped row should shrink its label, not push the row. */
    .q-btn {
        max-width: 100%;
    }

    /* Multi-column grids collapse rather than forcing a minimum track wider
       than the screen — minmax(320px, 1fr) on a 360px phone leaves no room for
       the page's own padding. */
    .report-columns,
    .form-row,
    .settings-grid {
        grid-template-columns: 1fr !important;
    }
}

/* ---- Vertical density (user direction 2026-09-18) --------------------------------------------
   "this project is data driven, and therefore all forms and pages have to be compacted so user
   does not have to scroll infinitely."

   Reported against the School Day page, but the shapes named — an oversized page-header block, card
   headers with a large icon tile, one control per row — are in these shared stylesheets and are
   therefore on EVERY page. So this is one scale change, not a patch to one screen, which is the
   same reasoning the 2026-09-17 size scale followed.

   What a page cost before, measured from the CSS rather than guessed: the page header alone spent
   109px (h1 35 + its 8px margin + a 21px subtitle + 20px padding + 24px margin + a border) before
   any content, and each card header spent 64px (20px padding top and bottom around a 24px row) to
   say one word. A screen with two cards and six fields spent roughly 690px before showing data.

   These are TOKENS and shared rules on purpose. A page must still not set its own title size,
   control height or row gap — that rule is what stopped the drift these numbers came from. */

:root {
    /* The vertical rhythm every page block is built from. */
    --qm-page-header-gap: 6px;      /* below the title, above the rule. Was 8, 12, then 44. */
    --qm-block-gap: 10px;           /* between cards and sections; was 12, 16, then 24. */
    --qm-field-gap: 12px;

    /* An empty state: one line of news, not a poster (2026-09-19). Both empty-state families read
       these, and no page sets its own. */
    --qm-empty-pad: 18px 16px;
    --qm-empty-icon: 28px;           /* between form fields; was 14, and 20 before that. */

    /* =========================================================================================
       ONE TYPE SCALE (2026-09-19). Six steps and a figure size — that is all of them.

       Measured before it existed, with scripts/e2e/browser/type-audit.mjs: EIGHTEEN distinct
       sizes were on screen across fifteen pages — 10, 11, 11.5, 12, 12.5, 12.8, 13, 13.5, 13.6,
       14, 15, 15.2, 16, 18, 20, 22, 24, 28 — most of them accidents of a rem value against a
       16px root (0.8rem = 12.8px, 0.85rem = 13.6px, 0.95rem = 15.2px). Body text was 14px and
       read as heavy on a data screen; it is 13px now, the same size as the text in a control, so
       a table cell and the input above it finally agree.

       CHANGE THE TOKEN, NEVER A PAGE. A raw px font-size in a page rule is the drift coming back,
       and type-audit.mjs fails when the count of distinct sizes climbs.

       The excluded set keeps its own sizes and is deliberately outside this: the kiosk, the public
       display and signage, public feedback, booking, ticket status, shared documents, the print
       sheets and the sign-in pages are read across a room or off paper.
       ========================================================================================= */
    --qm-text-xs:   11px;   /* chip, stat label, table meta, timestamp */
    --qm-text-sm:   12px;   /* secondary text, hints, table cells */
    --qm-text-base: 13px;   /* body, controls, almost everything */
    --qm-text-md:   15px;   /* card title, h3, h4 */
    --qm-text-lg:   17px;   /* h2, section heading */
    --qm-text-xl:   20px;   /* h1, the page title */
    --qm-text-stat: 20px;   /* a figure on a stat tile — the one place a number outranks its label */
}

/* A page is the frame the content sits in and has no padding of its own — the gutter belongs to
   .qm-main (--qm-page-pad). Seventeen components wrote `\.admin-page { padding: 0 }` into their
   own <style> to say this, and two more wrote `padding: 24px; max-width: 900px; margin: 0 auto`,
   which (a <style> block being global, not scoped) capped whatever hub happened to be hosting
   them — 312px of a 1212px page unused on Appearance. Declared once, here. */
.admin-page {
    padding: 0;
}

.form-group {
    margin-bottom: var(--qm-field-gap);
}

/* THE MISSING RULE, added 2026-09-18, and the single biggest cause of the report that started this:
   "all forms and pages have to be compacted so user does not have to scroll infinitely".

   .form-row is used 59 times across 23 admin pages and had NO base rule anywhere — only
   `.login-container .form-row`, scoped to the login page. So on every admin page it was an
   unstyled div and its children stacked full-width, one control per row, which is exactly what the
   School Day screenshot showed. The mobile block above has been collapsing `.form-row` to
   `grid-template-columns: 1fr` this whole time, overriding a property nothing ever set: proof the
   grid was intended and simply lost.

   auto-fit with a 240px floor means two controls sit side by side on a desktop and stack on a
   phone without needing a breakpoint of their own, and a row holding one control still fills the
   width as it did before. */
.form-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: var(--qm-field-gap) 16px;
    align-items: start;
}

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

/* A field that genuinely needs the whole width inside a row says so. */
.form-row .form-group--wide,
.form-row .form-row__wide { grid-column: 1 / -1; }

/* Mandatory-field indicators (2026-09-19). A form with required fields opens with one line saying what
   the asterisk means; each required label carries the same asterisk (QInput/QSelect Required="true",
   .q-input__required). A form that refused to submit says so once, under its fields, in .form-error —
   the per-field messages say what is wrong with each. */
.form-required-note {
    margin: 0 0 var(--qm-field-gap);
    font-size: var(--qm-text-xs);
    color: var(--qm-text-muted);
}

.form-error {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: var(--qm-field-gap) 0 0;
    font-size: var(--qm-text-sm);
    color: var(--qm-danger);
}

/* Radzen's data grid carries its own 14px (0.875rem), set through its own custom properties on a
   selector of higher specificity than anything in this file (`.rz-datatable-data td .rz-cell-data`),
   so a plain font-size rule here lost — measured, not assumed. It was the last off-scale size on a
   data page after the 2026-09-19 type sweep. Pointing Radzen's VARIABLES at the scale wins without a
   specificity fight, and keeps working if Radzen reshuffles its selectors. */
.qm-main {
    --rz-grid-cell-font-size: var(--qm-text-base);
    --rz-grid-header-font-size: var(--qm-text-sm);
    --rz-grid-filter-font-size: var(--qm-text-base);
    --rz-pager-summary-font-size: var(--qm-text-sm);
    --rz-body-font-size: var(--qm-text-base);
}
