/* Custom Properties */
:root {
    --primary-light: #5B74BC;
    --primary: #4C60A7;
    --primary-dark: #292A64;
    --background: #FFFFFF;
    --surface: #E9E9EC;
    --divider: #D1D1D6;
    /* The edge of a form box. An empty box has nothing in it, so its border is the only
       thing saying it is there, and WCAG 2.2 success criterion 1.4.11 asks for 3:1
       against the colour behind it
       (w3.org/WAI/WCAG22/Understanding/non-text-contrast.html, read 22 September 2026).
       Measured in the browser on 22 September 2026: Bootstrap's default #dee2e6 gave
       1.24:1 on the report form, and --divider is no better at that job. This value
       measures 3.27:1 on white and 5.2:1 on the dark theme's background, so one token
       serves both. e2e/field-contrast.spec.js measures it rather than trusting it. */
    --field-border: #8E8E93;
    --text-primary: #424242;
    --text-secondary: #757575;

    /* Derived colors */
    --success-color: #27ae60;
    --warning-color: #f39c12;
    --danger-color: #e74c3c;
    --info-color: #3498db;
    --sidebar-width: 280px;
    --transition-speed: 0.3s;

    /* One primary colour, under both of its names.
     *
     * This project calls its main colour --primary. Bootstrap calls its own
     * --bs-primary. Both existed, and 36 rules across six of this project's
     * stylesheets read the Bootstrap one, which nothing had ever changed. So
     * those 36 rules drew #0d6efd, Bootstrap's blue, while the rest of the site
     * drew #4C60A7. The active view toggle on the report list is the one a
     * person could see: a blue button in a row of purple ones.
     *
     * Pointing Bootstrap's name at this project's colour fixes all 36 in one
     * place, and no rule is edited. Bootstrap gives this as the way to restyle
     * after compilation: "Each .btn-* modifier class updates the appropriate
     * CSS variables to minimize additional CSS rules"
     * (getbootstrap.com/docs/5.3/components/buttons/, read 21 September 2026).
     *
     * base.css loads after bootstrap.min.css, so this wins. That is the same
     * reason the shape and elevation values below work, and it is checked in
     * templates/base.html where the two files are linked in that order.
     *
     * --bs-primary-rgb is the same colour as three numbers. Bootstrap uses it
     * inside rgba() for faint backgrounds, which cannot read a hex value. It is
     * written out because CSS has no way to take a hex apart.
     */
    --bs-primary: var(--primary);
    --bs-primary-rgb: 76, 96, 167;

    /* Shape and elevation, decided once.
     *
     * base.css loads after bootstrap.min.css, so these :root values replace
     * Bootstrap's own. Every rounded-* utility and every component reads them -
     * verified in the copy this project ships: .rounded-3 is
     * border-radius: var(--bs-border-radius-lg), .rounded-4 is
     * var(--bs-border-radius-xl), .rounded-pill is var(--bs-border-radius-pill),
     * .shadow-sm is var(--bs-box-shadow-sm)
     * (getbootstrap.com/docs/5.3/customize/css-variables/, read 20 September
     * 2026). So the 380-odd places in the markup that use those utilities change
     * from here, and none of them is edited.
     *
     * Square corners. The utilities are left in the markup on purpose: they say
     * what an author meant, and the size they resolve to is decided here.
     *
     * .rounded-circle is a literal 50% in Bootstrap and does not read these. The
     * three places that are still round are round because of what they are, not
     * because of a radius: a spinner, an unread dot and a timeline dot. Every
     * chip that holds an icon or a person's initials follows the token instead,
     * so the avatar in the navbar is the same shape as the reviewer avatars on
     * a report.
     */
    --bs-border-radius: 0;
    --bs-border-radius-sm: 0;
    --bs-border-radius-lg: 0;
    --bs-border-radius-xl: 0;
    --bs-border-radius-xxl: 0;
    --bs-border-radius-2xl: 0;
    --bs-border-radius-pill: 0;

    /* One tap target size for every control a finger has to hit.
     *
     * 44px is not a new decision. This file already used it in six places for
     * buttons, inputs, selects, pagination links, the settings switch and the
     * theme toggle, and the comment beside one of them records why: it exceeds
     * the WCAG 2.2, 2.5.8 floor of "at least 24 by 24 CSS pixels"
     * (w3.org/WAI/WCAG22/Understanding/target-size-minimum.html, read 20
     * September 2026).
     *
     * It was six copies of one number, and the drift showed: the navbar bell is
     * a button, so it got 44, and the avatar beside it is a plain div, so it
     * stayed at 40 and the pair looked wrong. One number, every reader. */
    --control-size: 44px;

    /* The space between a button's icon and its words.
     *
     * There were two ways of making it and they disagreed. 164 icons carried a
     * me-1 or me-2 class, 13 relied on a plain space character, and the plain
     * space stopped showing once .btn became a flex box, because the words
     * become their own item and a space at the start of one collapses. That is
     * why "Save draft" and "Cancel" read as one word joined to a symbol.
     *
     * The gap below is now the only thing that makes this space, so it cannot
     * differ from one button to the next. */
    --icon-label-gap: 0.375rem;

    /* Three levels of lift, and no more. NN/g on visual hierarchy: "If
     * everything is contrasted, then nothing stands out", with no more than
     * three contrast variations
     * (nngroup.com/articles/visual-hierarchy-ux-definition/, read 20 September
     * 2026). Twenty different shadow values were in this file; a reader could
     * not tell which surface was meant to be above which.
     *
     * Two layers per level: a tight dark line that reads as a real edge against
     * a white background, and a wider soft one that does the lifting. A single
     * blurred shadow on white goes grey and muddy rather than lifting.
     */
    --bs-box-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.10);
    --bs-box-shadow: 0 2px 4px rgba(16, 24, 40, 0.06), 0 4px 8px rgba(16, 24, 40, 0.10);
    --bs-box-shadow-lg: 0 4px 8px rgba(16, 24, 40, 0.06), 0 12px 24px rgba(16, 24, 40, 0.12);
}

/* Dark mode variables */
[data-theme="dark"] {
    --primary-light: #7B94DC;
    --primary: #5B74BC;
    --primary-dark: #4C60A7;

    /* --bs-primary reads var(--primary) and so follows the line above on its
     * own. --bs-primary-rgb is the same colour written as three numbers, which
     * cannot follow anything, so the dark value is written out here. #5B74BC is
     * rgb(91, 116, 188). */
    --bs-primary-rgb: 91, 116, 188;
    --background: #1a1a1a;
    --surface: #3a3a3a;
    --divider: #404040;
    --text-primary: #e0e0e0;
    --text-secondary: #b0b0b0;

    /* Dark mode specific */
    --body-bg: #1a1a1a;
    --body-color: #e0e0e0;
    --card-bg: #2d2d2d;
    --border-color: #404040;
    --navbar-bg: #2d2d2d;
    --table-bg: #2d2d2d;
    --table-hover-bg: #3a3a3a;
    --dropdown-bg: #2d2d2d;
    --dropdown-color: #e0e0e0;
    --input-bg: #3a3a3a;
    --input-color: #e0e0e0;
    --input-border: #505050;
    --sidebar-gradient-start: #3a3d7a;
    --sidebar-gradient-end: #292A64;
}

/* Global Typography & Utilities */
h1, h2, h3, h4, h5, h6 {
    letter-spacing: -0.025em;
}

.ls-1 { letter-spacing: 0.05em; }
.x-small { font-size: 0.7rem; }

/* Allow a flex item to shrink below its content width so a long child (for example a long building-type
   name) can truncate instead of pushing its siblings out of the row. Bootstrap 5.3 ships no min-width:0
   helper, so we add this one reusable utility. Apply it to every flex ancestor between the row and the
   element that should truncate, because a flex item defaults to min-width:auto and will not otherwise
   shrink. Pairs with Bootstrap's .text-truncate on the element that carries the text. */
.min-w-0 {
    min-width: 0;
}

/* Text truncation utilities */
.text-truncate-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.text-truncate-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Thin progress bar utility */
.progress-thin {
    height: 4px;
}

/* Glassmorphism System */
:root {
    --glass-bg: rgba(255, 255, 255, 0.7);
    --glass-border: rgba(255, 255, 255, 0.4);
}

[data-theme="dark"] {
    --glass-bg: rgba(30, 30, 30, 0.7);
    --glass-border: rgba(255, 255, 255, 0.1);
}

.glass-card {
    background: var(--glass-bg);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--glass-border) !important;
    transition: box-shadow var(--transition-speed) ease;
}

.glass-card:hover {
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.08) !important;
}

/* Enhanced Bootstrap Components */
.badge.bg-success-subtle {
    background-color: rgba(25, 135, 84, 0.1) !important;
    color: #198754 !important;
}

.badge.bg-warning-subtle {
    background-color: rgba(255, 193, 7, 0.1) !important;
    color: #856404 !important;
}

.shadow-sm {
    box-shadow: 0 .125rem .25rem rgba(0,0,0,.045) !important;
}

/* Submit feedback overlay: blur + green spinner (document create/edit) */
.submit-feedback-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1040;
    display: flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    background: rgba(0, 0, 0, 0.12);
}

/* Universal Animations */
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes slideUp {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
}

.fade-in {
    animation: fadeIn 0.4s ease forwards;
}

.slide-up {
    animation: slideUp 0.5s ease forwards;
}

/* Primary layout containers transition */
main {
    animation: fadeIn 0.3s ease-in;
}

/* Light mode variables (default) */
[data-theme="light"] {
    --body-bg: #FFFFFF;
    --body-color: #424242;
    --card-bg: #FFFFFF;
    --border-color: #D1D1D6;
    --navbar-bg: #FFFFFF;
    --table-bg: #FFFFFF;
    --table-hover-bg: #E9E9EC;
    --dropdown-bg: #FFFFFF;
    --dropdown-color: #424242;
    --input-bg: #FFFFFF;
    --input-color: #424242;
    --input-border: #D1D1D6;
    --sidebar-gradient-start: #4C60A7;
    --sidebar-gradient-end: #292A64;
}

/* Base Styles */
body {
    background-color: var(--body-bg);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    color: var(--body-color);
    transition: background-color var(--transition-speed), color var(--transition-speed);
}

/* Loader */
.loader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(255, 255, 255, 0.9);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 9999;
    transition: opacity 0.3s ease;
}

[data-theme="dark"] .loader {
    background: rgba(0, 0, 0, 0.9);
}

.loader.hidden {
    opacity: 0;
    pointer-events: none;
}

.spinner-border.text-primary {
    color: var(--primary) !important;
}

/* Enhanced Sidebar */
.sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--sidebar-width);
    background: linear-gradient(135deg, var(--sidebar-gradient-start) 0%, var(--sidebar-gradient-end) 100%);
    color: #ffffff;
    z-index: 1045;
    overflow-y: auto;
    transition: transform var(--transition-speed) ease;
    box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
}

/* Custom Scrollbar for Sidebar */
.sidebar::-webkit-scrollbar {
    width: 6px;
}

.sidebar::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.1);
}

.sidebar::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.3);
    border-radius: var(--bs-border-radius);
}

.sidebar::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.5);
}

.sidebar-header {
    background-color: rgba(0, 0, 0, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    padding: 1.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    backdrop-filter: blur(10px);
}

.sidebar-header h5 {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: 0.5px;
}

.sidebar-header .btn-close {
    filter: invert(1);
    opacity: 0.8;
    transition: opacity var(--transition-speed);
}

.sidebar-header .btn-close:hover {
    opacity: 1;
}

/* Navigation Links with Icons */
.sidebar-body .nav-link {
    color: rgba(255, 255, 255, 0.9);
    padding: 14px 24px;
    border-radius: 0;
    transition: background-color var(--transition-speed) ease, color var(--transition-speed) ease, padding-left var(--transition-speed) ease;
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    position: relative;
    overflow: hidden;
}

.sidebar-body .nav-link::before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
    transition: left 0.5s ease;
}

.sidebar-body .nav-link:hover::before {
    left: 100%;
}

.sidebar-body .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.1);
    color: #ffffff;
    padding-left: 30px;
}

.sidebar-body .nav-link.active {
    background-color: var(--primary-light);
    color: #ffffff;
    border-left: 4px solid #ffffff;
    font-weight: 500;
}

.sidebar-body .nav-link i {
    font-size: 1.1rem;
    width: 20px;
    text-align: center;
}

/* Sidebar Accordion Customization */
.sidebar .accordion-button {
    color: rgba(255, 255, 255, 0.9);
}

.sidebar .accordion-button:not(.collapsed) {
    background-color: rgba(255, 255, 255, 0.1);
    color: #ffffff;
}

.sidebar .accordion-button:focus {
    box-shadow: none;
}

.sidebar .accordion-button::after {
    filter: invert(1) brightness(2);
}

.sidebar .accordion-body {
    background-color: transparent;
    padding: 0;
}

.sidebar .accordion-body .nav-link {
    padding-left: 3.5rem; /* Indent sub-menu items */
    font-size: 0.9rem;
}

.sidebar .accordion-body .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.15);
}

.sidebar .accordion-body .nav-link.active {
    background-color: var(--primary);
    border-left: 4px solid #ffffff;
    font-weight: 500;
}


/* Section Headers */
.sidebar-section {
    padding: 20px 24px 10px;
    font-size: 0.75rem;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.6);
    font-weight: 600;
    letter-spacing: 1.5px;
    margin-top: 10px;
}

/* Enhanced Top Navigation */
.navbar {
    background: var(--navbar-bg);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    padding: 1rem 1.5rem;
    border-bottom: 1px solid var(--divider);
    transition: all var(--transition-speed);
    color: var(--body-color);
}

[data-theme="light"] .navbar {
    background-color: #FFFFFF;
}

[data-theme="dark"] .navbar {
    background: linear-gradient(135deg, var(--sidebar-gradient-start) 0%, var(--sidebar-gradient-end) 100%);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    color: #ffffff;
}

.navbar-brand {
    font-weight: 600;
    font-size: 1.25rem;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

[data-theme="dark"] .navbar-brand {
    color: #ffffff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

/* Single sidebar control: chevron (>>/<<) only; hamburger hidden at all breakpoints */
.navbar-toggler {
    display: none !important;
    border: 1px solid var(--primary-light);
    color: var(--primary-light);
    background-color: rgba(91, 116, 188, 0.1);
}

.navbar-toggler:hover {
    background-color: rgba(91, 116, 188, 0.2);
    border-color: var(--primary-light);
}

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

[data-theme="light"] .navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.75)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}

[data-theme="dark"] .navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.75)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
    filter: none;
}

/* Breadcrumb styling for navbar - make it super visible */
.navbar .breadcrumb {
    background: transparent;
    margin: 0;
}

[data-theme="dark"] .navbar .breadcrumb-item a {
    color: rgba(255, 255, 255, 0.95);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.navbar .breadcrumb-item a:hover {
    color: #ffffff;
}

[data-theme="dark"] .navbar .breadcrumb-item.active {
    color: rgba(255, 255, 255, 0.8);
}

[data-theme="dark"] .navbar .breadcrumb-item + .breadcrumb-item::before {
    color: rgba(255, 255, 255, 0.7);
    font-weight: 600;
}

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

[data-theme="light"] .navbar .breadcrumb-item a:hover {
    color: var(--text-primary);
}

[data-theme="light"] .navbar .breadcrumb-item.active {
    color: var(--text-primary);
    font-weight: 500;
}

/* Search bar styling for navbar - make it super visible */
/*.navbar .search-bar {*/
/*    position: relative;*/
/*}*/

/*.navbar .search-bar .form-control {*/
/*    background-color: rgba(255, 255, 255, 0.95);*/
/*    border: 1px solid rgba(255, 255, 255, 0.95);*/
/*    color: var(--primary-dark);*/
/*    padding: 0.5rem 1rem 0.5rem 2.5rem;*/
/*    backdrop-filter: blur(10px);*/
/*    font-weight: 500;*/
/*}*/

/*.navbar .search-bar .form-control::placeholder {*/
/*    color: var(--primary-dark);*/
/*    opacity: 0.7;*/
/*}*/

/*.navbar .search-bar .form-control:focus {*/
/*    background-color: #ffffff;*/
/*    border-color: #ffffff;*/
/*    box-shadow: 0 0 0 0.2rem rgba(255, 255, 255, 0.3);*/
/*    color: var(--primary-dark);*/
/*}*/

/*.navbar .search-bar .search-icon {*/
/*    position: absolute;*/
/*    left: 0.75rem;*/
/*    top: 50%;*/
/*    transform: translateY(-50%);*/
/*    color: var(--primary-dark);*/
/*    z-index: 2;*/
/*}*/

/* Theme Switcher - Single button design */
.theme-switcher {
    display: flex;
    align-items: center;
    padding: 0.25rem;
    /*background-color: rgba(255, 255, 255, 0.15);*/
    border-radius: var(--bs-border-radius);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    backdrop-filter: blur(10px);
}

.theme-toggle-btn {
    width: 40px;
    height: 40px;
    border-radius: var(--bs-border-radius);
    /*border: 2px solid transparent;*/
    /*background: rgba(255, 255, 255, 0.2);*/
    /*color: rgba(255, 255, 255, 0.9);*/
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition-speed);
    font-size: 1.1rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.theme-toggle-btn:hover {
    background-color: rgba(255, 255, 255, 0.3);
    color: #ffffff;
    transform: scale(1.05);
}

.theme-toggle-btn:active {
    transform: scale(0.95);
}

/* Theme-specific button styling */
[data-theme="light"] .theme-toggle-btn {
    background: rgba(76, 96, 167, 0.9);
    color: #ffffff;
    box-shadow: 0 2px 8px rgba(76, 96, 167, 0.3);
    border: 2px solid rgba(76, 96, 167, 0.3);
}

[data-theme="light"] .theme-toggle-btn:hover {
    background: rgba(76, 96, 167, 1);
    color: #ffffff;
    box-shadow: 0 4px 12px rgba(76, 96, 167, 0.4);
    transform: scale(1.05);
}

[data-theme="dark"] .theme-toggle-btn {
    background: rgba(255, 255, 255, 0.9);
    color: var(--primary-dark);
    box-shadow: 0 2px 8px rgba(255, 255, 255, 0.3);
    border: 2px solid rgba(255, 255, 255, 0.3);
}

[data-theme="dark"] .theme-toggle-btn:hover {
    background: rgba(255, 255, 255, 1);
    color: var(--primary-dark);
    box-shadow: 0 4px 12px rgba(255, 255, 255, 0.4);
    transform: scale(1.05);
}

/* System theme styling */
[data-theme="system"] .theme-toggle-btn {
    background: rgba(128, 128, 128, 0.9);
    color: #ffffff;
    box-shadow: 0 2px 8px rgba(128, 128, 128, 0.3);
    border: 2px solid rgba(128, 128, 128, 0.3);
}

[data-theme="system"] .theme-toggle-btn:hover {
    background: rgba(128, 128, 128, 1);
    color: #ffffff;
    box-shadow: 0 4px 12px rgba(128, 128, 128, 0.4);
    transform: scale(1.05);
}

/* Ensure theme switcher is always visible */
.theme-switcher {
    z-index: 1000;
    position: relative;
}

/* Theme switching animation */
.theme-toggle-btn i {
    transition: transform var(--transition-speed) ease;
}

.theme-toggle-btn:hover i {
    transform: rotate(15deg);
}

.theme-toggle-btn:active i {
    transform: rotate(-15deg) scale(0.9);
}

/* The notification bell and its dropdown live in css/notification_bell.css, which the
   shell loads on every page. They were here as well, in an older form, and the two
   copies disagreed. */

.modal-backdrop.show {
    opacity: 0.5;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.modal-content {
    border: none;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    background: var(--glass-bg, rgba(255, 255, 255, 0.9));
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

/* User Menu */
.user-menu {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.user-avatar {
    width: var(--control-size);
    height: var(--control-size);
    border-radius: var(--bs-border-radius);
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%);
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    cursor: pointer;
    /*border: 2px solid rgba(255, 255, 255, 0.3);*/
    backdrop-filter: blur(10px);
    transition: all var(--transition-speed);
}

[data-theme="light"] .user-avatar {
    background: var(--surface);
    color: var(--text-primary);
    border: 1px solid var(--divider);
}

[data-theme="light"] .user-avatar:hover {
    border-color: var(--primary);
    background: var(--card-bg);
    color: var(--primary);
}

.user-avatar:hover {
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0.2) 100%);
    border-color: rgba(255, 255, 255, 0.5);
}

/* Enhanced Cards */
.dashboard-card {
    border-radius: var(--bs-border-radius);
    padding: 1.75rem;
    color: white;
    margin-bottom: 1.5rem;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
    position: relative;
    overflow: hidden;
    transition: box-shadow var(--transition-speed);
}

.dashboard-card::before {
    content: '';
    position: absolute;
    top: -50%;
    right: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
    transform: rotate(45deg);
}

.dashboard-card:hover {
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

.dashboard-card h3 {
    font-size: 2.5rem;
    font-weight: 300;
    margin: 0.5rem 0 0;
    position: relative;
    z-index: 1;
}

.dashboard-card p {
    margin: 0;
    opacity: 0.95;
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 500;
    position: relative;
    z-index: 1;
}

.dashboard-card .card-icon {
    position: absolute;
    right: 20px;
    bottom: 20px;
    font-size: 4rem;
    opacity: 0.2;
}

/* Table Enhancements */
.table-card {
    background: var(--card-bg);
    border-radius: var(--bs-border-radius);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    overflow: hidden;
    transition: box-shadow var(--transition-speed), background-color var(--transition-speed);
    border: 1px solid var(--divider);
}

[data-theme="dark"] .table-card {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

.table-card:hover {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.table-card-header {
    background-color: var(--surface);
    padding: 1.25rem 1.5rem;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

[data-theme="dark"] .table-card-header {
    background-color: rgba(255, 255, 255, 0.08);
}

.table-card-header h5 {
    margin: 0;
    color: var(--body-color);
    font-weight: 600;
}

[data-theme="dark"] .table-card-header h5 {
    color: #ffffff;
}

.table {
    margin-bottom: 0;
    color: var(--body-color);
}

.table th {
    background-color: var(--surface);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.8rem;
    letter-spacing: 1px;
    border-bottom: 2px solid var(--border-color);
    color: var(--text-secondary);
    padding: 1rem;
}

[data-theme="dark"] .table th {
    background-color: rgba(255, 255, 255, 0.08);
    color: #ffffff;
}

.table td {
    padding: 1rem;
    vertical-align: middle;
    background-color: var(--table-bg);
    border-bottom: 1px solid var(--border-color);
}

[data-theme="dark"] .table td {
    color: var(--body-color);
}

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

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

/* Status Badges */
.status-badge {
    font-size: 0.75rem;
    padding: 6px 12px;
    border-radius: var(--bs-border-radius);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Button Styles */
.btn-light {
    background-color: var(--surface);
    border-color: var(--divider);
    color: var(--text-primary);
}

.btn-light:hover {
    background-color: var(--card-bg);
    border-color: var(--primary);
    color: var(--primary);
}

/* The outline buttons used to be styled here, one rule per variant, by setting
 * border-color and color directly. Those rules were deleted on 21 September
 * 2026 and the one further down this file that sets the --bs-btn-* variables
 * now does the whole job.
 *
 * Both were in the file at the same time and the pair fought. Bootstrap's own
 * declaration is border-color: var(--bs-btn-border-color), so a rule setting
 * border-color directly beats a rule that only sets the variable. The rules
 * here were therefore what the screen drew, and the newer rule was changing a
 * variable nothing read any more. That is why an ordinary button could be one
 * colour on one page and another colour on the next.
 *
 * Deleted, not made more specific. Two rules for one thing is the drift; an
 * !important would have kept both and moved the argument rather than ending it.
 *
 * btn-outline-danger below is kept on purpose, for the reason written beside
 * the variable rule: destructive is the one action that has earned a colour of
 * its own.
 */
.btn-outline-danger {
    color: var(--danger-color);
    border-color: var(--danger-color);
}

.btn-outline-danger:hover {
    background-color: var(--danger-color);
    border-color: var(--danger-color);
    color: white;
}

.btn-action {
    padding: 0.375rem 0.75rem;
    font-size: 0.875rem;
    border-radius: var(--bs-border-radius);
    transition: all var(--transition-speed);
}

.btn-action:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

/* Welcome Section */
.welcome-section {
    background: linear-gradient(135deg, var(--surface) 0%, var(--card-bg) 100%);
    border-radius: var(--bs-border-radius);
    padding: 2.5rem;
    margin-bottom: 2rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    position: relative;
    overflow: hidden;
    border: 1px solid var(--divider);
}

.welcome-section::before {
    content: '';
    position: absolute;
    top: -50%;
    right: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, rgba(91, 116, 188, 0.05) 0%, transparent 70%);
    transform: rotate(45deg);
}

.welcome-section h1 {
    font-size: 2rem;
    margin-bottom: 0.5rem;
    color: var(--text-primary);
    position: relative;
    z-index: 1;
}

[data-theme="dark"] .welcome-section h1 {
    color: #ffffff;
}

.welcome-section p {
    color: var(--text-secondary);
    margin-bottom: 0;
    position: relative;
    z-index: 1;
}


/* Search Bar */
/*.search-bar {*/
/*    position: relative;*/
/*    min-width: 200px;*/
/*    max-width: 400px;*/
/*    flex: 1;*/
/*}*/

/*.search-bar input {*/
/*    width: 100%;*/
/*    padding: 0.5rem 2.5rem 0.5rem 1rem;*/
/*    border: 1px solid var(--border-color);*/
/*    background-color: var(--input-bg);*/
/*    color: var(--input-color);*/
/*    transition: all var(--transition-speed);*/
/*}*/

/*.search-bar input::placeholder {*/
/*    color: var(--text-secondary);*/
/*}*/

/*.search-bar input:focus {*/
/*    outline: none;*/
/*    border-color: var(--primary);*/
/*    box-shadow: 0 0 0 3px rgba(91, 116, 188, 0.1);*/
/*}*/

/*.search-bar .search-icon {*/
/*    position: absolute;*/
/*    right: 0.75rem;*/
/*    top: 50%;*/
/*    transform: translateY(-50%);*/
/*    color: var(--text-secondary);*/
/*    pointer-events: none;*/
/*}*/

/* Mobile Search Toggle */
/*.mobile-search-toggle {*/
/*    display: none;*/
/*    background-color: rgba(255, 255, 255, 0.15);*/
/*    border: 1px solid rgba(255, 255, 255, 0.2);*/
/*    color: #ffffff;*/
/*    backdrop-filter: blur(10px);*/
/*}*/

/*.mobile-search-toggle:hover {*/
/*    background-color: rgba(255, 255, 255, 0.2);*/
/*    border-color: rgba(255, 255, 255, 0.4);*/
/*}*/

/* Main Content - Sticky footer support via flexbox */
.main-content {
    background-color: var(--body-bg);
    transition: background-color var(--transition-speed);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.main-content > main {
    flex: 1 0 auto;
}

.main-content > footer {
    flex-shrink: 0;
    max-width: 100%;
    box-sizing: border-box;
}

/* Dropdown Menus */
.dropdown-menu {
    background-color: var(--dropdown-bg);
    border: 1px solid var(--border-color);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
}

.dropdown-item {
    color: var(--dropdown-color);
    transition: all var(--transition-speed);
}

.dropdown-item:hover {
    background-color: var(--surface);
    color: var(--primary);
}

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

.dropdown-divider {
    border-color: var(--border-color);
}

/* User dropdown styling - make text super visible */
.dropdown-header {
    background-color: rgba(255, 255, 255, 0.95);
    color: var(--primary-dark);
    padding: 1rem 1.25rem;
}

.dropdown-header strong {
    color: var(--primary-dark);
    font-weight: 600;
    font-size: 1rem;
}

.dropdown-header small {
    color: var(--primary-dark) !important;
    font-weight: 500;
    font-size: 0.9rem;
    opacity: 0.8;
}

/* Override Bootstrap's text-muted and text-black-50 */
.dropdown-header .text-muted,
.dropdown-header .text-black-50 {
    color: var(--primary-dark) !important;
    opacity: 0.8 !important;
}

/* Animations */
@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.fade-in {
    animation: fadeIn 0.5s ease forwards;
}

/* Quick Actions */
.quick-actions {
    display: flex;
    gap: 1rem;
    margin-bottom: 2rem;
}

.quick-action-btn {
    padding: 1rem 1.5rem;
    border-radius: var(--bs-border-radius);
    background-color: var(--card-bg);
    transition: all var(--transition-speed);
    text-decoration: none;
    color: var(--body-color);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
    border: 1px solid var(--divider);
}

[data-theme="dark"] .quick-action-btn {
    color: #ffffff;
}

.quick-action-btn:hover {
    border-color: var(--primary);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    color: var(--primary);
}

.quick-action-btn i {
    font-size: 1.25rem;
    color: var(--primary);
}

/* Breadcrumb Enhancement */
.breadcrumb {
    background-color: transparent;
    padding: 0;
    margin-bottom: 1rem;
}

.breadcrumb-item a {
    color: var(--primary);
    text-decoration: none;
    transition: color var(--transition-speed);
}

.breadcrumb-item a:hover {
    color: var(--primary-dark);
}

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

[data-theme="dark"] .breadcrumb-item.active {
    color: #ffffff;
}

/* Alert Styles */
.alert {
    border: none;
    border-radius: var(--bs-border-radius);
}

/* Bootstrap compatibility: Django messages.error emits "error" tag, not "danger" */
.alert.alert-error {
    border-color: #dc3545;
    background-color: #f8d7da;
    color: #721c24;
}

[data-theme="dark"] .alert.alert-error {
    border-color: #dc3545;
    background-color: rgba(220, 53, 69, 0.2);
    color: #ea868f;
}

/* Loading States */
.skeleton {
    background: linear-gradient(90deg, var(--surface) 25%, var(--card-bg) 50%, var(--surface) 75%);
    background-size: 200% 100%;
    animation: loading 1.5s infinite;
}

@keyframes loading {
    0% {
        background-position: 200% 0;
    }
    100% {
        background-position: -200% 0;
    }
}

/* Custom Tooltips */
.custom-tooltip {
    position: relative;
    cursor: help;
}

.custom-tooltip::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: 125%;
    left: 50%;
    transform: translateX(-50%) scale(0);
    background-color: var(--primary-dark);
    color: white;
    padding: 0.5rem 1rem;
    border-radius: var(--bs-border-radius);
    font-size: 0.875rem;
    white-space: nowrap;
    opacity: 0;
    transition: all var(--transition-speed);
    pointer-events: none;
}

.custom-tooltip:hover::after {
    transform: translateX(-50%) scale(1);
    opacity: 1;
}

/* Footer */
footer {
    background-color: var(--surface);
    color: var(--text-secondary);
    border-top: 1px solid var(--divider);
}

[data-theme="dark"] footer {
    background-color: #232323;
    color: #ffffff;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

/* Form/card action footers: transparent background for smoother UI (no gray bar) */
.card-body footer,
form > footer {
    background-color: transparent;
}

[data-theme="dark"] .card-body footer,
[data-theme="dark"] form > footer {
    background-color: transparent;
}

[data-theme="dark"] footer small {
    color: var(--text-secondary);
}

/* Custom gradients for dashboard cards */
.card-gradient-1 {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
}

.card-gradient-2 {
    background: linear-gradient(135deg, var(--primary-light) 0%, var(--primary) 100%);
}

.card-gradient-3 {
    background: linear-gradient(135deg, #5B74BC 0%, #7B94DC 100%);
}

/* Footer Theming - Matches Sidebar */
.footer-themed {
    background: linear-gradient(135deg, var(--sidebar-gradient-start) 0%, var(--sidebar-gradient-end) 100%);
    color: #ffffff !important;
    border-top: 1px solid rgba(255, 255, 255, 0.1) !important;
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
    transition: background var(--transition-speed) ease;
}

.footer-themed small {
    color: #ffffff !important;
    font-weight: 600;
    letter-spacing: 0.02em;
    font-size: 0.95rem;
    padding: 0.75rem 1.5rem;
}

.footer-themed .bi-fire {
    font-size: 1.1rem;
    color: var(--danger-color);
}

/* Footer link hover/focus for accessibility and on-brand appearance */
.footer-themed a.footer-themed-link,
.footer-themed .footer-themed-link {
    transition: opacity var(--transition-speed) ease;
}
.footer-themed a.footer-themed-link:hover,
.footer-themed a.footer-themed-link:focus-visible {
    opacity: 1;
    text-decoration: underline;
}
.footer-themed a.footer-themed-link:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.8);
    outline-offset: 2px;
}

/* Auth buttons styling for non-authenticated users */
.auth-buttons .btn {
    backdrop-filter: blur(10px);
    font-weight: 600;
    padding: 0.5rem 1.25rem;
    transition: all var(--transition-speed);
    border-width: 2px;
}

.auth-buttons .btn-outline-primary {
    background-color: rgba(255, 255, 255, 0.95);
    border: 2px solid rgba(255, 255, 255, 0.95);
    color: var(--primary-dark);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

[data-theme="light"] .auth-buttons .btn-outline-primary {
    color: var(--primary);
    border-color: var(--primary);
    background-color: transparent;
    box-shadow: none;
}

[data-theme="light"] .auth-buttons .btn-outline-primary:hover {
    background-color: var(--primary);
    color: white;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.auth-buttons .btn-primary {
    background: linear-gradient(135deg, var(--primary-light) 0%, var(--primary) 100%);
    border: 2px solid var(--primary-light);
    color: #ffffff;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.auth-buttons .btn-primary:hover {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    border-color: var(--primary);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

/* Active state for current page */
.auth-buttons .btn-primary[href*="login"],
.auth-buttons .btn-primary[href*="signup"] {
    background: linear-gradient(135deg, var(--primary-light) 0%, var(--primary) 100%);
    border-color: var(--primary-light);
    color: #ffffff;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.auth-buttons .btn-primary[href*="login"]:hover,
.auth-buttons .btn-primary[href*="signup"]:hover {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
    border-color: var(--primary);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

/* ===== BOOTSTRAP 5.3.7 MEDIA QUERIES ===== */
/* Using Bootstrap 5.3.7 standard breakpoints for consistency */

/* X-Small devices (portrait phones, less than 576px) - Default styles */
/* No media query needed - these are the base styles */

/* Small devices (landscape phones, 576px and up) */
@media (min-width: 576px) {
    .quick-action-btn {
        flex: 1 1 calc(50% - 0.5rem);
    }
}

/* Medium devices (tablets, 768px and up) */
@media (min-width: 768px) {
    .theme-switcher {
        display: flex !important;
    }

    /*.search-bar {*/
    /*    display: block;*/
    /*    position: relative;*/
    /*    top: auto;*/
    /*    left: auto;*/
    /*    right: auto;*/
    /*    margin-top: 0;*/
    /*    padding: 0;*/
    /*    background-color: transparent;*/
    /*    box-shadow: none;*/
    /*    z-index: auto;*/
    /*}*/
    /*.mobile-search-toggle {*/
    /*    display: none;*/
    /*}*/
}

/* Large devices (desktops, 992px and up) */
@media (min-width: 992px) {
    .sidebar {
        transform: translateX(0);
        transition: transform var(--transition-speed) ease;
    }

    .sidebar.sidebar-collapsed {
        transform: translateX(-100%);
    }

    /* Footer responds to sidebar: it lives inside .main-content, which gets this margin (margin-left: 0 when body.sidebar-collapsed). */
    .main-content {
        margin-left: var(--sidebar-width);
        transition: margin-left var(--transition-speed) ease;
    }

    body.sidebar-collapsed .main-content {
        margin-left: 0;
    }

    /* Cookie policy page: standalone for all users; no sidebar so no left margin */
    body.cookie-policy-standalone .main-content {
        margin-left: 0;
    }

    /* Expand tab: visible only when sidebar is collapsed */
    .sidebar-toggle-tab {
        display: none;
        position: fixed;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        width: 40px;
        height: 48px;
        z-index: 1040;
        align-items: center;
        justify-content: center;
        border: 0;
        border-radius: 0 var(--bs-border-radius) var(--bs-border-radius) 0;
        background: linear-gradient(135deg, var(--sidebar-gradient-start) 0%, var(--sidebar-gradient-end) 100%);
        color: #fff;
        box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
        cursor: pointer;
        padding: 0;
    }

    .sidebar-toggle-tab:hover {
        color: #fff;
        opacity: 0.95;
    }

    body.sidebar-collapsed .sidebar-toggle-tab {
        display: flex;
    }

    .navbar-toggler {
        display: none;
    }

    .sidebar-header .btn-close {
        display: none;
    }
}

/* XX-Large devices (larger desktops, 1400px and up) */
@media (min-width: 1400px) {
    .dashboard-card h3 {
        font-size: 2.75rem;
    }

    .welcome-section h1 {
        font-size: 2.25rem;
    }
}

/* ===== MAX-WIDTH MEDIA QUERIES (Bootstrap 5.3.7 style) ===== */

/* Small devices (landscape phones, less than 768px) */
@media (max-width: 767.98px) {
    .navbar {
        padding: 0.75rem 1rem;
    }

    .user-menu {
        gap: 0.5rem;
    }

    .breadcrumb {
        display: none !important;
    }

    .table-responsive {
        font-size: 0.875rem;
    }

    .table th {
        font-size: 0.75rem;
        padding: 0.75rem 0.5rem;
    }

    .table td {
        padding: 0.75rem 0.5rem;
    }

    .status-badge {
        font-size: 0.7rem;
        padding: 4px 8px;
    }

    .btn-action {
        padding: 0.25rem 0.5rem;
        font-size: 0.75rem;
    }

    /*.search-bar {*/
    /*    display: none;*/
    /*    position: absolute;*/
    /*    top: 100%;*/
    /*    left: 0;*/
    /*    right: 0;*/
    /*    margin-top: 0.5rem;*/
    /*    padding: 0 1rem;*/
    /*    background-color: var(--navbar-bg);*/
    /*    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);*/
    /*    z-index: 1000;*/
    /*}*/
    /*.search-bar.show {*/
    /*    display: block;*/
    /*}*/
    /*.mobile-search-toggle {*/
    /*    display: block;*/
    /*}*/
    /* Theme switcher mobile responsiveness - consolidated here */
    .theme-switcher {
        padding: 0.2rem;
    }

    .theme-toggle-btn {
        width: var(--control-size);
        height: var(--control-size);
        font-size: 1.2rem;
    }

    .theme-toggle-btn:hover {
        transform: none; /* Disable hover effects on mobile */
    }
}

/* Medium devices (tablets, less than 992px) */
@media (max-width: 991.98px) {
    .table .d-none-mobile {
        display: none;
    }

    .sidebar {
        transform: translateX(-100%);
    }

    .sidebar.show {
        transform: translateX(0);
    }

    .sidebar-backdrop {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, 0.5);
        z-index: 1040;
        display: none;
    }

    .sidebar.show + .sidebar-backdrop {
        display: block;
    }

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

}

/* X-Small devices (portrait phones, less than 576px) */
@media (max-width: 575.98px) {
    .dashboard-card {
        padding: 1.25rem;
    }

    .dashboard-card h3 {
        font-size: 2rem;
    }

    .dashboard-card .card-icon {
        font-size: 3rem;
    }

    .welcome-section {
        padding: 1.5rem;
    }

    .welcome-section h1 {
        font-size: 1.5rem;
    }

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

    .quick-action-btn {
        flex: 1 1 calc(50% - 0.5rem);
        min-width: 140px;
    }

    .table-card {
        margin: 0 -1rem;
        border-radius: 0;
    }

    .theme-switcher {
        display: none;
    }
}

/* X-Large devices (large desktops, less than 1400px) */
@media (max-width: 1399.98px) {
    .dashboard-card h3 {
        font-size: 2.25rem;
    }

    .welcome-section h1 {
        font-size: 1.875rem;
    }
}

/* Session security modal: theme alignment (Bootstrap 5.3 + app theme) */
.session-security-modal-wrapper {
    position: fixed;
    inset: 0;
    z-index: 1060;
    display: flex;
    align-items: center;
    justify-content: center;
}
.session-security-modal-wrapper .session_security_overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
}
.session-security-modal-wrapper .session_security_modal {
    position: relative;
    z-index: 1061;
}
.session-security-modal-wrapper .session_security_modal .modal-content {
    background: var(--glass-bg, var(--background));
    border-color: var(--primary);
}

/* Global modal safety: avoid mobile clipping and preserve readable content */
.modal .modal-body {
    overflow-wrap: anywhere;
}

@media (max-width: 575.98px) {
    .modal .modal-dialog {
        margin: 0.5rem;
        max-width: calc(100vw - 1rem);
    }
}

/* Pagination touch targets and safe mobile wrapping */
.pagination.pagination-touch .page-link {
    min-width: var(--control-size);
    min-height: var(--control-size);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

@media (max-width: 575.98px) {
    .pagination.pagination-touch {
        flex-wrap: wrap;
        row-gap: 0.25rem;
    }
}

/* Download progress banner (global, cross-page) */
.download-progress-banner-container {
    /* Not Bootstrap's d-flex: that is display:flex!important, which beats the hidden attribute
       base.js uses to take the panel away, and left an empty "Preparing 1 report" on screen. */
    display: flex;
    z-index: 9999;
    width: min(40rem, calc(100vw - 1rem));
}

/* A floor for the reference: at 320px the step controls fill the row, and without one the
   reference shrank to a single letter per line. The head row wraps the controls instead. */
.download-panel-title {
    flex-basis: 8rem;
}

/* Previous, position and next wrap as one group. Not d-inline-flex: its !important would beat
   the hidden attribute that removes the group when only one report is in hand. */
.download-panel-step {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.download-progress-row .progress {
    --bs-progress-bg: var(--surface);
}

.download-progress-row .download-progress-bar {
    background-color: var(--bs-primary) !important;
    color: #fff;
}

/* One outline button, on every page.
 *
 * Counted across the templates before changing anything: btn-outline-secondary
 * 80 times, btn-outline-primary 46, btn-outline-danger 15, btn-outline-info 4,
 * btn-outline-warning 3, btn-outline-dark 1. Bootstrap's outline variants colour
 * the border, so one report-list row drew six different border colours, and none
 * of them meant anything.
 *
 * NN/g on visual hierarchy: "If everything is contrasted, then nothing stands
 * out", and no more than three contrast variations
 * (nngroup.com/articles/visual-hierarchy-ux-definition/, read 20 September 2026).
 *
 * Every Bootstrap button variant is a block of --bs-btn-* local variables -
 * verified in the copy this project ships - and Bootstrap's own documentation
 * gives those as the way to restyle a component after compilation
 * (getbootstrap.com/docs/5.3/customize/css-variables/, read 20 September 2026).
 * So this is one rule, and not an edit to 150 places in the markup.
 *
 * btn-outline-danger is left alone on purpose. Destructive is the one action
 * that has earned a colour of its own.
 */
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-success,
.btn-outline-info,
.btn-outline-warning,
.btn-outline-dark,
.btn-outline-light {
    --bs-btn-color: var(--text-primary);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--divider);
    --bs-btn-hover-color: var(--background);
    --bs-btn-hover-bg: var(--primary);
    --bs-btn-hover-border-color: var(--primary);
    --bs-btn-active-color: var(--background);
    --bs-btn-active-bg: var(--primary-dark);
    --bs-btn-active-border-color: var(--primary-dark);
    --bs-btn-focus-shadow-rgb: 76, 96, 167;
    --bs-btn-disabled-color: var(--text-secondary);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--divider);
}

/* The card on a page you reach before signing in, and the space around it.
 *
 * Five pages show one card in the middle of the screen: sign in, register,
 * both password reset steps, resend activation link, and the two invitation
 * pages. They are the same card doing the same job.
 *
 * It was written four times, byte for byte, in four page stylesheets -
 * .login-card, .signup-card, .password-reset-card and
 * .password-reset-confirm-card - and the resend activation page had no copy at
 * all. So that one page drew Bootstrap's plain white card while the other four
 * drew the surface colour, and its card sat at the top of the screen while the
 * others were centred. Nothing was written wrong anywhere. One page simply
 * never got a line that four other files each have their own copy of, which is
 * the same shape as the footer that was missing from the drafts page.
 *
 * Reported by the dev from a screenshot on 21 September 2026 and confirmed by
 * reading all five templates and all four stylesheets.
 *
 * Both values come from tokens declared at the top of this file, so the colour
 * and the corner move from one place.
 */
.auth-container {
    flex: 1 0 auto;
    display: flex;
    align-items: center;
    padding-inline: 0.25rem;
}

.auth-card {
    background-color: var(--surface);
    border: none;
    border-radius: var(--bs-border-radius);
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
    padding: 1rem 1.25rem;
    backdrop-filter: saturate(120%) blur(2px);
}

/* Roomier once there is width for it. 768px is Bootstrap's md breakpoint, which
 * is the one the rest of this page's markup already switches on. */
@media (min-width: 768px) {
    .auth-card {
        padding: 1.25rem 3rem;
    }
}

/* Tighter on a phone. Three of the four deleted copies carried this rule, so it
 * is kept here to leave the page looking the same below 576px as it did before
 * the four became one. 575.98px is Bootstrap's own sm boundary. */
@media (max-width: 575.98px) {
    .auth-card {
        padding: 1rem;
    }
}

/* The filled button, in this project's colour.
 *
 * Bootstrap writes its own blue straight into .btn-primary - the shipped copy
 * reads --bs-btn-bg: #0d6efd, not a variable pointing anywhere - so pointing
 * --bs-primary at this project's colour further up cannot reach it. Every
 * filled button on the site was therefore Bootstrap blue while everything
 * around it was #4C60A7. It showed up on the report list on a phone, where the
 * cards draw a filled View button.
 *
 * Set here the same way as the outline buttons below: by giving Bootstrap's own
 * variables this project's tokens, so no button in any template is edited and
 * dark mode follows on its own, because --primary is redeclared there.
 *
 * White on #4C60A7 measures 5.93:1, and on the dark theme's #5B74BC it measures
 * 4.50:1. WCAG 2.2, 1.4.3 Contrast (Minimum) asks for 4.5:1 for ordinary text
 * (w3.org/WAI/WCAG22/Understanding/contrast-minimum.html, read 21 September
 * 2026), so both pass, and the light theme is better than the Bootstrap blue it
 * replaces, which measures 4.50:1 itself.
 */
.btn-primary {
    --bs-btn-bg: var(--primary);
    --bs-btn-border-color: var(--primary);
    --bs-btn-hover-bg: var(--primary-dark);
    --bs-btn-hover-border-color: var(--primary-dark);
    --bs-btn-active-bg: var(--primary-dark);
    --bs-btn-active-border-color: var(--primary-dark);
    --bs-btn-disabled-bg: var(--primary);
    --bs-btn-disabled-border-color: var(--primary);
    --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

/* Icons sit on the middle of the line, and a button is big enough to press.
 *
 * A Bootstrap Icon is a font glyph in an <i>, and an inline glyph sits on the
 * text baseline, which is below the centre of the button. That is the icon that
 * looks a little low, and it shifts whenever the text beside it changes size or
 * disappears at a breakpoint. Centring the button's own contents fixes both,
 * because the glyph is no longer positioned against a baseline.
 *
 * The gap below is what spaces a button's contents. This comment used to say
 * the opposite - that the me-1 and me-2 margins in the markup did the spacing
 * and no gap was set here. That was true when it was written and stopped being
 * true in commit 89b06c1, which added the gap and switched those margins off
 * inside a button so nothing is spaced twice.
 *
 * WCAG 2.2, 2.5.8 Target Size (Minimum): "The size of the target for pointer
 * inputs is at least 24 by 24 CSS pixels"
 * (w3.org/WAI/WCAG22/Understanding/target-size-minimum.html, read 20 September
 * 2026). 1.75rem is 28px at the default root size, which clears it including the
 * small buttons used in the action rows.
 */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--icon-label-gap);
}

/* The gap above is the only thing that spaces a button's contents, so the
 * spacing classes the markup still carries inside a button are switched off.
 * Without this a button with me-2 on its icon would be spaced twice and would
 * not match the button beside it.
 *
 * !important is needed rather than preferred: Bootstrap writes its spacing
 * utilities with !important, so nothing without it can win. Only the spacing
 * classes are targeted, so ms-auto and anything else a button holds still
 * works. Outside a button these classes are untouched and still do their job. */
.btn > .bi,
.btn > i[class*="bi-"],
.btn > .ms-1,
.btn > .ms-2,
.btn > .me-1,
.btn > .me-2 {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

/* An icon-only button has no text to give it width, so it needs the same floor
   sideways that every control already has downwards. The height floor is set
   once, further down, with the other controls. */
.btn:not(.btn-link) {
    min-width: var(--control-size);
}

.btn > .bi,
.btn > i[class*="bi-"] {
    line-height: 1;
    flex-shrink: 0;
}

/*
 * Two of Bootstrap's own components write a number instead of reading the radius
 * variables: the close button (.375rem) and the checkbox (.25em). Every other
 * component reads --bs-border-radius, so these two kept their corners after the
 * token was set and were the only two things left rounded on a swept page.
 *
 * The radio button is left alone on purpose. Bootstrap draws it at 50%, and a
 * round radio beside a square checkbox is how a person tells "choose one" from
 * "choose any" before reading either label.
 */
.btn-close,
.form-check-input:not([type="radio"]) {
    border-radius: var(--bs-border-radius);
}

/* Global navbar search */
.navbar-layout {
    min-height: 3.5rem;
    align-items: center;
    flex-wrap: nowrap;
}

.navbar-middle {
    min-width: 0;
    flex: 1 1 auto;
}

/* Full-width navbar breadcrumb row (below logo/search); horizontal scroll on narrow viewports */
.navbar-breadcrumb-row {
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
}

.navbar-breadcrumb-row .breadcrumb {
    flex-wrap: nowrap;
    margin-bottom: 0;
}

.navbar-breadcrumb-row .breadcrumb-item {
    flex-shrink: 0;
}

.app-global-search {
    width: clamp(20rem, 52vw, 66rem);
    max-width: 100%;
}

.app-global-search .search-bar {
    width: 100%;
}

.app-global-search .input-group-text,
.app-global-search .form-control {
    border-color: var(--divider);
}

.search-results-panel {
    width: 100%;
    max-height: min(65vh, 28rem);
    overflow: auto;
}

.search-result-item {
    cursor: pointer;
}

.search-result-item.active,
.search-result-item:hover {
    background-color: var(--surface);
}

@media (max-width: 767.98px) {
    .mobile-search-toggle {
        min-width: 2.5rem;
        min-height: 2.5rem;
    }

    .app-global-search-mobile {
        position: fixed;
        left: 0.5rem;
        right: 0.5rem;
        top: var(--mobile-search-top, 4.25rem);
        z-index: 1051;
        display: none;
    }

    .app-global-search-mobile.show {
        display: block;
    }

    .app-global-search-mobile .search-bar {
        border-radius: var(--bs-border-radius);
    }

}

@media (min-width: 1200px) {
    .app-global-search {
        width: clamp(28rem, 56vw, 74rem);
    }
}

.download-progress-row .download-progress-bar.progress-bar-animated {
    background-image: linear-gradient(
        45deg,
        rgba(255, 255, 255, 0.35) 25%,
        transparent 25%,
        transparent 50%,
        rgba(255, 255, 255, 0.35) 50%,
        rgba(255, 255, 255, 0.35) 75%,
        transparent 75%,
        transparent
    ) !important;
    background-size: 1.25rem 1.25rem;
    animation: fstg-progress-stripes 0.65s linear infinite !important;
    will-change: background-position;
}

/* Work with no measurable progress: a short bar travelling across the track.
 *
 * Not a full-width bar. A filled bar means finished, whatever the text beside it
 * says, and the first version of this filled the track while the report was
 * still queued - it read as a download that had completed and then stopped.
 *
 * Bootstrap 5.3 has no indeterminate mode (getbootstrap.com/docs/5.3/components/
 * progress/, read 20 September 2026), so the state is built here. The travelling
 * segment is the long-standing pattern for "working, length unknown", and it
 * cannot be mistaken for a percentage.
 *
 * 35% wide, so translateX is in units of 35% of the track: -100% puts it just off
 * the left edge and 285% just past the right. */
.download-progress-row .download-progress-bar.is-indeterminate {
    width: 35% !important;
    animation: fstg-progress-travel 1.6s ease-in-out infinite !important;
    will-change: transform;
}

@keyframes fstg-progress-travel {
    0% {
        transform: translateX(-100%);
    }
    100% {
        transform: translateX(285%);
    }
}

@keyframes fstg-progress-stripes {
    0% {
        background-position-x: 1.25rem;
    }
    100% {
        background-position-x: 0;
    }
}

/* Filter panel chevron: rotates smoothly when panel collapses/expands */
.fstg-filter-chevron {
    transition: transform var(--transition-speed) ease;
    display: inline-block;
}

/* Point chevron down when panel is collapsed (aria-expanded="false") */
#filterToggleBtn[aria-expanded="false"] .fstg-filter-chevron {
    transform: rotate(180deg);
}

/* ===================================================================
   Mobile-first table card-stacking utility
   Usage: add .table-mobile-stack to <table> + data-label="..." to each <td>.
   On desktop (>= 768px): zero impact — table renders normally.
   On mobile (< 768px): each <tr> becomes a rounded card; each <td>
   shows its data-label as an uppercase label prefix in a 2-column grid.
   thead is visually hidden but preserved for screen readers (WCAG 1.3.1).
   Action cells: use data-label="" to render full-width with no label prefix.
   =================================================================== */
@media (max-width: 767.98px) {
    .table-mobile-stack thead {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    .table-mobile-stack,
    .table-mobile-stack tbody,
    .table-mobile-stack tbody tr {
        display: block;
        width: 100%;
    }

    .table-mobile-stack tbody tr {
        border: 1px solid rgba(0, 0, 0, .08);
        border-radius: var(--bs-border-radius);
        margin-bottom: 1rem;
        box-shadow: 0 2px 8px rgba(0, 0, 0, .06);
        background: var(--bs-body-bg, #fff);
        overflow: hidden;
    }

    .table-mobile-stack td {
        display: grid;
        grid-template-columns: 9rem 1fr;
        align-items: start;
        padding: .6rem .75rem;
        border: none;
        border-bottom: 1px solid rgba(0, 0, 0, .05);
        text-align: left !important;
        font-size: .875rem;
    }

    .table-mobile-stack td:last-child {
        border-bottom: none;
    }

    .table-mobile-stack td::before {
        content: attr(data-label);
        font-weight: 600;
        font-size: .725rem;
        color: var(--bs-secondary-color, #6c757d);
        text-transform: uppercase;
        letter-spacing: .04em;
        padding-right: .5rem;
        align-self: center;
        white-space: nowrap;
    }

    /* Action cells: no label prefix, value spans full width */
    .table-mobile-stack td[data-label=""] {
        grid-template-columns: 1fr;
        justify-items: stretch;
    }

    .table-mobile-stack td[data-label=""]::before {
        display: none;
    }

    /* Dark mode overrides inside mobile breakpoint */
    [data-theme="dark"] .table-mobile-stack tbody tr {
        background: var(--card-bg, #2d2d2d);
        border-color: var(--border-color, #404040);
    }

    [data-theme="dark"] .table-mobile-stack td {
        border-bottom-color: var(--border-color, #404040);
    }
}

/* Activity log / ticket description cell: constrain width on desktop, unrestricted on mobile card */
.activity-desc-cell {
    max-width: 18rem;
}

/* Empty state icon circular wrapper (replaces inline style="width:120px;height:120px;") */
.empty-state-icon-wrap {
    width: 7.5rem;
    height: 7.5rem;
}

/* Larger toggle switch for settings (e.g. notification preferences). Bootstrap's
   default switch is ~20px, below the WCAG 2.2 touch-target size; this enlarges
   the control and gives the row a 44px tap height. Colour reuses the theme. */
.form-switch.form-switch-lg {
    min-height: var(--control-size);
    display: flex;
    align-items: center;
}

.form-switch.form-switch-lg .form-check-input {
    width: 3rem;
    height: 1.5rem;
    margin-top: 0;
    cursor: pointer;
}

.form-switch.form-switch-lg .form-check-input:checked {
    background-color: var(--primary);
    border-color: var(--primary);
}

.form-switch.form-switch-lg .form-check-input:focus {
    border-color: var(--primary-light);
    box-shadow: 0 0 0 0.25rem rgba(76, 96, 167, 0.25);
}

/*
 * Reduced motion (WCAG 2.2 - 2.3.3 Animation from Interactions). Honour a request for less movement.
 * This is the last reduced-motion block in the file, so its !important rules are not undone by an
 * earlier !important animation (the download-progress stripes set theirs with !important). Motion is
 * removed, not function: hover, focus and open/close states still change, just without the movement.
 * Near-instant durations (rather than "none") keep any JS that waits on transitionend working.
 */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    /* The download-progress bar sets its animation with !important at a higher specificity than the
       universal rule above, so it needs its own switch-off here (same selector, later in the file).
       The bar stays where it is and the message beside it keeps reporting, through aria-live, so the
       status is still available without movement. */
    .download-progress-row .download-progress-bar.progress-bar-animated,
    .download-progress-row .download-progress-bar.is-indeterminate {
        animation: none !important;
        will-change: auto !important;
    }

    /* Existing rule kept: the large form switch should not slide its knob. */
    .form-switch.form-switch-lg .form-check-input {
        transition: none;
    }
}

/*
 * Global accessibility hardening (WCAG 2.2 AA) - applies to every form across the app.
 * Kept here in base.css as the single source of truth; cannot be expressed with utility classes.
 * Refs (accessed 18/06/2026): WCAG 2.5.8 Target Size Minimum (AA, 24x24 CSS px), 2.5.5 Enhanced (AAA, 44x44).
 */

/* Visible keyboard focus ring for interactive controls (WCAG 2.4.11 / 2.4.13). */
.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible,
.accordion-button:focus-visible,
.dropdown-toggle:focus-visible {
    outline: 2px solid var(--primary-light);
    outline-offset: 2px;
}

/*
 * Target size 44px (AAA, exceeds the 24px AA floor) = Fitts's Law comfortable tap target.
 * .form-select-sm is excluded: it is used inside single-line uploaded-file chips where 44px would break layout.
 */
.btn:not(.btn-link),
.form-control,
.form-select:not(.form-select-sm) {
    min-height: var(--control-size);
}

/* Every box a person types in, and every menu they choose from, carries that edge. */
.form-control,
.form-select {
    border-color: var(--field-border);
}

/* Checkbox/radio rows in the multi-step wizard get a 44px tap row. Scoped to .step-content so the
   compact code-selection dropdown (.dropdown-item .form-check-input) elsewhere is unaffected. */
.step-content .form-check {
    min-height: var(--control-size);
    display: flex;
    align-items: center;
    gap: 0.5em;
    padding-left: 0; /* replace Bootstrap's padding-left + float model with flex + gap */
}

.step-content .form-check .form-check-input {
    margin-top: 0;
    margin-left: 0;
    float: none;
    flex-shrink: 0;
}
/*
 * The message deck: several messages pile up instead of running down the screen.
 *
 * A column of toasts is bounded by nothing. Six messages at once ran past the bottom of a
 * phone screen, and the ones off the edge could not be read or dismissed. Here every message
 * sits in the same grid cell, so the deck is as tall as one message no matter how many there
 * are. The ones behind are offset down, scaled a little smaller and dimmed, which is the pile
 * the eye reads as "there are more".
 *
 * It opens into a column on hover and on focus. Focus matters as much as hover: with the deck
 * closed the messages behind are `inert` (hidden from assistive technology and out of the tab
 * order, developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inert, read
 * 22 September 2026), so without opening on focus a keyboard would never reach them. Opening
 * it is what removes `inert`, and base.js does that on focusin.
 *
 * Nothing here announces anything. Every message's words go to #appToastLive, a hidden live
 * region, the moment the message is raised, because `inert` takes the visible copy out of the
 * accessibility tree.
 *
 * Open, it is bounded too: max-height with scrolling, so twenty messages cannot run off the
 * screen either.
 *
 * Movement is not switched off here. The reduced-motion block above already flattens every
 * transition in the file, and what is left - the offset and the scale - is layout rather than
 * animation, so the pile still reads as a pile without anything moving.
 */
.app-toast-deck {
    --toast-peek: 10px;      /* how much of each message behind shows */
    --toast-shrink: 0.04;    /* how much smaller each one behind is drawn */
    --toast-depth: 3;        /* how many are drawn before the rest are left out */
    display: grid;
    max-height: calc(100vh - 2rem);
    max-width: min(24rem, calc(100vw - 1.5rem));
}

/* One cell. Every message is in it, so the deck's height is the tallest message, not the sum.
 *
 * The deck is anchored to the bottom of the screen, so the pile grows upward: each message
 * behind is drawn higher, not lower. It is at the bottom because the download progress banner
 * owns the top - it is fixed to the top centre, it stays until its download ends, and it
 * carries a Cancel button, so nothing may cover it. Measured on 22 September 2026 with the
 * deck at the top right: it overlapped that banner at 320, 375, 768 and 1280. */
.app-toast-deck > .toast {
    grid-area: 1 / 1;
    width: 100%;
    transform-origin: bottom center;
    transform:
        translateY(calc(var(--toast-index, 0) * var(--toast-peek) * -1))
        scale(calc(1 - var(--toast-index, 0) * var(--toast-shrink)));
    transition: transform 0.18s ease, opacity 0.18s ease;
    z-index: calc(100 - var(--toast-index, 0));
    /* Open, the newest belongs nearest the bottom edge, where it was when the deck was closed.
       Index 0 is the newest, so the largest order puts it last in the column. */
    order: calc(0 - var(--toast-index, 0));
}

/* Behind the front one: not in the way of a click meant for the front one. Matched on a data
   attribute base.js sets, not on the inline style, because how a browser writes a custom
   property back into the style attribute is not something to depend on. */
.app-toast-deck > .toast[data-toast-front="false"] {
    pointer-events: none;
}

/* Past the depth the pile shows, a message is drawn nowhere. It has already been announced. */
.app-toast-deck > .toast[data-toast-hidden="true"] {
    opacity: 0;
}

/* Open: a real column, scrolling if it has to, every message full size and reachable. */
.app-toast-deck.is-open {
    grid-auto-flow: row;
    gap: 0.5rem;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.app-toast-deck.is-open > .toast {
    grid-area: auto;
    transform: none;
    opacity: 1;
    pointer-events: auto;
}

/* The count, shown only while the deck is closed and holding more than it draws. */
/* The count sits above the pile, which is the direction the pile grows. */
.app-toast-deck-more {
    position: absolute;
    bottom: calc(100% - 0.5rem);
    right: 0.75rem;
    z-index: 200;
}

.app-toast-deck.is-open .app-toast-deck-more {
    display: none;
}

/* Report preview (apps/word/templates/document_preview.html). The pages are drawn by the pdf.js
   viewer, styled by static/js/pdfjs/pdf_viewer.css; these rules only size the parts around it. */
/* The bar and Stop while the report is made: a readable width on a desktop, the full width on a phone. */
.report-preview-working {
    max-width: 24rem;
}

/* The page number box: wide enough for three digits. */
.report-preview-page-number {
    width: 3.5rem;
}

/* The toolbar's buttons meet the 24px minimum target of WCAG 2.2 criterion 2.5.8 with room to spare. */
.report-preview-toolbar .btn {
    min-width: 2rem;
    min-height: 2rem;
}

/* The pdf.js viewer scrolls inside its own box, which it requires to be absolutely placed.
   The frame gives that box its height: most of the screen, so the toolbar stays in view above it. */
.report-preview-frame {
    position: relative;
    height: calc(100dvh - 12rem);
    min-height: 20rem;
    border: 1px solid var(--field-border);
    background-color: var(--bs-secondary-bg);
}

.report-preview-viewer {
    position: absolute;
    inset: 0;
    overflow: auto;
}

/* The picture scanned when turning on two-step sign-in. The SVG from the qrcode library carries a
   fixed size, so it is made to fill a box that never grows past 14rem or past a 320px screen. */
.qr-code-box {
    display: inline-block;
    width: min(100%, 14rem);
}

.qr-code-box svg {
    display: block;
    width: 100%;
    height: auto;
}

/* Recovery codes: one per line on a phone, two columns from 576px, in a font where 0 and O differ. */
.recovery-code-list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
    padding: 0;
    list-style: none;
}

@media (min-width: 576px) {
    .recovery-code-list {
        grid-template-columns: 1fr 1fr;
    }
}
