﻿/* 0. DESIGN TOKENS
   The light theme's values, named once: rules use var(--name), so a change of palette, radius or
   shadow is made here. The dark theme gives the same names other values (see DARK THEME at the end). */
:root {
    /* Surfaces */
    --surface-page: #f2f5f7;      /* page background (plano333.pt's light sections) */
    --surface: #ffffff;           /* sidebar, top bar, panels, cards drawn by us */
    --surface-hover: #f8f9fa;     /* hovered rows and menu items */
    --surface-sunken: #f1f3f5;    /* code boxes (recovery codes, authenticator key) */
    --surface-muted: #e9ecef;     /* quiet badges */

    /* Text */
    --text: #212529;
    --text-soft: #495057;         /* menu items, quiet badges */
    --text-muted: #565e64;        /* secondary text (4.5:1 on the page background) */
    --text-faint: #6c757d;        /* small section labels */
    --text-on-fill: #ffffff;      /* text on brand and primary fills */

    /* Lines */
    --border: #dee2e6;
    --border-strong: #ced4da;

    /* Brand: plano333.pt's navy and the gold of its logo. Gold is for fills and marks with navy
       text on them, never for text on white (too little contrast). */
    --brand-900: #212d45;         /* banners, headers, the menu header */
    --brand-700: #39486d;         /* buttons, links, active states */
    --brand-500: #4f6081;
    --brand-300: #557dbc;         /* focus borders */
    --brand-200: #a9bfe2;         /* info badges, notes and highlights (dark text reads on it) */
    --brand-tint: #e6eaf1;        /* active menu item, quiet brand backgrounds */
    --accent: #f8b526;
    --accent-hover: #e0a31f;
    --focus-ring: rgba(57, 72, 109, .25);

    /* What the brand colours are used for; dark mode gives each its own value */
    --action: var(--brand-700);          /* button fills, active pills, checked switches */
    --action-hover: var(--brand-900);
    --link: var(--brand-700);            /* links and navy text */
    --nav-active-text: var(--brand-900); /* the menu's hovered and active item */

    /* Actions and states (text shades are the darker "emphasis" ones, for 4.5:1 contrast) */
    --primary-text: #0a58ca;
    --success-text: #146c43;
    --danger-text: #b02a37;
    --danger-tint: rgba(220, 53, 69, .12);
    --warning-text: #997404;
    --warning-tint: #fff3cd;
    --code: #a3165b;

    /* Type: the plano333.pt fonts (wwwroot/fonts/fonts.css), then the system's own while they load */
    --font-fallback: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-body: "Manrope", var(--font-fallback);
    --font-heading: "Plus Jakarta Sans", var(--font-fallback);

    /* Shape */
    --radius-xs: 4px;
    --radius-s: .375rem;
    --radius-m: .5rem;
    --radius-l: 1rem;
    --shadow-float: 0 .5rem 1rem rgba(0, 0, 0, .3);    /* floating cards */
    --shadow-panel: -4px 0 16px rgba(0, 0, 0, .2);     /* side panels */

    /* Height of the top bar, shared by the menu header so the two line up */
    --bar-height: 64px;
}

@media (max-width: 767.98px) {
    :root { --bar-height: 56px; }
}

/* Base text: 14px at 1.43 line height, smoothed, links without underline (the type scale further
   down builds on this; these were MudBlazor's values when it set the page's base text) */
html {
    -webkit-tap-highlight-color: transparent;
}

body {
    font-size: .875rem;
    line-height: 1.43;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

a { text-decoration: none; }

body,
.leaflet-container {
    font-family: var(--font-body);
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--font-heading);
    font-weight: 600; /* as on plano333.pt */
}

/* 1. GLOBAL LAYOUT */
html, body {
    height: 100vh; /* Fallback for browsers without dynamic viewport units */
    height: 100dvh; /* Mobile: excludes the collapsing address bar so nothing is cut off at the bottom */
    margin: 0;
    padding: 0;
    overflow-y: hidden; /* Prevents the entire browser window from scrolling */
    overflow-x: auto; /* Below min-width, scroll horizontally instead of squishing the layout */
    min-width: 320px;
}

h1:focus {
    outline: none; /* FocusOnNavigate focuses the page heading; no visible ring needed */
}

/* The main flex wrapper to put Sidebar & Content side-by-side */
.wrapper {
    display: flex;
    width: 100%;
    height: 100vh; /* Lock wrapper to the viewport */
    height: 100dvh;
    align-items: stretch;
    min-height: 100vh;
    min-height: 100dvh;
}

/* 2. SIDEBAR STYLING */
#sidebar {
    min-width: 250px;
    max-width: 250px;
    height: 100vh; /* Lock sidebar height */
    height: 100dvh;
    overflow-y: auto; /* Allow sidebar to scroll independently if menu gets too long */
    background: var(--surface); /* White background */
    color: var(--text); /* Dark text */
    border-right: 1px solid var(--border); /* faint border to separate from content */
    transition: all 0.3s;
    display: flex;
    flex-direction: column;
}

    /* Light Mode Links */
    #sidebar .nav-link {
        padding: 15px 10px;
        font-size: 1.1em;
        display: block;
        color: var(--text-soft); /* Dark gray text */
        border-radius: 0;
    }

        #sidebar .nav-link:hover {
            color: var(--nav-active-text);
            background: var(--surface-hover);
        }

        /* Active item: a soft navy pill with the gold mark of the logo on its left edge */
        #sidebar .nav-link.active {
            color: var(--nav-active-text);
            background: var(--brand-tint);
            box-shadow: inset 3px 0 0 var(--accent);
            font-weight: 600;
        }

    
    

    

    

        

/* Sidebar Header Borders */
#sidebar .sidebar-header {
    border-bottom: 1px solid var(--border); /* Light mode border */
}

/* --- Collapsed State Logic (Shared) --- */
#sidebar.active {
    min-width: 80px;
    max-width: 80px;
    text-align: center;
}

    #sidebar.active .sidebar-text,
    #sidebar.active .sidebar-header h3 span {
        display: none;
    }

#sidebar i {
    font-size: 1.4rem;
    margin-right: 10px;
    vertical-align: middle;
}

#sidebar.active i {
    margin-right: 0;
    display: block;
    margin-bottom: 5px;
}

/* 3. MAIN CONTENT AREA */
#content {
    width: 100%;
    height: 100vh; /* Lock content height */
    height: 100dvh;
    display: flex;
    flex-direction: column;
    transition: all 0.3s;
    overflow-y: auto; /* THIS is what allows the page content to scroll! */
    overflow-x: hidden;
}

/* Top Navbar (inside content) */
.top-navbar {
    padding: 10px 20px;
    flex-shrink: 0; /* Prevent navbar from shrinking */

    /* Make the navbar sticky so it doesn't scroll away */
    position: sticky;
    top: 0;
    z-index: 1030;
    background-color: var(--surface); /* Must have a background to hide scrolling text underneath */
}

/* 4. THEME MODES */
/* Light Mode (Default) */
body {
    background-color: var(--surface-page);
    color: var(--text);
}

    
    

        

        

        

/* 5. FULL SCREEN MAP HELPER */
/* Use this class on the page that contains the map */
.map-page-container {
    flex-grow: 1; /* Fills all remaining vertical space */
    position: relative;
    padding: 0; /* No padding for full edge-to-edge map */
}

#map {
    height: 100%;
    width: 100%;
}

/* 6. CUSTOM COMPONENTS (USERS & TRAINING PANELS) */

.panel-header {
    background-color: var(--brand-700);
    color: var(--text-on-fill);
    padding: 10px;
    text-align: center;
    font-size: 1rem;
    border-radius: var(--radius-xs) var(--radius-xs) 0 0;
}

.panel-border {
    border: 2px solid var(--brand-700);
    border-top: none;
    padding: 15px;
    background-color: var(--surface);
    min-height: 600px;
}

    

    

    

    
    

    

    

    

        

        

    

    
    

    

    

    

    

    

    

    

/* ========================================================
   12. TOP BAR
   ======================================================== */

/* Keep the navbar pinned to the top while the page scrolls */
.top-navbar {
    position: sticky;
    top: 0;
    z-index: 1030;
    border-bottom: 1px solid var(--border);
}

/* Light mode default colors for the custom text classes */
.text-dark-toggle {
    color: var(--text-soft);
}

    

    

    

    
    

/* Base Icon Styling */
#sidebar i {
    font-size: 1.4rem;
    margin-right: 10px;
    vertical-align: middle;
    /* FIX: Force a uniform box so FA icons don't shift text */
    width: 35px !important;
    height: 35px !important;
    line-height: 30px; /* Centers the icon vertically */
    text-align: center; /* Centers the icon horizontally */
    display: inline-block;
}

/* Collapsed Sidebar Icon Styling */
#sidebar.active i {
    margin-right: 0;
    margin-bottom: 15px; /* Increase this to space them out better vertically */
    /* FIX: Use flexbox or margins to center the block securely */
    display: block;
    margin-left: auto;
    margin-right: auto;
}

/*Iphone prevent 300ms zoom delay*/
button, .btn, .list-group-item, .btn-close {
    touch-action: manipulation;
}

/* Mobile/desktop switches at 768px with class names of our own (they began as a way round a UI
   library that redefined Bootstrap's d-md-* utilities at another breakpoint) */
.wt-mobile-only { display: block; }
.wt-desktop-flex, .wt-desktop-block, .wt-desktop-inline-block { display: none; }

@media (min-width: 768px) {
    .wt-mobile-only { display: none; }
    .wt-desktop-flex { display: flex; }
    .wt-desktop-block { display: block; }
    .wt-desktop-inline-block { display: inline-block; }
}

/* ========================================================
   13. SMARTPHONE OPTIMIZATIONS (Max-width: 767.98px)
   ======================================================== */
@media (max-width: 767.98px) {

    /* 1. Detach Sidebar and make it a hidden Off-Canvas Overlay */
    #sidebar {
        position: fixed !important;
        top: 0;
        left: -260px !important; /* Hide off-screen by default */
        height: 100vh !important;
        height: 100dvh !important;
        min-width: 250px !important;
        max-width: 250px !important;
        z-index: 2000 !important; /* Sit above everything */
        box-shadow: none; /* No shadow bleeding into the screen edge while hidden */
        transition: left 0.3s ease !important;
        padding-bottom: env(safe-area-inset-bottom);
    }

        /* 2. When the hamburger menu adds the .active class, slide it in */
        #sidebar.active {
            left: 0 !important;
            box-shadow: 4px 0 15px rgba(0,0,0,0.5);
            /* .active means "open" here, not the desktop 80px collapse: undo its centring */
            text-align: left;
        }

            /* Override the 80px desktop collapse behavior so text is visible on mobile */
            #sidebar.active .sidebar-text,
            #sidebar.active .sidebar-header h3 span {
                display: inline-block !important;
            }

            #sidebar.active i {
                display: inline-block !important;
                margin-right: 10px !important;
                margin-bottom: 0 !important;
            }

    /* 3. Force main content to use 100% of the available width */
    #content {
        width: 100% !important;
        min-width: 100% !important;
    }

    /* 4. Make Tabs horizontally swipeable to prevent squishing */
    .nav-tabs, .nav-pills {
        flex-wrap: nowrap !important;
        overflow-x: auto !important;
        overflow-y: hidden !important;
        -webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */
        white-space: nowrap;
        padding-bottom: 4px; /* Space for the scrollbar */
    }

        /* Style the tiny scrollbar for the tabs */
        .nav-tabs::-webkit-scrollbar, .nav-pills::-webkit-scrollbar {
            height: 3px;
        }

        .nav-tabs::-webkit-scrollbar-track, .nav-pills::-webkit-scrollbar-track {
            background: transparent;
        }

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

    /* 5. Prevent Map Header controls from wrapping awkwardly */
    .input-group-sm {
        flex-wrap: nowrap !important;
    }

    /* 6. Keep the hamburger toggle clickable above the off-canvas sidebar overlay */
    #sidebarToggleBtn {
        position: relative;
        z-index: 2001;
    }

    /* 7. Tighter page padding so content gets the width */
    #content > main {
        padding: 0.75rem !important;
        padding-bottom: calc(0.75rem + env(safe-area-inset-bottom)) !important;
    }

    .top-navbar {
        padding: 6px 10px;
    }

    /* 8. iOS zooms the page when focusing inputs smaller than 16px */
    input.form-control, select.form-select, textarea.form-control,
    .form-control-sm, .form-select-sm {
        font-size: 16px;
    }

    /* 9. Full-width, scrollable modals on small screens (full-screen ones keep no margin, or
       their 100% width would run off the right edge) */
    .modal-dialog:not([class*="modal-fullscreen"]) {
        margin: 0.5rem;
    }

    .modal.d-block {
        overflow-y: auto;
    }
}

/* Top bar buttons ("Log In", "Register") must never wrap onto two lines */
.top-navbar .btn {
    white-space: nowrap;
}

/* ========================================================
   STATION PAGES: list + map
   ======================================================== */
/* Station pages fill the window: only the station list scrolls, the map keeps its place */
main:has(> .station-page) {
    min-height: 0;
}

.station-page {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    flex: 1 1 0;
    min-height: 0;
}

/* The list comes first at every width: it is what users come for */
.station-page-list {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    order: 1;
}

    .station-page-list .card-body {
        overflow: auto;
        min-height: 0;
    }

    /* Column titles stay visible while the list scrolls */
    .station-page-list thead th {
        position: sticky;
        top: 0;
        z-index: 1;
    }

/* Phones/tablets: map below the list at a fixed height, the list fills the rest */
.station-page-map {
    flex: none;
    height: 38dvh;
    min-height: 200px;
    order: 2;
}

.station-page-map-canvas {
    position: absolute;
    inset: 0;
}

@media (min-width: 1200px) {
    /* Large screens: list on the left half, map on the right half, both as tall as the window */
    .station-page {
        flex-direction: row;
    }

    .station-page-list,
    .station-page-map {
        flex: 1 1 50%;
        min-height: 0;
    }

    .station-page-map {
        height: auto;
    }

    /* Half-width list: drop the country column and the "It's mine" label (own class: it
       hides only at this width) */
    .station-page .st-wide-hide {
        display: none !important;
    }
}

/* Bar shown by Blazor when the server session ended with an error */
#blazor-error-ui {
    display: none;
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    z-index: 3000;
    padding: 0.75rem 1.25rem calc(0.75rem + env(safe-area-inset-bottom));
    background: var(--warning-tint);
    color: var(--text);
    box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.2);
}

/* ========================================================
   14. CONNECTION LOST BANNER (Blazor Server reconnect UI)
   ======================================================== */
#components-reconnect-modal {
    display: none;
}

    #components-reconnect-modal.components-reconnect-show,
    #components-reconnect-modal.components-reconnect-failed,
    #components-reconnect-modal.components-reconnect-rejected {
        display: flex;
        position: fixed;
        inset: 0;
        z-index: 3000;
        align-items: center;
        justify-content: center;
        /* Dim the page behind the message */
        background-color: rgba(0, 0, 0, 0.45) !important;
        padding: 1rem;
    }

    
    

    #components-reconnect-modal .reconnect-card {
        background: var(--surface);
        color: var(--text);
        border-radius: var(--radius-m);
        padding: 1.25rem 1.5rem;
        max-width: 360px;
        width: 100%;
        text-align: center;
        box-shadow: var(--shadow-float);
    }

    #components-reconnect-modal .reconnect-state {
        display: none;
    }

    #components-reconnect-modal.components-reconnect-show .reconnect-show,
    #components-reconnect-modal.components-reconnect-failed .reconnect-failed,
    #components-reconnect-modal.components-reconnect-rejected .reconnect-failed {
        display: block;
    }

/* ========================================================
   15. THEME CONTRAST (WCAG AA: 4.5:1 text, 3:1 large text)
   ======================================================== */

/* Light theme: Bootstrap's blue/green/red text is just under 4.5:1 on the light grey
   backgrounds used here; use the darker "emphasis" shades for text. */
.text-primary { color: var(--primary-text) !important; }
.text-success { color: var(--success-text) !important; }
.text-danger { color: var(--danger-text) !important; }
.text-secondary { color: var(--text-muted) !important; }

/* "Available" station badge (was a faded grey badge) */
.badge-available {
    background-color: var(--surface-muted);
    color: var(--text-soft);
    border: 1px solid var(--border-strong);
}

    

    

/* Blue text on dark panels (home banner, headers) in either theme */
.bg-dark .text-primary { color: #6ea8fe !important; }

/* Brand colours on the app's own controls: navy for buttons, links, tabs, switches and focus rings.
   Bootstrap's "primary" blue stays on .text-primary, .bg-primary and .border-primary: it is the HF
   band's colour. Bootstrap writes these values as plain hex, so each is set again here. */
:root {
    --bs-dark-rgb: 33, 45, 69;              /* .bg-dark: headers, session bars and banners in navy */
    --bs-link-color: var(--link);
    --bs-link-color-rgb: 57, 72, 109;
    --bs-link-hover-color: var(--brand-900);
    --bs-link-hover-color-rgb: 33, 45, 69;

    /* Bootstrap's cyan "info" becomes a light brand blue: badges, notes, row highlights */
    --bs-info: var(--brand-200);
    --bs-info-rgb: 169, 191, 226;
    --bs-info-text-emphasis: var(--brand-900);
    --bs-info-bg-subtle: var(--brand-tint);
    --bs-info-border-subtle: #c5d0e3;
}

.btn-primary {
    --bs-btn-bg: var(--action);
    --bs-btn-border-color: var(--action);
    --bs-btn-hover-bg: var(--action-hover);
    --bs-btn-hover-border-color: var(--action-hover);
    --bs-btn-active-bg: var(--action-hover);
    --bs-btn-active-border-color: var(--action-hover);
    --bs-btn-disabled-bg: var(--action);
    --bs-btn-disabled-border-color: var(--action);
    --bs-btn-focus-shadow-rgb: 57, 72, 109;
}

.btn-outline-primary {
    --bs-btn-color: var(--link);
    --bs-btn-border-color: var(--link);
    --bs-btn-hover-bg: var(--action);
    --bs-btn-hover-border-color: var(--action);
    --bs-btn-active-bg: var(--action-hover);
    --bs-btn-active-border-color: var(--action-hover);
    --bs-btn-disabled-color: var(--link);
    --bs-btn-disabled-border-color: var(--link);
    --bs-btn-focus-shadow-rgb: 57, 72, 109;
}

.nav-pills {
    --bs-nav-pills-link-active-bg: var(--action);
}

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

.form-control:focus,
.form-select:focus,
.form-check-input:focus {
    border-color: var(--brand-300);
    box-shadow: 0 0 0 .25rem var(--focus-ring);
}

/* The menu header: navy with the logo, as on plano333.pt */
#sidebar .sidebar-header {
    background: var(--brand-900);
    color: var(--text-on-fill);
    border-bottom-color: var(--brand-900) !important;
}

/* On the navy banner of Home, the main buttons are gold with navy text, like the site's calls to action */
.brand-hero .btn-primary {
    --bs-btn-color: var(--brand-900);
    --bs-btn-bg: var(--accent);
    --bs-btn-border-color: var(--accent);
    --bs-btn-hover-color: var(--brand-900);
    --bs-btn-hover-bg: var(--accent-hover);
    --bs-btn-hover-border-color: var(--accent-hover);
    --bs-btn-active-color: var(--brand-900);
    --bs-btn-active-bg: var(--accent-hover);
    --bs-btn-active-border-color: var(--accent-hover);
}

.nav-link { color: var(--link); }
code { color: var(--code); }

/* ========================================================
   16. LOGIN / REGISTRATION CARD
   ======================================================== */
.auth-page {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding: 2rem 0 1rem;
}

.auth-card {
    width: 100%;
    max-width: 420px;
    border: 0;
    border-radius: var(--radius-l);
    overflow: hidden;
}

.auth-logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin-bottom: 0.75rem;
    border-radius: 50%;
    background: var(--brand-700);
    color: var(--text-on-fill);
    font-size: 1.6rem;
}

    .auth-logo.success { background: var(--success-text); }
    .auth-logo.danger { background: var(--danger-text); }
    .auth-logo.warning { background: var(--warning-text); }

.auth-divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 1rem 0;
    color: var(--text-muted);
    font-size: 0.85rem;
}

    .auth-divider::before,
    .auth-divider::after {
        content: "";
        flex: 1;
        border-top: 1px solid var(--border-strong);
    }

    

@media (max-width: 767.98px) {
    .auth-page { padding-top: 0.5rem; }
}

/* Account pages opened from "My profile" */
.auth-card-wide {
    max-width: 560px;
}

    /* Their forms were laid out for a two-column page: use the full card width */
    .auth-card-wide .row > [class*="col-md-"] {
        flex: 0 0 100%;
        max-width: 100%;
    }

    .manage-body h3 {
        font-size: 1.25rem;
        font-weight: 700;
        margin-bottom: 1rem;
    }

/* Account pages opened from "My profile": header, action lists, recovery codes */
.min-w-0 { min-width: 0; }

.manage-header-icon {
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.35rem;
    color: var(--link);
    background: var(--brand-tint);
}

    .manage-header-icon.danger {
        color: var(--danger-text);
        background: var(--danger-tint);
    }

.manage-section {
    font-size: .8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-faint);
    margin: 1.25rem 0 .5rem;
}

.recovery-codes {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: .5rem;
}

    .recovery-codes code {
        display: block;
        text-align: center;
        padding: .5rem;
        font-size: 1rem;
        border-radius: var(--radius-s);
        background: var(--surface-sunken);
        color: var(--text);
    }

.authenticator-key {
    font-family: var(--bs-font-monospace);
    font-size: 1.05rem;
    letter-spacing: .05em;
    word-break: break-all;
    padding: .5rem .75rem;
    border-radius: var(--radius-s);
    background: var(--surface-sunken);
    color: var(--text);
}

/* Headings focused from code (to scroll them into view) do not need a focus box */
h1[tabindex="-1"]:focus, h2[tabindex="-1"]:focus { outline: none; }

/* Type scale shared by every page: text, tables, lists, buttons and inputs 14px (the base
   text size); panel titles 16px; page and card titles 20px (.fs-5). Bootstrap sizes buttons and inputs
   at 16px by default, which made them larger on some pages than the text around them. */
main .btn:not(.btn-lg):not(.btn-sm),
main .form-control:not(.form-control-lg),
main .form-select:not(.form-select-lg),
main .input-group-text {
    font-size: .875rem;
}

/* Login, registration and account pages keep their larger form fields */
.auth-card .form-control,
.auth-card .form-select {
    font-size: 1rem;
}

/* CAPTCHA widget (ALTCHA): full width and drawn like the form fields above it, in both themes */
.captcha-widget altcha-widget {
    --altcha-max-width: 100%;
    --altcha-color-base: transparent;
    --altcha-color-base-content: var(--text);
    --altcha-color-neutral: var(--text-muted);
    --altcha-color-primary: var(--action);
    --altcha-border-color: var(--bs-border-color);
    --altcha-border-radius: var(--bs-border-radius);
    --altcha-shadow: none;
}

/* iOS zooms into inputs below 16px: keep them at 16px on phones */
@media (max-width: 767.98px) {
    main input.form-control, main select.form-select, main textarea.form-control {
        font-size: 16px;
    }
}

/* Page guide opened by the "?" button (PageHelp) */
.page-help-btn {
    width: 2rem;
    height: 2rem;
    padding: 0;
    border-radius: 50%;
    flex-shrink: 0;
    line-height: 1;
}

/* Same width as the button, to keep a title centred when the button sits on one side */
.page-help-spacer {
    width: 2rem;
    flex-shrink: 0;
}

.page-help-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .35);
    z-index: 1060;
}

.page-help-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(400px, 100vw);
    z-index: 1061;
    overflow-y: auto;
    padding: 1.25rem;
    background: var(--surface);
    color: var(--text);
    text-align: left;
    font-weight: normal;
    font-size: .875rem;
    box-shadow: var(--shadow-panel);
}

.page-help-steps {
    list-style: none;
    padding: 0;
    margin: 0 0 1rem;
    counter-reset: help;
}

    .page-help-steps li {
        display: flex;
        gap: .75rem;
        align-items: flex-start;
        padding: .6rem 0;
        border-bottom: 1px solid var(--border);
    }

.page-help-icon {
    flex: 0 0 3.5rem;
    white-space: nowrap;
    display: inline-flex;
    justify-content: center;
    font-size: 1.15rem;
    color: var(--link);
}

/* Compact dismissible alerts (py-2): Bootstrap pads the close button for the normal alert height,
   which puts the X below the text; match the smaller padding so it lines up */
.alert-dismissible.py-2 .btn-close {
    padding: 0.75rem 1rem;
}

/* Our own icons (wwwroot/img/icons), drawn like Bootstrap Icons: the SVG gives the shape, the text
   colour fills it, 1em in size and centred in any box (the sidebar gives icons a 35px one), so
   <i class="app-icon app-icon-pmr"> goes wherever a "bi" class does */
.app-icon {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
    background-color: currentColor;
    -webkit-mask: var(--app-icon) center / 1em 1em no-repeat;
    mask: var(--app-icon) center / 1em 1em no-repeat;
}

/* The plano333.pt logo: the wide one (made for dark backgrounds) in the navy menu header and on the
   banner of Home; the square one when the menu is collapsed to icons */
/* The top bar and the menu header share one height (--bar-height), so their bottom edges line up;
   placed after the earlier .top-navbar rules and the phone media query, whose padding it replaces */
.top-navbar {
    height: var(--bar-height);
    padding-top: 0;
    padding-bottom: 0;
}

#sidebar .sidebar-header {
    height: var(--bar-height);
    padding: 0 1rem !important;     /* replaces Bootstrap's p-3 on the element */
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* The menu's right border: next to the navy header it takes the dark theme's soft navy-grey
   (a light grey line would cut through the navy band), the theme's own border colour below */
#sidebar {
    border-image: linear-gradient(to bottom, #33405b var(--bar-height), var(--border) var(--bar-height)) 1;
}

.sidebar-logo-wide {
    height: calc(var(--bar-height) - 20px);
    width: auto;
}

.sidebar-logo {
    display: none;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-s);
    flex-shrink: 0;
}

/* Menu collapsed to icons (computers): the square logo fits the 80px width */
@media (min-width: 768px) {
    #sidebar.active .sidebar-logo-wide { display: none; }
    #sidebar.active .sidebar-logo { display: block; }
}

.hero-logo {
    height: 72px;
    width: auto;
    max-width: 100%;
}

@media (max-width: 767.98px) {
    .hero-logo { height: 56px; }
}

/* PMR446: a licence-free handheld radio */
.app-icon-pmr { --app-icon: url("img/icons/pmr-radio.svg"); }

/* "That station heard you": an ear with incoming waves */
.app-icon-heard { --app-icon: url("img/icons/heard-ear.svg"); }

/* Bands: HF a Yagi beam on a lattice tower, VHF a repeater tower with waves, CB a car set with its
   microphone (PMR446 is the handheld above) */
.app-icon-hf { --app-icon: url("img/icons/band-hf.svg"); }
.app-icon-vhf { --app-icon: url("img/icons/band-vhf.svg"); }
.app-icon-cb { --app-icon: url("img/icons/band-cb.svg"); }

/* A station: a house with a Yagi on a mast beside it */
.app-icon-station { --app-icon: url("img/icons/station.svg"); }

/* Logbooks: mine has an operator on its cover, a session's an antenna */
.app-icon-logbook-mine { --app-icon: url("img/icons/logbook-mine.svg"); }
.app-icon-logbook-session { --app-icon: url("img/icons/logbook-session.svg"); }

/* Menu: home, dashboard (a radio's spectrum display: live activity), weekly training (an operator's
   headset), users, training sessions (a calendar with an antenna), roles (a shield with an
   operator) and settings */
.app-icon-home { --app-icon: url("img/icons/home.svg"); }
.app-icon-dashboard { --app-icon: url("img/icons/dashboard.svg"); }
.app-icon-training { --app-icon: url("img/icons/training.svg"); }
.app-icon-users { --app-icon: url("img/icons/users.svg"); }
.app-icon-sessions { --app-icon: url("img/icons/sessions.svg"); }
.app-icon-roles { --app-icon: url("img/icons/roles.svg"); }
.app-icon-settings { --app-icon: url("img/icons/settings.svg"); }

/* Map radius: a position pin inside a dashed circle */
.app-icon-radius { --app-icon: url("img/icons/radius.svg"); }

/* Band and mode: a tuning dial with its scale */
.app-icon-tuning { --app-icon: url("img/icons/tuning.svg"); }

/* ========================================================
   SHELL: shapes, top bar, focus, motion, map controls
   ======================================================== */

/* One set of corner radii: 8px for buttons, inputs and small boxes, 12px for cards, 16px for
   dialogs (Bootstrap reads these variables in all its components) */
:root {
    --bs-border-radius: .5rem;
    --bs-border-radius-sm: .375rem;
    --bs-border-radius-lg: .75rem;
    --bs-border-radius-xl: 1rem;
}

.card { --bs-card-border-radius: .75rem; --bs-card-inner-border-radius: calc(.75rem - 1px); }
.modal { --bs-modal-border-radius: var(--radius-l); --bs-modal-inner-border-radius: calc(var(--radius-l) - 1px); }
.dropdown-menu { --bs-dropdown-border-radius: var(--radius-m); }

/* A table filling a card body (p-0) scrolls inside it; rounding that body makes its own
   overflow clip the striped rows at the card's corners instead of painting square ones */
.card > .card-body.p-0:first-child {
    border-top-left-radius: var(--bs-card-inner-border-radius);
    border-top-right-radius: var(--bs-card-inner-border-radius);
}

.card > .card-body.p-0:last-child {
    border-bottom-left-radius: var(--bs-card-inner-border-radius);
    border-bottom-right-radius: var(--bs-card-inner-border-radius);
}

/* The top bar: navy in both themes, one band with the menu header and its logo, as the header of
   plano333.pt. Its controls are set one by one (not with data-bs-theme="dark", which would also
   turn the account menu dark in the light theme). */
.top-navbar {
    background-color: var(--brand-900);
    border-bottom-color: var(--brand-900);
    color: #ffffff;
}

.top-navbar .text-dark-toggle,
.top-navbar .top-nav-text { color: rgba(255, 255, 255, .85); }

.top-navbar .top-nav-icon:hover .text-dark-toggle,
.top-navbar .top-nav-text:hover,
.top-navbar .top-nav-text:hover .text-dark-toggle { color: #ffffff; }

.top-navbar #sidebarToggleBtn {
    --bs-btn-color: rgba(255, 255, 255, .85);
    --bs-btn-hover-color: #ffffff;
    --bs-btn-hover-bg: rgba(255, 255, 255, .1);
    --bs-btn-active-color: #ffffff;
    --bs-btn-active-bg: rgba(255, 255, 255, .15);
}

/* Language picker: a quiet outline with a white chevron instead of a white box */
.top-navbar .form-select {
    color: #ffffff;
    background-color: transparent;
    border-color: rgba(255, 255, 255, .3);
    --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

.top-navbar .form-select:focus { border-color: var(--accent); box-shadow: 0 0 0 .2rem rgba(248, 181, 38, .3); }

/* The options list is drawn by the browser on a light background */
.top-navbar .form-select option { color: #212529; }

/* Signed out: "Log in" in gold like the site's calls to action, "Register" as a white outline */
.top-navbar .btn-primary {
    --bs-btn-color: var(--brand-900);
    --bs-btn-bg: var(--accent);
    --bs-btn-border-color: var(--accent);
    --bs-btn-hover-color: var(--brand-900);
    --bs-btn-hover-bg: var(--accent-hover);
    --bs-btn-hover-border-color: var(--accent-hover);
    --bs-btn-active-color: var(--brand-900);
    --bs-btn-active-bg: var(--accent-hover);
    --bs-btn-active-border-color: var(--accent-hover);
}

.top-navbar .btn-outline-primary {
    --bs-btn-color: #ffffff;
    --bs-btn-border-color: rgba(255, 255, 255, .5);
    --bs-btn-hover-color: var(--brand-900);
    --bs-btn-hover-bg: #ffffff;
    --bs-btn-hover-border-color: #ffffff;
    --bs-btn-active-color: var(--brand-900);
    --bs-btn-active-bg: #ffffff;
    --bs-btn-active-border-color: #ffffff;
}

/* The navy focus ring would vanish on the navy bar: gold there */
.top-navbar :focus-visible { outline-color: var(--accent) !important; }

/* Keyboard focus is always visible (mouse clicks do not show it) */
a:focus-visible,
.nav-link:focus-visible,
.dropdown-item:focus-visible,
.list-group-item-action:focus-visible {
    outline: 2px solid var(--link);
    outline-offset: 2px;
}

#sidebar .nav-link:focus-visible { outline-offset: -2px; }

/* People who asked their system for less motion get no sliding menu or animations */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        transition-duration: .01ms !important;
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
    }
}

/* Map controls and popups follow the theme instead of Leaflet's fixed white */
.leaflet-bar a,
.leaflet-bar a:hover {
    background-color: var(--surface);
    color: var(--text);
    border-bottom-color: var(--border);
}

.leaflet-bar a:hover { background-color: var(--surface-hover); }

.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-float);
}

.leaflet-popup-content-wrapper { border-radius: var(--radius-m); }

.leaflet-container a { color: var(--link); }
.leaflet-container a.leaflet-popup-close-button { color: var(--text-muted); }

.leaflet-container .leaflet-control-attribution {
    background: var(--surface);
    background: color-mix(in srgb, var(--surface) 80%, transparent);
    color: var(--text-muted);
}

/* ========================================================
   PAGES
   ======================================================== */

/* Home: the three parts of the 3-3-3 rule as one set of cards, each icon in a soft circle beside
   its title (one line instead of two keeps the cards short) */
.rule-card {
    padding: 1.5rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: .75rem;
    box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .05);
}

.rule-head {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-bottom: .75rem;
}

.rule-icon {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    background: var(--brand-tint);
    color: var(--link);
    font-size: 1.4rem;
}

.rule-title {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 0;
}

/* Home hero buttons: full width, one per line (as on phones) until both fit side by side in the
   hero itself (~620px); measured on the hero, so the side menu counts */
.hero-body {
    container-type: inline-size;
}

.hero-buttons {
    display: grid;
    gap: .5rem;
}

@container (min-width: 640px) {
    .hero-buttons {
        display: flex;
        flex-wrap: wrap;
    }
}

/* Logbooks: the table needs ~760px for all its columns. Narrower (also a tablet with the side menu
   open) the place moves under the call sign and the JSON button keeps only its icon */
.logbook-card {
    container-type: inline-size;
}

@container (max-width: 759.98px) {
    .logbook-card .logbook-location {
        display: none !important;
    }

    .logbook-card .logbook-place-inline {
        display: block !important;
    }

    .logbook-card .logbook-json-label {
        display: none;
    }
}

/* Training lobby: as many session cards as fit, never narrower than 260px (a fixed three columns
   squeezed one card to a word per line next to the side menu) */
.lobby-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
    gap: 1.5rem;
}

    .lobby-grid > .lobby-empty {
        grid-column: 1 / -1;
    }

/* Users: user, stations and actions side by side need ~760px. Narrower (a tablet with the side
   menu open, not only a phone) each user's parts stack, as on phones */
.users-list {
    container-type: inline-size;
}

@container (max-width: 759.98px) {
    .users-list .users-head {
        display: none !important;
    }

    .users-list .users-row > [class*="col-"] {
        flex: 0 0 auto;
        width: 100%;
    }

    .users-list .users-row > [class*="col-"]:not(:last-child) {
        margin-bottom: .5rem !important;
    }
}

/* The three cards sit side by side only when the space they get (not the window: the side menu
   takes 250px) leaves room for an icon and "3 Minutos" on one line; otherwise one per row */
.rule-cards {
    container-type: inline-size;
}

@container (max-width: 759.98px) {
    .rule-cards > .row > [class*="col-"] {
        flex: 0 0 auto;
        width: 100%;
    }

    .rule-cards > .row > [class*="col-"]:not(:last-child) {
        margin-bottom: 1rem !important;
    }
}

/* About: the credits as role / name pairs in two aligned columns */
.about-credits {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .35rem 1rem;
}

.about-credits dt {
    font-weight: 400;
    color: var(--text-muted);
}

.about-credits dd {
    margin: 0;
    font-weight: 600;
}

/* Station pages: the operator as a quiet chip (a solid blue badge read as the HF band on every page) */
.operator-chip {
    display: inline-block;
    padding: .35em .65em;
    font-size: .75em;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    border-radius: var(--bs-border-radius);
    background: var(--brand-tint);
    color: var(--nav-active-text);
}

/* Your own station in lists: the gold of the logo (blue read as the HF band) */
.badge-me {
    background-color: var(--accent);
    color: var(--brand-900);
}

/* A selected row in a list is navy like the other active states (Bootstrap's blue is the HF band) */
.list-group {
    --bs-list-group-active-bg: var(--action);
    --bs-list-group-active-border-color: var(--action);
}

.list-group-item.active .text-muted { color: rgba(255, 255, 255, .8) !important; }

/* Profile Stations tab: one header colour for every band; the band shows in a round badge
   filled with its colour, ringed with a lighter shade of it */
.station-band-header { background-color: var(--brand-tint); }

.band-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    font-size: 1.1rem;
    color: #ffffff;
    background-color: rgb(var(--band-rgb));
    box-shadow: 0 0 0 3px rgba(var(--band-rgb), .25);
}

/* A linked station on the profile's Stations tab: a bar and a faint tint in its band colour
   (--band-rgb, set by StationLinkPanel), so bands with stations stand out from empty ones */
.station-row {
    background-color: rgba(var(--band-rgb), .08);
    box-shadow: inset 4px 0 0 rgba(var(--band-rgb), .85);
    padding-left: 1.25rem;
}

body.dark-mode .station-row { background-color: rgba(var(--band-rgb), .14); }

/* Unlinking a station from a profile: a quiet cross that only turns red when pointed at */
.station-unlink {
    color: var(--text-muted);
    border: 0;
}

.station-unlink:hover,
.station-unlink:focus-visible {
    color: var(--bs-danger);
    background-color: rgba(var(--bs-danger-rgb), .1);
}

/* ========================================================
   DARK THEME
   The top bar's switch sets body.dark-mode and data-bs-theme="dark" on <html>, which turns on
   Bootstrap's own dark theme for cards, lists, modals, forms, tables, tabs, alerts and dropdowns.
   Here the tokens and Bootstrap's colour variables get dark values tinted with the site's navy,
   so our components and Bootstrap's follow together; the rules after it only cover colours that
   Bootstrap writes as fixed values whatever the theme.
   ======================================================== */
body.dark-mode {
    /* Surfaces, darkest first: the page, then cards and bars, then raised and hovered things */
    --surface-page: #141b29;
    --surface: #1c2537;
    --surface-hover: #243049;
    --surface-sunken: #141b29;
    --surface-muted: #2c3854;

    --text: #e6e9ef;
    --text-soft: #c9d0dc;
    --text-muted: #aab3c2;        /* 7:1 on the cards */
    --text-faint: #9aa4b5;

    --border: #33405b;
    --border-strong: #46546f;

    /* Navy is too dark for text and thin lines here: a lighter steel blue takes those jobs */
    --brand-tint: rgba(255, 255, 255, .08);
    --brand-300: #8fa3cc;
    --focus-ring: rgba(143, 163, 204, .35);
    --action: #4f6081;
    --action-hover: #61739a;
    --link: #a9bce0;
    --nav-active-text: #ffffff;

    --code: #f0a6ca;
    --warning-tint: #4d3b05;
    --shadow-float: 0 .5rem 1rem rgba(0, 0, 0, .5);
    --shadow-panel: -4px 0 16px rgba(0, 0, 0, .5);

    /* Bootstrap's dark theme, in the same colours */
    --bs-body-bg: var(--surface);
    --bs-body-bg-rgb: 28, 37, 55;
    --bs-body-color: var(--text);
    --bs-body-color-rgb: 230, 233, 239;
    --bs-emphasis-color: #ffffff;
    --bs-emphasis-color-rgb: 255, 255, 255;
    --bs-secondary-color: var(--text-muted);
    --bs-secondary-color-rgb: 170, 179, 194;
    --bs-secondary-bg: var(--surface-hover);
    --bs-secondary-bg-rgb: 36, 48, 73;
    --bs-tertiary-color: var(--text-faint);
    --bs-tertiary-bg: #202a3f;
    --bs-tertiary-bg-rgb: 32, 42, 63;
    --bs-border-color: var(--border);
    --bs-border-color-translucent: rgba(255, 255, 255, .12);
    --bs-heading-color: inherit;
    --bs-link-color: var(--link);
    --bs-link-color-rgb: 169, 188, 224;
    --bs-link-hover-color: #c9d6ee;
    --bs-link-hover-color-rgb: 201, 214, 238;
    --bs-code-color: var(--code);
    --bs-info-text-emphasis: #c9d6ec;
    --bs-info-bg-subtle: #1f2b44;
    --bs-info-border-subtle: #39486d;}

/* White and light-grey utility backgrounds (the top bar, quiet panels) */
body.dark-mode .bg-white {
    background-color: var(--surface) !important;
    color: var(--text) !important;
}

body.dark-mode .bg-light {
    background-color: var(--surface-hover) !important;
    color: var(--text) !important;
}

body.dark-mode .text-dark { color: var(--text) !important; }

/* ...except dark text on the light yellow and blue info badges and headers, which must stay dark */
body.dark-mode .bg-warning.text-dark, body.dark-mode .bg-warning .text-dark, body.dark-mode .bg-warning,
body.dark-mode .bg-info.text-dark, body.dark-mode .bg-info .text-dark {
    color: #212529 !important;
}

/* Buttons whose colours Bootstrap fixes for light backgrounds */
body.dark-mode .btn-light {
    --bs-btn-color: var(--text);
    --bs-btn-bg: var(--surface-hover);
    --bs-btn-border-color: var(--border-strong);
    --bs-btn-hover-color: #ffffff;
    --bs-btn-hover-bg: var(--surface-muted);
    --bs-btn-hover-border-color: var(--border-strong);
    --bs-btn-active-color: #ffffff;
    --bs-btn-active-bg: var(--surface-muted);
    --bs-btn-active-border-color: var(--border-strong);
}

body.dark-mode .btn-outline-secondary {
    --bs-btn-color: var(--text-soft);
    --bs-btn-border-color: var(--border-strong);
    --bs-btn-hover-color: #ffffff;
    --bs-btn-hover-bg: var(--surface-muted);
    --bs-btn-hover-border-color: var(--border-strong);
    --bs-btn-active-color: #ffffff;
    --bs-btn-active-bg: var(--surface-muted);
    --bs-btn-active-border-color: var(--border-strong);
}

body.dark-mode .btn-outline-success {
    --bs-btn-color: #75b798;
    --bs-btn-border-color: #75b798;
    --bs-btn-hover-color: #ffffff;
    --bs-btn-hover-bg: #198754;
    --bs-btn-hover-border-color: #198754;
}

body.dark-mode .btn-outline-danger {
    --bs-btn-color: #ea868f;
    --bs-btn-border-color: #ea868f;
    --bs-btn-hover-color: #ffffff;
    --bs-btn-hover-bg: #dc3545;
    --bs-btn-hover-border-color: #dc3545;
}

/* Band and state text colours, lighter so they read on the dark cards */
body.dark-mode .text-primary { color: #9ec5fe !important; }
body.dark-mode .text-success { color: #8fd19e !important; }
body.dark-mode .text-danger { color: #f1aeb5 !important; }
body.dark-mode .text-secondary { color: #ced4da !important; }
body.dark-mode .text-info { color: var(--brand-200) !important; }
body.dark-mode .table .text-primary,
body.dark-mode .list-group-item .text-primary { color: #b6d4fe !important; }

body.dark-mode .badge.bg-secondary {
    background-color: #5c636a !important;
    color: #f8f9fa !important;
    border: 1px solid #6c757d;
}

/* "No stations linked" and similar faded notes stay readable */
body.dark-mode .opacity-50 { opacity: .75 !important; }

body.dark-mode .table tr.table-primary > td,
body.dark-mode .table tr.table-primary > th {
    background-color: #1f3b63 !important;
    box-shadow: inset 0 0 0 9999px #1f3b63 !important;
    color: #ffffff !important;
}

body.dark-mode .manage-header-icon.danger { color: #f1aeb5; background: rgba(234, 134, 143, .18); }

